ok() does not support '%S'. Store the Ansi version, convert to Unicode
[wine] / programs / wineconsole / curses.c
1 /*
2  * a GUI application for displaying a console
3  *      (N)Curses back end
4  *
5  * Copyright 2002 Eric Pouech
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 /* Known issues & FIXME:
23  * - not all key mapping functions have been written
24  * - allow dyn loading of curses library (extreme care should be taken for 
25  *   functions which can be implemented as macros)
26  */
27
28 #include "config.h"
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <errno.h>
33 #ifdef HAVE_CURSES_H
34 #include <curses.h>
35 #endif
36 #ifdef HAVE_NCURSES_H
37 #include <ncurses.h>
38 #endif
39 #include <unistd.h>
40 #include <winnls.h>
41 #include "winecon_private.h"
42
43 #include "wine/server.h"
44 #include "wine/debug.h"
45
46 WINE_DEFAULT_DEBUG_CHANNEL(wineconsole);
47
48 #define PRIVATE(data)   ((struct inner_data_curse*)((data)->private))
49
50 #if defined(HAVE_CURSES_H) || defined(HAVE_NCURSES_H)
51
52 struct inner_data_curse 
53 {
54     mmask_t             initial_mouse_mask;
55     HANDLE              hInput;
56     WINDOW*             pad;
57     chtype*             line;
58 };
59
60 /******************************************************************
61  *              WCCURSES_ResizeScreenBuffer
62  *
63  *
64  */
65 static void WCCURSES_ResizeScreenBuffer(struct inner_data* data)
66 {
67     /* reallocate a new pad. next event would redraw the whole pad */
68     if (PRIVATE(data)->pad) delwin(PRIVATE(data)->pad);
69     PRIVATE(data)->pad = newpad(data->curcfg.sb_height, data->curcfg.sb_width);
70     if (!PRIVATE(data)->pad)
71         WINE_FIXME("Cannot create pad\n");
72     PRIVATE(data)->line = HeapReAlloc(GetProcessHeap(), 0, PRIVATE(data)->line, 
73                                       sizeof(chtype) * data->curcfg.sb_width);
74 }
75
76 /******************************************************************
77  *              WCCURSES_PosCursor
78  *
79  * Set a new position for the cursor (and refresh any modified part of our pad)
80  */
81 static void     WCCURSES_PosCursor(const struct inner_data* data)
82 {
83     if (data->curcfg.cursor_visible &&
84         data->cursor.Y >= data->curcfg.win_pos.Y &&
85         data->cursor.Y < data->curcfg.win_pos.Y + data->curcfg.win_height &&
86         data->cursor.X >= data->curcfg.win_pos.X &&
87         data->cursor.X < data->curcfg.win_pos.X + data->curcfg.win_width)
88     {
89         if (curs_set(2) == ERR) curs_set(1);
90         wmove(PRIVATE(data)->pad, data->cursor.Y, data->cursor.X);
91     }
92     else
93     {
94         curs_set(0);
95     }
96     prefresh(PRIVATE(data)->pad,
97              data->curcfg.win_pos.Y, data->curcfg.win_pos.X,
98              0, 0, data->curcfg.win_height, data->curcfg.win_width);
99 }
100
101 /******************************************************************
102  *              WCCURSES_ShapeCursor
103  *
104  * Sets a new shape for the cursor
105  */
106 void    WCCURSES_ShapeCursor(struct inner_data* data, int size, int vis, BOOL force)
107 {
108     /* we can't do much about the size... */
109     data->curcfg.cursor_size = size;
110     data->curcfg.cursor_visible = vis ? TRUE : FALSE;
111     WCCURSES_PosCursor(data);
112 }
113
114 /******************************************************************
115  *              WCCURSES_ComputePositions
116  *
117  * Recomputes all the components (mainly scroll bars) positions
118  */
119 void    WCCURSES_ComputePositions(struct inner_data* data)
120 {
121     if (PRIVATE(data)->pad) WCCURSES_PosCursor(data);
122 }
123
124 /******************************************************************
125  *              WCCURSES_SetTitle
126  *
127  * Sets the title to the wine console
128  */
129 static void     WCCURSES_SetTitle(const struct inner_data* data)
130 {
131     WCHAR   wbuf[256];
132
133     if (WINECON_GetConsoleTitle(data->hConIn, wbuf, sizeof(wbuf)/sizeof(WCHAR)))
134     {
135         char        buffer[256];
136         
137         WideCharToMultiByte(CP_ACP, 0, wbuf, -1, buffer, sizeof(buffer), 
138                             NULL, NULL);
139         fputs("\033]2;", stdout);
140         fputs(buffer, stdout);
141         fputc('\a', stdout);
142         fflush(stdout);
143     }
144 }
145
146 /******************************************************************
147  *              Refresh
148  *
149  *
150  */
151 static void WCCURSES_Refresh(const struct inner_data* data, int tp, int bm)
152 {
153     int         x, y;
154     CHAR_INFO*  cell;
155     DWORD       attr;
156     char        ch;
157
158     for (y = tp; y <= bm; y++)
159     {
160         cell = &data->cells[y * data->curcfg.sb_width];
161         for (x = 0; x < data->curcfg.sb_width; x++)
162         {
163             WideCharToMultiByte(CP_ACP, 0, &cell[x].Char.UnicodeChar, 1, 
164                                 &ch, 1, NULL, NULL);
165             attr = (BYTE)ch;
166             
167             if (cell[x].Attributes & FOREGROUND_RED)       attr |= COLOR_PAIR(COLOR_RED);
168             if (cell[x].Attributes & FOREGROUND_BLUE)      attr |= COLOR_PAIR(COLOR_BLUE);
169             if (cell[x].Attributes & FOREGROUND_GREEN)     attr |= COLOR_PAIR(COLOR_GREEN);
170             if (cell[x].Attributes & BACKGROUND_RED)       attr |= COLOR_PAIR(COLOR_RED << 3);
171             if (cell[x].Attributes & BACKGROUND_BLUE)      attr |= COLOR_PAIR(COLOR_BLUE << 3);
172             if (cell[x].Attributes & BACKGROUND_GREEN)     attr |= COLOR_PAIR(COLOR_GREEN << 3);
173
174             if (cell[x].Attributes & FOREGROUND_INTENSITY) attr |= A_BOLD;
175             PRIVATE(data)->line[x] = attr;
176         }
177         mvwaddchnstr(PRIVATE(data)->pad, y, 0, PRIVATE(data)->line, data->curcfg.sb_width);
178     }
179     prefresh(PRIVATE(data)->pad,
180              data->curcfg.win_pos.Y, data->curcfg.win_pos.X,
181              0, 0, data->curcfg.win_height, data->curcfg.win_width);
182 }
183
184 /******************************************************************
185  *              WCCURSES_Scroll
186  *
187  *
188  */
189 static void WCCURSES_Scroll(struct inner_data* data, int pos, BOOL horz)
190 {
191     if (horz)
192     {
193         data->curcfg.win_pos.X = pos;
194     }
195     else
196     {
197         data->curcfg.win_pos.Y = pos;
198     }
199     WCCURSES_PosCursor(data);
200 }
201
202 /******************************************************************
203  *              WCCURSES_SetFont
204  *
205  *
206  */
207 static void WCCURSES_SetFont(struct inner_data* data, const WCHAR* font, 
208                             unsigned height, unsigned weight)
209 {
210     /* FIXME: really not much to do ? */
211 }
212
213 /* Ascii -> VK, generated by calling VkKeyScanA(i) */
214 static int vkkeyscan_table[256] = 
215 {
216      0,0,0,0,0,0,0,0,8,9,0,0,0,13,0,0,0,0,0,19,145,556,0,0,0,0,0,27,0,0,0,
217      0,32,305,478,307,308,309,311,222,313,304,312,443,188,189,190,191,48,
218      49,50,51,52,53,54,55,56,57,442,186,444,187,446,447,306,321,322,323,
219      324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,
220      341,342,343,344,345,346,219,220,221,310,445,192,65,66,67,68,69,70,71,
221      72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,475,476,477,
222      448,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
223      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
224      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
225      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,400,0,0,0,0,0,0
226 };
227
228 static int mapvkey_0[256] = 
229 {
230      0,0,0,0,0,0,0,0,14,15,0,0,0,28,0,0,42,29,56,69,58,0,0,0,0,0,0,1,0,0,
231      0,0,57,73,81,79,71,75,72,77,80,0,0,0,55,82,83,0,11,2,3,4,5,6,7,8,9,
232      10,0,0,0,0,0,0,0,30,48,46,32,18,33,34,35,23,36,37,38,50,49,24,25,16,
233      19,31,20,22,47,17,45,21,44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,55,78,0,74,
234      0,53,59,60,61,62,63,64,65,66,67,68,87,88,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
235      0,0,0,0,0,0,69,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
236      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,39,13,51,12,52,53,41,0,0,0,0,0,0,0,0,0,
237      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,43,27,40,76,96,0,0,0,0,0,0,0,0,
238      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
239 }; 
240
241 /******************************************************************
242  *              WCCURSES_FillSimpleChar
243  *
244  *
245  */
246 static unsigned WCCURSES_FillSimpleChar(INPUT_RECORD* ir, unsigned inchar)
247 {
248      unsigned vk;
249      unsigned second;
250      DWORD    cks = 0;
251
252      switch (inchar)
253      {
254      case 127: inchar = '\b'; break;
255      case  10: inchar = '\r'; break;
256      case  27:
257          /* we assume that ESC & and the second character are atomically generated
258           * otherwise, we'll have a race here
259           */
260          if ((second = wgetch(stdscr)) != ERR)
261          {
262              /* we got a alt-something key... */
263              /* FIXME: we don't generate the keydown message for the Alt key */
264              cks = LEFT_ALT_PRESSED;
265              inchar = second;
266          }
267          break;
268      }
269      
270      ir->EventType                        = KEY_EVENT;
271      ir->Event.KeyEvent.bKeyDown          = 1;
272      ir->Event.KeyEvent.wRepeatCount      = 1;
273      ir->Event.KeyEvent.dwControlKeyState = cks;
274      vk = vkkeyscan_table[inchar];
275      if (vk & 0x0100)
276           ir->Event.KeyEvent.dwControlKeyState |= SHIFT_PRESSED;
277      if (vk & 0x0200 || (unsigned char)inchar <= 26)
278           ir->Event.KeyEvent.dwControlKeyState |= LEFT_CTRL_PRESSED;
279      if (vk & 0x0400)
280           ir->Event.KeyEvent.dwControlKeyState |= LEFT_ALT_PRESSED;
281      ir->Event.KeyEvent.wVirtualKeyCode = vk;
282      ir->Event.KeyEvent.wVirtualScanCode = mapvkey_0[vk & 0x00ff]; /* VirtualKeyCodes to ScanCode */
283      ir->Event.KeyEvent.uChar.UnicodeChar = (unsigned char)inchar;
284
285      return TRUE;
286 }
287
288 /******************************************************************
289  *              WCCURSES_FillComplexChar
290  *
291  *
292  */
293 static unsigned WCCURSES_FillComplexChar(INPUT_RECORD* ir, WORD vk, WORD kc)
294 {
295      ir->EventType                        = KEY_EVENT;
296      ir->Event.KeyEvent.bKeyDown          = 1;
297      ir->Event.KeyEvent.wRepeatCount      = 1;
298      ir->Event.KeyEvent.dwControlKeyState = 0;
299      
300      ir->Event.KeyEvent.wVirtualScanCode  = vk;
301      ir->Event.KeyEvent.wVirtualKeyCode   = kc;
302      ir->Event.KeyEvent.dwControlKeyState |= ENHANCED_KEY;
303      ir->Event.KeyEvent.uChar.UnicodeChar = 0;
304      
305      return TRUE;
306 }
307
308 /******************************************************************
309  *              WCCURSES_FillMouse
310  *
311  *
312  */
313 static unsigned WCCURSES_FillMouse(INPUT_RECORD* ir)
314 {
315      static     unsigned        bstate /* = 0 */;
316      static     COORD           pos /* = {0, 0} */;
317      
318      MEVENT     mevt;
319      
320      if (getmouse(&mevt) == ERR)
321          return FALSE;
322      
323      WINE_TRACE("[%u]: (%d, %d) %08lx\n", 
324                 mevt.id, mevt.x, mevt.y, (unsigned long)mevt.bstate);
325      
326      /* macros to ease mapping ncurse button numbering to windows's one */
327 #define BTN1_BIT        FROM_LEFT_1ST_BUTTON_PRESSED
328 #define BTN2_BIT        RIGHTMOST_BUTTON_PRESSED
329 #define BTN3_BIT        FROM_LEFT_2ND_BUTTON_PRESSED
330 #define BTN4_BIT        0 /* not done yet */
331      
332      if (mevt.bstate & BUTTON1_PRESSED)  bstate |= BTN1_BIT;
333      if (mevt.bstate & BUTTON1_RELEASED) bstate &= ~BTN1_BIT;
334      if (mevt.bstate & BUTTON2_PRESSED)  bstate |= BTN2_BIT;
335      if (mevt.bstate & BUTTON2_RELEASED) bstate &= ~BTN2_BIT;
336      if (mevt.bstate & BUTTON3_PRESSED)  bstate |= BTN3_BIT;
337      if (mevt.bstate & BUTTON3_RELEASED) bstate &= ~BTN3_BIT;
338      
339      ir->EventType = MOUSE_EVENT;
340      ir->Event.MouseEvent.dwMousePosition.X = mevt.x;
341      ir->Event.MouseEvent.dwMousePosition.Y = mevt.y;
342      
343      ir->Event.MouseEvent.dwButtonState = bstate;
344
345      /* partial conversion */
346      ir->Event.MouseEvent.dwControlKeyState = 0;
347      if (mevt.bstate & BUTTON_SHIFT)    ir->Event.MouseEvent.dwControlKeyState |= SHIFT_PRESSED;
348      /* choose to map to left ctrl... could use both ? */
349      if (mevt.bstate & BUTTON_CTRL)     ir->Event.MouseEvent.dwControlKeyState |= LEFT_CTRL_PRESSED;
350      /* choose to map to left alt... could use both ? */
351      if (mevt.bstate & BUTTON_ALT)      ir->Event.MouseEvent.dwControlKeyState |= LEFT_ALT_PRESSED;
352      /* FIXME: unsupported yet flags: CAPSLOCK_ON, ENHANCED_KEY (??), NUMLOCK_ON, SCROLLLOCK_ON 
353       * could be reported from the key events...
354       */
355      
356      ir->Event.MouseEvent.dwEventFlags = 0;
357      /* FIXME: we no longer generate double click events */
358
359      if (!(mevt.bstate & (BUTTON1_PRESSED|BUTTON1_RELEASED|BUTTON2_PRESSED|BUTTON2_RELEASED|BUTTON3_PRESSED|BUTTON3_RELEASED)) &&
360          (mevt.x != pos.X || mevt.y != pos.Y))
361      {
362           ir->Event.MouseEvent.dwEventFlags |= MOUSE_MOVED;
363      }
364      pos.X = mevt.x; pos.Y = mevt.y;
365
366      return FALSE;
367 }
368
369 /******************************************************************
370  *              WCCURSES_FillCode
371  *
372  *
373  */
374 static unsigned WCCURSES_FillCode(INPUT_RECORD* ir, int inchar)
375 {
376     unsigned secondEvent = 0;
377
378     switch (inchar)
379     {
380     case KEY_BREAK:
381         goto notFound;
382     case KEY_DOWN:
383         secondEvent = WCCURSES_FillComplexChar(ir, 0x50, 0x28);
384         break;
385     case KEY_UP:
386         secondEvent = WCCURSES_FillComplexChar(ir, 0x48, 0x26);
387         break;
388     case KEY_LEFT:
389         secondEvent = WCCURSES_FillComplexChar(ir, 0x4b, 0x25);
390         break;
391     case KEY_RIGHT:
392         secondEvent = WCCURSES_FillComplexChar(ir, 0x4d, 0x27);
393         break;
394     case KEY_HOME:
395         secondEvent = WCCURSES_FillComplexChar(ir, 0x47, 0x24);
396         break;
397     case KEY_BACKSPACE:
398         secondEvent = WCCURSES_FillSimpleChar(ir, '\b');
399         break;
400         
401     case KEY_F0: /* up to F63 */
402         goto notFound;
403                     
404     case KEY_F( 1):
405     case KEY_F( 2):
406     case KEY_F( 3):
407     case KEY_F( 4):
408     case KEY_F( 5):
409     case KEY_F( 6):
410     case KEY_F( 7):
411     case KEY_F( 8):
412     case KEY_F( 9):
413     case KEY_F(10):
414         secondEvent = WCCURSES_FillComplexChar(ir, 0x3b + inchar - KEY_F(1), 0);
415         break;
416     case KEY_F(11):
417     case KEY_F(12):
418         secondEvent = WCCURSES_FillComplexChar(ir, 0xd9 + inchar - KEY_F(11), 0);
419         break;
420                     
421     case KEY_DL:
422     case KEY_IL:
423     case KEY_DC:
424     case KEY_IC:
425     case KEY_EIC:
426     case KEY_CLEAR:
427     case KEY_EOS:
428     case KEY_EOL:
429     case KEY_SF:
430     case KEY_SR:
431         goto notFound;
432                     
433     case KEY_NPAGE:
434         secondEvent = WCCURSES_FillComplexChar(ir, 0x51, 0x22);
435         break;
436     case KEY_PPAGE:
437         secondEvent = WCCURSES_FillComplexChar(ir, 0x49, 0x21);
438         break;
439         
440     case KEY_STAB:
441     case KEY_CTAB:
442     case KEY_CATAB:
443     case KEY_ENTER:
444     case KEY_SRESET:
445     case KEY_RESET:
446     case KEY_PRINT:
447     case KEY_LL:
448     case KEY_A1:
449     case KEY_A3:
450     case KEY_B2:
451     case KEY_C1:
452     case KEY_C3:
453     case KEY_BTAB:
454     case KEY_BEG:
455     case KEY_CANCEL:
456     case KEY_CLOSE:
457     case KEY_COMMAND:
458     case KEY_COPY:
459     case KEY_CREATE:
460     case KEY_END:
461     case KEY_EXIT:
462     case KEY_FIND:
463     case KEY_HELP:
464     case KEY_MARK:
465     case KEY_MESSAGE:
466         goto notFound;
467                     
468     case KEY_MOUSE:
469         secondEvent = WCCURSES_FillMouse(ir);
470         break;
471         
472     case KEY_MOVE:
473     case KEY_NEXT:
474     case KEY_OPEN:
475     case KEY_OPTIONS:
476     case KEY_PREVIOUS:
477     case KEY_REDO:
478     case KEY_REFERENCE:
479     case KEY_REFRESH:
480     case KEY_REPLACE:
481     case KEY_RESIZE:
482     case KEY_RESTART:
483     case KEY_RESUME:
484     case KEY_SAVE:
485     case KEY_SBEG:
486     case KEY_SCANCEL:
487     case KEY_SCOMMAND:
488     case KEY_SCOPY:
489     case KEY_SCREATE:
490     case KEY_SDC:
491     case KEY_SDL:
492     case KEY_SELECT:
493     case KEY_SEND:
494     case KEY_SEOL:
495     case KEY_SEXIT:
496     case KEY_SFIND:
497     case KEY_SHELP:
498     case KEY_SHOME:
499     case KEY_SIC:
500     case KEY_SLEFT:
501     case KEY_SMESSAGE:
502     case KEY_SMOVE:
503     case KEY_SNEXT:
504     case KEY_SOPTIONS:
505     case KEY_SPREVIOUS:
506     case KEY_SPRINT:
507     case KEY_SREDO:
508     case KEY_SREPLACE:
509     case KEY_SRIGHT:
510     case KEY_SRSUME:
511     case KEY_SSAVE:
512     case KEY_SSUSPEND:
513     case KEY_SUNDO:
514     case KEY_SUSPEND:
515     case KEY_UNDO:
516     notFound:
517         WINE_FIXME("Not done yet (%d)\n", inchar);
518         break;
519     default:
520         WINE_ERR("Unknown val (%d)\n", inchar);
521         break;
522     }
523     return secondEvent;
524 }
525
526 /******************************************************************
527  *              WCCURSES_GetEvents
528  *
529  *
530  */
531 static void WCCURSES_GetEvents(struct inner_data* data)
532 {
533      int                inchar;
534      INPUT_RECORD       ir[2];
535      unsigned           secondEvent = 0;
536      DWORD              n;
537
538      if ((inchar = wgetch(stdscr)) == ERR) {WINE_FIXME("Ooch. somebody beat us\n");return;}
539
540      WINE_TRACE("Got %d\n", inchar);
541
542      ir->EventType = 0;
543           
544      if (inchar & KEY_CODE_YES)
545      {
546          secondEvent = WCCURSES_FillCode(ir, inchar);
547      }
548      else
549      {
550          secondEvent = WCCURSES_FillSimpleChar(ir, inchar);
551      }
552
553      if (secondEvent != 0)
554      {
555          ir[1] = ir[0];
556
557          switch (ir[1].EventType)
558          {
559          case KEY_EVENT:
560              ir[1].Event.KeyEvent.bKeyDown = 0;
561              break;
562          case MOUSE_EVENT:
563              ir[1].Event.MouseEvent.dwButtonState &= ~secondEvent;
564              break;
565          default:       
566              WINE_FIXME("oooo\n");
567              break;
568          }
569      }
570      if (ir[0].EventType != 0)
571          WriteConsoleInput(data->hConIn, ir, secondEvent ? 2 : 1, &n);
572 }
573
574 /******************************************************************
575  *              WCCURSES_DeleteBackend
576  *
577  *
578  */
579 static void WCCURSES_DeleteBackend(struct inner_data* data)
580 {
581     mmask_t     mm;
582
583     if (!PRIVATE(data)) return;
584
585     CloseHandle(PRIVATE(data)->hInput);
586
587     delwin(PRIVATE(data)->pad);
588     mousemask(PRIVATE(data)->initial_mouse_mask, &mm);
589     endwin();
590
591     HeapFree(GetProcessHeap(), 0, PRIVATE(data)->line);
592     HeapFree(GetProcessHeap(), 0, PRIVATE(data));
593     PRIVATE(data) = NULL;
594 }
595
596 /******************************************************************
597  *              WCCURSES_MainLoop
598  *
599  *
600  */
601 static int WCCURSES_MainLoop(struct inner_data* data)
602 {
603     HANDLE hin[2];
604
605     hin[0] = PRIVATE(data)->hInput;
606     hin[1] = data->hSynchro;
607
608     for (;;) 
609     {
610         unsigned ret = WaitForMultipleObjects(2, hin, FALSE, INFINITE);
611         switch (ret)
612         {
613         case WAIT_OBJECT_0:
614             WCCURSES_GetEvents(data);
615             break;
616         case WAIT_OBJECT_0+1:
617             if (!WINECON_GrabChanges(data)) return 0;
618             break;
619         default:
620             WINE_ERR("got pb\n");
621             /* err */
622             break;
623         }
624     }
625 }
626
627 /******************************************************************
628  *              WCCURSES_InitBackend
629  *
630  * Initialisation part II: creation of window.
631  *
632  */
633 BOOL WCCURSES_InitBackend(struct inner_data* data)
634 {
635     data->private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct inner_data_curse));
636     if (!data->private) return FALSE;
637
638     data->fnMainLoop           = WCCURSES_MainLoop;
639     data->fnPosCursor          = WCCURSES_PosCursor;
640     data->fnShapeCursor        = WCCURSES_ShapeCursor;
641     data->fnComputePositions   = WCCURSES_ComputePositions;
642     data->fnRefresh            = WCCURSES_Refresh;
643     data->fnResizeScreenBuffer = WCCURSES_ResizeScreenBuffer;
644     data->fnSetTitle           = WCCURSES_SetTitle;
645     data->fnScroll             = WCCURSES_Scroll;
646     data->fnSetFont            = WCCURSES_SetFont;
647     data->fnDeleteBackend      = WCCURSES_DeleteBackend;
648
649     if (wine_server_fd_to_handle(0, GENERIC_READ|SYNCHRONIZE, FALSE, 
650                                  (obj_handle_t*)&PRIVATE(data)->hInput))
651     {
652         WINE_FIXME("Cannot open 0\n");
653         return 0;
654     }
655
656     initscr();
657
658     /* creating the basic colors - FIXME intensity not handled yet */
659     if (has_colors())
660     {
661         int i, j;
662
663         start_color();
664         for (i = 0; i < 8; i++)
665             for (j = 0; j < 8; j++)
666                 init_pair(i | (j << 3), i, j);
667     }
668
669     raw();
670     noecho();
671     intrflush(stdscr, FALSE);
672     nodelay(stdscr, TRUE);
673     keypad(stdscr, TRUE);
674     mousemask(0xffffffff, &PRIVATE(data)->initial_mouse_mask);
675     /* no click event generation... we just need button up/down event */
676     mouseinterval(-1);
677
678     return TRUE;
679 }
680
681 #else
682 BOOL WCCURSES_InitBackend(struct inner_data* data)
683 {
684     return FALSE;
685 }
686 #endif