3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc.
5 This file is part of Cygwin.
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
12 #include <sys/termios.h>
21 #include <sys/cygwin.h>
30 #include "shared_info.h"
33 #define CONVERT_LIMIT 16384
36 cp_convert (UINT destcp, char *dest, UINT srccp, const char *src, DWORD size)
40 else if (destcp == srccp)
43 memcpy (dest, src, size);
47 WCHAR wbuffer[CONVERT_LIMIT]; /* same size as the maximum input, s.b. */
48 if (!MultiByteToWideChar (srccp, 0, src, size, wbuffer, sizeof (wbuffer)))
50 if (!WideCharToMultiByte (destcp, 0, wbuffer, size, dest, size,
58 * Scroll the screen context.
61 * xn, yn - new ul corner
62 * Negative values represents current screen dimensions
65 #define srTop (dev_state->info.winTop + dev_state->scroll_region.Top)
66 #define srBottom ((dev_state->scroll_region.Bottom < 0) ? dev_state->info.winBottom : dev_state->info.winTop + dev_state->scroll_region.Bottom)
68 #define use_tty ISSTATE (myself, PID_USETTY)
70 const char * get_nonascii_key (INPUT_RECORD&, char *);
72 static console_state NO_COPY *shared_console_info;
74 dev_console NO_COPY *fhandler_console::dev_state;
76 /* Allocate and initialize the shared record for the current console.
77 Returns a pointer to shared_console_info. */
79 fhandler_console::get_tty_stuff (int flags = 0)
82 return &shared_console_info->tty_min_state;
84 shared_locations sh_shared_console = SH_SHARED_CONSOLE;
86 (console_state *) open_shared (NULL, 0, cygheap->console_h,
87 sizeof (*shared_console_info),
89 dev_state = &shared_console_info->dev_state;
91 ProtectHandleINH (cygheap->console_h);
92 if (!shared_console_info->tty_min_state.ntty)
94 shared_console_info->tty_min_state.setntty (TTY_CONSOLE);
95 shared_console_info->tty_min_state.setsid (myself->sid);
96 myself->set_ctty (&shared_console_info->tty_min_state, flags, NULL);
98 dev_state->scroll_region.Bottom = -1;
99 dev_state->dwLastCursorPosition.X = -1;
100 dev_state->dwLastCursorPosition.Y = -1;
101 dev_state->underline_color = FOREGROUND_GREEN | FOREGROUND_BLUE;
102 dev_state->dim_color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
103 dev_state->meta_mask = LEFT_ALT_PRESSED;
104 /* Set the mask that determines if an input keystroke is modified by
105 META. We set this based on the keyboard layout language loaded
106 for the current thread. The left <ALT> key always generates
107 META, but the right <ALT> key only generates META if we are using
108 an English keyboard because many "international" keyboards
109 replace common shell symbols ('[', '{', etc.) with accented
110 language-specific characters (umlaut, accent grave, etc.). On
111 these keyboards right <ALT> (called AltGr) is used to produce the
112 shell symbols and should not be interpreted as META. */
113 if (PRIMARYLANGID (LOWORD (GetKeyboardLayout (0))) == LANG_ENGLISH)
114 dev_state->meta_mask |= RIGHT_ALT_PRESSED;
115 dev_state->set_default_attr ();
118 return &shared_console_info->tty_min_state;
124 fhandler_console::get_tty_stuff ();
127 /* Return the tty structure associated with a given tty number. If the
128 tty number is < 0, just return a dummy record. */
130 tty_list::get_tty (int n)
133 if (n == TTY_CONSOLE)
134 return fhandler_console::get_tty_stuff ();
136 return &cygwin_shared->tty.ttys[n];
142 /* Determine if a console is associated with this process prior to a spawn.
143 If it is, then we'll return 1. If the console has been initialized, then
144 set it into a more friendly state for non-cygwin apps. */
146 set_console_state_for_spawn ()
148 HANDLE h = CreateFile ("CONIN$", GENERIC_READ, FILE_SHARE_WRITE,
149 &sec_none_nih, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
152 if (h == INVALID_HANDLE_VALUE)
155 if (shared_console_info != NULL)
157 /* ACK. Temporarily define for use in TTYSETF macro */
158 SetConsoleMode (h, ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT);
159 shared_console_info->tty_min_state.rstcons (true);
166 /* The results of GetConsoleCP() and GetConsoleOutputCP() cannot be
167 cached, because a program or the user can change these values at
170 dev_console::con_to_str (char *d, const char *s, DWORD sz)
172 return cp_convert (get_cp (), d, GetConsoleCP (), s, sz);
176 dev_console::str_to_con (char *d, const char *s, DWORD sz)
178 if (alternate_charset_active)
180 /* no translation when alternate charset is active */
184 return cp_convert (GetConsoleOutputCP (), d, get_cp (), s, sz);
188 fhandler_console::set_raw_win32_keyboard_mode (bool new_mode)
190 bool old_mode = dev_state->raw_win32_keyboard_mode;
191 dev_state->raw_win32_keyboard_mode = new_mode;
192 syscall_printf ("raw keyboard mode %sabled", dev_state->raw_win32_keyboard_mode ? "en" : "dis");
197 fhandler_console::set_cursor_maybe ()
199 CONSOLE_SCREEN_BUFFER_INFO now;
201 if (!GetConsoleScreenBufferInfo (get_output_handle (), &now))
204 if (dev_state->dwLastCursorPosition.X != now.dwCursorPosition.X ||
205 dev_state->dwLastCursorPosition.Y != now.dwCursorPosition.Y)
207 SetConsoleCursorPosition (get_output_handle (), now.dwCursorPosition);
208 dev_state->dwLastCursorPosition = now.dwCursorPosition;
213 fhandler_console::send_winch_maybe ()
215 SHORT y = dev_state->info.dwWinSize.Y;
216 SHORT x = dev_state->info.dwWinSize.X;
217 dev_state->fillin_info (get_output_handle ());
219 if (y != dev_state->info.dwWinSize.Y || x != dev_state->info.dwWinSize.X)
221 extern fhandler_tty_master *tty_master;
222 dev_state->scroll_region.Top = 0;
223 dev_state->scroll_region.Bottom = -1;
225 tty_master->set_winsize (true);
227 tc->kill_pgrp (SIGWINCH);
232 fhandler_console::read (void *pv, size_t& buflen)
234 HANDLE h = get_io_handle ();
236 #define buf ((char *) pv)
241 int copied_chars = get_readahead_into_buffer (buf, buflen);
245 buflen = copied_chars;
254 if (&_my_tls != _main_tls)
258 w4[1] = signal_arrived;
266 if ((bgres = bg_check (SIGTTIN)) <= bg_eof)
272 set_cursor_maybe (); /* to make cursor appear on the screen immediately */
273 switch (WaitForMultipleObjects (nwait, w4, FALSE, INFINITE))
277 case WAIT_OBJECT_0 + 1:
284 INPUT_RECORD input_rec;
285 const char *toadd = NULL;
287 if (!ReadConsoleInput (h, &input_rec, 1, &nread))
289 syscall_printf ("ReadConsoleInput failed, %E");
290 goto err; /* seems to be failure */
293 /* check the event that occurred */
294 switch (input_rec.EventType)
297 #define virtual_key_code (input_rec.Event.KeyEvent.wVirtualKeyCode)
298 #define control_key_state (input_rec.Event.KeyEvent.dwControlKeyState)
300 dev_state->nModifiers = 0;
303 /* allow manual switching to/from raw mode via ctrl-alt-scrolllock */
304 if (input_rec.Event.KeyEvent.bKeyDown &&
305 virtual_key_code == VK_SCROLL &&
306 control_key_state & (LEFT_ALT_PRESSED | LEFT_CTRL_PRESSED) == LEFT_ALT_PRESSED | LEFT_CTRL_PRESSED
309 set_raw_win32_keyboard_mode (!dev_state->raw_win32_keyboard_mode);
314 if (dev_state->raw_win32_keyboard_mode)
316 __small_sprintf (tmp, "\033{%u;%u;%u;%u;%u;%luK",
317 input_rec.Event.KeyEvent.bKeyDown,
318 input_rec.Event.KeyEvent.wRepeatCount,
319 input_rec.Event.KeyEvent.wVirtualKeyCode,
320 input_rec.Event.KeyEvent.wVirtualScanCode,
321 input_rec.Event.KeyEvent.uChar.UnicodeChar,
322 input_rec.Event.KeyEvent.dwControlKeyState);
324 nread = strlen (toadd);
328 #define ich (input_rec.Event.KeyEvent.uChar.AsciiChar)
329 #define wch (input_rec.Event.KeyEvent.uChar.UnicodeChar)
330 #define ALT_PRESSED (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)
331 #define CTRL_PRESSED (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)
333 /* Ignore key up events, except for left alt events with non-zero character
335 if (!input_rec.Event.KeyEvent.bKeyDown &&
337 Event for left alt, with a non-zero character, comes from
338 "alt + numerics" key sequence.
339 e.g. <left-alt> 0233 => é
342 // ?? experimentally determined on an XP system
343 && virtual_key_code == VK_MENU
344 // left alt -- see http://www.microsoft.com/hwdev/tech/input/Scancode.asp
345 && input_rec.Event.KeyEvent.wVirtualScanCode == 0x38))
348 if (control_key_state & SHIFT_PRESSED)
349 dev_state->nModifiers |= 1;
350 if (control_key_state & RIGHT_ALT_PRESSED)
351 dev_state->nModifiers |= 2;
352 if (control_key_state & CTRL_PRESSED)
353 dev_state->nModifiers |= 4;
354 if (control_key_state & LEFT_ALT_PRESSED)
355 dev_state->nModifiers |= 8;
358 /* arrow/function keys */
359 (input_rec.Event.KeyEvent.dwControlKeyState & ENHANCED_KEY))
361 toadd = get_nonascii_key (input_rec, tmp);
364 dev_state->nModifiers = 0;
367 nread = strlen (toadd);
372 /* Need this check since US code page seems to have a bug when
373 converting a CTRL-U. */
374 if ((unsigned char) ich > 0x7f)
375 dev_state->con_to_str (tmp + 1, tmp + 1, 1);
376 /* Determine if the keystroke is modified by META. The tricky
377 part is to distinguish whether the right Alt key should be
378 recognized as Alt, or as AltGr. */
380 if (wincap.altgr_is_ctrl_alt ())
381 /* WinNT: AltGr is reported as Ctrl+Alt, and Ctrl+Alt is
382 treated just like AltGr. However, if Ctrl+Alt+key generates
383 an ASCII control character, interpret is as META. */
384 meta = (control_key_state & ALT_PRESSED) != 0
385 && ((control_key_state & CTRL_PRESSED) == 0
386 || ((signed char) ich >= 0 && ich <= 0x1f || ich == 0x7f));
388 /* Win9x: there's no way to distinguish Alt from AltGr, so rely
389 on dev_state->meta_mask heuristic (see fhandler_console constructor). */
390 meta = (control_key_state & dev_state->meta_mask) != 0;
396 tmp[1] = cyg_tolower (tmp[1]);
399 dev_state->nModifiers &= ~4;
410 if (dev_state->use_mouse)
412 MOUSE_EVENT_RECORD& mouse_event = input_rec.Event.MouseEvent;
414 /* Treat the double-click event like a regular button press */
415 if (mouse_event.dwEventFlags == DOUBLE_CLICK)
417 syscall_printf ("mouse: double-click -> click");
418 mouse_event.dwEventFlags = 0;
421 /* Did something other than a click occur? */
422 if (mouse_event.dwEventFlags)
425 /* Retrieve reported mouse position */
426 int x = mouse_event.dwMousePosition.X;
427 int y = mouse_event.dwMousePosition.Y;
429 /* Adjust mouse position by scroll buffer offset */
430 CONSOLE_SCREEN_BUFFER_INFO now;
431 if (GetConsoleScreenBufferInfo (get_output_handle (), &now))
433 y -= now.srWindow.Top;
434 x -= now.srWindow.Left;
438 syscall_printf ("mouse: cannot adjust position by scroll buffer offset");
442 /* If the mouse event occurred out of the area we can handle,
444 if ((x + ' ' + 1 > 0xFF) || (y + ' ' + 1 > 0xFF))
446 syscall_printf ("mouse: position out of range");
450 /* Ignore unimportant mouse buttons */
451 mouse_event.dwButtonState &= 0x7;
453 /* This code assumes Windows never reports multiple button
454 events at the same time. */
457 if (mouse_event.dwButtonState == dev_state->dwLastButtonState)
459 syscall_printf ("mouse: button state unchanged");
462 else if (mouse_event.dwButtonState < dev_state->dwLastButtonState)
465 strcpy (sz, "btn up");
467 else if ((mouse_event.dwButtonState & 1) != (dev_state->dwLastButtonState & 1))
470 strcpy (sz, "btn1 down");
472 else if ((mouse_event.dwButtonState & 2) != (dev_state->dwLastButtonState & 2))
475 strcpy (sz, "btn2 down");
477 else if ((mouse_event.dwButtonState & 4) != (dev_state->dwLastButtonState & 4))
480 strcpy (sz, "btn3 down");
483 /* Remember the current button state */
484 dev_state->dwLastButtonState = mouse_event.dwButtonState;
486 /* If a button was pressed, remember the modifiers */
489 dev_state->nModifiers = 0;
490 if (mouse_event.dwControlKeyState & SHIFT_PRESSED)
491 dev_state->nModifiers |= 0x4;
492 if (mouse_event.dwControlKeyState & (RIGHT_ALT_PRESSED|LEFT_ALT_PRESSED))
493 dev_state->nModifiers |= 0x8;
494 if (mouse_event.dwControlKeyState & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED))
495 dev_state->nModifiers |= 0x10;
498 b |= dev_state->nModifiers;
500 /* We can now create the code. */
501 sprintf (tmp, "\033[M%c%c%c", b + ' ', x + ' ' + 1, y + ' ' + 1);
502 syscall_printf ("mouse: %s at (%d,%d)", sz, x, y);
510 case WINDOW_BUFFER_SIZE_EVENT:
519 line_edit_status res = line_edit (toadd, nread, ti);
520 if (res == line_edit_signalled)
522 else if (res == line_edit_input_done)
529 if ((ch = get_readahead ()) < 0)
533 buf[copied_chars++] = (unsigned char)(ch & 0xff);
538 buflen = copied_chars;
543 buflen = (size_t) -1;
547 set_sig_errno (EINTR);
548 buflen = (size_t) -1;
552 fhandler_console::set_input_state ()
555 input_tcsetattr (0, &tc->ti);
559 dev_console::fillin_info (HANDLE h)
562 CONSOLE_SCREEN_BUFFER_INFO linfo;
564 if ((ret = GetConsoleScreenBufferInfo (h, &linfo)))
566 info.winTop = linfo.srWindow.Top;
567 info.winBottom = linfo.srWindow.Bottom;
568 info.dwWinSize.Y = 1 + linfo.srWindow.Bottom - linfo.srWindow.Top;
569 info.dwWinSize.X = 1 + linfo.srWindow.Right - linfo.srWindow.Left;
570 info.dwBufferSize = linfo.dwSize;
571 info.dwCursorPosition = linfo.dwCursorPosition;
572 info.wAttributes = linfo.wAttributes;
576 memset (&info, 0, sizeof info);
577 info.dwWinSize.Y = 25;
578 info.dwWinSize.X = 80;
586 fhandler_console::scroll_screen (int x1, int y1, int x2, int y2, int xn, int yn)
592 dev_state->fillin_info (get_output_handle ());
593 sr1.Left = x1 >= 0 ? x1 : dev_state->info.dwWinSize.X - 1;
595 sr1.Top = dev_state->info.winTop;
597 sr1.Top = y1 > 0 ? y1 : dev_state->info.winBottom;
598 sr1.Right = x2 >= 0 ? x2 : dev_state->info.dwWinSize.X - 1;
600 sr1.Bottom = dev_state->info.winTop;
602 sr1.Bottom = y2 > 0 ? y2 : dev_state->info.winBottom;
605 sr2.Bottom = srBottom;
606 sr2.Right = dev_state->info.dwWinSize.X - 1;
607 if (sr1.Bottom > sr2.Bottom && sr1.Top <= sr2.Bottom)
608 sr1.Bottom = sr2.Bottom;
609 dest.X = xn >= 0 ? xn : dev_state->info.dwWinSize.X - 1;
611 dest.Y = dev_state->info.winTop;
613 dest.Y = yn > 0 ? yn : dev_state->info.winBottom;
614 fill.Char.AsciiChar = ' ';
615 fill.Attributes = dev_state->current_win32_attr;
616 ScrollConsoleScreenBuffer (get_output_handle (), &sr1, &sr2, dest, &fill);
618 /* ScrollConsoleScreenBuffer on Windows 95 is buggy - when scroll distance
619 * is more than half of screen, filling doesn't work as expected */
621 if (sr1.Top != sr1.Bottom)
622 if (dest.Y <= sr1.Top) /* forward scroll */
623 clear_screen (0, 1 + dest.Y + sr1.Bottom - sr1.Top, sr2.Right, sr2.Bottom);
624 else /* reverse scroll */
625 clear_screen (0, sr1.Top, sr2.Right, dest.Y - 1);
629 fhandler_console::open (int flags, mode_t)
633 tcinit (get_tty_stuff (flags));
635 set_io_handle (NULL);
636 set_output_handle (NULL);
638 set_flags ((flags & ~O_TEXT) | O_BINARY);
640 /* Open the input handle as handle_ */
641 h = CreateFile ("CONIN$", GENERIC_READ | GENERIC_WRITE,
642 FILE_SHARE_READ | FILE_SHARE_WRITE, &sec_none,
643 OPEN_EXISTING, 0, 0);
645 if (h == INVALID_HANDLE_VALUE)
651 uninterruptible_io (true); // Handled explicitly in read code
653 h = CreateFile ("CONOUT$", GENERIC_READ | GENERIC_WRITE,
654 FILE_SHARE_READ | FILE_SHARE_WRITE, &sec_none,
655 OPEN_EXISTING, 0, 0);
657 if (h == INVALID_HANDLE_VALUE)
662 set_output_handle (h);
664 if (dev_state->fillin_info (get_output_handle ()))
666 dev_state->current_win32_attr = dev_state->info.wAttributes;
667 if (!dev_state->default_color)
668 dev_state->default_color = dev_state->info.wAttributes;
669 dev_state->set_default_attr ();
673 if (GetConsoleMode (get_io_handle (), &cflags))
675 cflags |= ENABLE_PROCESSED_INPUT;
676 SetConsoleMode (get_io_handle (), ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT | cflags);
682 debug_printf ("incremented open_fhs, now %d", cygheap->open_fhs);
683 debug_printf ("opened conin$ %p, conout$ %p", get_io_handle (),
684 get_output_handle ());
690 fhandler_console::close ()
692 CloseHandle (get_io_handle ());
693 CloseHandle (get_output_handle ());
694 if (!hExeced && --(cygheap->open_fhs) <= 0 && myself->ctty != TTY_CONSOLE)
696 syscall_printf ("open_fhs %d", cygheap->open_fhs);
699 debug_printf ("decremented open_fhs, now %d", cygheap->open_fhs);
704 * Special console dup to duplicate input and output
709 fhandler_console::dup (fhandler_base *child, HANDLE from_proc)
711 fhandler_console *fhc = (fhandler_console *) child;
713 if (!fhc->open (get_flags () & ~O_NOCTTY, 0))
714 system_printf ("error opening console, %E");
720 fhandler_console::ioctl (unsigned int cmd, void *buf)
727 st = dev_state->fillin_info (get_output_handle ());
730 /* *not* the buffer size, the actual screen size... */
731 /* based on Left Top Right Bottom of srWindow */
732 ((struct winsize *) buf)->ws_row = dev_state->info.dwWinSize.Y;
733 ((struct winsize *) buf)->ws_col = dev_state->info.dwWinSize.X;
734 syscall_printf ("WINSZ: (row=%d,col=%d)",
735 ((struct winsize *) buf)->ws_row,
736 ((struct winsize *) buf)->ws_col);
741 syscall_printf ("WINSZ failed");
750 if (* (int *) buf == 6)
752 * (int *) buf = dev_state->nModifiers;
762 return fhandler_base::ioctl (cmd, buf);
766 fhandler_console::tcflush (int queue)
769 if (queue == TCIFLUSH
770 || queue == TCIOFLUSH)
772 if (!FlushConsoleInputBuffer (get_io_handle ()))
782 fhandler_console::output_tcsetattr (int, struct termios const *t)
784 /* All the output bits we can ignore */
786 DWORD flags = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT;
788 int res = SetConsoleMode (get_output_handle (), flags) ? 0 : -1;
789 syscall_printf ("%d = tcsetattr (,%x) (ENABLE FLAGS %x) (lflag %x oflag %x)",
790 res, t, flags, t->c_lflag, t->c_oflag);
795 fhandler_console::input_tcsetattr (int, struct termios const *t)
797 /* Ignore the optional_actions stuff, since all output is emitted
802 if (!GetConsoleMode (get_io_handle (), &oflags))
807 /* Enable/disable LF -> CRLF conversions */
808 rbinary ((t->c_iflag & INLCR) ? false : true);
811 /* There's some disparity between what we need and what's
812 available. We've got ECHO and ICANON, they've
813 got ENABLE_ECHO_INPUT and ENABLE_LINE_INPUT. */
817 if (t->c_lflag & ECHO)
819 flags |= ENABLE_ECHO_INPUT;
821 if (t->c_lflag & ICANON)
823 flags |= ENABLE_LINE_INPUT;
826 if (flags & ENABLE_ECHO_INPUT
827 && !(flags & ENABLE_LINE_INPUT))
829 /* This is illegal, so turn off the echo here, and fake it
830 when we read the characters */
832 flags &= ~ENABLE_ECHO_INPUT;
835 if (t->c_lflag & ISIG)
837 flags |= ENABLE_PROCESSED_INPUT;
842 flags = 0; // ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT;
847 flags |= ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT;
854 res = SetConsoleMode (get_io_handle (), flags) ? 0 : -1;
857 syscall_printf ("%d = tcsetattr (,%x) enable flags %p, c_lflag %p iflag %p",
858 res, t, flags, t->c_lflag, t->c_iflag);
866 fhandler_console::tcsetattr (int a, struct termios const *t)
868 int res = output_tcsetattr (a, t);
871 return input_tcsetattr (a, t);
875 fhandler_console::tcgetattr (struct termios *t)
884 if (!GetConsoleMode (get_io_handle (), &flags))
891 if (flags & ENABLE_ECHO_INPUT)
894 if (flags & ENABLE_LINE_INPUT)
895 t->c_lflag |= ICANON;
897 if (flags & ENABLE_PROCESSED_INPUT)
900 /* What about ENABLE_WINDOW_INPUT
901 and ENABLE_MOUSE_INPUT ? */
903 /* All the output bits we can ignore */
906 syscall_printf ("%d = tcgetattr (%p) enable flags %p, t->lflag %p, t->iflag %p",
907 res, t, flags, t->c_lflag, t->c_iflag);
911 fhandler_console::fhandler_console () :
916 dev_console::set_color (HANDLE h)
922 WORD save_fg = win_fg;
923 win_fg = (win_bg & BACKGROUND_RED ? FOREGROUND_RED : 0) |
924 (win_bg & BACKGROUND_GREEN ? FOREGROUND_GREEN : 0) |
925 (win_bg & BACKGROUND_BLUE ? FOREGROUND_BLUE : 0) |
926 (win_bg & BACKGROUND_INTENSITY ? FOREGROUND_INTENSITY : 0);
927 win_bg = (save_fg & FOREGROUND_RED ? BACKGROUND_RED : 0) |
928 (save_fg & FOREGROUND_GREEN ? BACKGROUND_GREEN : 0) |
929 (save_fg & FOREGROUND_BLUE ? BACKGROUND_BLUE : 0) |
930 (save_fg & FOREGROUND_INTENSITY ? BACKGROUND_INTENSITY : 0);
933 win_fg = underline_color;
934 /* emulate blink with bright background */
936 win_bg |= BACKGROUND_INTENSITY;
937 if (intensity == INTENSITY_INVISIBLE)
939 else if (intensity == INTENSITY_BOLD)
940 win_fg |= FOREGROUND_INTENSITY;
941 current_win32_attr = win_fg | win_bg;
943 SetConsoleTextAttribute (h, current_win32_attr);
946 #define FOREGROUND_ATTR_MASK (FOREGROUND_RED | FOREGROUND_GREEN | \
947 FOREGROUND_BLUE | FOREGROUND_INTENSITY)
948 #define BACKGROUND_ATTR_MASK (BACKGROUND_RED | BACKGROUND_GREEN | \
949 BACKGROUND_BLUE | BACKGROUND_INTENSITY)
951 dev_console::set_default_attr ()
953 blink = underline = reverse = false;
954 intensity = INTENSITY_NORMAL;
955 fg = default_color & FOREGROUND_ATTR_MASK;
956 bg = default_color & BACKGROUND_ATTR_MASK;
961 * Clear the screen context from x1/y1 to x2/y2 cell.
962 * Negative values represents current screen dimensions
965 fhandler_console::clear_screen (int x1, int y1, int x2, int y2)
971 dev_state->fillin_info (get_output_handle ());
974 x1 = dev_state->info.dwWinSize.X - 1;
976 y1 = dev_state->info.winBottom;
978 x2 = dev_state->info.dwWinSize.X - 1;
980 y2 = dev_state->info.winBottom;
982 num = abs (y1 - y2) * dev_state->info.dwBufferSize.X + abs (x1 - x2) + 1;
984 if ((y2 * dev_state->info.dwBufferSize.X + x2) > (y1 * dev_state->info.dwBufferSize.X + x1))
994 FillConsoleOutputCharacterA (get_output_handle (), ' ',
998 FillConsoleOutputAttribute (get_output_handle (),
999 dev_state->current_win32_attr,
1006 fhandler_console::cursor_set (bool rel_to_top, int x, int y)
1010 dev_state->fillin_info (get_output_handle ());
1011 if (y > dev_state->info.winBottom)
1012 y = dev_state->info.winBottom;
1015 else if (rel_to_top)
1016 y += dev_state->info.winTop;
1018 if (x > dev_state->info.dwWinSize.X)
1019 x = dev_state->info.dwWinSize.X - 1;
1025 SetConsoleCursorPosition (get_output_handle (), pos);
1029 fhandler_console::cursor_rel (int x, int y)
1031 dev_state->fillin_info (get_output_handle ());
1032 x += dev_state->info.dwCursorPosition.X;
1033 y += dev_state->info.dwCursorPosition.Y;
1034 cursor_set (false, x, y);
1038 fhandler_console::cursor_get (int *x, int *y)
1040 dev_state->fillin_info (get_output_handle ());
1041 *y = dev_state->info.dwCursorPosition.Y;
1042 *x = dev_state->info.dwCursorPosition.X;
1056 #define TAB 8 /* We should't let the console deal with these */
1060 static const char base_chars[256] =
1062 /*00 01 02 03 04 05 06 07 */ IGN, ERR, ERR, NOR, NOR, NOR, NOR, BEL,
1063 /*08 09 0A 0B 0C 0D 0E 0F */ BAK, TAB, DWN, ERR, ERR, CR, ERR, IGN,
1064 /*10 11 12 13 14 15 16 17 */ NOR, NOR, ERR, ERR, ERR, ERR, ERR, ERR,
1065 /*18 19 1A 1B 1C 1D 1E 1F */ NOR, NOR, ERR, ESC, ERR, ERR, ERR, ERR,
1066 /* ! " # $ % & ' */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
1067 /*() * + , - . / */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
1068 /*0 1 2 3 4 5 6 7 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
1069 /*8 9 : ; < = > ? */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
1070 /*@ A B C D E F G */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
1071 /*H I J K L M N O */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
1072 /*P Q R S T U V W */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
1073 /*X Y Z [ \ ] ^ _ */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
1074 /*` a b c d e f g */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
1075 /*h i j k l m n o */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
1076 /*p q r s t u v w */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
1077 /*x y z { | } ~ 7F */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
1078 /*80 81 82 83 84 85 86 87 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
1079 /*88 89 8A 8B 8C 8D 8E 8F */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
1080 /*90 91 92 93 94 95 96 97 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
1081 /*98 99 9A 9B 9C 9D 9E 9F */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
1082 /*A0 A1 A2 A3 A4 A5 A6 A7 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
1083 /*A8 A9 AA AB AC AD AE AF */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
1084 /*B0 B1 B2 B3 B4 B5 B6 B7 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
1085 /*B8 B9 BA BB BC BD BE BF */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
1086 /*C0 C1 C2 C3 C4 C5 C6 C7 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
1087 /*C8 C9 CA CB CC CD CE CF */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
1088 /*D0 D1 D2 D3 D4 D5 D6 D7 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
1089 /*D8 D9 DA DB DC DD DE DF */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
1090 /*E0 E1 E2 E3 E4 E5 E6 E7 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
1091 /*E8 E9 EA EB EC ED EE EF */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
1092 /*F0 F1 F2 F3 F4 F5 F6 F7 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR,
1093 /*F8 F9 FA FB FC FD FE FF */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR };
1096 fhandler_console::char_command (char c)
1103 case 'm': /* Set Graphics Rendition */
1104 for (int i = 0; i <= dev_state->nargs_; i++)
1105 switch (dev_state->args_[i])
1107 case 0: /* normal color */
1108 dev_state->set_default_attr ();
1111 dev_state->intensity = INTENSITY_BOLD;
1114 dev_state->underline = 1;
1116 case 5: /* blink mode */
1117 dev_state->blink = true;
1119 case 7: /* reverse */
1120 dev_state->reverse = true;
1122 case 8: /* invisible */
1123 dev_state->intensity = INTENSITY_INVISIBLE;
1126 dev_state->intensity = INTENSITY_DIM;
1128 case 10: /* end alternate charset */
1129 dev_state->alternate_charset_active = false;
1131 case 11: /* start alternate charset */
1132 dev_state->alternate_charset_active = true;
1135 dev_state->underline = false;
1138 dev_state->reverse = false;
1140 case 30: /* BLACK foreground */
1143 case 31: /* RED foreground */
1144 dev_state->fg = FOREGROUND_RED;
1146 case 32: /* GREEN foreground */
1147 dev_state->fg = FOREGROUND_GREEN;
1149 case 33: /* YELLOW foreground */
1150 dev_state->fg = FOREGROUND_RED | FOREGROUND_GREEN;
1152 case 34: /* BLUE foreground */
1153 dev_state->fg = FOREGROUND_BLUE;
1155 case 35: /* MAGENTA foreground */
1156 dev_state->fg = FOREGROUND_RED | FOREGROUND_BLUE;
1158 case 36: /* CYAN foreground */
1159 dev_state->fg = FOREGROUND_BLUE | FOREGROUND_GREEN;
1161 case 37: /* WHITE foreg */
1162 dev_state->fg = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
1165 dev_state->fg = dev_state->default_color & FOREGROUND_ATTR_MASK;
1167 case 40: /* BLACK background */
1170 case 41: /* RED background */
1171 dev_state->bg = BACKGROUND_RED;
1173 case 42: /* GREEN background */
1174 dev_state->bg = BACKGROUND_GREEN;
1176 case 43: /* YELLOW background */
1177 dev_state->bg = BACKGROUND_RED | BACKGROUND_GREEN;
1179 case 44: /* BLUE background */
1180 dev_state->bg = BACKGROUND_BLUE;
1182 case 45: /* MAGENTA background */
1183 dev_state->bg = BACKGROUND_RED | BACKGROUND_BLUE;
1185 case 46: /* CYAN background */
1186 dev_state->bg = BACKGROUND_BLUE | BACKGROUND_GREEN;
1188 case 47: /* WHITE background */
1189 dev_state->bg = BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED;
1192 dev_state->bg = dev_state->default_color & BACKGROUND_ATTR_MASK;
1195 dev_state->set_color (get_output_handle ());
1199 if (!dev_state->saw_question_mark)
1201 switch (dev_state->args_[0])
1203 case 4: /* Insert mode */
1204 dev_state->insert_mode = (c == 'h') ? true : false;
1205 syscall_printf ("insert mode %sabled", dev_state->insert_mode ? "en" : "dis");
1210 switch (dev_state->args_[0])
1212 case 47: /* Save/Restore screen */
1213 if (c == 'h') /* save */
1215 CONSOLE_SCREEN_BUFFER_INFO now;
1216 COORD cob = { 0, 0 };
1218 if (!GetConsoleScreenBufferInfo (get_output_handle (), &now))
1221 dev_state->savebufsiz.X = now.srWindow.Right - now.srWindow.Left + 1;
1222 dev_state->savebufsiz.Y = now.srWindow.Bottom - now.srWindow.Top + 1;
1224 if (dev_state->savebuf)
1225 cfree (dev_state->savebuf);
1226 dev_state->savebuf = (PCHAR_INFO) cmalloc (HEAP_1_BUF, sizeof (CHAR_INFO) *
1227 dev_state->savebufsiz.X * dev_state->savebufsiz.Y);
1229 ReadConsoleOutputA (get_output_handle (), dev_state->savebuf,
1230 dev_state->savebufsiz, cob, &now.srWindow);
1234 CONSOLE_SCREEN_BUFFER_INFO now;
1235 COORD cob = { 0, 0 };
1237 if (!GetConsoleScreenBufferInfo (get_output_handle (), &now))
1240 if (!dev_state->savebuf)
1243 WriteConsoleOutputA (get_output_handle (), dev_state->savebuf,
1244 dev_state->savebufsiz, cob, &now.srWindow);
1246 cfree (dev_state->savebuf);
1247 dev_state->savebuf = NULL;
1248 dev_state->savebufsiz.X = dev_state->savebufsiz.Y = 0;
1252 case 1000: /* Mouse support */
1253 dev_state->use_mouse = (c == 'h') ? true : false;
1254 syscall_printf ("mouse support %sabled", dev_state->use_mouse ? "en" : "dis");
1257 case 2000: /* Raw keyboard mode */
1258 set_raw_win32_keyboard_mode ((c == 'h') ? true : false);
1261 default: /* Ignore */
1262 syscall_printf ("unknown h/l command: %d", dev_state->args_[0]);
1267 switch (dev_state->args_[0])
1269 case 0: /* Clear to end of screen */
1270 cursor_get (&x, &y);
1271 clear_screen (x, y, -1, -1);
1273 case 1: /* Clear from beginning of screen to cursor */
1274 cursor_get (&x, &y);
1275 clear_screen (0, 0, x, y);
1277 case 2: /* Clear screen */
1278 clear_screen (0, 0, -1, -1);
1279 cursor_set (true, 0,0);
1287 cursor_rel (0, -(dev_state->args_[0] ? dev_state->args_[0] : 1));
1290 cursor_rel (0, dev_state->args_[0] ? dev_state->args_[0] : 1);
1293 cursor_rel (dev_state->args_[0] ? dev_state->args_[0] : 1, 0);
1296 cursor_rel (-(dev_state->args_[0] ? dev_state->args_[0] : 1),0);
1299 switch (dev_state->args_[0])
1301 case 0: /* Clear to end of line */
1302 cursor_get (&x, &y);
1303 clear_screen (x, y, -1, y);
1305 case 2: /* Clear line */
1306 cursor_get (&x, &y);
1307 clear_screen (0, y, -1, y);
1309 case 1: /* Clear from bol to cursor */
1310 cursor_get (&x, &y);
1311 clear_screen (0, y, x, y);
1319 cursor_set (true, (dev_state->args_[1] ? dev_state->args_[1] : 1) - 1,
1320 (dev_state->args_[0] ? dev_state->args_[0] : 1) - 1);
1322 case 'G': /* hpa - position cursor at column n - 1 */
1323 cursor_get (&x, &y);
1324 cursor_set (false, (dev_state->args_[0] ? dev_state->args_[0] - 1 : 0), y);
1326 case 'd': /* vpa - position cursor at line n */
1327 cursor_get (&x, &y);
1328 cursor_set (true, x, (dev_state->args_[0] ? dev_state->args_[0] - 1 : 0));
1330 case 's': /* Save cursor position */
1331 cursor_get (&dev_state->savex, &dev_state->savey);
1332 dev_state->savey -= dev_state->info.winTop;
1334 case 'u': /* Restore cursor position */
1335 cursor_set (true, dev_state->savex, dev_state->savey);
1338 cursor_get (&x, &y);
1339 cursor_set (false, 8 * (x / 8 + 1), y);
1341 case 'L': /* AL - insert blank lines */
1342 dev_state->args_[0] = dev_state->args_[0] ? dev_state->args_[0] : 1;
1343 cursor_get (&x, &y);
1344 scroll_screen (0, y, -1, -1, 0, y + dev_state->args_[0]);
1346 case 'M': /* DL - delete lines */
1347 dev_state->args_[0] = dev_state->args_[0] ? dev_state->args_[0] : 1;
1348 cursor_get (&x, &y);
1349 scroll_screen (0, y + dev_state->args_[0], -1, -1, 0, y);
1351 case '@': /* IC - insert chars */
1352 dev_state->args_[0] = dev_state->args_[0] ? dev_state->args_[0] : 1;
1353 cursor_get (&x, &y);
1354 scroll_screen (x, y, -1, y, x + dev_state->args_[0], y);
1356 case 'P': /* DC - delete chars */
1357 dev_state->args_[0] = dev_state->args_[0] ? dev_state->args_[0] : 1;
1358 cursor_get (&x, &y);
1359 scroll_screen (x + dev_state->args_[0], y, -1, y, x, y);
1361 case 'S': /* SF - Scroll forward */
1362 dev_state->args_[0] = dev_state->args_[0] ? dev_state->args_[0] : 1;
1363 scroll_screen (0, dev_state->args_[0], -1, -1, 0, 0);
1365 case 'T': /* SR - Scroll down */
1366 dev_state->fillin_info (get_output_handle ());
1367 dev_state->args_[0] = dev_state->args_[0] ? dev_state->args_[0] : 1;
1368 scroll_screen (0, 0, -1, -1, 0, dev_state->info.winTop + dev_state->args_[0]);
1370 case 'X': /* ec - erase chars */
1371 dev_state->args_[0] = dev_state->args_[0] ? dev_state->args_[0] : 1;
1372 cursor_get (&x, &y);
1373 scroll_screen (x + dev_state->args_[0], y, -1, y, x, y);
1374 scroll_screen (x, y, -1, y, x + dev_state->args_[0], y);
1376 case 'Z': /* Back tab */
1377 cursor_get (&x, &y);
1378 cursor_set (false, ((8 * (x / 8 + 1)) - 8), y);
1380 case 'b': /* Repeat char #1 #2 times */
1381 if (dev_state->insert_mode)
1383 cursor_get (&x, &y);
1384 scroll_screen (x, y, -1, y, x + dev_state->args_[1], y);
1386 while (dev_state->args_[1]--)
1387 WriteFile (get_output_handle (), &dev_state->args_[0], 1, (DWORD *) &x, 0);
1389 case 'c': /* u9 - Terminal enquire string */
1390 strcpy (buf, "\033[?6c");
1391 puts_readahead (buf);
1394 switch (dev_state->args_[0])
1396 case 6: /* u7 - Cursor position request */
1397 cursor_get (&x, &y);
1398 y -= dev_state->info.winTop;
1399 /* x -= dev_state->info.winLeft; // not available yet */
1400 __small_sprintf (buf, "\033[%d;%dR", y + 1, x + 1);
1401 puts_readahead (buf);
1407 case 'r': /* Set Scroll region */
1408 dev_state->scroll_region.Top = dev_state->args_[0] ? dev_state->args_[0] - 1 : 0;
1409 dev_state->scroll_region.Bottom = dev_state->args_[1] ? dev_state->args_[1] - 1 : -1;
1410 cursor_set (true, 0, 0);
1412 case 'g': /* TAB set/clear */
1420 const unsigned char *
1421 fhandler_console::write_normal (const unsigned char *src,
1422 const unsigned char *end)
1424 /* Scan forward to see what a char which needs special treatment */
1426 const unsigned char *found = src;
1430 char ch = base_chars[*found];
1436 /* Print all the base ones out */
1439 DWORD len = found - src;
1443 char buf[CONVERT_LIMIT];
1444 done = buf_len = min (sizeof (buf), len);
1445 if (!dev_state->str_to_con (buf, (const char *) src, buf_len))
1447 debug_printf ("conversion error, handle %p",
1448 get_output_handle ());
1453 if (dev_state->insert_mode)
1456 cursor_get (&x, &y);
1457 scroll_screen (x, y, -1, y, x + buf_len, y);
1460 if (!WriteFile (get_output_handle (), buf, buf_len, &done, 0))
1462 debug_printf ("write failed, handle %p", get_output_handle ());
1475 switch (base_chars[*src])
1478 MessageBeep (0xFFFFFFFF);
1481 dev_state->state_ = gotesc;
1484 cursor_get (&x, &y);
1487 if (y >= dev_state->info.winBottom && !dev_state->scroll_region.Top)
1488 WriteFile (get_output_handle (), "\n", 1, &done, 0);
1491 scroll_screen (0, srTop + 1, -1, srBottom, 0, srTop);
1495 cursor_set (false, ((tc->ti.c_oflag & ONLCR) ? 0 : x), y + 1);
1504 cursor_get (&x, &y);
1505 cursor_set (false, 0, y);
1508 WriteFile (get_output_handle (), src, 1, &done, 0);
1511 cursor_get (&x, &y);
1512 cursor_set (false, 8 * (x / 8 + 1), y);
1521 fhandler_console::write (const void *vsrc, size_t len)
1523 /* Run and check for ansi sequences */
1524 unsigned const char *src = (unsigned char *) vsrc;
1525 unsigned const char *end = src + len;
1527 debug_printf ("%x, %d", vsrc, len);
1531 debug_printf ("at %d(%c) state is %d", *src, isprint (*src) ? *src : ' ',
1533 switch (dev_state->state_)
1536 src = write_normal (src, end);
1537 if (!src) /* write_normal failed */
1543 dev_state->state_ = gotsquare;
1544 dev_state->saw_question_mark = false;
1545 for (dev_state->nargs_ = 0; dev_state->nargs_ < MAXARGS; dev_state->nargs_++)
1546 dev_state->args_[dev_state->nargs_] = 0;
1547 dev_state->nargs_ = 0;
1549 else if (*src == ']')
1551 dev_state->rarg = 0;
1552 dev_state->my_title_buf[0] = '\0';
1553 dev_state->state_ = gotrsquare;
1555 else if (*src == 'M') /* Reverse Index */
1557 dev_state->fillin_info (get_output_handle ());
1558 scroll_screen (0, 0, -1, -1, 0, dev_state->info.winTop + 1);
1559 dev_state->state_ = normal;
1561 else if (*src == 'c') /* Reset Linux terminal */
1563 dev_state->set_default_attr ();
1564 clear_screen (0, 0, -1, -1);
1565 cursor_set (true, 0, 0);
1566 dev_state->state_ = normal;
1568 else if (*src == '8') /* Restore cursor position */
1570 cursor_set (true, dev_state->savex, dev_state->savey);
1571 dev_state->state_ = normal;
1573 else if (*src == '7') /* Save cursor position */
1575 cursor_get (&dev_state->savex, &dev_state->savey);
1576 dev_state->savey -= dev_state->info.winTop;
1577 dev_state->state_ = normal;
1579 else if (*src == 'R')
1580 dev_state->state_ = normal;
1583 dev_state->state_ = normal;
1590 dev_state->args_[dev_state->nargs_] = dev_state->args_[dev_state->nargs_] * 10 + *src - '0';
1593 else if (*src == ';')
1596 dev_state->nargs_++;
1597 if (dev_state->nargs_ >= MAXARGS)
1598 dev_state->nargs_--;
1602 dev_state->state_ = gotcommand;
1606 char_command (*src++);
1607 dev_state->state_ = normal;
1611 dev_state->rarg = dev_state->rarg * 10 + (*src - '0');
1612 else if (*src == ';' && (dev_state->rarg == 2 || dev_state->rarg == 0))
1613 dev_state->state_ = gettitle;
1615 dev_state->state_ = eattitle;
1621 int n = strlen (dev_state->my_title_buf);
1624 if (*src == '\007' && dev_state->state_ == gettitle)
1627 strcpy (old_title, dev_state->my_title_buf);
1628 set_console_title (dev_state->my_title_buf);
1630 dev_state->state_ = normal;
1632 else if (n < TITLESIZE)
1634 dev_state->my_title_buf[n++] = *src;
1635 dev_state->my_title_buf[n] = '\0';
1643 dev_state->state_ = gotarg1;
1644 dev_state->nargs_++;
1647 else if (isalpha (*src))
1648 dev_state->state_ = gotcommand;
1649 else if (*src != '@' && !isalpha (*src) && !isdigit (*src))
1652 dev_state->saw_question_mark = true;
1653 /* ignore any extra chars between [ and first arg or command */
1657 dev_state->state_ = gotarg1;
1662 syscall_printf ("%d = write_console (,..%d)", len, len);
1670 } keytable[] NO_COPY = {
1671 /* NORMAL */ /* SHIFT */ /* CTRL */ /* ALT */
1672 {VK_LEFT, {"\033[D", "\033[D", "\033[D", "\033\033[D"}},
1673 {VK_RIGHT, {"\033[C", "\033[C", "\033[C", "\033\033[C"}},
1674 {VK_UP, {"\033[A", "\033[A", "\033[A", "\033\033[A"}},
1675 {VK_DOWN, {"\033[B", "\033[B", "\033[B", "\033\033[B"}},
1676 {VK_PRIOR, {"\033[5~", "\033[5~", "\033[5~", "\033\033[5~"}},
1677 {VK_NEXT, {"\033[6~", "\033[6~", "\033[6~", "\033\033[6~"}},
1678 {VK_HOME, {"\033[1~", "\033[1~", "\033[1~", "\033\033[1~"}},
1679 {VK_END, {"\033[4~", "\033[4~", "\033[4~", "\033\033[4~"}},
1680 {VK_INSERT, {"\033[2~", "\033[2~", "\033[2~", "\033\033[2~"}},
1681 {VK_DELETE, {"\033[3~", "\033[3~", "\033[3~", "\033\033[3~"}},
1682 {VK_F1, {"\033[[A", "\033[23~", NULL, NULL}},
1683 {VK_F2, {"\033[[B", "\033[24~", NULL, NULL}},
1684 {VK_F3, {"\033[[C", "\033[25~", NULL, NULL}},
1685 {VK_F4, {"\033[[D", "\033[26~", NULL, NULL}},
1686 {VK_F5, {"\033[[E", "\033[28~", NULL, NULL}},
1687 {VK_F6, {"\033[17~", "\033[29~", "\036", NULL}},
1688 {VK_F7, {"\033[18~", "\033[31~", NULL, NULL}},
1689 {VK_F8, {"\033[19~", "\033[32~", NULL, NULL}},
1690 {VK_F9, {"\033[20~", "\033[33~", NULL, NULL}},
1691 {VK_F10, {"\033[21~", "\033[34~", NULL, NULL}},
1692 {VK_F11, {"\033[23~", NULL, NULL, NULL}},
1693 {VK_F12, {"\033[24~", NULL, NULL, NULL}},
1694 {VK_NUMPAD5, {"\033[G", NULL, NULL, NULL}},
1695 {VK_CLEAR, {"\033[G", NULL, NULL, NULL}},
1696 {'6', {NULL, NULL, "\036", NULL}},
1697 {0, {"", NULL, NULL, NULL}}
1701 get_nonascii_key (INPUT_RECORD& input_rec, char *tmp)
1707 int modifier_index = NORMAL;
1709 if (input_rec.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED)
1710 modifier_index = SHIFT;
1711 else if (input_rec.Event.KeyEvent.dwControlKeyState &
1712 (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
1713 modifier_index = CONTROL;
1714 else if (input_rec.Event.KeyEvent.dwControlKeyState &
1715 (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
1716 modifier_index = ALT;
1718 for (int i = 0; keytable[i].vk; i++)
1719 if (input_rec.Event.KeyEvent.wVirtualKeyCode == keytable[i].vk)
1720 return keytable[i].val[modifier_index];
1722 if (input_rec.Event.KeyEvent.uChar.AsciiChar)
1724 tmp[0] = input_rec.Event.KeyEvent.uChar.AsciiChar;
1732 fhandler_console::init (HANDLE f, DWORD a, mode_t bin)
1734 // this->fhandler_termios::init (f, mode, bin);
1735 /* Ensure both input and output console handles are open */
1738 a &= GENERIC_READ | GENERIC_WRITE;
1739 if (a == GENERIC_READ)
1741 if (a == GENERIC_WRITE)
1743 if (a == (GENERIC_READ | GENERIC_WRITE))
1745 open (flags | O_BINARY);
1746 if (f != INVALID_HANDLE_VALUE)
1747 CloseHandle (f); /* Reopened by open */
1749 tcsetattr (0, &tc->ti);
1753 fhandler_console::igncr_enabled ()
1755 return tc->ti.c_iflag & IGNCR;
1759 fhandler_console::set_close_on_exec (bool val)
1761 fhandler_base::set_close_on_exec (val);
1762 set_no_inheritance (output_handle, val);
1766 fhandler_console::fixup_after_fork (HANDLE)
1768 HANDLE h = get_handle ();
1769 HANDLE oh = get_output_handle ();
1771 /* Windows does not allow duplication of console handles between processes
1772 so open the console explicitly. */
1774 cygheap->open_fhs--; /* The downside of storing this in cygheap. */
1775 if (!open (O_NOCTTY | get_flags (), 0))
1776 system_printf ("error opening console after fork, %E");
1778 if (!close_on_exec ())
1786 set_console_title (char *title)
1790 strncpy (buf, title, sizeof (buf) - 1);
1791 buf[sizeof (buf) - 1] = '\0';
1792 if ((rc = WaitForSingleObject (tty_mutex, 15000)) != WAIT_OBJECT_0)
1793 sigproc_printf ("wait for title mutex failed rc %d, %E", rc);
1794 SetConsoleTitle (buf);
1795 ReleaseMutex (tty_mutex);
1796 debug_printf ("title '%s'", buf);
1800 fhandler_console::fixup_after_exec ()
1802 HANDLE h = get_handle ();
1803 HANDLE oh = get_output_handle ();
1805 cygheap->open_fhs--; /* The downside of storing this in cygheap. */
1806 if (!open (O_NOCTTY | get_flags (), 0))
1808 bool sawerr = false;
1809 if (!get_io_handle ())
1811 system_printf ("error opening input console handle after exec, errno %d, %E", get_errno ());
1814 if (!get_output_handle ())
1816 system_printf ("error opening output console handle after exec, errno %d, %E", get_errno ());
1821 system_printf ("error opening console after exec, errno %d, %E", get_errno ());