diff options
Diffstat (limited to 'winsup/cygwin/fhandler_console.cc')
-rw-r--r-- | winsup/cygwin/fhandler_console.cc | 1774 |
1 files changed, 0 insertions, 1774 deletions
diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc deleted file mode 100644 index 2c48325fc..000000000 --- a/winsup/cygwin/fhandler_console.cc +++ /dev/null @@ -1,1774 +0,0 @@ -/* fhandler_console.cc - - Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. - -This file is part of Cygwin. - -This software is a copyrighted work licensed under the terms of the -Cygwin license. Please consult the file "CYGWIN_LICENSE" for -details. */ - -#include "winsup.h" -#include <sys/termios.h> -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <unistd.h> -#include <wingdi.h> -#include <winuser.h> -#include <wincon.h> -#include <winnls.h> -#include <ctype.h> -#include <sys/cygwin.h> -#include "cygerrno.h" -#include "security.h" -#include "fhandler.h" -#include "path.h" -#include "dtable.h" -#include "cygheap.h" -#include "sigproc.h" -#include "pinfo.h" -#include "shared_info.h" -#include "cygthread.h" - -#define CONVERT_LIMIT 4096 - -static BOOL -cp_convert (UINT destcp, char *dest, UINT srccp, const char *src, DWORD size) -{ - if (!size) - /* no action */; - else if (destcp == srccp) - { - if (dest != src) - memcpy (dest, src, size); - } - else - { - WCHAR wbuffer[CONVERT_LIMIT]; /* same size as the maximum input, s.b. */ - if (!MultiByteToWideChar (srccp, 0, src, size, wbuffer, sizeof (wbuffer))) - return FALSE; - if (!WideCharToMultiByte (destcp, 0, wbuffer, size, dest, size, - NULL, NULL)) - return FALSE; - } - return TRUE; -} - -/* The results of GetConsoleCP() and GetConsoleOutputCP() cannot be - cached, because a program or the user can change these values at - any time. */ -inline BOOL -con_to_str (char *d, const char *s, DWORD sz) -{ - return cp_convert (get_cp (), d, GetConsoleCP (), s, sz); -} - -inline BOOL -str_to_con (char *d, const char *s, DWORD sz) -{ - return cp_convert (GetConsoleOutputCP (), d, get_cp (), s, sz); -} - -/* - * Scroll the screen context. - * x1, y1 - ul corner - * x2, y2 - dr corner - * xn, yn - new ul corner - * Negative values represents current screen dimensions - */ - -#define srTop (info.winTop + scroll_region.Top) -#define srBottom ((scroll_region.Bottom < 0) ? info.winBottom : info.winTop + scroll_region.Bottom) - -#define use_tty ISSTATE (myself, PID_USETTY) - -const char * get_nonascii_key (INPUT_RECORD&, char *); - -static tty_min NO_COPY *shared_console_info = NULL; - -/* Allocate and initialize the shared record for the current console. - Returns a pointer to shared_console_info. */ -static tty_min * -get_tty_stuff (int flags = 0) -{ - if (shared_console_info) - return shared_console_info; - - shared_console_info = (tty_min *) open_shared (NULL, 0, cygheap->console_h, - sizeof (*shared_console_info), - NULL); - ProtectHandleINH (cygheap->console_h); - if (!shared_console_info->ntty) - { - shared_console_info->setntty (TTY_CONSOLE); - shared_console_info->setsid (myself->sid); - shared_console_info->set_ctty (TTY_CONSOLE, flags); - } - return shared_console_info; -} - -void -set_console_ctty () -{ - (void) get_tty_stuff (); -} - -/* Return the tty structure associated with a given tty number. If the - tty number is < 0, just return a dummy record. */ -tty_min * -tty_list::get_tty (int n) -{ - static tty_min nada; - if (n == TTY_CONSOLE) - return get_tty_stuff (); - else if (n >= 0) - return &cygwin_shared->tty.ttys[n]; - else - return &nada; -} - - -/* Determine if a console is associated with this process prior to a spawn. - If it is, then we'll return 1. If the console has been initialized, then - set it into a more friendly state for non-cygwin apps. */ -int __stdcall -set_console_state_for_spawn () -{ - HANDLE h = CreateFile ("CONIN$", GENERIC_READ, FILE_SHARE_WRITE, - &sec_none_nih, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, - NULL); - - if (h == INVALID_HANDLE_VALUE) - return 0; - - if (shared_console_info != NULL) - { -# define tc shared_console_info /* ACK. Temporarily define for use in TTYSETF macro */ - SetConsoleMode (h, ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT); - TTYSETF (RSTCONS); -# undef tc - } - - CloseHandle (h); - return 1; -} - -BOOL -fhandler_console::set_raw_win32_keyboard_mode (BOOL new_mode) -{ - BOOL old_mode = raw_win32_keyboard_mode; - raw_win32_keyboard_mode = new_mode; - syscall_printf ("raw keyboard mode %sabled", raw_win32_keyboard_mode ? "en" : "dis"); - return old_mode; -}; - -void -fhandler_console::set_cursor_maybe () -{ - CONSOLE_SCREEN_BUFFER_INFO now; - - if (!GetConsoleScreenBufferInfo (get_output_handle (), &now)) - return; - - if (dwLastCursorPosition.X != now.dwCursorPosition.X || - dwLastCursorPosition.Y != now.dwCursorPosition.Y) - { - SetConsoleCursorPosition (get_output_handle (), now.dwCursorPosition); - dwLastCursorPosition = now.dwCursorPosition; - } -} - -void -fhandler_console::send_winch_maybe () -{ - SHORT y = info.dwWinSize.Y; - SHORT x = info.dwWinSize.X; - fillin_info (); - - if (y != info.dwWinSize.Y || x != info.dwWinSize.X) - tc->kill_pgrp (SIGWINCH); -} - -int __stdcall -fhandler_console::read (void *pv, size_t buflen) -{ - HANDLE h = get_io_handle (); - -#define buf ((char *) pv) - - int ch; - set_input_state (); - - int copied_chars = get_readahead_into_buffer (buf, buflen); - - if (copied_chars) - return copied_chars; - - HANDLE w4[2]; - DWORD nwait; - char tmp[60]; - - w4[0] = h; - if (cygthread::is ()) - nwait = 1; - else - { - w4[1] = signal_arrived; - nwait = 2; - } - - for (;;) - { - int bgres; - if ((bgres = bg_check (SIGTTIN)) <= bg_eof) - return bgres; - - set_cursor_maybe (); /* to make cursor appear on the screen immediately */ - switch (WaitForMultipleObjects (nwait, w4, FALSE, INFINITE)) - { - case WAIT_OBJECT_0: - break; - case WAIT_OBJECT_0 + 1: - goto sig_exit; - default: - __seterrno (); - return -1; - } - - DWORD nread; - INPUT_RECORD input_rec; - const char *toadd = NULL; - - if (!ReadConsoleInput (h, &input_rec, 1, &nread)) - { - __seterrno (); - syscall_printf ("ReadConsoleInput failed, %E"); - return -1; /* seems to be failure */ - } - - /* check the event that occurred */ - switch (input_rec.EventType) - { - case KEY_EVENT: -#define virtual_key_code (input_rec.Event.KeyEvent.wVirtualKeyCode) -#define control_key_state (input_rec.Event.KeyEvent.dwControlKeyState) - -#ifdef DEBUGGING - /* allow manual switching to/from raw mode via ctrl-alt-scrolllock */ - if (input_rec.Event.KeyEvent.bKeyDown && - virtual_key_code == VK_SCROLL && - control_key_state & (LEFT_ALT_PRESSED | LEFT_CTRL_PRESSED) == LEFT_ALT_PRESSED | LEFT_CTRL_PRESSED - ) - { - set_raw_win32_keyboard_mode (!raw_win32_keyboard_mode); - continue; - } -#endif - - if (raw_win32_keyboard_mode) - { - __small_sprintf (tmp, "\033{%u;%u;%u;%u;%u;%luK", - input_rec.Event.KeyEvent.bKeyDown, - input_rec.Event.KeyEvent.wRepeatCount, - input_rec.Event.KeyEvent.wVirtualKeyCode, - input_rec.Event.KeyEvent.wVirtualScanCode, - input_rec.Event.KeyEvent.uChar.UnicodeChar, - input_rec.Event.KeyEvent.dwControlKeyState); - toadd = tmp; - nread = strlen (toadd); - break; - } - - if (!input_rec.Event.KeyEvent.bKeyDown) - continue; - -#define ich (input_rec.Event.KeyEvent.uChar.AsciiChar) -#define wch (input_rec.Event.KeyEvent.uChar.UnicodeChar) -#define ALT_PRESSED (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED) -#define CTRL_PRESSED (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) - - if (wch == 0 || - /* arrow/function keys */ - (input_rec.Event.KeyEvent.dwControlKeyState & ENHANCED_KEY)) - { - toadd = get_nonascii_key (input_rec, tmp); - if (!toadd) - continue; - nread = strlen (toadd); - } - else - { - tmp[1] = ich; - /* Need this check since US code page seems to have a bug when - converting a CTRL-U. */ - if ((unsigned char) ich > 0x7f) - con_to_str (tmp + 1, tmp + 1, 1); - /* 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; - if (wincap.altgr_is_ctrl_alt ()) - /* WinNT: AltGr is reported as Ctrl+Alt, and Ctrl+Alt is - treated just like AltGr. However, if Ctrl+Alt+key generates - an ASCII control character, interpret is as META. */ - meta = (control_key_state & ALT_PRESSED) != 0 - && ((control_key_state & CTRL_PRESSED) == 0 - || (ich >= 0 && ich <= 0x1f || ich == 0x7f)); - else - /* Win9x: there's no way to distinguish Alt from AltGr, so rely - on meta_mask heuristic (see fhandler_console constructor). */ - meta = (control_key_state & meta_mask) != 0; - if (!meta) - toadd = tmp + 1; - else - { - tmp[0] = '\033'; - tmp[1] = cyg_tolower (tmp[1]); - toadd = tmp; - nread++; - } - } -#undef ich -#undef wch -#undef ALT_PRESSED -#undef CTRL_PRESSED - break; - - case MOUSE_EVENT: - send_winch_maybe (); - if (use_mouse) - { - MOUSE_EVENT_RECORD& mouse_event = input_rec.Event.MouseEvent; - - /* Treat the double-click event like a regular button press */ - if (mouse_event.dwEventFlags == DOUBLE_CLICK) - { - syscall_printf ("mouse: double-click -> click"); - mouse_event.dwEventFlags = 0; - } - - /* Did something other than a click occur? */ - if (mouse_event.dwEventFlags) - continue; - - /* If the mouse event occurred out of the area we can handle, - ignore it. */ - int x = mouse_event.dwMousePosition.X; - int y = mouse_event.dwMousePosition.Y; - if ((x + ' ' + 1 > 0xFF) || (y + ' ' + 1 > 0xFF)) - { - syscall_printf ("mouse: position out of range"); - continue; - } - - /* Ignore unimportant mouse buttons */ - mouse_event.dwButtonState &= 0x7; - - /* This code assumes Windows never reports multiple button - events at the same time. */ - int b = 0; - char sz[32]; - if (mouse_event.dwButtonState == dwLastButtonState) - { - syscall_printf ("mouse: button state unchanged"); - continue; - } - else if (mouse_event.dwButtonState < dwLastButtonState) - { - b = 3; - strcpy (sz, "btn up"); - } - else if ((mouse_event.dwButtonState & 1) != (dwLastButtonState & 1)) - { - b = 0; - strcpy (sz, "btn1 down"); - } - else if ((mouse_event.dwButtonState & 2) != (dwLastButtonState & 2)) - { - b = 1; - strcpy (sz, "btn2 down"); - } - else if ((mouse_event.dwButtonState & 4) != (dwLastButtonState & 4)) - { - b = 2; - strcpy (sz, "btn3 down"); - } - - /* Remember the current button state */ - dwLastButtonState = mouse_event.dwButtonState; - - /* If a button was pressed, remember the modifiers */ - if (b != 3) - { - nModifiers = 0; - if (mouse_event.dwControlKeyState & SHIFT_PRESSED) - nModifiers |= 0x4; - if (mouse_event.dwControlKeyState & (RIGHT_ALT_PRESSED|LEFT_ALT_PRESSED)) - nModifiers |= 0x8; - if (mouse_event.dwControlKeyState & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED)) - nModifiers |= 0x10; - } - - b |= nModifiers; - - /* We can now create the code. */ - sprintf (tmp, "\033[M%c%c%c", b + ' ', x + ' ' + 1, y + ' ' + 1); - syscall_printf ("mouse: %s at (%d,%d)", sz, x, y); - - toadd = tmp; - nread = 6; - } - break; - - case FOCUS_EVENT: - case WINDOW_BUFFER_SIZE_EVENT: - send_winch_maybe (); - /* fall through */ - default: - continue; - } - - if (toadd) - { - int res = line_edit (toadd, nread); - if (res < 0) - goto sig_exit; - else if (res) - break; - } -#undef ich - } - - while (buflen) - if ((ch = get_readahead ()) < 0) - break; - else - { - buf[copied_chars++] = (unsigned char)(ch & 0xff); - buflen--; - } -#undef buf - - return copied_chars; - - sig_exit: - set_sig_errno (EINTR); - return -1; -} - -void -fhandler_console::set_input_state () -{ - if (TTYISSETF (RSTCONS)) - input_tcsetattr (0, &tc->ti); -} - -BOOL -fhandler_console::fillin_info (void) -{ - BOOL ret; - CONSOLE_SCREEN_BUFFER_INFO linfo; - - if ((ret = GetConsoleScreenBufferInfo (get_output_handle (), &linfo))) - { - info.winTop = linfo.srWindow.Top; - info.winBottom = linfo.srWindow.Bottom; - info.dwWinSize.Y = 1 + linfo.srWindow.Bottom - linfo.srWindow.Top; - info.dwWinSize.X = 1 + linfo.srWindow.Right - linfo.srWindow.Left; - info.dwBufferSize = linfo.dwSize; - info.dwCursorPosition = linfo.dwCursorPosition; - info.wAttributes = linfo.wAttributes; - } - else - { - memset (&info, 0, sizeof info); - info.dwWinSize.Y = 25; - info.dwWinSize.X = 80; - info.winBottom = 24; - } - - return ret; -} - -void -fhandler_console::scroll_screen (int x1, int y1, int x2, int y2, int xn, int yn) -{ - SMALL_RECT sr1, sr2; - CHAR_INFO fill; - COORD dest; - - (void) fillin_info (); - sr1.Left = x1 >= 0 ? x1 : info.dwWinSize.X - 1; - if (y1 == 0) - sr1.Top = info.winTop; - else - sr1.Top = y1 > 0 ? y1 : info.winBottom; - sr1.Right = x2 >= 0 ? x2 : info.dwWinSize.X - 1; - if (y2 == 0) - sr1.Bottom = info.winTop; - else - sr1.Bottom = y2 > 0 ? y2 : info.winBottom; - sr2.Top = srTop; - sr2.Left = 0; - sr2.Bottom = srBottom; - sr2.Right = info.dwWinSize.X - 1; - if (sr1.Bottom > sr2.Bottom && sr1.Top <= sr2.Bottom) - sr1.Bottom = sr2.Bottom; - dest.X = xn >= 0 ? xn : info.dwWinSize.X - 1; - if (yn == 0) - dest.Y = info.winTop; - else - dest.Y = yn > 0 ? yn : info.winBottom; - fill.Char.AsciiChar = ' '; - fill.Attributes = current_win32_attr; - ScrollConsoleScreenBuffer (get_output_handle (), &sr1, &sr2, dest, &fill); - - /* ScrollConsoleScreenBuffer on Windows 95 is buggy - when scroll distance - * is more than half of screen, filling doesn't work as expected */ - - if (sr1.Top != sr1.Bottom) - if (dest.Y <= sr1.Top) /* forward scroll */ - clear_screen (0, 1 + dest.Y + sr1.Bottom - sr1.Top, sr2.Right, sr2.Bottom); - else /* reverse scroll */ - clear_screen (0, sr1.Top, sr2.Right, dest.Y - 1); -} - -int -fhandler_console::open (path_conv *, int flags, mode_t) -{ - HANDLE h; - - tcinit (get_tty_stuff (flags)); - - set_io_handle (NULL); - set_output_handle (NULL); - - set_flags ((flags & ~O_TEXT) | O_BINARY); - - /* Open the input handle as handle_ */ - h = CreateFile ("CONIN$", GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, &sec_none, - OPEN_EXISTING, 0, 0); - - if (h == INVALID_HANDLE_VALUE) - { - __seterrno (); - return 0; - } - set_io_handle (h); - set_r_no_interrupt (1); // Handled explicitly in read code - - h = CreateFile ("CONOUT$", GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, &sec_none, - OPEN_EXISTING, 0, 0); - - if (h == INVALID_HANDLE_VALUE) - { - __seterrno (); - return 0; - } - set_output_handle (h); - - if (fillin_info ()) - default_color = info.wAttributes; - - set_default_attr (); - - DWORD cflags; - if (GetConsoleMode (get_io_handle (), &cflags)) - { - cflags |= ENABLE_PROCESSED_INPUT; - SetConsoleMode (get_io_handle (), ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT | cflags); - } - - TTYCLEARF (RSTCONS); - set_open_status (); - debug_printf ("opened conin$ %p, conout$ %p", - get_io_handle (), get_output_handle ()); - - return 1; -} - -int -fhandler_console::close (void) -{ - CloseHandle (get_io_handle ()); - CloseHandle (get_output_handle ()); - set_io_handle (NULL); - set_output_handle (NULL); - return 0; -} - -/* - * Special console dup to duplicate input and output - * handles. - */ - -int -fhandler_console::dup (fhandler_base *child) -{ - fhandler_console *fhc = (fhandler_console *) child; - - if (!fhc->open (NULL, get_flags () & ~O_NOCTTY, 0)) - system_printf ("error opening console, %E"); - - fhc->default_color = default_color; - fhc->underline_color = underline_color; - fhc->dim_color = dim_color; - fhc->state_ = state_; - fhc->nargs_ = nargs_; - for (int i = 0; i < MAXARGS; i++) - fhc->args_[i] = args_[i]; - fhc->rarg = rarg; - fhc->saw_question_mark = saw_question_mark; - - strncpy (fhc->my_title_buf, my_title_buf, TITLESIZE + 1) ; - - fhc->current_win32_attr = current_win32_attr; - fhc->intensity = intensity; - fhc->underline = underline; - fhc->blink = blink; - fhc->reverse = reverse; - fhc->fg = fg; - fhc->bg = bg; - - fhc->savex = savex; - fhc->savey = savey; - - fhc->savebufsiz = savebufsiz; - if (savebuf) - { - fhc->savebuf = (PCHAR_INFO) cmalloc (HEAP_1_BUF, sizeof (CHAR_INFO) * - savebufsiz.X * savebufsiz.Y); - memcpy (fhc->savebuf, savebuf, sizeof (CHAR_INFO) * - savebufsiz.X * savebufsiz.Y); - } - - fhc->scroll_region = scroll_region; - fhc->dwLastCursorPosition = dwLastCursorPosition; - fhc->dwLastButtonState = dwLastButtonState; - fhc->nModifiers = nModifiers; - - fhc->insert_mode = insert_mode; - fhc->use_mouse = use_mouse; - fhc->raw_win32_keyboard_mode = raw_win32_keyboard_mode; - - return 0; -} - -int -fhandler_console::ioctl (unsigned int cmd, void *buf) -{ - switch (cmd) - { - case TIOCGWINSZ: - int st; - - st = fillin_info (); - if (st) - { - /* *not* the buffer size, the actual screen size... */ - /* based on Left Top Right Bottom of srWindow */ - ((struct winsize *) buf)->ws_row = info.dwWinSize.Y; - ((struct winsize *) buf)->ws_col = info.dwWinSize.X; - syscall_printf ("WINSZ: (row=%d,col=%d)", - ((struct winsize *) buf)->ws_row, - ((struct winsize *) buf)->ws_col); - return 0; - } - else - { - syscall_printf ("WINSZ failed"); - __seterrno (); - return -1; - } - return 0; - case TIOCSWINSZ: - (void) bg_check (SIGTTOU); - return 0; - } - - return fhandler_base::ioctl (cmd, buf); -} - -int -fhandler_console::tcflush (int queue) -{ - int res = 0; - if (queue == TCIFLUSH - || queue == TCIOFLUSH) - { - if (!FlushConsoleInputBuffer (get_io_handle ())) - { - __seterrno (); - res = -1; - } - } - return res; -} - -int -fhandler_console::output_tcsetattr (int, struct termios const *t) -{ - /* All the output bits we can ignore */ - - DWORD flags = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT; - - int res = SetConsoleMode (get_output_handle (), flags) ? 0 : -1; - syscall_printf ("%d = tcsetattr (,%x) (ENABLE FLAGS %x) (lflag %x oflag %x)", - res, t, flags, t->c_lflag, t->c_oflag); - return res; -} - -int -fhandler_console::input_tcsetattr (int, struct termios const *t) -{ - /* Ignore the optional_actions stuff, since all output is emitted - instantly */ - - DWORD oflags; - - if (!GetConsoleMode (get_io_handle (), &oflags)) - oflags = 0; - DWORD flags = 0; - -#if 0 - /* Enable/disable LF -> CRLF conversions */ - set_r_binary ((t->c_iflag & INLCR) ? 0 : 1); -#endif - - /* There's some disparity between what we need and what's - available. We've got ECHO and ICANON, they've - got ENABLE_ECHO_INPUT and ENABLE_LINE_INPUT. */ - - tc->ti = *t; - - if (t->c_lflag & ECHO) - { - flags |= ENABLE_ECHO_INPUT; - } - if (t->c_lflag & ICANON) - { - flags |= ENABLE_LINE_INPUT; - } - - if (flags & ENABLE_ECHO_INPUT - && !(flags & ENABLE_LINE_INPUT)) - { - /* This is illegal, so turn off the echo here, and fake it - when we read the characters */ - - flags &= ~ENABLE_ECHO_INPUT; - } - - if (t->c_lflag & ISIG) - { - flags |= ENABLE_PROCESSED_INPUT; - } - - if (use_tty) - { - flags = 0; // ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT; - tc->ti.c_iflag = 0; - tc->ti.c_lflag = 0; - } - - flags |= ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT; - - int res; - if (flags == oflags) - res = 0; - else - { - res = SetConsoleMode (get_io_handle (), flags) ? 0 : -1; - if (res < 0) - __seterrno (); - syscall_printf ("%d = tcsetattr (,%x) enable flags %p, c_lflag %p iflag %p", - res, t, flags, t->c_lflag, t->c_iflag); - } - - TTYCLEARF (RSTCONS); - return res; -} - -int -fhandler_console::tcsetattr (int a, struct termios const *t) -{ - int res = output_tcsetattr (a, t); - if (res != 0) - return res; - return input_tcsetattr (a, t); -} - -int -fhandler_console::tcgetattr (struct termios *t) -{ - int res; - *t = tc->ti; - - t->c_cflag |= CS8; - - DWORD flags; - - if (!GetConsoleMode (get_io_handle (), &flags)) - { - __seterrno (); - res = -1; - } - else - { - if (flags & ENABLE_ECHO_INPUT) - t->c_lflag |= ECHO; - - if (flags & ENABLE_LINE_INPUT) - t->c_lflag |= ICANON; - - if (flags & ENABLE_PROCESSED_INPUT) - t->c_lflag |= ISIG; - - /* What about ENABLE_WINDOW_INPUT - and ENABLE_MOUSE_INPUT ? */ - - /* All the output bits we can ignore */ - res = 0; - } - syscall_printf ("%d = tcgetattr (%p) enable flags %p, t->lflag %p, t->iflag %p", - res, t, flags, t->c_lflag, t->c_iflag); - return res; -} - -fhandler_console::fhandler_console () : - fhandler_termios (FH_CONSOLE, -1), - default_color (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE), - underline_color (FOREGROUND_GREEN | FOREGROUND_BLUE), - dim_color (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE), - meta_mask (LEFT_ALT_PRESSED), state_ (normal), nargs_ (0), savex (0), - savey (0), savebuf (NULL), dwLastButtonState (0), nModifiers (0), - insert_mode (false), use_mouse (false), raw_win32_keyboard_mode (false) -{ - for (int i = 0; i < MAXARGS; i++) args_ [i] = 0; - savebufsiz.X = savebufsiz.Y = 0; - scroll_region.Top = 0; - scroll_region.Bottom = -1; - dwLastCursorPosition.X = -1; - dwLastCursorPosition.Y = -1; - /* Set the mask that determines if an input keystroke is modified by - META. We set this based on the keyboard layout language loaded - for the current thread. The left <ALT> key always generates - META, but the right <ALT> key only generates META if we are using - an English keyboard because many "international" keyboards - replace common shell symbols ('[', '{', etc.) with accented - language-specific characters (umlaut, accent grave, etc.). On - these keyboards right <ALT> (called AltGr) is used to produce the - shell symbols and should not be interpreted as META. */ - if (PRIMARYLANGID (LOWORD (GetKeyboardLayout (0))) == LANG_ENGLISH) - meta_mask |= RIGHT_ALT_PRESSED; - -} - -#define FOREGROUND_ATTR_MASK (FOREGROUND_RED | FOREGROUND_GREEN | \ - FOREGROUND_BLUE | FOREGROUND_INTENSITY) -#define BACKGROUND_ATTR_MASK (BACKGROUND_RED | BACKGROUND_GREEN | \ - BACKGROUND_BLUE | BACKGROUND_INTENSITY) -void -fhandler_console::set_default_attr () -{ - blink = underline = reverse = FALSE; - intensity = INTENSITY_NORMAL; - fg = default_color & FOREGROUND_ATTR_MASK; - bg = default_color & BACKGROUND_ATTR_MASK; - current_win32_attr = get_win32_attr (); - SetConsoleTextAttribute (get_output_handle (), current_win32_attr); -} - -WORD -fhandler_console::get_win32_attr () -{ - WORD win_fg = fg; - WORD win_bg = bg; - if (reverse) - { - WORD save_fg = win_fg; - win_fg = (win_bg & BACKGROUND_RED ? FOREGROUND_RED : 0) | - (win_bg & BACKGROUND_GREEN ? FOREGROUND_GREEN : 0) | - (win_bg & BACKGROUND_BLUE ? FOREGROUND_BLUE : 0) | - (win_fg & FOREGROUND_INTENSITY); - win_bg = (save_fg & FOREGROUND_RED ? BACKGROUND_RED : 0) | - (save_fg & FOREGROUND_GREEN ? BACKGROUND_GREEN : 0) | - (save_fg & FOREGROUND_BLUE ? BACKGROUND_BLUE : 0) | - (win_bg & BACKGROUND_INTENSITY); - } - if (underline) win_fg = underline_color; - /* emulate blink with bright background */ - if (blink) win_bg |= BACKGROUND_INTENSITY; - if (intensity == INTENSITY_INVISIBLE) - win_fg = win_bg; - else if (intensity == INTENSITY_BOLD) - win_fg |= FOREGROUND_INTENSITY; - return (win_fg | win_bg); -} - -/* - * Clear the screen context from x1/y1 to x2/y2 cell. - * Negative values represents current screen dimensions - */ -void -fhandler_console::clear_screen (int x1, int y1, int x2, int y2) -{ - COORD tlc; - DWORD done; - int num; - - (void)fillin_info (); - - if (x1 < 0) - x1 = info.dwWinSize.X - 1; - if (y1 < 0) - y1 = info.winBottom; - if (x2 < 0) - x2 = info.dwWinSize.X - 1; - if (y2 < 0) - y2 = info.winBottom; - - num = abs (y1 - y2) * info.dwBufferSize.X + abs (x1 - x2) + 1; - - if ((y2 * info.dwBufferSize.X + x2) > (y1 * info.dwBufferSize.X + x1)) - { - tlc.X = x1; - tlc.Y = y1; - } - else - { - tlc.X = x2; - tlc.Y = y2; - } - FillConsoleOutputCharacterA (get_output_handle (), ' ', - num, - tlc, - &done); - FillConsoleOutputAttribute (get_output_handle (), - current_win32_attr, - num, - tlc, - &done); -} - -void -fhandler_console::cursor_set (BOOL rel_to_top, int x, int y) -{ - COORD pos; - - (void) fillin_info (); - if (y > info.winBottom) - y = info.winBottom; - else if (y < 0) - y = 0; - else if (rel_to_top) - y += info.winTop; - - if (x > info.dwWinSize.X) - x = info.dwWinSize.X - 1; - else if (x < 0) - x = 0; - - pos.X = x; - pos.Y = y; - SetConsoleCursorPosition (get_output_handle (), pos); -} - -void -fhandler_console::cursor_rel (int x, int y) -{ - fillin_info (); - x += info.dwCursorPosition.X; - y += info.dwCursorPosition.Y; - cursor_set (FALSE, x, y); -} - -void -fhandler_console::cursor_get (int *x, int *y) -{ - fillin_info (); - *y = info.dwCursorPosition.Y; - *x = info.dwCursorPosition.X; -} - -#define BAK 1 -#define ESC 2 -#define NOR 0 -#define IGN 4 -#if 0 -#define ERR 5 -#else -#define ERR NOR -#endif -#define DWN 6 -#define BEL 7 -#define TAB 8 /* We should't let the console deal with these */ -#define CR 13 -#define LF 10 - -static const char base_chars[256] = -{ -/*00 01 02 03 04 05 06 07 */ IGN, ERR, ERR, NOR, NOR, NOR, NOR, BEL, -/*08 09 0A 0B 0C 0D 0E 0F */ BAK, TAB, DWN, ERR, ERR, CR, ERR, IGN, -/*10 11 12 13 14 15 16 17 */ NOR, NOR, ERR, ERR, ERR, ERR, ERR, ERR, -/*18 19 1A 1B 1C 1D 1E 1F */ NOR, NOR, ERR, ESC, ERR, ERR, ERR, ERR, -/* ! " # $ % & ' */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*() * + , - . / */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*0 1 2 3 4 5 6 7 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*8 9 : ; < = > ? */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*@ A B C D E F G */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*H I J K L M N O */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*P Q R S T U V W */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*X Y Z [ \ ] ^ _ */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*` a b c d e f g */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*h i j k l m n o */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*p q r s t u v w */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*x y z { | } ~ 7F */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*80 81 82 83 84 85 86 87 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*88 89 8A 8B 8C 8D 8E 8F */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*90 91 92 93 94 95 96 97 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*98 99 9A 9B 9C 9D 9E 9F */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*A0 A1 A2 A3 A4 A5 A6 A7 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*A8 A9 AA AB AC AD AE AF */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*B0 B1 B2 B3 B4 B5 B6 B7 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*B8 B9 BA BB BC BD BE BF */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*C0 C1 C2 C3 C4 C5 C6 C7 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*C8 C9 CA CB CC CD CE CF */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*D0 D1 D2 D3 D4 D5 D6 D7 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*D8 D9 DA DB DC DD DE DF */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*E0 E1 E2 E3 E4 E5 E6 E7 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*E8 E9 EA EB EC ED EE EF */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*F0 F1 F2 F3 F4 F5 F6 F7 */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR, -/*F8 F9 FA FB FC FD FE FF */ NOR, NOR, NOR, NOR, NOR, NOR, NOR, NOR }; - -void -fhandler_console::char_command (char c) -{ - int x, y; - char buf[40]; - - switch (c) - { - case 'm': /* Set Graphics Rendition */ - int i; - - for (i = 0; i <= nargs_; i++) - switch (args_[i]) - { - case 0: /* normal color */ - set_default_attr (); - break; - case 1: /* bold */ - intensity = INTENSITY_BOLD; - break; - case 4: - underline = 1; - break; - case 5: /* blink mode */ - blink = TRUE; - break; - case 7: /* reverse */ - reverse = TRUE; - break; - case 8: /* invisible */ - intensity = INTENSITY_INVISIBLE; - break; - case 9: /* dim */ - intensity = INTENSITY_DIM; - break; - case 24: - underline = FALSE; - break; - case 27: - reverse = FALSE; - break; - case 30: /* BLACK foreground */ - fg = 0; - break; - case 31: /* RED foreground */ - fg = FOREGROUND_RED; - break; - case 32: /* GREEN foreground */ - fg = FOREGROUND_GREEN; - break; - case 33: /* YELLOW foreground */ - fg = FOREGROUND_RED | FOREGROUND_GREEN; - break; - case 34: /* BLUE foreground */ - fg = FOREGROUND_BLUE; - break; - case 35: /* MAGENTA foreground */ - fg = FOREGROUND_RED | FOREGROUND_BLUE; - break; - case 36: /* CYAN foreground */ - fg = FOREGROUND_BLUE | FOREGROUND_GREEN; - break; - case 37: /* WHITE foreg */ - fg = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED; - break; - case 39: - fg = default_color & FOREGROUND_ATTR_MASK; - break; - case 40: /* BLACK background */ - bg = 0; - break; - case 41: /* RED background */ - bg = BACKGROUND_RED; - break; - case 42: /* GREEN background */ - bg = BACKGROUND_GREEN; - break; - case 43: /* YELLOW background */ - bg = BACKGROUND_RED | BACKGROUND_GREEN; - break; - case 44: /* BLUE background */ - bg = BACKGROUND_BLUE; - break; - case 45: /* MAGENTA background */ - bg = BACKGROUND_RED | BACKGROUND_BLUE; - break; - case 46: /* CYAN background */ - bg = BACKGROUND_BLUE | BACKGROUND_GREEN; - break; - case 47: /* WHITE background */ - bg = BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED; - break; - case 49: - bg = default_color & BACKGROUND_ATTR_MASK; - break; - } - current_win32_attr = get_win32_attr (); - SetConsoleTextAttribute (get_output_handle (), current_win32_attr); - break; - case 'h': - case 'l': - if (!saw_question_mark) - { - switch (args_[0]) - { - case 4: /* Insert mode */ - insert_mode = (c == 'h') ? TRUE : FALSE; - syscall_printf ("insert mode %sabled", insert_mode ? "en" : "dis"); - break; - } - break; - } - switch (args_[0]) - { - case 47: /* Save/Restore screen */ - if (c == 'h') /* save */ - { - CONSOLE_SCREEN_BUFFER_INFO now; - COORD cob = { 0, 0 }; - - if (!GetConsoleScreenBufferInfo (get_output_handle (), &now)) - break; - - savebufsiz.X = now.srWindow.Right - now.srWindow.Left + 1; - savebufsiz.Y = now.srWindow.Bottom - now.srWindow.Top + 1; - - if (savebuf) - cfree (savebuf); - savebuf = (PCHAR_INFO) cmalloc (HEAP_1_BUF, sizeof (CHAR_INFO) * - savebufsiz.X * savebufsiz.Y); - - ReadConsoleOutputA (get_output_handle (), savebuf, - savebufsiz, cob, &now.srWindow); - } - else /* restore */ - { - CONSOLE_SCREEN_BUFFER_INFO now; - COORD cob = { 0, 0 }; - - if (!GetConsoleScreenBufferInfo (get_output_handle (), &now)) - break; - - if (!savebuf) - break; - - WriteConsoleOutputA (get_output_handle (), savebuf, - savebufsiz, cob, &now.srWindow); - - cfree (savebuf); - savebuf = NULL; - savebufsiz.X = savebufsiz.Y = 0; - } - break; - - case 1000: /* Mouse support */ - use_mouse = (c == 'h') ? TRUE : FALSE; - syscall_printf ("mouse support %sabled", use_mouse ? "en" : "dis"); - break; - - case 2000: /* Raw keyboard mode */ - set_raw_win32_keyboard_mode ((c == 'h') ? TRUE : FALSE); - break; - - default: /* Ignore */ - syscall_printf ("unknown h/l command: %d", args_[0]); - break; - } - break; - case 'J': - switch (args_[0]) - { - case 0: /* Clear to end of screen */ - cursor_get (&x, &y); - clear_screen (x, y, -1, -1); - break; - case 1: /* Clear from beginning of screen to cursor */ - cursor_get (&x, &y); - clear_screen (0, 0, x, y); - break; - case 2: /* Clear screen */ - clear_screen (0, 0, -1, -1); - cursor_set (TRUE, 0,0); - break; - default: - goto bad_escape; - } - break; - - case 'A': - cursor_rel (0, -(args_[0] ? args_[0] : 1)); - break; - case 'B': - cursor_rel (0, args_[0] ? args_[0] : 1); - break; - case 'C': - cursor_rel (args_[0] ? args_[0] : 1, 0); - break; - case 'D': - cursor_rel (-(args_[0] ? args_[0] : 1),0); - break; - case 'K': - switch (args_[0]) - { - case 0: /* Clear to end of line */ - cursor_get (&x, &y); - clear_screen (x, y, -1, y); - break; - case 2: /* Clear line */ - cursor_get (&x, &y); - clear_screen (0, y, -1, y); - break; - case 1: /* Clear from bol to cursor */ - cursor_get (&x, &y); - clear_screen (0, y, x, y); - break; - default: - goto bad_escape; - } - break; - case 'H': - case 'f': - cursor_set (TRUE, (args_[1] ? args_[1] : 1) - 1, - (args_[0] ? args_[0] : 1) - 1); - break; - case 'G': /* hpa - position cursor at column n - 1 */ - cursor_get (&x, &y); - cursor_set (FALSE, (args_[0] ? args_[0] - 1 : 0), y); - break; - case 'd': /* vpa - position cursor at line n */ - cursor_get (&x, &y); - cursor_set (TRUE, x, (args_[0] ? args_[0] - 1 : 0)); - break; - case 's': /* Save cursor position */ - cursor_get (&savex, &savey); - savey -= info.winTop; - break; - case 'u': /* Restore cursor position */ - cursor_set (TRUE, savex, savey); - break; - case 'I': /* TAB */ - cursor_get (&x, &y); - cursor_set (FALSE, 8 * (x / 8 + 1), y); - break; - case 'L': /* AL - insert blank lines */ - args_[0] = args_[0] ? args_[0] : 1; - cursor_get (&x, &y); - scroll_screen (0, y, -1, -1, 0, y + args_[0]); - break; - case 'M': /* DL - delete lines */ - args_[0] = args_[0] ? args_[0] : 1; - cursor_get (&x, &y); - scroll_screen (0, y + args_[0], -1, -1, 0, y); - break; - case '@': /* IC - insert chars */ - args_[0] = args_[0] ? args_[0] : 1; - cursor_get (&x, &y); - scroll_screen (x, y, -1, y, x + args_[0], y); - break; - case 'P': /* DC - delete chars */ - args_[0] = args_[0] ? args_[0] : 1; - cursor_get (&x, &y); - scroll_screen (x + args_[0], y, -1, y, x, y); - break; - case 'S': /* SF - Scroll forward */ - args_[0] = args_[0] ? args_[0] : 1; - scroll_screen (0, args_[0], -1, -1, 0, 0); - break; - case 'T': /* SR - Scroll down */ - fillin_info (); - args_[0] = args_[0] ? args_[0] : 1; - scroll_screen (0, 0, -1, -1, 0, info.winTop + args_[0]); - break; - case 'X': /* ec - erase chars */ - args_[0] = args_[0] ? args_[0] : 1; - cursor_get (&x, &y); - scroll_screen (x + args_[0], y, -1, y, x, y); - scroll_screen (x, y, -1, y, x + args_[0], y); - break; - case 'Z': /* Back tab */ - cursor_get (&x, &y); - cursor_set (FALSE, ((8 * (x / 8 + 1)) - 8), y); - break; - case 'b': /* Repeat char #1 #2 times */ - if (insert_mode) - { - cursor_get (&x, &y); - scroll_screen (x, y, -1, y, x + args_[1], y); - } - while (args_[1]--) - WriteFile (get_output_handle (), &args_[0], 1, (DWORD *) &x, 0); - break; - case 'c': /* u9 - Terminal enquire string */ - strcpy (buf, "\033[?6c"); - puts_readahead (buf); - break; - case 'n': - switch (args_[0]) - { - case 6: /* u7 - Cursor position request */ - cursor_get (&x, &y); - y -= info.winTop; - /* x -= info.winLeft; // not available yet */ - __small_sprintf (buf, "\033[%d;%dR", y + 1, x + 1); - puts_readahead (buf); - break; - default: - goto bad_escape; - } - break; - case 'r': /* Set Scroll region */ - scroll_region.Top = args_[0] ? args_[0] - 1 : 0; - scroll_region.Bottom = args_[1] ? args_[1] - 1 : -1; - cursor_set (TRUE, 0, 0); - break; - case 'g': /* TAB set/clear */ - break; - default: -bad_escape: - break; - } -} - -const unsigned char * -fhandler_console::write_normal (const unsigned char *src, - const unsigned char *end) -{ - /* Scan forward to see what a char which needs special treatment */ - DWORD done; - const unsigned char *found = src; - - while (found < end) - { - if (base_chars[*found] != NOR) - break; - found++; - } - - /* Print all the base ones out */ - if (found != src) - { - DWORD len = found - src; - do - { - DWORD buf_len; - char buf[CONVERT_LIMIT]; - done = buf_len = min (sizeof (buf), len); - if (!str_to_con (buf, (const char *) src, buf_len)) - { - debug_printf ("conversion error, handle %p", get_output_handle ()); - __seterrno (); - return 0; - } - - if (insert_mode) - { - int x, y; - cursor_get (&x, &y); - scroll_screen (x, y, -1, y, x + buf_len, y); - } - - if (!WriteFile (get_output_handle (), buf, buf_len, &done, 0)) - { - debug_printf ("write failed, handle %p", get_output_handle ()); - __seterrno (); - return 0; - } - len -= done; - src += done; - } - while (len > 0); - } - - if (src < end) - { - int x, y; - switch (base_chars[*src]) - { - case BEL: - Beep (412, 100); - break; - case ESC: - state_ = gotesc; - break; - case DWN: - cursor_get (&x, &y); - if (y >= srBottom) - { - if (y >= info.winBottom && !scroll_region.Top) - WriteFile (get_output_handle (), "\n", 1, &done, 0); - else - { - scroll_screen (0, srTop + 1, -1, srBottom, 0, srTop); - y--; - } - } - cursor_set (FALSE, ((tc->ti.c_oflag & ONLCR) ? 0 : x), y + 1); - break; - case BAK: - cursor_rel (-1, 0); - break; - case IGN: - cursor_rel (1, 0); - break; - case CR: - cursor_get (&x, &y); - cursor_set (FALSE, 0, y); - break; - case ERR: - WriteFile (get_output_handle (), src, 1, &done, 0); - break; - case TAB: - cursor_get (&x, &y); - cursor_set (FALSE, 8 * (x / 8 + 1), y); - break; - } - src ++; - } - return src; -} - -int -fhandler_console::write (const void *vsrc, size_t len) -{ - /* Run and check for ansi sequences */ - unsigned const char *src = (unsigned char *) vsrc; - unsigned const char *end = src + len; - - debug_printf ("%x, %d", vsrc, len); - - while (src < end) - { - debug_printf ("at %d(%c) state is %d", *src, isprint (*src) ? *src : ' ', - state_); - switch (state_) - { - case normal: - src = write_normal (src, end); - if (!src) /* write_normal failed */ - return -1; - break; - case gotesc: - if (*src == '[') - { - state_ = gotsquare; - saw_question_mark = FALSE; - for (nargs_ = 0; nargs_ < MAXARGS; nargs_++) - args_[nargs_] = 0; - nargs_ = 0; - } - else if (*src == ']') - { - rarg = 0; - my_title_buf[0] = '\0'; - state_ = gotrsquare; - } - else if (*src == 'M') /* Reverse Index */ - { - fillin_info (); - scroll_screen (0, 0, -1, -1, 0, info.winTop + 1); - state_ = normal; - } - else if (*src == 'c') /* Reset Linux terminal */ - { - set_default_attr (); - clear_screen (0, 0, -1, -1); - cursor_set (TRUE, 0, 0); - state_ = normal; - } - else if (*src == '8') /* Restore cursor position */ - { - cursor_set (TRUE, savex, savey); - state_ = normal; - } - else if (*src == '7') /* Save cursor position */ - { - cursor_get (&savex, &savey); - savey -= info.winTop; - state_ = normal; - } - else if (*src == 'R') - state_ = normal; - else - { - state_ = normal; - } - src++; - break; - case gotarg1: - if (isdigit (*src)) - { - args_[nargs_] = args_[nargs_] * 10 + *src - '0'; - src++; - } - else if (*src == ';') - { - src++; - nargs_++; - if (nargs_ >= MAXARGS) - nargs_--; - } - else - { - state_ = gotcommand; - } - break; - case gotcommand: - char_command (*src++); - state_ = normal; - break; - case gotrsquare: - if (isdigit (*src)) - rarg = rarg * 10 + (*src - '0'); - else if (*src == ';' && (rarg == 2 || rarg == 0)) - state_ = gettitle; - else - state_ = eattitle; - src++; - break; - case eattitle: - case gettitle: - { - int n = strlen (my_title_buf); - if (*src < ' ' || *src >= '\177') - { - if (*src == '\007' && state_ == gettitle) - { - if (old_title) - strcpy (old_title, my_title_buf); - set_console_title (my_title_buf); - } - state_ = normal; - } - else if (n < TITLESIZE) - { - my_title_buf[n++] = *src; - my_title_buf[n] = '\0'; - } - src++; - break; - } - case gotsquare: - if (*src == ';') - { - state_ = gotarg1; - nargs_++; - src++; - } - else if (isalpha (*src)) - { - state_ = gotcommand; - } - else if (*src != '@' && !isalpha (*src) && !isdigit (*src)) - { - if (*src == '?') - saw_question_mark = TRUE; - /* ignore any extra chars between [ and first arg or command */ - src++; - } - else - state_ = gotarg1; - break; - } - } - - syscall_printf ("%d = write_console (,..%d)", len, len); - - return len; -} - -static struct { - int vk; - const char *val[4]; -} keytable[] NO_COPY = { - /* NORMAL */ /* SHIFT */ /* CTRL */ /* ALT */ - {VK_LEFT, {"\033[D", "\033[D", "\033[D", "\033\033[D"}}, - {VK_RIGHT, {"\033[C", "\033[C", "\033[C", "\033\033[C"}}, - {VK_UP, {"\033[A", "\033[A", "\033[A", "\033\033[A"}}, - {VK_DOWN, {"\033[B", "\033[B", "\033[B", "\033\033[B"}}, - {VK_PRIOR, {"\033[5~", "\033[5~", "\033[5~", "\033\033[5~"}}, - {VK_NEXT, {"\033[6~", "\033[6~", "\033[6~", "\033\033[6~"}}, - {VK_HOME, {"\033[1~", "\033[1~", "\033[1~", "\033\033[1~"}}, - {VK_END, {"\033[4~", "\033[4~", "\033[4~", "\033\033[4~"}}, - {VK_INSERT, {"\033[2~", "\033[2~", "\033[2~", "\033\033[2~"}}, - {VK_DELETE, {"\033[3~", "\033[3~", "\033[3~", "\033\033[3~"}}, - {VK_F1, {"\033[[A", "\033[23~", NULL, NULL}}, - {VK_F2, {"\033[[B", "\033[24~", NULL, NULL}}, - {VK_F3, {"\033[[C", "\033[25~", NULL, NULL}}, - {VK_F4, {"\033[[D", "\033[26~", NULL, NULL}}, - {VK_F5, {"\033[[E", "\033[28~", NULL, NULL}}, - {VK_F6, {"\033[17~", "\033[29~", "\036", NULL}}, - {VK_F7, {"\033[18~", "\033[31~", NULL, NULL}}, - {VK_F8, {"\033[19~", "\033[32~", NULL, NULL}}, - {VK_F9, {"\033[20~", "\033[33~", NULL, NULL}}, - {VK_F10, {"\033[21~", "\033[34~", NULL, NULL}}, - {VK_F11, {"\033[23~", NULL, NULL, NULL}}, - {VK_F12, {"\033[24~", NULL, NULL, NULL}}, - {VK_NUMPAD5, {"\033[G", NULL, NULL, NULL}}, - {VK_CLEAR, {"\033[G", NULL, NULL, NULL}}, - {'6', {NULL, NULL, "\036", NULL}}, - {0, {"", NULL, NULL, NULL}} -}; - -const char * -get_nonascii_key (INPUT_RECORD& input_rec, char *tmp) -{ -#define NORMAL 0 -#define SHIFT 1 -#define CONTROL 2 -#define ALT 3 - int modifier_index = NORMAL; - - if (input_rec.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED) - modifier_index = SHIFT; - else if (input_rec.Event.KeyEvent.dwControlKeyState & - (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) - modifier_index = CONTROL; - else if (input_rec.Event.KeyEvent.dwControlKeyState & - (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) - modifier_index = ALT; - - for (int i = 0; keytable[i].vk; i++) - if (input_rec.Event.KeyEvent.wVirtualKeyCode == keytable[i].vk) - return keytable[i].val[modifier_index]; - - if (input_rec.Event.KeyEvent.uChar.AsciiChar) - { - tmp[0] = input_rec.Event.KeyEvent.uChar.AsciiChar; - tmp[1] = '\0'; - return tmp; - } - return NULL; -} - -void -fhandler_console::init (HANDLE f, DWORD a, mode_t bin) -{ - // this->fhandler_termios::init (f, mode, bin); - /* Ensure both input and output console handles are open */ - int flags = 0; - - a &= GENERIC_READ | GENERIC_WRITE; - if (a == GENERIC_READ) - flags = O_RDONLY; - if (a == GENERIC_WRITE) - flags = O_WRONLY; - if (a == (GENERIC_READ | GENERIC_WRITE)) - flags = O_RDWR; - open ((path_conv *) NULL, flags | O_BINARY); - if (f != INVALID_HANDLE_VALUE) - CloseHandle (f); /* Reopened by open */ - - this->tcsetattr (0, &tc->ti); -} - -int -fhandler_console::igncr_enabled (void) -{ - return tc->ti.c_iflag & IGNCR; -} - -void -fhandler_console::set_close_on_exec (int val) -{ - this->fhandler_base::set_close_on_exec (val); - set_inheritance (output_handle, val); -} - -void -fhandler_console::fixup_after_fork (HANDLE) -{ - HANDLE h = get_handle (); - HANDLE oh = get_output_handle (); - - /* Windows does not allow duplication of console handles between processes - so open the console explicitly. */ - - if (!open (NULL, O_NOCTTY | get_flags (), 0)) - system_printf ("error opening console after fork, %E"); - - if (!get_close_on_exec ()) - { - CloseHandle (h); - CloseHandle (oh); - } -} - -void __stdcall -set_console_title (char *title) -{ - int rc; - char buf[257]; - strncpy (buf, title, sizeof (buf) - 1); - buf[sizeof (buf) - 1] = '\0'; - if ((rc = WaitForSingleObject (title_mutex, 15000)) != WAIT_OBJECT_0) - sigproc_printf ("wait for title mutex failed rc %d, %E", rc); - SetConsoleTitle (buf); - ReleaseMutex (title_mutex); - debug_printf ("title '%s'", buf); -} - -void -fhandler_console::fixup_after_exec (HANDLE) -{ - HANDLE h = get_handle (); - HANDLE oh = get_output_handle (); - - if (!open (NULL, O_NOCTTY | get_flags (), 0)) - { - int sawerr = 0; - if (!get_io_handle ()) - { - system_printf ("error opening input console handle after exec, errno %d, %E", get_errno ()); - sawerr = 1; - } - if (!get_output_handle ()) - { - system_printf ("error opening input console handle after exec, errno %d, %E", get_errno ()); - sawerr = 1; - } - - if (!sawerr) - system_printf ("error opening console after exec, errno %d, %E", get_errno ()); - } - - CloseHandle (h); - CloseHandle (oh); - return; -} |