Cygwin: console: Fix read() in non-canonical mode.
- In non-canonical mode, cygwin console returned only one character even if several keys are typed before read() called. This patch fixes this behaviour.
This commit is contained in:
parent
3355a6d4b9
commit
fca4cda7a4
@ -499,354 +499,378 @@ fhandler_console::process_input_message (void)
|
|||||||
|
|
||||||
termios *ti = &(get_ttyp ()->ti);
|
termios *ti = &(get_ttyp ()->ti);
|
||||||
|
|
||||||
DWORD nread;
|
/* Per MSDN, max size of buffer required is below 64K. */
|
||||||
INPUT_RECORD input_rec;
|
#define INREC_SIZE (65536 / sizeof (INPUT_RECORD))
|
||||||
const char *toadd = NULL;
|
|
||||||
|
|
||||||
if (!ReadConsoleInputW (get_handle (), &input_rec, 1, &nread))
|
fhandler_console::input_states stat = input_processing;
|
||||||
|
DWORD total_read, i;
|
||||||
|
INPUT_RECORD input_rec[INREC_SIZE];
|
||||||
|
|
||||||
|
if (!PeekConsoleInputW (get_handle (), input_rec, INREC_SIZE, &total_read))
|
||||||
{
|
{
|
||||||
termios_printf ("ReadConsoleInput failed, %E");
|
termios_printf ("PeekConsoleInput failed, %E");
|
||||||
return input_error;
|
return input_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
const WCHAR &unicode_char = input_rec.Event.KeyEvent.uChar.UnicodeChar;
|
for (i = 0; i < total_read; i ++)
|
||||||
const DWORD &ctrl_key_state = input_rec.Event.KeyEvent.dwControlKeyState;
|
|
||||||
|
|
||||||
/* check the event that occurred */
|
|
||||||
switch (input_rec.EventType)
|
|
||||||
{
|
{
|
||||||
case KEY_EVENT:
|
DWORD nread = 1;
|
||||||
|
const char *toadd = NULL;
|
||||||
|
|
||||||
con.nModifiers = 0;
|
const WCHAR &unicode_char =
|
||||||
|
input_rec[i].Event.KeyEvent.uChar.UnicodeChar;
|
||||||
|
const DWORD &ctrl_key_state =
|
||||||
|
input_rec[i].Event.KeyEvent.dwControlKeyState;
|
||||||
|
|
||||||
|
/* check the event that occurred */
|
||||||
|
switch (input_rec[i].EventType)
|
||||||
|
{
|
||||||
|
case KEY_EVENT:
|
||||||
|
|
||||||
|
con.nModifiers = 0;
|
||||||
|
|
||||||
#ifdef DEBUGGING
|
#ifdef DEBUGGING
|
||||||
/* allow manual switching to/from raw mode via ctrl-alt-scrolllock */
|
/* allow manual switching to/from raw mode via ctrl-alt-scrolllock */
|
||||||
if (input_rec.Event.KeyEvent.bKeyDown
|
if (input_rec[i].Event.KeyEvent.bKeyDown
|
||||||
&& input_rec.Event.KeyEvent.wVirtualKeyCode == VK_SCROLL
|
&& input_rec[i].Event.KeyEvent.wVirtualKeyCode == VK_SCROLL
|
||||||
&& (ctrl_key_state & (LEFT_ALT_PRESSED | LEFT_CTRL_PRESSED))
|
&& (ctrl_key_state & (LEFT_ALT_PRESSED | LEFT_CTRL_PRESSED))
|
||||||
== (LEFT_ALT_PRESSED | LEFT_CTRL_PRESSED))
|
== (LEFT_ALT_PRESSED | LEFT_CTRL_PRESSED))
|
||||||
{
|
{
|
||||||
set_raw_win32_keyboard_mode (!con.raw_win32_keyboard_mode);
|
set_raw_win32_keyboard_mode (!con.raw_win32_keyboard_mode);
|
||||||
return input_processing;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (con.raw_win32_keyboard_mode)
|
if (con.raw_win32_keyboard_mode)
|
||||||
{
|
{
|
||||||
__small_sprintf (tmp, "\033{%u;%u;%u;%u;%u;%luK",
|
__small_sprintf (tmp, "\033{%u;%u;%u;%u;%u;%luK",
|
||||||
input_rec.Event.KeyEvent.bKeyDown,
|
input_rec[i].Event.KeyEvent.bKeyDown,
|
||||||
input_rec.Event.KeyEvent.wRepeatCount,
|
input_rec[i].Event.KeyEvent.wRepeatCount,
|
||||||
input_rec.Event.KeyEvent.wVirtualKeyCode,
|
input_rec[i].Event.KeyEvent.wVirtualKeyCode,
|
||||||
input_rec.Event.KeyEvent.wVirtualScanCode,
|
input_rec[i].Event.KeyEvent.wVirtualScanCode,
|
||||||
input_rec.Event.KeyEvent.uChar.UnicodeChar,
|
input_rec[i].Event.KeyEvent.uChar.UnicodeChar,
|
||||||
input_rec.Event.KeyEvent.dwControlKeyState);
|
input_rec[i].Event.KeyEvent.dwControlKeyState);
|
||||||
toadd = tmp;
|
toadd = tmp;
|
||||||
nread = strlen (toadd);
|
nread = strlen (toadd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ignore key up events, except for Alt+Numpad events. */
|
||||||
|
if (!input_rec[i].Event.KeyEvent.bKeyDown &&
|
||||||
|
!is_alt_numpad_event (&input_rec[i]))
|
||||||
|
continue;
|
||||||
|
/* Ignore Alt+Numpad keys. They are eventually handled below after
|
||||||
|
releasing the Alt key. */
|
||||||
|
if (input_rec[i].Event.KeyEvent.bKeyDown
|
||||||
|
&& is_alt_numpad_key (&input_rec[i]))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ctrl_key_state & SHIFT_PRESSED)
|
||||||
|
con.nModifiers |= 1;
|
||||||
|
if (ctrl_key_state & RIGHT_ALT_PRESSED)
|
||||||
|
con.nModifiers |= 2;
|
||||||
|
if (ctrl_key_state & CTRL_PRESSED)
|
||||||
|
con.nModifiers |= 4;
|
||||||
|
if (ctrl_key_state & LEFT_ALT_PRESSED)
|
||||||
|
con.nModifiers |= 8;
|
||||||
|
|
||||||
|
/* Allow Backspace to emit ^? and escape sequences. */
|
||||||
|
if (input_rec[i].Event.KeyEvent.wVirtualKeyCode == VK_BACK)
|
||||||
|
{
|
||||||
|
char c = con.backspace_keycode;
|
||||||
|
nread = 0;
|
||||||
|
if (ctrl_key_state & ALT_PRESSED)
|
||||||
|
{
|
||||||
|
if (con.metabit)
|
||||||
|
c |= 0x80;
|
||||||
|
else
|
||||||
|
tmp[nread++] = '\e';
|
||||||
|
}
|
||||||
|
tmp[nread++] = c;
|
||||||
|
tmp[nread] = 0;
|
||||||
|
toadd = tmp;
|
||||||
|
}
|
||||||
|
/* Allow Ctrl-Space to emit ^@ */
|
||||||
|
else if (input_rec[i].Event.KeyEvent.wVirtualKeyCode
|
||||||
|
== (wincap.has_con_24bit_colors () ? '2' : VK_SPACE)
|
||||||
|
&& (ctrl_key_state & CTRL_PRESSED)
|
||||||
|
&& !(ctrl_key_state & ALT_PRESSED))
|
||||||
|
toadd = "";
|
||||||
|
else if (unicode_char == 0
|
||||||
|
/* arrow/function keys */
|
||||||
|
|| (input_rec[i].Event.KeyEvent.dwControlKeyState
|
||||||
|
& ENHANCED_KEY))
|
||||||
|
{
|
||||||
|
toadd = get_nonascii_key (input_rec[i], tmp);
|
||||||
|
if (!toadd)
|
||||||
|
{
|
||||||
|
con.nModifiers = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
nread = strlen (toadd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nread = con.con_to_str (tmp + 1, 59, unicode_char);
|
||||||
|
/* Determine if the keystroke is modified by META. The tricky
|
||||||
|
part is to distinguish whether the right Alt key should be
|
||||||
|
recognized as Alt, or as AltGr. */
|
||||||
|
bool meta =
|
||||||
|
/* Alt but not AltGr (= left ctrl + right alt)? */
|
||||||
|
(ctrl_key_state & ALT_PRESSED) != 0
|
||||||
|
&& ((ctrl_key_state & CTRL_PRESSED) == 0
|
||||||
|
/* but also allow Alt-AltGr: */
|
||||||
|
|| (ctrl_key_state & ALT_PRESSED) == ALT_PRESSED
|
||||||
|
|| (unicode_char <= 0x1f || unicode_char == 0x7f));
|
||||||
|
if (!meta)
|
||||||
|
{
|
||||||
|
/* Determine if the character is in the current multibyte
|
||||||
|
charset. The test is easy. If the multibyte sequence
|
||||||
|
is > 1 and the first byte is ASCII CAN, the character
|
||||||
|
has been translated into the ASCII CAN + UTF-8 replacement
|
||||||
|
sequence. If so, just ignore the keypress.
|
||||||
|
FIXME: Is there a better solution? */
|
||||||
|
if (nread > 1 && tmp[1] == 0x18)
|
||||||
|
beep ();
|
||||||
|
else
|
||||||
|
toadd = tmp + 1;
|
||||||
|
}
|
||||||
|
else if (con.metabit)
|
||||||
|
{
|
||||||
|
tmp[1] |= 0x80;
|
||||||
|
toadd = tmp + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tmp[0] = '\033';
|
||||||
|
tmp[1] = cyg_tolower (tmp[1]);
|
||||||
|
toadd = tmp;
|
||||||
|
nread++;
|
||||||
|
con.nModifiers &= ~4;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
/* Ignore key up events, except for Alt+Numpad events. */
|
case MOUSE_EVENT:
|
||||||
if (!input_rec.Event.KeyEvent.bKeyDown &&
|
send_winch_maybe ();
|
||||||
!is_alt_numpad_event (&input_rec))
|
|
||||||
return input_processing;
|
|
||||||
/* Ignore Alt+Numpad keys. They are eventually handled below after
|
|
||||||
releasing the Alt key. */
|
|
||||||
if (input_rec.Event.KeyEvent.bKeyDown
|
|
||||||
&& is_alt_numpad_key (&input_rec))
|
|
||||||
return input_processing;
|
|
||||||
|
|
||||||
if (ctrl_key_state & SHIFT_PRESSED)
|
|
||||||
con.nModifiers |= 1;
|
|
||||||
if (ctrl_key_state & RIGHT_ALT_PRESSED)
|
|
||||||
con.nModifiers |= 2;
|
|
||||||
if (ctrl_key_state & CTRL_PRESSED)
|
|
||||||
con.nModifiers |= 4;
|
|
||||||
if (ctrl_key_state & LEFT_ALT_PRESSED)
|
|
||||||
con.nModifiers |= 8;
|
|
||||||
|
|
||||||
/* Allow Backspace to emit ^? and escape sequences. */
|
|
||||||
if (input_rec.Event.KeyEvent.wVirtualKeyCode == VK_BACK)
|
|
||||||
{
|
|
||||||
char c = con.backspace_keycode;
|
|
||||||
nread = 0;
|
|
||||||
if (ctrl_key_state & ALT_PRESSED)
|
|
||||||
{
|
{
|
||||||
if (con.metabit)
|
MOUSE_EVENT_RECORD& mouse_event = input_rec[i].Event.MouseEvent;
|
||||||
c |= 0x80;
|
/* As a unique guard for mouse report generation,
|
||||||
else
|
call mouse_aware() which is common with select(), so the result
|
||||||
tmp[nread++] = '\e';
|
of select() and the actual read() will be consistent on the
|
||||||
}
|
issue of whether input (i.e. a mouse escape sequence) will
|
||||||
tmp[nread++] = c;
|
be available or not */
|
||||||
tmp[nread] = 0;
|
if (mouse_aware (mouse_event))
|
||||||
toadd = tmp;
|
|
||||||
}
|
|
||||||
/* Allow Ctrl-Space to emit ^@ */
|
|
||||||
else if (input_rec.Event.KeyEvent.wVirtualKeyCode
|
|
||||||
== (wincap.has_con_24bit_colors () ? '2' : VK_SPACE)
|
|
||||||
&& (ctrl_key_state & CTRL_PRESSED)
|
|
||||||
&& !(ctrl_key_state & ALT_PRESSED))
|
|
||||||
toadd = "";
|
|
||||||
else if (unicode_char == 0
|
|
||||||
/* arrow/function keys */
|
|
||||||
|| (input_rec.Event.KeyEvent.dwControlKeyState & ENHANCED_KEY))
|
|
||||||
{
|
|
||||||
toadd = get_nonascii_key (input_rec, tmp);
|
|
||||||
if (!toadd)
|
|
||||||
{
|
|
||||||
con.nModifiers = 0;
|
|
||||||
return input_processing;
|
|
||||||
}
|
|
||||||
nread = strlen (toadd);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nread = con.con_to_str (tmp + 1, 59, unicode_char);
|
|
||||||
/* Determine if the keystroke is modified by META. The tricky
|
|
||||||
part is to distinguish whether the right Alt key should be
|
|
||||||
recognized as Alt, or as AltGr. */
|
|
||||||
bool meta =
|
|
||||||
/* Alt but not AltGr (= left ctrl + right alt)? */
|
|
||||||
(ctrl_key_state & ALT_PRESSED) != 0
|
|
||||||
&& ((ctrl_key_state & CTRL_PRESSED) == 0
|
|
||||||
/* but also allow Alt-AltGr: */
|
|
||||||
|| (ctrl_key_state & ALT_PRESSED) == ALT_PRESSED
|
|
||||||
|| (unicode_char <= 0x1f || unicode_char == 0x7f));
|
|
||||||
if (!meta)
|
|
||||||
{
|
|
||||||
/* Determine if the character is in the current multibyte
|
|
||||||
charset. The test is easy. If the multibyte sequence
|
|
||||||
is > 1 and the first byte is ASCII CAN, the character
|
|
||||||
has been translated into the ASCII CAN + UTF-8 replacement
|
|
||||||
sequence. If so, just ignore the keypress.
|
|
||||||
FIXME: Is there a better solution? */
|
|
||||||
if (nread > 1 && tmp[1] == 0x18)
|
|
||||||
beep ();
|
|
||||||
else
|
|
||||||
toadd = tmp + 1;
|
|
||||||
}
|
|
||||||
else if (con.metabit)
|
|
||||||
{
|
|
||||||
tmp[1] |= 0x80;
|
|
||||||
toadd = tmp + 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tmp[0] = '\033';
|
|
||||||
tmp[1] = cyg_tolower (tmp[1]);
|
|
||||||
toadd = tmp;
|
|
||||||
nread++;
|
|
||||||
con.nModifiers &= ~4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MOUSE_EVENT:
|
|
||||||
send_winch_maybe ();
|
|
||||||
{
|
|
||||||
MOUSE_EVENT_RECORD& mouse_event = input_rec.Event.MouseEvent;
|
|
||||||
/* As a unique guard for mouse report generation,
|
|
||||||
call mouse_aware() which is common with select(), so the result
|
|
||||||
of select() and the actual read() will be consistent on the
|
|
||||||
issue of whether input (i.e. a mouse escape sequence) will
|
|
||||||
be available or not */
|
|
||||||
if (mouse_aware (mouse_event))
|
|
||||||
{
|
|
||||||
/* Note: Reported mouse position was already retrieved by
|
|
||||||
mouse_aware() and adjusted by window scroll buffer offset */
|
|
||||||
|
|
||||||
/* Treat the double-click event like a regular button press */
|
|
||||||
if (mouse_event.dwEventFlags == DOUBLE_CLICK)
|
|
||||||
{
|
{
|
||||||
syscall_printf ("mouse: double-click -> click");
|
/* Note: Reported mouse position was already retrieved by
|
||||||
mouse_event.dwEventFlags = 0;
|
mouse_aware() and adjusted by window scroll buffer offset */
|
||||||
}
|
|
||||||
|
|
||||||
/* This code assumes Windows never reports multiple button
|
/* Treat the double-click event like a regular button press */
|
||||||
events at the same time. */
|
if (mouse_event.dwEventFlags == DOUBLE_CLICK)
|
||||||
int b = 0;
|
|
||||||
char sz[32];
|
|
||||||
char mode6_term = 'M';
|
|
||||||
|
|
||||||
if (mouse_event.dwEventFlags == MOUSE_WHEELED)
|
|
||||||
{
|
|
||||||
if (mouse_event.dwButtonState & 0xFF800000)
|
|
||||||
{
|
{
|
||||||
b = 0x41;
|
syscall_printf ("mouse: double-click -> click");
|
||||||
strcpy (sz, "wheel down");
|
mouse_event.dwEventFlags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This code assumes Windows never reports multiple button
|
||||||
|
events at the same time. */
|
||||||
|
int b = 0;
|
||||||
|
char sz[32];
|
||||||
|
char mode6_term = 'M';
|
||||||
|
|
||||||
|
if (mouse_event.dwEventFlags == MOUSE_WHEELED)
|
||||||
|
{
|
||||||
|
if (mouse_event.dwButtonState & 0xFF800000)
|
||||||
|
{
|
||||||
|
b = 0x41;
|
||||||
|
strcpy (sz, "wheel down");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
b = 0x40;
|
||||||
|
strcpy (sz, "wheel up");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
b = 0x40;
|
/* Ignore unimportant mouse buttons */
|
||||||
strcpy (sz, "wheel up");
|
mouse_event.dwButtonState &= 0x7;
|
||||||
|
|
||||||
|
if (mouse_event.dwEventFlags == MOUSE_MOVED)
|
||||||
|
{
|
||||||
|
b = con.last_button_code;
|
||||||
|
}
|
||||||
|
else if (mouse_event.dwButtonState < con.dwLastButtonState
|
||||||
|
&& !con.ext_mouse_mode6)
|
||||||
|
{
|
||||||
|
b = 3;
|
||||||
|
strcpy (sz, "btn up");
|
||||||
|
}
|
||||||
|
else if ((mouse_event.dwButtonState & 1)
|
||||||
|
!= (con.dwLastButtonState & 1))
|
||||||
|
{
|
||||||
|
b = 0;
|
||||||
|
strcpy (sz, "btn1 down");
|
||||||
|
}
|
||||||
|
else if ((mouse_event.dwButtonState & 2)
|
||||||
|
!= (con.dwLastButtonState & 2))
|
||||||
|
{
|
||||||
|
b = 2;
|
||||||
|
strcpy (sz, "btn2 down");
|
||||||
|
}
|
||||||
|
else if ((mouse_event.dwButtonState & 4)
|
||||||
|
!= (con.dwLastButtonState & 4))
|
||||||
|
{
|
||||||
|
b = 1;
|
||||||
|
strcpy (sz, "btn3 down");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (con.ext_mouse_mode6 /* distinguish release */
|
||||||
|
&& mouse_event.dwButtonState < con.dwLastButtonState)
|
||||||
|
mode6_term = 'm';
|
||||||
|
|
||||||
|
con.last_button_code = b;
|
||||||
|
|
||||||
|
if (mouse_event.dwEventFlags == MOUSE_MOVED)
|
||||||
|
{
|
||||||
|
b += 32;
|
||||||
|
strcpy (sz, "move");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Remember the modified button state */
|
||||||
|
con.dwLastButtonState = mouse_event.dwButtonState;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Remember mouse position */
|
||||||
|
con.dwLastMousePosition.X = con.dwMousePosition.X;
|
||||||
|
con.dwLastMousePosition.Y = con.dwMousePosition.Y;
|
||||||
|
|
||||||
|
/* Remember the modifiers */
|
||||||
|
con.nModifiers = 0;
|
||||||
|
if (mouse_event.dwControlKeyState & SHIFT_PRESSED)
|
||||||
|
con.nModifiers |= 0x4;
|
||||||
|
if (mouse_event.dwControlKeyState & ALT_PRESSED)
|
||||||
|
con.nModifiers |= 0x8;
|
||||||
|
if (mouse_event.dwControlKeyState & CTRL_PRESSED)
|
||||||
|
con.nModifiers |= 0x10;
|
||||||
|
|
||||||
|
/* Indicate the modifiers */
|
||||||
|
b |= con.nModifiers;
|
||||||
|
|
||||||
|
/* We can now create the code. */
|
||||||
|
if (con.ext_mouse_mode6)
|
||||||
|
{
|
||||||
|
__small_sprintf (tmp, "\033[<%d;%d;%d%c", b,
|
||||||
|
con.dwMousePosition.X + 1,
|
||||||
|
con.dwMousePosition.Y + 1,
|
||||||
|
mode6_term);
|
||||||
|
nread = strlen (tmp);
|
||||||
|
}
|
||||||
|
else if (con.ext_mouse_mode15)
|
||||||
|
{
|
||||||
|
__small_sprintf (tmp, "\033[%d;%d;%dM", b + 32,
|
||||||
|
con.dwMousePosition.X + 1,
|
||||||
|
con.dwMousePosition.Y + 1);
|
||||||
|
nread = strlen (tmp);
|
||||||
|
}
|
||||||
|
else if (con.ext_mouse_mode5)
|
||||||
|
{
|
||||||
|
unsigned int xcode = con.dwMousePosition.X + ' ' + 1;
|
||||||
|
unsigned int ycode = con.dwMousePosition.Y + ' ' + 1;
|
||||||
|
|
||||||
|
__small_sprintf (tmp, "\033[M%c", b + ' ');
|
||||||
|
nread = 4;
|
||||||
|
/* the neat nested encoding function of mintty
|
||||||
|
does not compile in g++, so let's unfold it: */
|
||||||
|
if (xcode < 0x80)
|
||||||
|
tmp [nread++] = xcode;
|
||||||
|
else if (xcode < 0x800)
|
||||||
|
{
|
||||||
|
tmp [nread++] = 0xC0 + (xcode >> 6);
|
||||||
|
tmp [nread++] = 0x80 + (xcode & 0x3F);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tmp [nread++] = 0;
|
||||||
|
if (ycode < 0x80)
|
||||||
|
tmp [nread++] = ycode;
|
||||||
|
else if (ycode < 0x800)
|
||||||
|
{
|
||||||
|
tmp [nread++] = 0xC0 + (ycode >> 6);
|
||||||
|
tmp [nread++] = 0x80 + (ycode & 0x3F);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tmp [nread++] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned int xcode = con.dwMousePosition.X + ' ' + 1;
|
||||||
|
unsigned int ycode = con.dwMousePosition.Y + ' ' + 1;
|
||||||
|
if (xcode >= 256)
|
||||||
|
xcode = 0;
|
||||||
|
if (ycode >= 256)
|
||||||
|
ycode = 0;
|
||||||
|
__small_sprintf (tmp, "\033[M%c%c%c", b + ' ',
|
||||||
|
xcode, ycode);
|
||||||
|
nread = 6; /* tmp may contain NUL bytes */
|
||||||
|
}
|
||||||
|
syscall_printf ("mouse: %s at (%d,%d)", sz,
|
||||||
|
con.dwMousePosition.X,
|
||||||
|
con.dwMousePosition.Y);
|
||||||
|
|
||||||
|
toadd = tmp;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FOCUS_EVENT:
|
||||||
|
if (con.use_focus)
|
||||||
|
{
|
||||||
|
if (input_rec[i].Event.FocusEvent.bSetFocus)
|
||||||
|
__small_sprintf (tmp, "\033[I");
|
||||||
else
|
else
|
||||||
{
|
__small_sprintf (tmp, "\033[O");
|
||||||
/* Ignore unimportant mouse buttons */
|
|
||||||
mouse_event.dwButtonState &= 0x7;
|
|
||||||
|
|
||||||
if (mouse_event.dwEventFlags == MOUSE_MOVED)
|
|
||||||
{
|
|
||||||
b = con.last_button_code;
|
|
||||||
}
|
|
||||||
else if (mouse_event.dwButtonState < con.dwLastButtonState
|
|
||||||
&& !con.ext_mouse_mode6)
|
|
||||||
{
|
|
||||||
b = 3;
|
|
||||||
strcpy (sz, "btn up");
|
|
||||||
}
|
|
||||||
else if ((mouse_event.dwButtonState & 1)
|
|
||||||
!= (con.dwLastButtonState & 1))
|
|
||||||
{
|
|
||||||
b = 0;
|
|
||||||
strcpy (sz, "btn1 down");
|
|
||||||
}
|
|
||||||
else if ((mouse_event.dwButtonState & 2)
|
|
||||||
!= (con.dwLastButtonState & 2))
|
|
||||||
{
|
|
||||||
b = 2;
|
|
||||||
strcpy (sz, "btn2 down");
|
|
||||||
}
|
|
||||||
else if ((mouse_event.dwButtonState & 4)
|
|
||||||
!= (con.dwLastButtonState & 4))
|
|
||||||
{
|
|
||||||
b = 1;
|
|
||||||
strcpy (sz, "btn3 down");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (con.ext_mouse_mode6 /* distinguish release */
|
|
||||||
&& mouse_event.dwButtonState < con.dwLastButtonState)
|
|
||||||
mode6_term = 'm';
|
|
||||||
|
|
||||||
con.last_button_code = b;
|
|
||||||
|
|
||||||
if (mouse_event.dwEventFlags == MOUSE_MOVED)
|
|
||||||
{
|
|
||||||
b += 32;
|
|
||||||
strcpy (sz, "move");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Remember the modified button state */
|
|
||||||
con.dwLastButtonState = mouse_event.dwButtonState;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remember mouse position */
|
|
||||||
con.dwLastMousePosition.X = con.dwMousePosition.X;
|
|
||||||
con.dwLastMousePosition.Y = con.dwMousePosition.Y;
|
|
||||||
|
|
||||||
/* Remember the modifiers */
|
|
||||||
con.nModifiers = 0;
|
|
||||||
if (mouse_event.dwControlKeyState & SHIFT_PRESSED)
|
|
||||||
con.nModifiers |= 0x4;
|
|
||||||
if (mouse_event.dwControlKeyState & ALT_PRESSED)
|
|
||||||
con.nModifiers |= 0x8;
|
|
||||||
if (mouse_event.dwControlKeyState & CTRL_PRESSED)
|
|
||||||
con.nModifiers |= 0x10;
|
|
||||||
|
|
||||||
/* Indicate the modifiers */
|
|
||||||
b |= con.nModifiers;
|
|
||||||
|
|
||||||
/* We can now create the code. */
|
|
||||||
if (con.ext_mouse_mode6)
|
|
||||||
{
|
|
||||||
__small_sprintf (tmp, "\033[<%d;%d;%d%c", b,
|
|
||||||
con.dwMousePosition.X + 1,
|
|
||||||
con.dwMousePosition.Y + 1,
|
|
||||||
mode6_term);
|
|
||||||
nread = strlen (tmp);
|
|
||||||
}
|
|
||||||
else if (con.ext_mouse_mode15)
|
|
||||||
{
|
|
||||||
__small_sprintf (tmp, "\033[%d;%d;%dM", b + 32,
|
|
||||||
con.dwMousePosition.X + 1,
|
|
||||||
con.dwMousePosition.Y + 1);
|
|
||||||
nread = strlen (tmp);
|
|
||||||
}
|
|
||||||
else if (con.ext_mouse_mode5)
|
|
||||||
{
|
|
||||||
unsigned int xcode = con.dwMousePosition.X + ' ' + 1;
|
|
||||||
unsigned int ycode = con.dwMousePosition.Y + ' ' + 1;
|
|
||||||
|
|
||||||
__small_sprintf (tmp, "\033[M%c", b + ' ');
|
|
||||||
nread = 4;
|
|
||||||
/* the neat nested encoding function of mintty
|
|
||||||
does not compile in g++, so let's unfold it: */
|
|
||||||
if (xcode < 0x80)
|
|
||||||
tmp [nread++] = xcode;
|
|
||||||
else if (xcode < 0x800)
|
|
||||||
{
|
|
||||||
tmp [nread++] = 0xC0 + (xcode >> 6);
|
|
||||||
tmp [nread++] = 0x80 + (xcode & 0x3F);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
tmp [nread++] = 0;
|
|
||||||
if (ycode < 0x80)
|
|
||||||
tmp [nread++] = ycode;
|
|
||||||
else if (ycode < 0x800)
|
|
||||||
{
|
|
||||||
tmp [nread++] = 0xC0 + (ycode >> 6);
|
|
||||||
tmp [nread++] = 0x80 + (ycode & 0x3F);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
tmp [nread++] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
unsigned int xcode = con.dwMousePosition.X + ' ' + 1;
|
|
||||||
unsigned int ycode = con.dwMousePosition.Y + ' ' + 1;
|
|
||||||
if (xcode >= 256)
|
|
||||||
xcode = 0;
|
|
||||||
if (ycode >= 256)
|
|
||||||
ycode = 0;
|
|
||||||
__small_sprintf (tmp, "\033[M%c%c%c", b + ' ',
|
|
||||||
xcode, ycode);
|
|
||||||
nread = 6; /* tmp may contain NUL bytes */
|
|
||||||
}
|
|
||||||
syscall_printf ("mouse: %s at (%d,%d)", sz,
|
|
||||||
con.dwMousePosition.X,
|
|
||||||
con.dwMousePosition.Y);
|
|
||||||
|
|
||||||
toadd = tmp;
|
toadd = tmp;
|
||||||
|
nread = 3;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WINDOW_BUFFER_SIZE_EVENT:
|
||||||
|
if (send_winch_maybe ())
|
||||||
|
{
|
||||||
|
stat = input_winch;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
/* fall through */
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toadd)
|
||||||
|
{
|
||||||
|
ssize_t ret;
|
||||||
|
line_edit_status res = line_edit (toadd, nread, *ti, &ret);
|
||||||
|
if (res == line_edit_signalled)
|
||||||
|
{
|
||||||
|
stat = input_signalled;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
else if (res == line_edit_input_done)
|
||||||
|
{
|
||||||
|
input_ready = true;
|
||||||
|
stat = input_ok;
|
||||||
|
if (ti->c_lflag & ICANON)
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case FOCUS_EVENT:
|
|
||||||
if (con.use_focus)
|
|
||||||
{
|
|
||||||
if (input_rec.Event.FocusEvent.bSetFocus)
|
|
||||||
__small_sprintf (tmp, "\033[I");
|
|
||||||
else
|
|
||||||
__small_sprintf (tmp, "\033[O");
|
|
||||||
|
|
||||||
toadd = tmp;
|
|
||||||
nread = 3;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WINDOW_BUFFER_SIZE_EVENT:
|
|
||||||
if (send_winch_maybe ())
|
|
||||||
return input_winch;
|
|
||||||
/* fall through */
|
|
||||||
default:
|
|
||||||
return input_processing;
|
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
if (toadd)
|
/* Discard processed recored. */
|
||||||
{
|
DWORD dummy;
|
||||||
ssize_t ret;
|
ReadConsoleInputW (get_handle (), input_rec, min (total_read, i+1), &dummy);
|
||||||
line_edit_status res = line_edit (toadd, nread, *ti, &ret);
|
return stat;
|
||||||
if (res == line_edit_signalled)
|
|
||||||
return input_signalled;
|
|
||||||
else if (res == line_edit_input_done)
|
|
||||||
{
|
|
||||||
input_ready = true;
|
|
||||||
return input_ok;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return input_processing;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
Loading…
x
Reference in New Issue
Block a user