]> ncurses.scripts.mit.edu Git - ncurses.git/blobdiff - ncurses/win32con/win_driver.c
ncurses 6.5 - patch 20240511
[ncurses.git] / ncurses / win32con / win_driver.c
index 1b38f6a4bc06666c67f7fd6ffaced464907508fd..2425b3a44ce6f21eb2261d2a73a2cc4bf64b60ee 100644 (file)
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2018,2020 Free Software Foundation, Inc.              *
+ * Copyright 2018-2021,2023 Thomas E. Dickey                                *
+ * Copyright 2008-2016,2017 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
 
 #define CUR TerminalType(my_term).
 
-MODULE_ID("$Id: win_driver.c,v 1.62 2020/01/18 17:02:38 tom Exp $")
+#define CONTROL_PRESSED (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)
 
-#ifndef __GNUC__
-#  error We need GCC to compile for MinGW
-#endif
+MODULE_ID("$Id: win_driver.c,v 1.74 2023/09/16 16:27:44 tom Exp $")
+
+#define TypeAlloca(type,count) (type*) _alloca(sizeof(type) * (size_t) (count))
 
 #define WINMAGIC NCDRV_MAGIC(NCDRV_WINCONSOLE)
 
@@ -83,39 +84,40 @@ static bool okConsoleHandle(TERMINAL_CONTROL_BLOCK *);
 #define write_screen WriteConsoleOutput
 #define read_screen  ReadConsoleOutput
 #endif
-
+/* *INDENT-OFF* */
 static const LONG keylist[] =
 {
-    GenMap(VK_PRIOR, KEY_PPAGE),
-    GenMap(VK_NEXT, KEY_NPAGE),
-    GenMap(VK_END, KEY_END),
-    GenMap(VK_HOME, KEY_HOME),
-    GenMap(VK_LEFT, KEY_LEFT),
-    GenMap(VK_UP, KEY_UP),
-    GenMap(VK_RIGHT, KEY_RIGHT),
-    GenMap(VK_DOWN, KEY_DOWN),
+    GenMap(VK_PRIOR,  KEY_PPAGE),
+    GenMap(VK_NEXT,   KEY_NPAGE),
+    GenMap(VK_END,    KEY_END),
+    GenMap(VK_HOME,   KEY_HOME),
+    GenMap(VK_LEFT,   KEY_LEFT),
+    GenMap(VK_UP,     KEY_UP),
+    GenMap(VK_RIGHT,  KEY_RIGHT),
+    GenMap(VK_DOWN,   KEY_DOWN),
     GenMap(VK_DELETE, KEY_DC),
     GenMap(VK_INSERT, KEY_IC)
 };
 static const LONG ansi_keys[] =
 {
-    GenMap(VK_PRIOR, 'I'),
-    GenMap(VK_NEXT, 'Q'),
-    GenMap(VK_END, 'O'),
-    GenMap(VK_HOME, 'H'),
-    GenMap(VK_LEFT, 'K'),
-    GenMap(VK_UP, 'H'),
-    GenMap(VK_RIGHT, 'M'),
-    GenMap(VK_DOWN, 'P'),
+    GenMap(VK_PRIOR,  'I'),
+    GenMap(VK_NEXT,   'Q'),
+    GenMap(VK_END,    'O'),
+    GenMap(VK_HOME,   'H'),
+    GenMap(VK_LEFT,   'K'),
+    GenMap(VK_UP,     'H'),
+    GenMap(VK_RIGHT,  'M'),
+    GenMap(VK_DOWN,   'P'),
     GenMap(VK_DELETE, 'S'),
     GenMap(VK_INSERT, 'R')
 };
+/* *INDENT-ON* */
 #define N_INI ((int)array_length(keylist))
 #define FKEYS 24
 #define MAPSIZE (FKEYS + N_INI)
 #define NUMPAIRS 64
 
-/*   A process can only have a single console, so it's safe
+/*   A process can only have a single console, so it is safe
      to maintain all the information about it in a single
      static structure.
  */
