wineconsole & curses

Eric Pouech eric.pouech at wanadoo.fr
Sat Dec 21 13:57:58 CST 2002


this patch fixes a few issues with current curses mode:
- mouse clicks behaves now a bit better
- some drawings enhancements: more colors, correct unicode/ascii
   conversion
- Alt-? keystrokes are a bit more recognized

IDA-FW works again (from user to curses mode)
Thanks to Lionel for the debugging info

A+
-- 
Eric Pouech
-------------- next part --------------
Name:          wc_curse
ChangeLog:     
fixed several bugs:
	- wrong drawing for chars outside the 20-7F range
	- console mouse event generation
	- console Alt-? char event generation
prefix for curses functions is now WCCURSES_ instead of WCCURSE_
License:       X11
GenDate:       2002/12/21 19:51:09 UTC
ModifiedFiles: programs/wineconsole/curses.c programs/wineconsole/winecon_private.h programs/wineconsole/wineconsole.c
AddedFiles:    
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/programs/wineconsole/curses.c,v
retrieving revision 1.1
diff -u -u -r1.1 curses.c
--- programs/wineconsole/curses.c	13 Dec 2002 23:37:06 -0000	1.1
+++ programs/wineconsole/curses.c	21 Dec 2002 19:50:53 -0000
@@ -58,11 +58,11 @@
 };
 
 /******************************************************************
- *		WCUSER_ResizeScreenBuffer
+ *		WCCURSES_ResizeScreenBuffer
  *
  *
  */
-static void WCCURSE_ResizeScreenBuffer(struct inner_data* data)
+static void WCCURSES_ResizeScreenBuffer(struct inner_data* data)
 {
     /* reallocate a new pad. next event would redraw the whole pad */
     if (PRIVATE(data)->pad) delwin(PRIVATE(data)->pad);
@@ -74,11 +74,11 @@
 }
 
 /******************************************************************
- *		WCCURSE_PosCursor
+ *		WCCURSES_PosCursor
  *
  * Set a new position for the cursor (and refresh any modified part of our pad)
  */
