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