@@ -124,7 +126,6 @@ static struct {
     BOOL buffered;
     BOOL window_only;
     BOOL progMode;
-    BOOL isMinTTY;
     BOOL isTermInfoConsole;
     HANDLE out;
     HANDLE inp;
@@ -261,7 +262,7 @@ static BOOL
 con_write16(TERMINAL_CONTROL_BLOCK * TCB, int y, int x, cchar_t *str, int limit)
 {
     int actual = 0;
-    CHAR_INFO ci[limit];
+    CHAR_INFO *ci = TypeAlloca(CHAR_INFO, limit);
     COORD loc, siz;
     SMALL_RECT rec;
     int i;
@@ -310,7 +311,7 @@ con_write16(TERMINAL_CONTROL_BLOCK * TCB, int y, int x, cchar_t *str, int limit)
 static BOOL
 con_write8(TERMINAL_CONTROL_BLOCK * TCB, int y, int x, chtype *str, int n)
 {
-    CHAR_INFO ci[n];
+    CHAR_INFO *ci = TypeAlloca(CHAR_INFO, n);
     COORD loc, siz;
     SMALL_RECT rec;
     int i;
@@ -487,7 +488,7 @@ wcon_doupdate(TERMINAL_CONTROL_BLOCK * TCB)
 
        Width = screen_columns(sp);
        Height = screen_lines(sp);
-       nonempty = min(Height, NewScreen(sp)->_maxy + 1);
+       nonempty = Min(Height, NewScreen(sp)->_maxy + 1);
 
        T(("... %dx%d clear cur:%d new:%d",
           Height, Width,
@@ -509,7 +510,7 @@ wcon_doupdate(TERMINAL_CONTROL_BLOCK * TCB)
        if ((CurScreen(sp)->_clear || NewScreen(sp)->_clear)) {
            int x;
 #if USE_WIDEC_SUPPORT
-           cchar_t empty[Width];
+           cchar_t *empty = TypeAlloca(cchar_t, Width);
            wchar_t blank[2] =
            {
                L' ', L'\0'
@@ -518,7 +519,7 @@ wcon_doupdate(TERMINAL_CONTROL_BLOCK * TCB)
            for (x = 0; x < Width; x++)
                setcchar(&empty[x], blank, 0, 0, 0);
 #else
-           chtype empty[Width];
+           chtype *empty = TypeAlloca(chtype, Width);
 
            for (x = 0; x < Width; x++)
                empty[x] = ' ';
@@ -611,6 +612,12 @@ wcon_doupdate(TERMINAL_CONTROL_BLOCK * TCB)
     returnCode(result);
 }
 
+#ifdef __MING32__
+#define SysISATTY(fd) _isatty(fd)
+#else
+#define SysISATTY(fd) isatty(fd)
+#endif
+
 static bool
 wcon_CanHandle(TERMINAL_CONTROL_BLOCK * TCB,
               const char *tname,
@@ -642,6 +649,8 @@ wcon_CanHandle(TERMINAL_CONTROL_BLOCK * TCB,
        }
     } else if (tname != 0 && stricmp(tname, "unknown") == 0) {
        code = TRUE;
+    } else if (SysISATTY(TCB->term.Filedes)) {
+       code = TRUE;
     }
 
     /*
@@ -674,8 +683,8 @@ wcon_dobeepflash(TERMINAL_CONTROL_BLOCK * TCB,
     int max_cells = (high * wide);
     int i;
 
-    CHAR_INFO this_screen[max_cells];
-    CHAR_INFO that_screen[max_cells];
+    CHAR_INFO *this_screen = TypeAlloca(CHAR_INFO, max_cells);
+    CHAR_INFO *that_screen = TypeAlloca(CHAR_INFO, max_cells);
     COORD this_size;
     SMALL_RECT this_region;
     COORD bufferCoord;
@@ -700,7 +709,9 @@ wcon_dobeepflash(TERMINAL_CONTROL_BLOCK * TCB,
                        bufferCoord,
                        &this_region)) {
 
-           memcpy(that_screen, this_screen, sizeof(that_screen));
+           memcpy(that_screen,
+                  this_screen,
+                  sizeof(CHAR_INFO) * (size_t) max_cells);
 
            for (i = 0; i < max_cells; i++) {
                that_screen[i].Attributes = RevAttr(that_screen[i].Attributes);
@@ -1475,10 +1486,10 @@ Adjust(int milliseconds, int diff)
                     FROM_LEFT_4TH_BUTTON_PRESSED | \
                     RIGHTMOST_BUTTON_PRESSED)
 
-static int
+static mmask_t
 decode_mouse(SCREEN *sp, int mask)
 {
-    int result = 0;
+    mmask_t result = 0;
 
     (void) sp;
     assert(sp && console_initialized);
@@ -1667,14 +1678,14 @@ handle_mouse(SCREEN *sp, MOUSE_EVENT_RECORD mer)
 
        if (sp->_drv_mouse_new_buttons) {
 
-           work.bstate |= (mmask_t) decode_mouse(sp, sp->_drv_mouse_new_buttons);
+           work.bstate |= decode_mouse(sp, sp->_drv_mouse_new_buttons);
 
        } else {
 
            /* cf: BUTTON_PRESSED, BUTTON_RELEASED */
-           work.bstate |= (mmask_t) (decode_mouse(sp,
-                                                  sp->_drv_mouse_old_buttons)
-                                     >> 1);
+           work.bstate |= (decode_mouse(sp,
+                                        sp->_drv_mouse_old_buttons)
+                           >> 1);
 
            result = TRUE;
        }
@@ -1866,7 +1877,7 @@ get_handle(int fd)
 #if WINVER >= 0x0600
 /*   This function tests, whether or not the ncurses application
      is running as a descendant of MSYS2/cygwin mintty terminal
-     application. mintty doesn't use Windows Console for it's screen
+     application. mintty doesn't use Windows Console for its screen
      I/O, so the native Windows _isatty doesn't recognize it as
      character device. But we can discover we are at the end of an
      Pipe and can query to server side of the pipe, looking whether
@@ -1956,11 +1967,6 @@ _nc_mingw_isatty(int fd)
 {
     int result = 0;
 
-#ifdef __MING32__
-#define SysISATTY(fd) _isatty(fd)
-#else
-#define SysISATTY(fd) isatty(fd)
-#endif
     if (SysISATTY(fd)) {
        result = 1;
     } else {
@@ -1973,7 +1979,7 @@ _nc_mingw_isatty(int fd)
 
 /*   This is used when running in terminfo mode to discover,
      whether or not the "terminal" is actually a Windows
-     Console. It's the responsibility of the console to deal
+     Console. It is the responsibility of the console to deal
      with the terminal escape sequences that are sent by
      terminfo.
  */
@@ -2125,9 +2131,9 @@ _nc_mingw_console_read(
                *buf = (int) inp_rec.Event.KeyEvent.uChar.AsciiChar;
                vk = inp_rec.Event.KeyEvent.wVirtualKeyCode;
                /*
-                * There are 24 virtual function-keys, and typically
-                * 12 function-keys on a keyboard.  Use the shift-modifier
-                * to provide the remaining 12 keys.
+                * There are 24 virtual function-keys (defined in winuser.h),
+                * and typically 12 function-keys on a keyboard.  Use the
+                * shift-modifier to provide the remaining keys.
                 */
                if (vk >= VK_F1 && vk <= VK_F12) {
                    if (inp_rec.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED) {
@@ -2144,6 +2150,11 @@ _nc_mingw_console_read(
                        ungetch('\0');
                        *buf = AnsiKey(vk);
                    }
+               } else if (vk == VK_BACK) {
+                   if (!(inp_rec.Event.KeyEvent.dwControlKeyState
+                         & (SHIFT_PRESSED | CONTROL_PRESSED))) {
+                       *buf = KEY_BACKSPACE;
+                   }
                }
                break;
            } else if (inp_rec.EventType == MOUSE_EVENT) {
@@ -2171,9 +2182,6 @@ InitConsole(void)
        BOOL b;
 
        START_TRACE();
-       if (_nc_mingw_isatty(0)) {
-           CON.isMinTTY = TRUE;
-       }
 
        for (i = 0; i < (N_INI + FKEYS); i++) {
            if (i < N_INI) {
@@ -2212,14 +2220,14 @@ InitConsole(void)
        for (i = 0; i < NUMPAIRS; i++)
            CON.pairs[i] = a;
 
-       CON.inp = GetStdHandle(STD_INPUT_HANDLE);
-       CON.out = GetStdHandle(STD_OUTPUT_HANDLE);
-
        b = AllocConsole();
 
        if (!b)
            b = AttachConsole(ATTACH_PARENT_PROCESS);
 
+       CON.inp = GetDirectHandle("CONIN$", FILE_SHARE_READ);
+       CON.out = GetDirectHandle("CONOUT$", FILE_SHARE_WRITE);
+
        if (getenv("NCGDB") || getenv("NCURSES_CONSOLE2")) {
            T(("... will not buffer console"));
            buffered = FALSE;
@@ -2227,7 +2235,7 @@ InitConsole(void)
        } else {
            T(("... creating console buffer"));
            CON.hdl = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
-                                               0,
+                                               FILE_SHARE_READ | FILE_SHARE_WRITE,
                                                NULL,
                                                CONSOLE_TEXTMODE_BUFFER,
                                                NULL);