-static void	WCCURSE_PosCursor(const struct inner_data* data)
+static void	WCCURSES_PosCursor(const struct inner_data* data)
 {
     wmove(PRIVATE(data)->pad, data->cursor.Y, data->cursor.X);
     prefresh(PRIVATE(data)->pad, 
@@ -87,30 +87,30 @@
 }
 
 /******************************************************************
- *		WCCURSE_ShapeCursor
+ *		WCCURSES_ShapeCursor
  *
  * Sets a new shape for the cursor
  */
-void	WCCURSE_ShapeCursor(struct inner_data* data, int size, int vis, BOOL force)
+void	WCCURSES_ShapeCursor(struct inner_data* data, int size, int vis, BOOL force)
 {
 }
 
 /******************************************************************
- *		WCCURSE_ComputePositions
+ *		WCCURSES_ComputePositions
  *
  * Recomputes all the components (mainly scroll bars) positions
  */
-void	WCCURSE_ComputePositions(struct inner_data* data)
+void	WCCURSES_ComputePositions(struct inner_data* data)
 {
-    if (PRIVATE(data)->pad) WCCURSE_PosCursor(data);
+    if (PRIVATE(data)->pad) WCCURSES_PosCursor(data);
 }
 
 /******************************************************************
- *		WCCURSE_SetTitle
+ *		WCCURSES_SetTitle
  *
  * Sets the title to the wine console
  */
-static void	WCCURSE_SetTitle(const struct inner_data* data)
+static void	WCCURSES_SetTitle(const struct inner_data* data)
 {
     WCHAR   wbuf[256];
 
@@ -132,38 +132,44 @@
  *
  *
  */
-static void WCCURSE_Refresh(const struct inner_data* data, int tp, int bm)
+static void WCCURSES_Refresh(const struct inner_data* data, int tp, int bm)
 {
     int         x, y;
     CHAR_INFO*	cell;
-    WORD        color;
+    DWORD       attr;
+    char        ch;
 
     for (y = tp; y <= bm; y++)
     {
 	cell = &data->cells[y * data->curcfg.sb_width];
         for (x = 0; x < data->curcfg.sb_width; x++)
         {
-            color = 0;
-            if (cell[x].Attributes & FOREGROUND_RED)   color |= COLOR_RED;
-            if (cell[x].Attributes & FOREGROUND_BLUE)  color |= COLOR_BLUE;
-            if (cell[x].Attributes & FOREGROUND_GREEN) color |= COLOR_GREEN;
-            if (cell[x].Attributes & BACKGROUND_RED)   color |= COLOR_RED << 3;
-            if (cell[x].Attributes & BACKGROUND_BLUE)  color |= COLOR_BLUE << 3;
-            if (cell[x].Attributes & BACKGROUND_GREEN) color |= COLOR_GREEN << 3;
+            WideCharToMultiByte(CP_ACP, 0, &cell[x].Char.UnicodeChar, 1, 
+                                &ch, 1, NULL, NULL);
+            attr = (BYTE)ch;
+            
+            if (cell[x].Attributes & FOREGROUND_RED)       attr |= COLOR_PAIR(COLOR_RED);
+            if (cell[x].Attributes & FOREGROUND_BLUE)      attr |= COLOR_PAIR(COLOR_BLUE);
+            if (cell[x].Attributes & FOREGROUND_GREEN)     attr |= COLOR_PAIR(COLOR_GREEN);
+            if (cell[x].Attributes & BACKGROUND_RED)       attr |= COLOR_PAIR(COLOR_RED << 3);
+            if (cell[x].Attributes & BACKGROUND_BLUE)      attr |= COLOR_PAIR(COLOR_BLUE << 3);
+            if (cell[x].Attributes & BACKGROUND_GREEN)     attr |= COLOR_PAIR(COLOR_GREEN << 3);
 
-            PRIVATE(data)->line[x] = (unsigned char)cell[x].Char.UnicodeChar | COLOR_PAIR(color);
+            if (cell[x].Attributes & FOREGROUND_INTENSITY) attr |= A_BOLD;
+
+            PRIVATE(data)->line[x] = attr;
         }
         mvwaddchnstr(PRIVATE(data)->pad, y, 0, PRIVATE(data)->line, data->curcfg.sb_width);
     }
-    WCCURSE_PosCursor(data);
+    WCCURSES_PosCursor(data);
 }
 
 /******************************************************************
- *		WCCURSE_Scroll
+ *		WCCURSES_Scroll
  *
  *
  */
-static void WCCURSE_Scroll(struct inner_data* data, int pos, BOOL horz)
+static void WCCURSES_Scroll(struct inner_data* data, int pos, BOOL horz)
 {
     if (horz)
     {
@@ -173,16 +179,16 @@
     {
 	data->curcfg.win_pos.Y = pos;
     }
-    WCCURSE_Refresh(data, data->curcfg.win_pos.Y, 
-                    data->curcfg.win_pos.Y + data->curcfg.win_height - 1);
+    WCCURSES_Refresh(data, data->curcfg.win_pos.Y, 
+                     data->curcfg.win_pos.Y + data->curcfg.win_height - 1);
 }
 
 /******************************************************************
- *		WCCURSE_SetFont
+ *		WCCURSES_SetFont
  *
  *
  */
-static void WCCURSE_SetFont(struct inner_data* data, const WCHAR* font, 
+static void WCCURSES_SetFont(struct inner_data* data, const WCHAR* font, 
                             unsigned height, unsigned weight)
 {
     /* FIXME: really not much to do ? */
@@ -217,26 +223,38 @@
 }; 
 
 /******************************************************************
- *		WCCURSE_FillSimpleChar
+ *		WCCURSES_FillSimpleChar
  *
  *
  */
-static unsigned WCCURSE_FillSimpleChar(INPUT_RECORD* ir, unsigned inchar)
+static unsigned WCCURSES_FillSimpleChar(INPUT_RECORD* ir, unsigned inchar)
 {
-     unsigned 	vk;
-     
-     WINE_TRACE("[%u]\n", inchar);
+     unsigned vk;
+     unsigned second;
+     DWORD    cks = 0;
 
      switch (inchar)
      {
      case 127: inchar = '\b'; break;
      case  10: inchar = '\r'; break;
+     case  27:
+         /* we assume that ESC & and the second character are atomically generated
+          * otherwise, we'll have a race here
+          */
+         if ((second = wgetch(stdscr)) != ERR)
+         {
+             /* we got a alt-something key... */
+             /* FIXME: we don't generate the keydown message for the Alt key */
+             cks = LEFT_ALT_PRESSED;
+             inchar = second;
+         }
+         break;
      }
      
      ir->EventType                        = KEY_EVENT;
      ir->Event.KeyEvent.bKeyDown          = 1;
      ir->Event.KeyEvent.wRepeatCount      = 1;
-     ir->Event.KeyEvent.dwControlKeyState = 0;
+     ir->Event.KeyEvent.dwControlKeyState = cks;
      vk = vkkeyscan_table[inchar];
      if (vk & 0x0100)
 	  ir->Event.KeyEvent.dwControlKeyState |= SHIFT_PRESSED;
@@ -252,11 +270,11 @@
 }
 
 /******************************************************************
- *		WCCURSE_FillComplexChar
+ *		WCCURSES_FillComplexChar
  *
  *
  */
-static unsigned WCCURSE_FillComplexChar(INPUT_RECORD* ir, WORD vk, WORD kc)
+static unsigned WCCURSES_FillComplexChar(INPUT_RECORD* ir, WORD vk, WORD kc)
 {
      ir->EventType			  = KEY_EVENT;
      ir->Event.KeyEvent.bKeyDown	  = 1;
@@ -272,20 +290,19 @@
 }
 
 /******************************************************************
- *		WCCURSE_FillMouse
+ *		WCCURSES_FillMouse
  *
  *
  */
-static unsigned WCCURSE_FillMouse(INPUT_RECORD* ir)
+static unsigned WCCURSES_FillMouse(INPUT_RECORD* ir)
 {
      static	unsigned	bstate /* = 0 */;
      static	COORD 		pos /* = {0, 0} */;
      
      MEVENT	mevt;
-     BOOL	ret = 0;
      
      if (getmouse(&mevt) == ERR)
-	  return FALSE;
+         return FALSE;
      
      WINE_TRACE("[%u]: (%d, %d) %08lx\n", 
                 mevt.id, mevt.x, mevt.y, (unsigned long)mevt.bstate);
@@ -296,7 +313,6 @@
 #define	BTN3_BIT	FROM_LEFT_2ND_BUTTON_PRESSED
 #define	BTN4_BIT	0 /* not done yet */
      
-     /* FIXME: to be checked */
      if (mevt.bstate & BUTTON1_PRESSED)	 bstate |= BTN1_BIT;
      if (mevt.bstate & BUTTON1_RELEASED) bstate &= ~BTN1_BIT;
      if (mevt.bstate & BUTTON2_PRESSED)	 bstate |= BTN2_BIT;
@@ -304,28 +320,12 @@
      if (mevt.bstate & BUTTON3_PRESSED)	 bstate |= BTN3_BIT;
      if (mevt.bstate & BUTTON3_RELEASED) bstate &= ~BTN3_BIT;
      
-     /* for the clicked & double click events, since we'll generate automatically
-      * the release event, we don't have to store the state
-      */
-     if ((mevt.bstate & (BUTTON1_CLICKED|BUTTON1_DOUBLE_CLICKED)) && !(bstate & BTN1_BIT))
-     {
-	  ret = BTN1_BIT;
-     }
-     if ((mevt.bstate & (BUTTON2_CLICKED|BUTTON2_DOUBLE_CLICKED)) && !(bstate & BTN2_BIT))
-     {
-	  ret = BTN2_BIT;
-     }
-     if ((mevt.bstate & (BUTTON3_CLICKED|BUTTON3_DOUBLE_CLICKED)) && !(bstate & BTN3_BIT))
-     {
-	  ret = BTN3_BIT;
-     }
-     
      ir->EventType = MOUSE_EVENT;
      ir->Event.MouseEvent.dwMousePosition.X = mevt.x;
      ir->Event.MouseEvent.dwMousePosition.Y = mevt.y;
      
-     ir->Event.MouseEvent.dwButtonState = (bstate | ret);
-     
+     ir->Event.MouseEvent.dwButtonState = bstate;
+
      /* partial conversion */
      ir->Event.MouseEvent.dwControlKeyState = 0;
      if (mevt.bstate & BUTTON_SHIFT)	ir->Event.MouseEvent.dwControlKeyState |= SHIFT_PRESSED;
@@ -338,27 +338,24 @@
       */
      
      ir->Event.MouseEvent.dwEventFlags = 0;
-     if ((mevt.bstate & BUTTON1_DOUBLE_CLICKED) && ((bstate|ret) & BTN1_BIT))
-	  ir->Event.MouseEvent.dwEventFlags |= DOUBLE_CLICK;
-     if ((mevt.bstate & BUTTON2_DOUBLE_CLICKED) && ((bstate|ret) & BTN2_BIT))
-	  ir->Event.MouseEvent.dwEventFlags |= DOUBLE_CLICK;
-     if ((mevt.bstate & BUTTON3_DOUBLE_CLICKED) && ((bstate|ret) & BTN3_BIT))
-	  ir->Event.MouseEvent.dwEventFlags |= DOUBLE_CLICK;
-     if (mevt.x != pos.X || mevt.y != pos.Y)
+     /* FIXME: we no longer generate double click events */
+
+     if (!(mevt.bstate & (BUTTON1_PRESSED|BUTTON1_RELEASED|BUTTON2_PRESSED|BUTTON2_RELEASED|BUTTON3_PRESSED|BUTTON3_RELEASED)) &&
+         (mevt.x != pos.X || mevt.y != pos.Y))
      {
 	  ir->Event.MouseEvent.dwEventFlags |= MOUSE_MOVED;
      }
      pos.X = mevt.x; pos.Y = mevt.y;
-     
-     return ret;
+
+     return FALSE;
 }
 
 /******************************************************************
- *		WCCURSE_FillCode
+ *		WCCURSES_FillCode
  *
  *
  */
-static unsigned WCCURSE_FillCode(INPUT_RECORD* ir, int inchar)
+static unsigned WCCURSES_FillCode(INPUT_RECORD* ir, int inchar)
 {
     unsigned secondEvent = 0;
 
@@ -367,22 +364,22 @@
     case KEY_BREAK:
         goto notFound;
     case KEY_DOWN:
-        secondEvent = WCCURSE_FillComplexChar(ir, 0x50, 0x28);
+        secondEvent = WCCURSES_FillComplexChar(ir, 0x50, 0x28);
         break;
     case KEY_UP:
-        secondEvent = WCCURSE_FillComplexChar(ir, 0x48, 0x26);
+        secondEvent = WCCURSES_FillComplexChar(ir, 0x48, 0x26);
         break;
     case KEY_LEFT:
-        secondEvent = WCCURSE_FillComplexChar(ir, 0x4b, 0x25);
+        secondEvent = WCCURSES_FillComplexChar(ir, 0x4b, 0x25);
         break;
     case KEY_RIGHT:
-        secondEvent = WCCURSE_FillComplexChar(ir, 0x4d, 0x27);
+        secondEvent = WCCURSES_FillComplexChar(ir, 0x4d, 0x27);
         break;
     case KEY_HOME:
-        secondEvent = WCCURSE_FillComplexChar(ir, 0x47, 0x24);
+        secondEvent = WCCURSES_FillComplexChar(ir, 0x47, 0x24);
         break;
     case KEY_BACKSPACE:
-        secondEvent = WCCURSE_FillSimpleChar(ir, '\b');
+        secondEvent = WCCURSES_FillSimpleChar(ir, '\b');
         break;
         
     case KEY_F0: /* up to F63 */
@@ -398,11 +395,11 @@
     case KEY_F( 8):
     case KEY_F( 9):
     case KEY_F(10):
-        secondEvent = WCCURSE_FillComplexChar(ir, 0x3b + inchar - KEY_F(1), 0);
+        secondEvent = WCCURSES_FillComplexChar(ir, 0x3b + inchar - KEY_F(1), 0);
         break;
     case KEY_F(11):
     case KEY_F(12):
-        secondEvent = WCCURSE_FillComplexChar(ir, 0xd9 + inchar - KEY_F(11), 0);
+        secondEvent = WCCURSES_FillComplexChar(ir, 0xd9 + inchar - KEY_F(11), 0);
         break;
 		    
     case KEY_DL:
@@ -418,10 +415,10 @@
         goto notFound;
 		    
     case KEY_NPAGE:
-        secondEvent = WCCURSE_FillComplexChar(ir, 0x51, 0x22);
+        secondEvent = WCCURSES_FillComplexChar(ir, 0x51, 0x22);
         break;
     case KEY_PPAGE:
-        secondEvent = WCCURSE_FillComplexChar(ir, 0x49, 0x21);
+        secondEvent = WCCURSES_FillComplexChar(ir, 0x49, 0x21);
         break;
         
     case KEY_STAB:
@@ -453,7 +450,7 @@
         goto notFound;
 		    
     case KEY_MOUSE:
-        secondEvent = WCCURSE_FillMouse(ir);
+        secondEvent = WCCURSES_FillMouse(ir);
         break;
         
     case KEY_MOVE:
@@ -511,11 +508,11 @@
 }
 
 /******************************************************************
- *		WCCURSE_GetEvents
+ *		WCCURSES_GetEvents
  *
  *
  */
-static void WCCURSE_GetEvents(struct inner_data* data)
+static void WCCURSES_GetEvents(struct inner_data* data)
 {
      int		inchar;
      INPUT_RECORD       ir[2];
@@ -530,11 +527,11 @@
 	  
      if (inchar & KEY_CODE_YES)
      {
-         secondEvent = WCCURSE_FillCode(ir, inchar);
+         secondEvent = WCCURSES_FillCode(ir, inchar);
      }
      else
      {
-         secondEvent = WCCURSE_FillSimpleChar(ir, inchar);
+         secondEvent = WCCURSES_FillSimpleChar(ir, inchar);
      }
 
      if (secondEvent != 0)
@@ -559,11 +556,11 @@
 }
 
 /******************************************************************
- *		WCCURSE_DeleteBackend
+ *		WCCURSES_DeleteBackend
  *
  *
  */
-static void WCCURSE_DeleteBackend(struct inner_data* data)
+static void WCCURSES_DeleteBackend(struct inner_data* data)
 {
     mmask_t     mm;
 
@@ -581,11 +578,11 @@
 }
 
 /******************************************************************
- *		WCCURSE_MainLoop
+ *		WCCURSES_MainLoop
  *
  *
  */
-static int WCCURSE_MainLoop(struct inner_data* data)
+static int WCCURSES_MainLoop(struct inner_data* data)
 {
     HANDLE hin[2];
 
@@ -598,7 +595,7 @@
         switch (ret)
         {
         case WAIT_OBJECT_0:
-            WCCURSE_GetEvents(data);
+            WCCURSES_GetEvents(data);
             break;
         case WAIT_OBJECT_0+1:
             if (!WINECON_GrabChanges(data)) return 0;
@@ -612,26 +609,26 @@
 }
 
 /******************************************************************
- *		WCCURSE_InitBackend
+ *		WCCURSES_InitBackend
  *
  * Initialisation part II: creation of window.
  *
  */
-BOOL WCCURSE_InitBackend(struct inner_data* data)
+BOOL WCCURSES_InitBackend(struct inner_data* data)
 {
     data->private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct inner_data_curse));
     if (!data->private) return FALSE;
 
-    data->fnMainLoop           = WCCURSE_MainLoop;
-    data->fnPosCursor          = WCCURSE_PosCursor;
-    data->fnShapeCursor        = WCCURSE_ShapeCursor;
-    data->fnComputePositions   = WCCURSE_ComputePositions;
-    data->fnRefresh            = WCCURSE_Refresh;
-    data->fnResizeScreenBuffer = WCCURSE_ResizeScreenBuffer;
-    data->fnSetTitle           = WCCURSE_SetTitle;
-    data->fnScroll             = WCCURSE_Scroll;
-    data->fnSetFont            = WCCURSE_SetFont;
-    data->fnDeleteBackend      = WCCURSE_DeleteBackend;
+    data->fnMainLoop           = WCCURSES_MainLoop;
+    data->fnPosCursor          = WCCURSES_PosCursor;
+    data->fnShapeCursor        = WCCURSES_ShapeCursor;
+    data->fnComputePositions   = WCCURSES_ComputePositions;
+    data->fnRefresh            = WCCURSES_Refresh;
+    data->fnResizeScreenBuffer = WCCURSES_ResizeScreenBuffer;
+    data->fnSetTitle           = WCCURSES_SetTitle;
+    data->fnScroll             = WCCURSES_Scroll;
+    data->fnSetFont            = WCCURSES_SetFont;
+    data->fnDeleteBackend      = WCCURSES_DeleteBackend;
 
     if (wine_server_fd_to_handle(0, GENERIC_READ|SYNCHRONIZE, FALSE, 
                                  (obj_handle_t*)&PRIVATE(data)->hInput))
@@ -659,12 +656,16 @@
     nodelay(stdscr, TRUE);
     keypad(stdscr, TRUE);
     mousemask(0xffffffff, &PRIVATE(data)->initial_mouse_mask);
-
+    /* no click generation...
+     * --hmmm man page says -1, instead of 0, to disable click event generation
+     * -1 doesn't seem to work, while 0 does
+     */
+    mouseinterval(0);
     return TRUE;
 }
 
 #else
-BOOL WCCURSE_InitBackend(struct inner_data* data)
+BOOL WCCURSES_InitBackend(struct inner_data* data)
 {
     return FALSE;
 }
Index: programs/wineconsole/winecon_private.h
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/programs/wineconsole/winecon_private.h,v
retrieving revision 1.8
diff -u -u -r1.8 winecon_private.h
--- programs/wineconsole/winecon_private.h	4 Sep 2002 18:41:52 -0000	1.8
+++ programs/wineconsole/winecon_private.h	21 Dec 2002 14:42:48 -0000
@@ -89,4 +89,4 @@
 
 /* backends... */
 extern BOOL WCUSER_InitBackend(struct inner_data* data);
-extern BOOL WCCURSE_InitBackend(struct inner_data* data);
+extern BOOL WCCURSES_InitBackend(struct inner_data* data);
Index: programs/wineconsole/wineconsole.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/programs/wineconsole/wineconsole.c,v
retrieving revision 1.18
diff -u -u -r1.18 wineconsole.c
--- programs/wineconsole/wineconsole.c	13 Dec 2002 23:37:06 -0000	1.18
+++ programs/wineconsole/wineconsole.c	21 Dec 2002 14:42:38 -0000
@@ -633,7 +632,7 @@
         while (*src && *src != ' ') *dst++ = *src++;
         *dst = 0;
 
-        if (!(data = WINECON_Init(hInst, GetCurrentProcessId(), buffer, WCCURSE_InitBackend))) return 0;
+        if (!(data = WINECON_Init(hInst, GetCurrentProcessId(), buffer, WCCURSES_InitBackend))) return 0;
 	ret = WINECON_Spawn(data, wcmdLine);
         if (!ret)
 	{


More information about the wine-patches mailing list