summaryrefslogtreecommitdiffstats
path: root/Utilities/cmpdcurses/wincon
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmpdcurses/wincon')
-rw-r--r--Utilities/cmpdcurses/wincon/README.md76
-rw-r--r--Utilities/cmpdcurses/wincon/pdcclip.c149
-rw-r--r--Utilities/cmpdcurses/wincon/pdcdisp.c329
-rw-r--r--Utilities/cmpdcurses/wincon/pdcgetsc.c42
-rw-r--r--Utilities/cmpdcurses/wincon/pdckbd.c699
-rw-r--r--Utilities/cmpdcurses/wincon/pdcscrn.c686
-rw-r--r--Utilities/cmpdcurses/wincon/pdcsetsc.c130
-rw-r--r--Utilities/cmpdcurses/wincon/pdcutil.c26
-rw-r--r--Utilities/cmpdcurses/wincon/pdcwin.h27
9 files changed, 2164 insertions, 0 deletions
diff --git a/Utilities/cmpdcurses/wincon/README.md b/Utilities/cmpdcurses/wincon/README.md
new file mode 100644
index 0000000..6192afb
--- /dev/null
+++ b/Utilities/cmpdcurses/wincon/README.md
@@ -0,0 +1,76 @@
+PDCurses for Windows console
+============================
+
+This directory contains PDCurses source code files specific to the
+Microsoft Windows console. Although historically called "Win32", this
+port can just as easily be built for 64-bit systems. Windows 95 through
+Windows 10 are covered. (Some features require later versions.)
+
+
+Building
+--------
+
+- Choose the appropriate makefile for your compiler:
+
+ Makefile - GCC (MinGW or Cygnus)
+ Makefile.bcc - Borland C++
+ Makefile.vc - Microsoft Visual C++
+ Makefile.wcc - Watcom
+
+- Optionally, you can build in a different directory than the platform
+ directory by setting PDCURSES_SRCDIR to point to the directory where
+ you unpacked PDCurses, and changing to your target directory:
+
+ set PDCURSES_SRCDIR=c:\pdcurses
+
+- Build it:
+
+ make -f makefilename
+
+ (For Watcom, use "wmake" instead of "make"; for MSVC, "nmake"; for
+ MinGW, "mingw32-make".) You'll get the library (pdcurses.lib or .a,
+ depending on your compiler) and a lot of object files.
+
+ You can also give the optional parameter "WIDE=Y", to build the
+ library with wide-character (Unicode) support:
+
+ wmake -f Makefile.wcc WIDE=Y
+
+ When built this way, the library is not compatible with Windows 9x,
+ unless you also link with the Microsoft Layer for Unicode (not
+ tested).
+
+ Another option, "UTF8=Y", makes PDCurses ignore the system locale, and
+ treat all narrow-character strings as UTF-8. This option has no effect
+ unless WIDE=Y is also set. Use it to get around the poor support for
+ UTF-8 in the Windows console:
+
+ make -f Makefile.bcc WIDE=Y UTF8=Y
+
+ You can also use the optional parameter "DLL=Y" with Visual C++,
+ MinGW or Cygwin, to build the library as a DLL:
+
+ nmake -f Makefile.vc WIDE=Y DLL=Y
+
+ When you build the library as a Windows DLL, you must always define
+ PDC_DLL_BUILD when linking against it. (Or, if you only want to use
+ the DLL, you could add this definition to your curses.h.)
+
+ Add the target "demos" to build the sample programs.
+
+- If your build stops with errors about PCONSOLE_SCREEN_BUFFER_INFOEX,
+ add the parameter "INFOEX=N" to your make command line and try again.
+ (This will happen with older compile environments.)
+
+
+Distribution Status
+-------------------
+
+The files in this directory are released to the public domain.
+
+
+Acknowledgements
+----------------
+
+Windows console port was originally provided by Chris Szurgot
+<szurgot@itribe.net>
diff --git a/Utilities/cmpdcurses/wincon/pdcclip.c b/Utilities/cmpdcurses/wincon/pdcclip.c
new file mode 100644
index 0000000..7402212
--- /dev/null
+++ b/Utilities/cmpdcurses/wincon/pdcclip.c
@@ -0,0 +1,149 @@
+/* PDCurses */
+
+#include "pdcwin.h"
+
+#include <string.h>
+
+/*man-start**************************************************************
+
+clipboard
+---------
+
+### Synopsis
+
+ int PDC_getclipboard(char **contents, long *length);
+ int PDC_setclipboard(const char *contents, long length);
+ int PDC_freeclipboard(char *contents);
+ int PDC_clearclipboard(void);
+
+### Description
+
+ PDC_getclipboard() gets the textual contents of the system's
+ clipboard. This function returns the contents of the clipboard in the
+ contents argument. It is the responsibility of the caller to free the
+ memory returned, via PDC_freeclipboard(). The length of the clipboard
+ contents is returned in the length argument.
+
+ PDC_setclipboard copies the supplied text into the system's
+ clipboard, emptying the clipboard prior to the copy.
+
+ PDC_clearclipboard() clears the internal clipboard.
+
+### Return Values
+
+ indicator of success/failure of call.
+ PDC_CLIP_SUCCESS the call was successful
+ PDC_CLIP_MEMORY_ERROR unable to allocate sufficient memory for
+ the clipboard contents
+ PDC_CLIP_EMPTY the clipboard contains no text
+ PDC_CLIP_ACCESS_ERROR no clipboard support
+
+### Portability
+ X/Open ncurses NetBSD
+ PDC_getclipboard - - -
+ PDC_setclipboard - - -
+ PDC_freeclipboard - - -
+ PDC_clearclipboard - - -
+
+**man-end****************************************************************/
+
+#ifdef PDC_WIDE
+# define PDC_TEXT CF_UNICODETEXT
+#else
+# define PDC_TEXT CF_OEMTEXT
+#endif
+
+int PDC_getclipboard(char **contents, long *length)
+{
+ HANDLE handle;
+ long len;
+
+ PDC_LOG(("PDC_getclipboard() - called\n"));
+
+ if (!OpenClipboard(NULL))
+ return PDC_CLIP_ACCESS_ERROR;
+
+ if ((handle = GetClipboardData(PDC_TEXT)) == NULL)
+ {
+ CloseClipboard();
+ return PDC_CLIP_EMPTY;
+ }
+
+#ifdef PDC_WIDE
+ len = wcslen((wchar_t *)handle) * 3;
+#else
+ len = strlen((char *)handle);
+#endif
+ *contents = (char *)GlobalAlloc(GMEM_FIXED, len + 1);
+
+ if (!*contents)
+ {
+ CloseClipboard();
+ return PDC_CLIP_MEMORY_ERROR;
+ }
+
+#ifdef PDC_WIDE
+ len = PDC_wcstombs((char *)*contents, (wchar_t *)handle, len);
+#else
+ strcpy((char *)*contents, (char *)handle);
+#endif
+ *length = len;
+ CloseClipboard();
+
+ return PDC_CLIP_SUCCESS;
+}
+
+int PDC_setclipboard(const char *contents, long length)
+{
+ HGLOBAL ptr1;
+ LPTSTR ptr2;
+
+ PDC_LOG(("PDC_setclipboard() - called\n"));
+
+ if (!OpenClipboard(NULL))
+ return PDC_CLIP_ACCESS_ERROR;
+
+ ptr1 = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE,
+ (length + 1) * sizeof(TCHAR));
+
+ if (!ptr1)
+ return PDC_CLIP_MEMORY_ERROR;
+
+ ptr2 = GlobalLock(ptr1);
+
+#ifdef PDC_WIDE
+ PDC_mbstowcs((wchar_t *)ptr2, contents, length);
+#else
+ memcpy((char *)ptr2, contents, length + 1);
+#endif
+ GlobalUnlock(ptr1);
+ EmptyClipboard();
+
+ if (!SetClipboardData(PDC_TEXT, ptr1))
+ {
+ GlobalFree(ptr1);
+ return PDC_CLIP_ACCESS_ERROR;
+ }
+
+ CloseClipboard();
+ GlobalFree(ptr1);
+
+ return PDC_CLIP_SUCCESS;
+}
+
+int PDC_freeclipboard(char *contents)
+{
+ PDC_LOG(("PDC_freeclipboard() - called\n"));
+
+ GlobalFree(contents);
+ return PDC_CLIP_SUCCESS;
+}
+
+int PDC_clearclipboard(void)
+{
+ PDC_LOG(("PDC_clearclipboard() - called\n"));
+
+ EmptyClipboard();
+
+ return PDC_CLIP_SUCCESS;
+}
diff --git a/Utilities/cmpdcurses/wincon/pdcdisp.c b/Utilities/cmpdcurses/wincon/pdcdisp.c
new file mode 100644
index 0000000..fdaec76
--- /dev/null
+++ b/Utilities/cmpdcurses/wincon/pdcdisp.c
@@ -0,0 +1,329 @@
+/* PDCurses */
+
+#include "pdcwin.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef PDC_WIDE
+# include "../common/acsuni.h"
+#else
+# include "../common/acs437.h"
+#endif
+
+DWORD pdc_last_blink;
+static bool blinked_off = FALSE;
+static bool in_italic = FALSE;
+
+/* position hardware cursor at (y, x) */
+
+void PDC_gotoyx(int row, int col)
+{
+ COORD coord;
+
+ PDC_LOG(("PDC_gotoyx() - called: row %d col %d from row %d col %d\n",
+ row, col, SP->cursrow, SP->curscol));
+
+ coord.X = col;
+ coord.Y = row;
+
+ SetConsoleCursorPosition(pdc_con_out, coord);
+}
+
+void _set_ansi_color(short f, short b, attr_t attr)
+{
+ char esc[64], *p;
+ short tmp, underline;
+ bool italic;
+
+ if (f < 16 && !pdc_color[f].mapped)
+ f = pdc_curstoansi[f];
+
+ if (b < 16 && !pdc_color[b].mapped)
+ b = pdc_curstoansi[b];
+
+ if (attr & A_REVERSE)
+ {
+ tmp = f;
+ f = b;
+ b = tmp;
+ }
+ attr &= SP->termattrs;
+ italic = !!(attr & A_ITALIC);
+ underline = !!(attr & A_UNDERLINE);
+
+ p = esc + sprintf(esc, "\x1b[");
+
+ if (f != pdc_oldf)
+ {
+ if (f < 8 && !pdc_color[f].mapped)
+ p += sprintf(p, "%d", f + 30);
+ else if (f < 16 && !pdc_color[f].mapped)
+ p += sprintf(p, "%d", f + 82);
+ else if (f < 256 && !pdc_color[f].mapped)
+ p += sprintf(p, "38;5;%d", f);
+ else
+ {
+ short red = DIVROUND(pdc_color[f].r * 255, 1000);
+ short green = DIVROUND(pdc_color[f].g * 255, 1000);
+ short blue = DIVROUND(pdc_color[f].b * 255, 1000);
+
+ p += sprintf(p, "38;2;%d;%d;%d", red, green, blue);
+ }
+
+ pdc_oldf = f;
+ }
+
+ if (b != pdc_oldb)
+ {
+ if (strlen(esc) > 2)
+ p += sprintf(p, ";");
+
+ if (b < 8 && !pdc_color[b].mapped)
+ p += sprintf(p, "%d", b + 40);
+ else if (b < 16 && !pdc_color[b].mapped)
+ p += sprintf(p, "%d", b + 92);
+ else if (b < 256 && !pdc_color[b].mapped)
+ p += sprintf(p, "48;5;%d", b);
+ else
+ {
+ short red = DIVROUND(pdc_color[b].r * 255, 1000);
+ short green = DIVROUND(pdc_color[b].g * 255, 1000);
+ short blue = DIVROUND(pdc_color[b].b * 255, 1000);
+
+ p += sprintf(p, "48;2;%d;%d;%d", red, green, blue);
+ }
+
+ pdc_oldb = b;
+ }
+
+ if (italic != in_italic)
+ {
+ if (strlen(esc) > 2)
+ p += sprintf(p, ";");
+
+ if (italic)
+ p += sprintf(p, "3");
+ else
+ p += sprintf(p, "23");
+
+ in_italic = italic;
+ }
+
+ if (underline != pdc_oldu)
+ {
+ if (strlen(esc) > 2)
+ p += sprintf(p, ";");
+
+ if (underline)
+ p += sprintf(p, "4");
+ else
+ p += sprintf(p, "24");
+
+ pdc_oldu = underline;
+ }
+
+ if (strlen(esc) > 2)
+ {
+ sprintf(p, "m");
+ if (!pdc_conemu)
+ SetConsoleMode(pdc_con_out, 0x0015);
+
+ WriteConsoleA(pdc_con_out, esc, strlen(esc), NULL, NULL);
+
+ if (!pdc_conemu)
+ SetConsoleMode(pdc_con_out, 0x0010);
+ }
+}
+
+void _new_packet(attr_t attr, int lineno, int x, int len, const chtype *srcp)
+{
+ int j;
+ short fore, back;
+ bool blink, ansi;
+
+ if (pdc_ansi && (lineno == (SP->lines - 1)) && ((x + len) == SP->cols))
+ {
+ len--;
+ if (len)
+ _new_packet(attr, lineno, x, len, srcp);
+ pdc_ansi = FALSE;
+ _new_packet(attr, lineno, x + len, 1, srcp + len);
+ pdc_ansi = TRUE;
+ return;
+ }
+
+ pair_content(PAIR_NUMBER(attr), &fore, &back);
+ ansi = pdc_ansi || (fore >= 16 || back >= 16);
+ blink = (SP->termattrs & A_BLINK) && (attr & A_BLINK);
+
+ if (blink)
+ {
+ attr &= ~A_BLINK;
+ if (blinked_off)
+ attr &= ~(A_UNDERLINE | A_RIGHT | A_LEFT);
+ }
+
+ if (attr & A_BOLD)
+ fore |= 8;
+ if (attr & A_BLINK)
+ back |= 8;
+
+ if (ansi)
+ {
+#ifdef PDC_WIDE
+ WCHAR buffer[512];
+#else
+ char buffer[512];
+#endif
+ for (j = 0; j < len; j++)
+ {
+ chtype ch = srcp[j];
+
+ if (ch & A_ALTCHARSET && !(ch & 0xff80))
+ {
+ ch = acs_map[ch & 0x7f];
+
+ if (pdc_wt && (ch & A_CHARTEXT) < ' ')
+ goto NONANSI;
+ }
+
+ if (blink && blinked_off)
+ ch = ' ';
+
+ buffer[j] = ch & A_CHARTEXT;
+ }
+
+ PDC_gotoyx(lineno, x);
+ _set_ansi_color(fore, back, attr);
+#ifdef PDC_WIDE
+ WriteConsoleW(pdc_con_out, buffer, len, NULL, NULL);
+#else
+ WriteConsoleA(pdc_con_out, buffer, len, NULL, NULL);
+#endif
+ }
+ else
+NONANSI:
+ {
+ CHAR_INFO buffer[512];
+ COORD bufSize, bufPos;
+ SMALL_RECT sr;
+ WORD mapped_attr;
+
+ fore = pdc_curstoreal[fore];
+ back = pdc_curstoreal[back];
+
+ if (attr & A_REVERSE)
+ mapped_attr = back | (fore << 4);
+ else
+ mapped_attr = fore | (back << 4);
+
+ if (attr & A_UNDERLINE)
+ mapped_attr |= 0x8000; /* COMMON_LVB_UNDERSCORE */
+ if (attr & A_LEFT)
+ mapped_attr |= 0x0800; /* COMMON_LVB_GRID_LVERTICAL */
+ if (attr & A_RIGHT)
+ mapped_attr |= 0x1000; /* COMMON_LVB_GRID_RVERTICAL */
+
+ for (j = 0; j < len; j++)
+ {
+ chtype ch = srcp[j];
+
+ if (ch & A_ALTCHARSET && !(ch & 0xff80))
+ ch = acs_map[ch & 0x7f];
+
+ if (blink && blinked_off)
+ ch = ' ';
+
+ buffer[j].Attributes = mapped_attr;
+ buffer[j].Char.UnicodeChar = ch & A_CHARTEXT;
+ }
+
+ bufPos.X = bufPos.Y = 0;
+ bufSize.X = len;
+ bufSize.Y = 1;
+
+ sr.Top = sr.Bottom = lineno;
+ sr.Left = x;
+ sr.Right = x + len - 1;
+
+ WriteConsoleOutput(pdc_con_out, buffer, bufSize, bufPos, &sr);
+ }
+}
+
+/* update the given physical line to look like the corresponding line in
+ curscr */
+
+void PDC_transform_line(int lineno, int x, int len, const chtype *srcp)
+{
+ attr_t old_attr, attr;
+ int i, j;
+
+ PDC_LOG(("PDC_transform_line() - called: lineno=%d\n", lineno));
+
+ old_attr = *srcp & (A_ATTRIBUTES ^ A_ALTCHARSET);
+
+ for (i = 1, j = 1; j < len; i++, j++)
+ {
+ attr = srcp[i] & (A_ATTRIBUTES ^ A_ALTCHARSET);
+
+ if (attr != old_attr)
+ {
+ _new_packet(old_attr, lineno, x, i, srcp);
+ old_attr = attr;
+ srcp += i;
+ x += i;
+ i = 0;
+ }
+ }
+
+ _new_packet(old_attr, lineno, x, i, srcp);
+}
+
+void PDC_blink_text(void)
+{
+ CONSOLE_CURSOR_INFO cci;
+ int i, j, k;
+ bool oldvis;
+
+ GetConsoleCursorInfo(pdc_con_out, &cci);
+ oldvis = cci.bVisible;
+ if (oldvis)
+ {
+ cci.bVisible = FALSE;
+ SetConsoleCursorInfo(pdc_con_out, &cci);
+ }
+
+ if (!(SP->termattrs & A_BLINK))
+ blinked_off = FALSE;
+ else
+ blinked_off = !blinked_off;
+
+ for (i = 0; i < SP->lines; i++)
+ {
+ const chtype *srcp = curscr->_y[i];
+
+ for (j = 0; j < SP->cols; j++)
+ if (srcp[j] & A_BLINK)
+ {
+ k = j;
+ while (k < SP->cols && (srcp[k] & A_BLINK))
+ k++;
+ PDC_transform_line(i, j, k - j, srcp + j);
+ j = k;
+ }
+ }
+
+ PDC_gotoyx(SP->cursrow, SP->curscol);
+ if (oldvis)
+ {
+ cci.bVisible = TRUE;
+ SetConsoleCursorInfo(pdc_con_out, &cci);
+ }
+
+ pdc_last_blink = GetTickCount();
+}
+
+void PDC_doupdate(void)
+{
+}
diff --git a/Utilities/cmpdcurses/wincon/pdcgetsc.c b/Utilities/cmpdcurses/wincon/pdcgetsc.c
new file mode 100644
index 0000000..a8323eb
--- /dev/null
+++ b/Utilities/cmpdcurses/wincon/pdcgetsc.c
@@ -0,0 +1,42 @@
+/* PDCurses */
+
+#include "pdcwin.h"
+
+/* get the cursor size/shape */
+
+int PDC_get_cursor_mode(void)
+{
+ CONSOLE_CURSOR_INFO ci;
+
+ PDC_LOG(("PDC_get_cursor_mode() - called\n"));
+
+ GetConsoleCursorInfo(pdc_con_out, &ci);
+
+ return ci.dwSize;
+}
+
+/* return number of screen rows */
+
+int PDC_get_rows(void)
+{
+ CONSOLE_SCREEN_BUFFER_INFO scr;
+
+ PDC_LOG(("PDC_get_rows() - called\n"));
+
+ GetConsoleScreenBufferInfo(pdc_con_out, &scr);
+
+ return scr.srWindow.Bottom - scr.srWindow.Top + 1;
+}
+
+/* return width of screen/viewport */
+
+int PDC_get_columns(void)
+{
+ CONSOLE_SCREEN_BUFFER_INFO scr;
+
+ PDC_LOG(("PDC_get_columns() - called\n"));
+
+ GetConsoleScreenBufferInfo(pdc_con_out, &scr);
+
+ return scr.srWindow.Right - scr.srWindow.Left + 1;
+}
diff --git a/Utilities/cmpdcurses/wincon/pdckbd.c b/Utilities/cmpdcurses/wincon/pdckbd.c
new file mode 100644
index 0000000..12f30f0
--- /dev/null
+++ b/Utilities/cmpdcurses/wincon/pdckbd.c
@@ -0,0 +1,699 @@
+/* PDCurses */
+
+#include "pdcwin.h"
+
+/* These variables are used to store information about the next
+ Input Event. */
+
+static INPUT_RECORD save_ip;
+static MOUSE_STATUS old_mouse_status;
+static DWORD event_count = 0;
+static SHORT left_key;
+static int key_count = 0;
+static int save_press = 0;
+
+#define KEV save_ip.Event.KeyEvent
+#define MEV save_ip.Event.MouseEvent
+#define REV save_ip.Event.WindowBufferSizeEvent
+
+/************************************************************************
+ * Table for key code translation of function keys in keypad mode *
+ * These values are for strict IBM keyboard compatibles only *
+ ************************************************************************/
+
+typedef struct
+{
+ unsigned short normal;
+ unsigned short shift;
+ unsigned short control;
+ unsigned short alt;
+ unsigned short extended;
+} KPTAB;
+
+static KPTAB kptab[] =
+{
+ {0, 0, 0, 0, 0 }, /* 0 */
+ {0, 0, 0, 0, 0 }, /* 1 VK_LBUTTON */
+ {0, 0, 0, 0, 0 }, /* 2 VK_RBUTTON */
+ {0, 0, 0, 0, 0 }, /* 3 VK_CANCEL */
+ {0, 0, 0, 0, 0 }, /* 4 VK_MBUTTON */
+ {0, 0, 0, 0, 0 }, /* 5 */
+ {0, 0, 0, 0, 0 }, /* 6 */
+ {0, 0, 0, 0, 0 }, /* 7 */
+ {0x08, 0x08, 0x7F, ALT_BKSP, 0 }, /* 8 VK_BACK */
+ {0x09, KEY_BTAB, CTL_TAB, ALT_TAB, 999 }, /* 9 VK_TAB */
+ {0, 0, 0, 0, 0 }, /* 10 */
+ {0, 0, 0, 0, 0 }, /* 11 */
+ {KEY_B2, 0x35, CTL_PAD5, ALT_PAD5, 0 }, /* 12 VK_CLEAR */
+ {0x0D, 0x0D, CTL_ENTER, ALT_ENTER, 1 }, /* 13 VK_RETURN */
+ {0, 0, 0, 0, 0 }, /* 14 */
+ {0, 0, 0, 0, 0 }, /* 15 */
+ {0, 0, 0, 0, 0 }, /* 16 VK_SHIFT HANDLED SEPARATELY */
+ {0, 0, 0, 0, 0 }, /* 17 VK_CONTROL HANDLED SEPARATELY */
+ {0, 0, 0, 0, 0 }, /* 18 VK_MENU HANDLED SEPARATELY */
+ {0, 0, 0, 0, 0 }, /* 19 VK_PAUSE */
+ {0, 0, 0, 0, 0 }, /* 20 VK_CAPITAL HANDLED SEPARATELY */
+ {0, 0, 0, 0, 0 }, /* 21 VK_HANGUL */
+ {0, 0, 0, 0, 0 }, /* 22 */
+ {0, 0, 0, 0, 0 }, /* 23 VK_JUNJA */
+ {0, 0, 0, 0, 0 }, /* 24 VK_FINAL */
+ {0, 0, 0, 0, 0 }, /* 25 VK_HANJA */
+ {0, 0, 0, 0, 0 }, /* 26 */
+ {0x1B, 0x1B, 0x1B, ALT_ESC, 0 }, /* 27 VK_ESCAPE */
+ {0, 0, 0, 0, 0 }, /* 28 VK_CONVERT */
+ {0, 0, 0, 0, 0 }, /* 29 VK_NONCONVERT */
+ {0, 0, 0, 0, 0 }, /* 30 VK_ACCEPT */
+ {0, 0, 0, 0, 0 }, /* 31 VK_MODECHANGE */
+ {0x20, 0x20, 0x20, 0x20, 0 }, /* 32 VK_SPACE */
+ {KEY_A3, 0x39, CTL_PAD9, ALT_PAD9, 3 }, /* 33 VK_PRIOR */
+ {KEY_C3, 0x33, CTL_PAD3, ALT_PAD3, 4 }, /* 34 VK_NEXT */
+ {KEY_C1, 0x31, CTL_PAD1, ALT_PAD1, 5 }, /* 35 VK_END */
+ {KEY_A1, 0x37, CTL_PAD7, ALT_PAD7, 6 }, /* 36 VK_HOME */
+ {KEY_B1, 0x34, CTL_PAD4, ALT_PAD4, 7 }, /* 37 VK_LEFT */
+ {KEY_A2, 0x38, CTL_PAD8, ALT_PAD8, 8 }, /* 38 VK_UP */
+ {KEY_B3, 0x36, CTL_PAD6, ALT_PAD6, 9 }, /* 39 VK_RIGHT */
+ {KEY_C2, 0x32, CTL_PAD2, ALT_PAD2, 10 }, /* 40 VK_DOWN */
+ {0, 0, 0, 0, 0 }, /* 41 VK_SELECT */
+ {0, 0, 0, 0, 0 }, /* 42 VK_PRINT */
+ {0, 0, 0, 0, 0 }, /* 43 VK_EXECUTE */
+ {0, 0, 0, 0, 0 }, /* 44 VK_SNAPSHOT*/
+ {PAD0, 0x30, CTL_PAD0, ALT_PAD0, 11 }, /* 45 VK_INSERT */
+ {PADSTOP, 0x2E, CTL_PADSTOP, ALT_PADSTOP,12 }, /* 46 VK_DELETE */
+ {0, 0, 0, 0, 0 }, /* 47 VK_HELP */
+ {0x30, 0x29, 0, ALT_0, 0 }, /* 48 */
+ {0x31, 0x21, 0, ALT_1, 0 }, /* 49 */
+ {0x32, 0x40, 0, ALT_2, 0 }, /* 50 */
+ {0x33, 0x23, 0, ALT_3, 0 }, /* 51 */
+ {0x34, 0x24, 0, ALT_4, 0 }, /* 52 */
+ {0x35, 0x25, 0, ALT_5, 0 }, /* 53 */
+ {0x36, 0x5E, 0, ALT_6, 0 }, /* 54 */
+ {0x37, 0x26, 0, ALT_7, 0 }, /* 55 */
+ {0x38, 0x2A, 0, ALT_8, 0 }, /* 56 */
+ {0x39, 0x28, 0, ALT_9, 0 }, /* 57 */
+ {0, 0, 0, 0, 0 }, /* 58 */
+ {0, 0, 0, 0, 0 }, /* 59 */
+ {0, 0, 0, 0, 0 }, /* 60 */
+ {0, 0, 0, 0, 0 }, /* 61 */
+ {0, 0, 0, 0, 0 }, /* 62 */
+ {0, 0, 0, 0, 0 }, /* 63 */
+ {0, 0, 0, 0, 0 }, /* 64 */
+ {0x61, 0x41, 0x01, ALT_A, 0 }, /* 65 */
+ {0x62, 0x42, 0x02, ALT_B, 0 }, /* 66 */
+ {0x63, 0x43, 0x03, ALT_C, 0 }, /* 67 */
+ {0x64, 0x44, 0x04, ALT_D, 0 }, /* 68 */
+ {0x65, 0x45, 0x05, ALT_E, 0 }, /* 69 */
+ {0x66, 0x46, 0x06, ALT_F, 0 }, /* 70 */
+ {0x67, 0x47, 0x07, ALT_G, 0 }, /* 71 */
+ {0x68, 0x48, 0x08, ALT_H, 0 }, /* 72 */
+ {0x69, 0x49, 0x09, ALT_I, 0 }, /* 73 */
+ {0x6A, 0x4A, 0x0A, ALT_J, 0 }, /* 74 */
+ {0x6B, 0x4B, 0x0B, ALT_K, 0 }, /* 75 */
+ {0x6C, 0x4C, 0x0C, ALT_L, 0 }, /* 76 */
+ {0x6D, 0x4D, 0x0D, ALT_M, 0 }, /* 77 */
+ {0x6E, 0x4E, 0x0E, ALT_N, 0 }, /* 78 */
+ {0x6F, 0x4F, 0x0F, ALT_O, 0 }, /* 79 */
+ {0x70, 0x50, 0x10, ALT_P, 0 }, /* 80 */
+ {0x71, 0x51, 0x11, ALT_Q, 0 }, /* 81 */
+ {0x72, 0x52, 0x12, ALT_R, 0 }, /* 82 */
+ {0x73, 0x53, 0x13, ALT_S, 0 }, /* 83 */
+ {0x74, 0x54, 0x14, ALT_T, 0 }, /* 84 */
+ {0x75, 0x55, 0x15, ALT_U, 0 }, /* 85 */
+ {0x76, 0x56, 0x16, ALT_V, 0 }, /* 86 */
+ {0x77, 0x57, 0x17, ALT_W, 0 }, /* 87 */
+ {0x78, 0x58, 0x18, ALT_X, 0 }, /* 88 */
+ {0x79, 0x59, 0x19, ALT_Y, 0 }, /* 89 */
+ {0x7A, 0x5A, 0x1A, ALT_Z, 0 }, /* 90 */
+ {0, 0, 0, 0, 0 }, /* 91 VK_LWIN */
+ {0, 0, 0, 0, 0 }, /* 92 VK_RWIN */
+ {0, 0, 0, 0, 0 }, /* 93 VK_APPS */
+ {0, 0, 0, 0, 0 }, /* 94 */
+ {0, 0, 0, 0, 0 }, /* 95 */
+ {0x30, 0, CTL_PAD0, ALT_PAD0, 0 }, /* 96 VK_NUMPAD0 */
+ {0x31, 0, CTL_PAD1, ALT_PAD1, 0 }, /* 97 VK_NUMPAD1 */
+ {0x32, 0, CTL_PAD2, ALT_PAD2, 0 }, /* 98 VK_NUMPAD2 */
+ {0x33, 0, CTL_PAD3, ALT_PAD3, 0 }, /* 99 VK_NUMPAD3 */
+ {0x34, 0, CTL_PAD4, ALT_PAD4, 0 }, /* 100 VK_NUMPAD4 */
+ {0x35, 0, CTL_PAD5, ALT_PAD5, 0 }, /* 101 VK_NUMPAD5 */
+ {0x36, 0, CTL_PAD6, ALT_PAD6, 0 }, /* 102 VK_NUMPAD6 */
+ {0x37, 0, CTL_PAD7, ALT_PAD7, 0 }, /* 103 VK_NUMPAD7 */
+ {0x38, 0, CTL_PAD8, ALT_PAD8, 0 }, /* 104 VK_NUMPAD8 */
+ {0x39, 0, CTL_PAD9, ALT_PAD9, 0 }, /* 105 VK_NUMPAD9 */
+ {PADSTAR, SHF_PADSTAR,CTL_PADSTAR, ALT_PADSTAR,999 }, /* 106 VK_MULTIPLY*/
+ {PADPLUS, SHF_PADPLUS,CTL_PADPLUS, ALT_PADPLUS,999 }, /* 107 VK_ADD */
+ {0, 0, 0, 0, 0 }, /* 108 VK_SEPARATOR */
+ {PADMINUS, SHF_PADMINUS,CTL_PADMINUS,ALT_PADMINUS,999}, /* 109 VK_SUBTRACT*/
+ {0x2E, 0, CTL_PADSTOP, ALT_PADSTOP,0 }, /* 110 VK_DECIMAL */
+ {PADSLASH, SHF_PADSLASH,CTL_PADSLASH,ALT_PADSLASH,2 }, /* 111 VK_DIVIDE */
+ {KEY_F(1), KEY_F(13), KEY_F(25), KEY_F(37), 0 }, /* 112 VK_F1 */
+ {KEY_F(2), KEY_F(14), KEY_F(26), KEY_F(38), 0 }, /* 113 VK_F2 */
+ {KEY_F(3), KEY_F(15), KEY_F(27), KEY_F(39), 0 }, /* 114 VK_F3 */
+ {KEY_F(4), KEY_F(16), KEY_F(28), KEY_F(40), 0 }, /* 115 VK_F4 */
+ {KEY_F(5), KEY_F(17), KEY_F(29), KEY_F(41), 0 }, /* 116 VK_F5 */
+ {KEY_F(6), KEY_F(18), KEY_F(30), KEY_F(42), 0 }, /* 117 VK_F6 */
+ {KEY_F(7), KEY_F(19), KEY_F(31), KEY_F(43), 0 }, /* 118 VK_F7 */
+ {KEY_F(8), KEY_F(20), KEY_F(32), KEY_F(44), 0 }, /* 119 VK_F8 */
+ {KEY_F(9), KEY_F(21), KEY_F(33), KEY_F(45), 0 }, /* 120 VK_F9 */
+ {KEY_F(10), KEY_F(22), KEY_F(34), KEY_F(46), 0 }, /* 121 VK_F10 */
+ {KEY_F(11), KEY_F(23), KEY_F(35), KEY_F(47), 0 }, /* 122 VK_F11 */
+ {KEY_F(12), KEY_F(24), KEY_F(36), KEY_F(48), 0 }, /* 123 VK_F12 */
+
+ /* 124 through 218 */
+
+ {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
+
+ {0x5B, 0x7B, 0x1B, ALT_LBRACKET,0 }, /* 219 */
+ {0x5C, 0x7C, 0x1C, ALT_BSLASH, 0 }, /* 220 */
+ {0x5D, 0x7D, 0x1D, ALT_RBRACKET,0 }, /* 221 */
+ {0, 0, 0x27, ALT_FQUOTE, 0 }, /* 222 */
+ {0, 0, 0, 0, 0 }, /* 223 */
+ {0, 0, 0, 0, 0 }, /* 224 */
+ {0, 0, 0, 0, 0 }, /* 225 */
+ {0, 0, 0, 0, 0 }, /* 226 */
+ {0, 0, 0, 0, 0 }, /* 227 */
+ {0, 0, 0, 0, 0 }, /* 228 */
+ {0, 0, 0, 0, 0 }, /* 229 */
+ {0, 0, 0, 0, 0 }, /* 230 */
+ {0, 0, 0, 0, 0 }, /* 231 */
+ {0, 0, 0, 0, 0 }, /* 232 */
+ {0, 0, 0, 0, 0 }, /* 233 */
+ {0, 0, 0, 0, 0 }, /* 234 */
+ {0, 0, 0, 0, 0 }, /* 235 */
+ {0, 0, 0, 0, 0 }, /* 236 */
+ {0, 0, 0, 0, 0 }, /* 237 */
+ {0, 0, 0, 0, 0 }, /* 238 */
+ {0, 0, 0, 0, 0 }, /* 239 */
+ {0, 0, 0, 0, 0 }, /* 240 */
+ {0, 0, 0, 0, 0 }, /* 241 */
+ {0, 0, 0, 0, 0 }, /* 242 */
+ {0, 0, 0, 0, 0 }, /* 243 */
+ {0, 0, 0, 0, 0 }, /* 244 */
+ {0, 0, 0, 0, 0 }, /* 245 */
+ {0, 0, 0, 0, 0 }, /* 246 */
+ {0, 0, 0, 0, 0 }, /* 247 */
+ {0, 0, 0, 0, 0 }, /* 248 */
+ {0, 0, 0, 0, 0 }, /* 249 */
+ {0, 0, 0, 0, 0 }, /* 250 */
+ {0, 0, 0, 0, 0 }, /* 251 */
+ {0, 0, 0, 0, 0 }, /* 252 */
+ {0, 0, 0, 0, 0 }, /* 253 */
+ {0, 0, 0, 0, 0 }, /* 254 */
+ {0, 0, 0, 0, 0 } /* 255 */
+};
+
+static KPTAB ext_kptab[] =
+{
+ {0, 0, 0, 0, }, /* MUST BE EMPTY */
+ {PADENTER, SHF_PADENTER, CTL_PADENTER, ALT_PADENTER}, /* 13 */
+ {PADSLASH, SHF_PADSLASH, CTL_PADSLASH, ALT_PADSLASH}, /* 111 */
+ {KEY_PPAGE, KEY_SPREVIOUS, CTL_PGUP, ALT_PGUP }, /* 33 */
+ {KEY_NPAGE, KEY_SNEXT, CTL_PGDN, ALT_PGDN }, /* 34 */
+ {KEY_END, KEY_SEND, CTL_END, ALT_END }, /* 35 */
+ {KEY_HOME, KEY_SHOME, CTL_HOME, ALT_HOME }, /* 36 */
+ {KEY_LEFT, KEY_SLEFT, CTL_LEFT, ALT_LEFT }, /* 37 */
+ {KEY_UP, KEY_SUP, CTL_UP, ALT_UP }, /* 38 */
+ {KEY_RIGHT, KEY_SRIGHT, CTL_RIGHT, ALT_RIGHT }, /* 39 */
+ {KEY_DOWN, KEY_SDOWN, CTL_DOWN, ALT_DOWN }, /* 40 */
+ {KEY_IC, KEY_SIC, CTL_INS, ALT_INS }, /* 45 */
+ {KEY_DC, KEY_SDC, CTL_DEL, ALT_DEL }, /* 46 */
+ {PADSLASH, SHF_PADSLASH, CTL_PADSLASH, ALT_PADSLASH}, /* 191 */
+};
+
+/* End of kptab[] */
+
+void PDC_set_keyboard_binary(bool on)
+{
+ DWORD mode;
+
+ PDC_LOG(("PDC_set_keyboard_binary() - called\n"));
+
+ GetConsoleMode(pdc_con_in, &mode);
+ SetConsoleMode(pdc_con_in, !on ? (mode | ENABLE_PROCESSED_INPUT) :
+ (mode & ~ENABLE_PROCESSED_INPUT));
+}
+
+/* check if a key or mouse event is waiting */
+
+bool PDC_check_key(void)
+{
+ if (key_count > 0)
+ return TRUE;
+
+ GetNumberOfConsoleInputEvents(pdc_con_in, &event_count);
+
+ return (event_count != 0);
+}
+
+/* _get_key_count returns 0 if save_ip doesn't contain an event which
+ should be passed back to the user. This function filters "useless"
+ events.
+
+ The function returns the number of keys waiting. This may be > 1
+ if the repetition of real keys pressed so far are > 1.
+
+ Returns 0 on NUMLOCK, CAPSLOCK, SCROLLLOCK.
+
+ Returns 1 for SHIFT, ALT, CTRL only if no other key has been pressed
+ in between, and SP->return_key_modifiers is set; these are returned
+ on keyup.
+
+ Normal keys are returned on keydown only. The number of repetitions
+ are returned. Dead keys (diacritics) are omitted. See below for a
+ description.
+*/
+
+static int _get_key_count(void)
+{
+ int num_keys = 0, vk;
+
+ PDC_LOG(("_get_key_count() - called\n"));
+
+ vk = KEV.wVirtualKeyCode;
+
+ if (KEV.bKeyDown)
+ {
+ /* key down */
+
+ save_press = 0;
+
+ if (vk == VK_CAPITAL || vk == VK_NUMLOCK || vk == VK_SCROLL)
+ {
+ /* throw away these modifiers */
+ }
+ else if (vk == VK_SHIFT || vk == VK_CONTROL || vk == VK_MENU)
+ {
+ /* These keys are returned on keyup only. */
+
+ save_press = vk;
+ switch (vk)
+ {
+ case VK_SHIFT:
+ left_key = GetKeyState(VK_LSHIFT);
+ break;
+ case VK_CONTROL:
+ left_key = GetKeyState(VK_LCONTROL);
+ break;
+ case VK_MENU:
+ left_key = GetKeyState(VK_LMENU);
+ }
+ }
+ else
+ {
+ /* Check for diacritics. These are dead keys. Some locales
+ have modified characters like umlaut-a, which is an "a"
+ with two dots on it. In some locales you have to press a
+ special key (the dead key) immediately followed by the
+ "a" to get a composed umlaut-a. The special key may have
+ a normal meaning with different modifiers. */
+
+ if (KEV.uChar.UnicodeChar || !(MapVirtualKey(vk, 2) & 0x80000000))
+ num_keys = KEV.wRepeatCount;
+ }
+ }
+ else
+ {
+ /* key up */
+
+ /* Only modifier keys or the results of ALT-numpad entry are
+ returned on keyup */
+
+ if ((vk == VK_MENU && KEV.uChar.UnicodeChar) ||
+ ((vk == VK_SHIFT || vk == VK_CONTROL || vk == VK_MENU) &&
+ vk == save_press))
+ {
+ save_press = 0;
+ num_keys = 1;
+ }
+ }
+
+ PDC_LOG(("_get_key_count() - returning: num_keys %d\n", num_keys));
+
+ return num_keys;
+}
+
+/* _process_key_event returns -1 if the key in save_ip should be
+ ignored. Otherwise it returns the keycode which should be returned
+ by PDC_get_key(). save_ip must be a key event.
+
+ CTRL-ALT support has been disabled, when is it emitted plainly? */
+
+static int _process_key_event(void)
+{
+ int key =
+#ifdef PDC_WIDE
+ KEV.uChar.UnicodeChar;
+#else
+ KEV.uChar.AsciiChar;
+#endif
+ WORD vk = KEV.wVirtualKeyCode;
+ DWORD state = KEV.dwControlKeyState;
+
+ int idx;
+ BOOL enhanced;
+
+ SP->key_code = TRUE;
+
+ /* Save the key modifiers. Do this first to allow to detect e.g. a
+ pressed CTRL key after a hit of NUMLOCK. */
+
+ if (state & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED))
+ SP->key_modifiers |= PDC_KEY_MODIFIER_ALT;
+
+ if (state & SHIFT_PRESSED)
+ SP->key_modifiers |= PDC_KEY_MODIFIER_SHIFT;
+
+ if (state & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED))
+ SP->key_modifiers |= PDC_KEY_MODIFIER_CONTROL;
+
+ if (state & NUMLOCK_ON)
+ SP->key_modifiers |= PDC_KEY_MODIFIER_NUMLOCK;
+
+ /* Handle modifier keys hit by themselves */
+
+ switch (vk)
+ {
+ case VK_SHIFT: /* shift */
+ if (!SP->return_key_modifiers)
+ return -1;
+
+ return (left_key & 0x8000) ? KEY_SHIFT_L : KEY_SHIFT_R;
+
+ case VK_CONTROL: /* control */
+ if (!SP->return_key_modifiers)
+ return -1;
+
+ return (left_key & 0x8000) ? KEY_CONTROL_L : KEY_CONTROL_R;
+
+ case VK_MENU: /* alt */
+ if (!key)
+ {
+ if (!SP->return_key_modifiers)
+ return -1;
+
+ return (left_key & 0x8000) ? KEY_ALT_L : KEY_ALT_R;
+ }
+ }
+
+ /* The system may emit Ascii or Unicode characters depending on
+ whether ReadConsoleInputA or ReadConsoleInputW is used.
+
+ Normally, if key != 0 then the system did the translation
+ successfully. But this is not true for LEFT_ALT (different to
+ RIGHT_ALT). In case of LEFT_ALT we can get key != 0. So
+ check for this first. */
+
+ if (key && ( !(state & LEFT_ALT_PRESSED) ||
+ (state & RIGHT_ALT_PRESSED) ))
+ {
+ /* This code should catch all keys returning a printable
+ character. Characters above 0x7F should be returned as
+ positive codes. */
+
+ if (kptab[vk].extended == 0)
+ {
+ SP->key_code = FALSE;
+ return key;
+ }
+ }
+
+ /* This case happens if a functional key has been entered. */
+
+ if ((state & ENHANCED_KEY) && (kptab[vk].extended != 999))
+ {
+ enhanced = TRUE;
+ idx = kptab[vk].extended;
+ }
+ else
+ {
+ enhanced = FALSE;
+ idx = vk;
+ }
+
+ if (state & SHIFT_PRESSED)
+ key = enhanced ? ext_kptab[idx].shift : kptab[idx].shift;
+
+ else if (state & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED))
+ key = enhanced ? ext_kptab[idx].control : kptab[idx].control;
+
+ else if (state & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED))
+ key = enhanced ? ext_kptab[idx].alt : kptab[idx].alt;
+
+ else
+ key = enhanced ? ext_kptab[idx].normal : kptab[idx].normal;
+
+ if (key < KEY_CODE_YES)
+ SP->key_code = FALSE;
+
+ return key;
+}
+
+static int _process_mouse_event(void)
+{
+ static const DWORD button_mask[] = {1, 4, 2};
+ short action, shift_flags = 0;
+ int i;
+
+ save_press = 0;
+ SP->key_code = TRUE;
+
+ memset(&SP->mouse_status, 0, sizeof(MOUSE_STATUS));
+
+ /* Handle scroll wheel */
+
+ if (MEV.dwEventFlags == 4)
+ {
+ SP->mouse_status.changes = (MEV.dwButtonState & 0xFF000000) ?
+ PDC_MOUSE_WHEEL_DOWN : PDC_MOUSE_WHEEL_UP;
+
+ SP->mouse_status.x = -1;
+ SP->mouse_status.y = -1;
+
+ memset(&old_mouse_status, 0, sizeof(old_mouse_status));
+
+ return KEY_MOUSE;
+ }
+
+ if (MEV.dwEventFlags == 8)
+ {
+ SP->mouse_status.changes = (MEV.dwButtonState & 0xFF000000) ?
+ PDC_MOUSE_WHEEL_RIGHT : PDC_MOUSE_WHEEL_LEFT;
+
+ SP->mouse_status.x = -1;
+ SP->mouse_status.y = -1;
+
+ memset(&old_mouse_status, 0, sizeof(old_mouse_status));
+
+ return KEY_MOUSE;
+ }
+
+ action = (MEV.dwEventFlags == 2) ? BUTTON_DOUBLE_CLICKED :
+ ((MEV.dwEventFlags == 1) ? BUTTON_MOVED : BUTTON_PRESSED);
+
+ for (i = 0; i < 3; i++)
+ SP->mouse_status.button[i] =
+ (MEV.dwButtonState & button_mask[i]) ? action : 0;
+
+ if (action == BUTTON_PRESSED && MEV.dwButtonState & 7 && SP->mouse_wait)
+ {
+ /* Check for a click -- a PRESS followed immediately by a release */
+
+ if (!event_count)
+ {
+ napms(SP->mouse_wait);
+
+ GetNumberOfConsoleInputEvents(pdc_con_in, &event_count);
+ }
+
+ if (event_count)
+ {
+ INPUT_RECORD ip;
+ DWORD count;
+ bool have_click = FALSE;
+
+ PeekConsoleInput(pdc_con_in, &ip, 1, &count);
+
+ for (i = 0; i < 3; i++)
+ {
+ if (SP->mouse_status.button[i] == BUTTON_PRESSED &&
+ !(ip.Event.MouseEvent.dwButtonState & button_mask[i]))
+ {
+ SP->mouse_status.button[i] = BUTTON_CLICKED;
+ have_click = TRUE;
+ }
+ }
+
+ /* If a click was found, throw out the event */
+
+ if (have_click)
+ ReadConsoleInput(pdc_con_in, &ip, 1, &count);
+ }
+ }
+
+ SP->mouse_status.x = MEV.dwMousePosition.X;
+ SP->mouse_status.y = MEV.dwMousePosition.Y;
+
+ SP->mouse_status.changes = 0;
+
+ for (i = 0; i < 3; i++)
+ {
+ if (old_mouse_status.button[i] != SP->mouse_status.button[i])
+ SP->mouse_status.changes |= (1 << i);
+
+ if (SP->mouse_status.button[i] == BUTTON_MOVED)
+ {
+ /* Discard non-moved "moves" */
+
+ if (SP->mouse_status.x == old_mouse_status.x &&
+ SP->mouse_status.y == old_mouse_status.y)
+ return -1;
+
+ /* Motion events always flag the button as changed */
+
+ SP->mouse_status.changes |= (1 << i);
+ SP->mouse_status.changes |= PDC_MOUSE_MOVED;
+ break;
+ }
+ }
+
+ old_mouse_status = SP->mouse_status;
+
+ /* Treat click events as release events for comparison purposes */
+
+ for (i = 0; i < 3; i++)
+ {
+ if (old_mouse_status.button[i] == BUTTON_CLICKED ||
+ old_mouse_status.button[i] == BUTTON_DOUBLE_CLICKED)
+ old_mouse_status.button[i] = BUTTON_RELEASED;
+ }
+
+ /* Check for SHIFT/CONTROL/ALT */
+
+ if (MEV.dwControlKeyState & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED))
+ shift_flags |= BUTTON_ALT;
+
+ if (MEV.dwControlKeyState & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED))
+ shift_flags |= BUTTON_CONTROL;
+
+ if (MEV.dwControlKeyState & SHIFT_PRESSED)
+ shift_flags |= BUTTON_SHIFT;
+
+ if (shift_flags)
+ {
+ for (i = 0; i < 3; i++)
+ {
+ if (SP->mouse_status.changes & (1 << i))
+ SP->mouse_status.button[i] |= shift_flags;
+ }
+ }
+
+ return KEY_MOUSE;
+}
+
+/* return the next available key or mouse event */
+
+int PDC_get_key(void)
+{
+ SP->key_modifiers = 0L;
+
+ if (!key_count)
+ {
+ DWORD count;
+
+ ReadConsoleInput(pdc_con_in, &save_ip, 1, &count);
+ event_count--;
+
+ if (save_ip.EventType == MOUSE_EVENT ||
+ save_ip.EventType == WINDOW_BUFFER_SIZE_EVENT)
+ key_count = 1;
+ else if (save_ip.EventType == KEY_EVENT)
+ key_count = _get_key_count();
+ }
+
+ if (key_count)
+ {
+ key_count--;
+
+ switch (save_ip.EventType)
+ {
+ case KEY_EVENT:
+ return _process_key_event();
+
+ case MOUSE_EVENT:
+ return _process_mouse_event();
+
+ case WINDOW_BUFFER_SIZE_EVENT:
+ if (REV.dwSize.Y != LINES || REV.dwSize.X != COLS)
+ {
+ if (!SP->resized)
+ {
+ SP->resized = TRUE;
+ SP->key_code = TRUE;
+ return KEY_RESIZE;
+ }
+ }
+ }
+ }
+
+ return -1;
+}
+
+/* discard any pending keyboard or mouse input -- this is the core
+ routine for flushinp() */
+
+void PDC_flushinp(void)
+{
+ PDC_LOG(("PDC_flushinp() - called\n"));
+
+ FlushConsoleInputBuffer(pdc_con_in);
+}
+
+bool PDC_has_mouse(void)
+{
+ return TRUE;
+}
+
+int PDC_mouse_set(void)
+{
+ DWORD mode;
+
+ /* If turning on mouse input: Set ENABLE_MOUSE_INPUT, and clear
+ all other flags, except processed input mode;
+ If turning off the mouse: Set QuickEdit Mode to the status it
+ had on startup, and clear all other flags, except etc. */
+
+ GetConsoleMode(pdc_con_in, &mode);
+ mode = (mode & 1) | 0x0088;
+ SetConsoleMode(pdc_con_in, mode | (SP->_trap_mbe ?
+ ENABLE_MOUSE_INPUT : pdc_quick_edit));
+
+ memset(&old_mouse_status, 0, sizeof(old_mouse_status));
+
+ return OK;
+}
+
+int PDC_modifiers_set(void)
+{
+ return OK;
+}
diff --git a/Utilities/cmpdcurses/wincon/pdcscrn.c b/Utilities/cmpdcurses/wincon/pdcscrn.c
new file mode 100644
index 0000000..e2f4ddd
--- /dev/null
+++ b/Utilities/cmpdcurses/wincon/pdcscrn.c
@@ -0,0 +1,686 @@
+/* PDCurses */
+
+#include "pdcwin.h"
+
+#include <stdlib.h>
+
+/* Color component table */
+
+PDCCOLOR pdc_color[PDC_MAXCOL];
+
+HANDLE std_con_out = INVALID_HANDLE_VALUE;
+HANDLE pdc_con_out = INVALID_HANDLE_VALUE;
+HANDLE pdc_con_in = INVALID_HANDLE_VALUE;
+
+DWORD pdc_quick_edit;
+
+static short realtocurs[16] =
+{
+ COLOR_BLACK, COLOR_BLUE, COLOR_GREEN, COLOR_CYAN, COLOR_RED,
+ COLOR_MAGENTA, COLOR_YELLOW, COLOR_WHITE, COLOR_BLACK + 8,
+ COLOR_BLUE + 8, COLOR_GREEN + 8, COLOR_CYAN + 8, COLOR_RED + 8,
+ COLOR_MAGENTA + 8, COLOR_YELLOW + 8, COLOR_WHITE + 8
+};
+
+static short ansitocurs[16] =
+{
+ COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE,
+ COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE, COLOR_BLACK + 8,
+ COLOR_RED + 8, COLOR_GREEN + 8, COLOR_YELLOW + 8, COLOR_BLUE + 8,
+ COLOR_MAGENTA + 8, COLOR_CYAN + 8, COLOR_WHITE + 8
+};
+
+short pdc_curstoreal[16], pdc_curstoansi[16];
+short pdc_oldf, pdc_oldb, pdc_oldu;
+bool pdc_conemu, pdc_wt, pdc_ansi;
+
+enum { PDC_RESTORE_NONE, PDC_RESTORE_BUFFER };
+
+/* Struct for storing console registry keys, and for use with the
+ undocumented WM_SETCONSOLEINFO message. Originally by James Brown,
+ www.catch22.net. */
+
+static struct
+{
+ ULONG Length;
+ COORD ScreenBufferSize;
+ COORD WindowSize;
+ ULONG WindowPosX;
+ ULONG WindowPosY;
+
+ COORD FontSize;
+ ULONG FontFamily;
+ ULONG FontWeight;
+ WCHAR FaceName[32];
+
+ ULONG CursorSize;
+ ULONG FullScreen;
+ ULONG QuickEdit;
+ ULONG AutoPosition;
+ ULONG InsertMode;
+
+ USHORT ScreenColors;
+ USHORT PopupColors;
+ ULONG HistoryNoDup;
+ ULONG HistoryBufferSize;
+ ULONG NumberOfHistoryBuffers;
+
+ COLORREF ColorTable[16];
+
+ ULONG CodePage;
+ HWND Hwnd;
+
+ WCHAR ConsoleTitle[0x100];
+} console_info;
+
+#ifdef HAVE_NO_INFOEX
+/* Console screen buffer information (extended version) */
+typedef struct _CONSOLE_SCREEN_BUFFER_INFOEX {
+ ULONG cbSize;
+ COORD dwSize;
+ COORD dwCursorPosition;
+ WORD wAttributes;
+ SMALL_RECT srWindow;
+ COORD dwMaximumWindowSize;
+ WORD wPopupAttributes;
+ BOOL bFullscreenSupported;
+ COLORREF ColorTable[16];
+} CONSOLE_SCREEN_BUFFER_INFOEX;
+typedef CONSOLE_SCREEN_BUFFER_INFOEX *PCONSOLE_SCREEN_BUFFER_INFOEX;
+#endif
+
+typedef BOOL (WINAPI *SetConsoleScreenBufferInfoExFn)(HANDLE hConsoleOutput,
+ PCONSOLE_SCREEN_BUFFER_INFOEX lpConsoleScreenBufferInfoEx);
+typedef BOOL (WINAPI *GetConsoleScreenBufferInfoExFn)(HANDLE hConsoleOutput,
+ PCONSOLE_SCREEN_BUFFER_INFOEX lpConsoleScreenBufferInfoEx);
+
+static SetConsoleScreenBufferInfoExFn pSetConsoleScreenBufferInfoEx = NULL;
+static GetConsoleScreenBufferInfoExFn pGetConsoleScreenBufferInfoEx = NULL;
+
+static CONSOLE_SCREEN_BUFFER_INFO orig_scr;
+static CONSOLE_SCREEN_BUFFER_INFOEX console_infoex;
+
+static LPTOP_LEVEL_EXCEPTION_FILTER xcpt_filter;
+
+static DWORD old_console_mode = 0;
+
+static bool is_nt;
+
+static void _reset_old_colors(void)
+{
+ pdc_oldf = -1;
+ pdc_oldb = -1;
+ pdc_oldu = 0;
+}
+
+static HWND _find_console_handle(void)
+{
+ TCHAR orgtitle[1024], temptitle[1024];
+ HWND wnd;
+
+ GetConsoleTitle(orgtitle, 1024);
+
+ wsprintf(temptitle, TEXT("%d/%d"), GetTickCount(), GetCurrentProcessId());
+ SetConsoleTitle(temptitle);
+
+ Sleep(40);
+
+ wnd = FindWindow(NULL, temptitle);
+
+ SetConsoleTitle(orgtitle);
+
+ return wnd;
+}
+
+/* Undocumented console message */
+
+#define WM_SETCONSOLEINFO (WM_USER + 201)
+
+/* Wrapper around WM_SETCONSOLEINFO. We need to create the necessary
+ section (file-mapping) object in the context of the process which
+ owns the console, before posting the message. Originally by JB. */
+
+static void _set_console_info(void)
+{
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ CONSOLE_CURSOR_INFO cci;
+ DWORD dwConsoleOwnerPid;
+ HANDLE hProcess;
+ HANDLE hSection, hDupSection;
+ PVOID ptrView;
+
+ /* Each-time initialization for console_info */
+
+ GetConsoleCursorInfo(pdc_con_out, &cci);
+ console_info.CursorSize = cci.dwSize;
+
+ GetConsoleScreenBufferInfo(pdc_con_out, &csbi);
+ console_info.ScreenBufferSize = csbi.dwSize;
+
+ console_info.WindowSize.X = csbi.srWindow.Right - csbi.srWindow.Left + 1;
+ console_info.WindowSize.Y = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
+
+ console_info.WindowPosX = csbi.srWindow.Left;
+ console_info.WindowPosY = csbi.srWindow.Top;
+
+ /* Open the process which "owns" the console */
+
+ GetWindowThreadProcessId(console_info.Hwnd, &dwConsoleOwnerPid);
+
+ hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwConsoleOwnerPid);
+
+ /* Create a SECTION object backed by page-file, then map a view of
+ this section into the owner process so we can write the contents
+ of the CONSOLE_INFO buffer into it */
+
+ hSection = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE,
+ 0, sizeof(console_info), 0);
+
+ /* Copy our console structure into the section-object */
+
+ ptrView = MapViewOfFile(hSection, FILE_MAP_WRITE|FILE_MAP_READ,
+ 0, 0, sizeof(console_info));
+
+ memcpy(ptrView, &console_info, sizeof(console_info));
+
+ UnmapViewOfFile(ptrView);
+
+ /* Map the memory into owner process */
+
+ DuplicateHandle(GetCurrentProcess(), hSection, hProcess, &hDupSection,
+ 0, FALSE, DUPLICATE_SAME_ACCESS);
+
+ /* Send console window the "update" message */
+
+ SendMessage(console_info.Hwnd, WM_SETCONSOLEINFO, (WPARAM)hDupSection, 0);
+
+ CloseHandle(hSection);
+ CloseHandle(hProcess);
+}
+
+static int _set_console_infoex(void)
+{
+ if (!pSetConsoleScreenBufferInfoEx(pdc_con_out, &console_infoex))
+ return ERR;
+
+ return OK;
+}
+
+static int _set_colors(void)
+{
+ SetConsoleTextAttribute(pdc_con_out, 7);
+ _reset_old_colors();
+
+ if (pSetConsoleScreenBufferInfoEx)
+ return _set_console_infoex();
+ else
+ {
+ _set_console_info();
+ return OK;
+ }
+}
+
+/* One-time initialization for console_info -- color table and font info
+ from the registry; other values from functions. */
+
+static void _init_console_info(void)
+{
+ DWORD scrnmode, len;
+ HKEY reghnd;
+ int i;
+
+ console_info.Hwnd = _find_console_handle();
+ console_info.Length = sizeof(console_info);
+
+ GetConsoleMode(pdc_con_in, &scrnmode);
+ console_info.QuickEdit = !!(scrnmode & 0x0040);
+ console_info.InsertMode = !!(scrnmode & 0x0020);
+
+ console_info.FullScreen = FALSE;
+ console_info.AutoPosition = 0x10000;
+ console_info.ScreenColors = SP->orig_back << 4 | SP->orig_fore;
+ console_info.PopupColors = 0xf5;
+
+ console_info.HistoryNoDup = FALSE;
+ console_info.HistoryBufferSize = 50;
+ console_info.NumberOfHistoryBuffers = 4;
+
+ console_info.CodePage = GetConsoleOutputCP();
+
+ RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Console"), 0,
+ KEY_QUERY_VALUE, &reghnd);
+
+ len = sizeof(DWORD);
+
+ /* Default color table */
+
+ for (i = 0; i < 16; i++)
+ {
+ char tname[13];
+
+ sprintf(tname, "ColorTable%02d", i);
+ RegQueryValueExA(reghnd, tname, NULL, NULL,
+ (LPBYTE)(&(console_info.ColorTable[i])), &len);
+ }
+
+ /* Font info */
+
+ RegQueryValueEx(reghnd, TEXT("FontSize"), NULL, NULL,
+ (LPBYTE)(&console_info.FontSize), &len);
+ RegQueryValueEx(reghnd, TEXT("FontFamily"), NULL, NULL,
+ (LPBYTE)(&console_info.FontFamily), &len);
+ RegQueryValueEx(reghnd, TEXT("FontWeight"), NULL, NULL,
+ (LPBYTE)(&console_info.FontWeight), &len);
+
+ len = sizeof(WCHAR) * 32;
+ RegQueryValueExW(reghnd, L"FaceName", NULL, NULL,
+ (LPBYTE)(console_info.FaceName), &len);
+
+ RegCloseKey(reghnd);
+}
+
+static int _init_console_infoex(void)
+{
+ console_infoex.cbSize = sizeof(console_infoex);
+
+ if (!pGetConsoleScreenBufferInfoEx(pdc_con_out, &console_infoex))
+ return ERR;
+
+ console_infoex.srWindow.Right++;
+ console_infoex.srWindow.Bottom++;
+
+ return OK;
+}
+
+static COLORREF *_get_colors(void)
+{
+ if (pGetConsoleScreenBufferInfoEx)
+ {
+ int status = OK;
+ if (!console_infoex.cbSize)
+ status = _init_console_infoex();
+ return (status == ERR) ? NULL :
+ (COLORREF *)(&(console_infoex.ColorTable));
+ }
+ else
+ {
+ if (!console_info.Hwnd)
+ _init_console_info();
+ return (COLORREF *)(&(console_info.ColorTable));
+ }
+}
+
+/* restore the original console buffer in the event of a crash */
+
+static LONG WINAPI _restore_console(LPEXCEPTION_POINTERS ep)
+{
+ PDC_scr_close();
+
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+/* restore the original console buffer on Ctrl+Break (or Ctrl+C,
+ if it gets re-enabled) */
+
+static BOOL WINAPI _ctrl_break(DWORD dwCtrlType)
+{
+ if (dwCtrlType == CTRL_BREAK_EVENT || dwCtrlType == CTRL_C_EVENT)
+ PDC_scr_close();
+
+ return FALSE;
+}
+
+/* close the physical screen -- may restore the screen to its state
+ before PDC_scr_open(); miscellaneous cleanup */
+
+void PDC_scr_close(void)
+{
+ PDC_LOG(("PDC_scr_close() - called\n"));
+
+ if (SP->visibility != 1)
+ curs_set(1);
+
+ PDC_reset_shell_mode();
+
+ /* Position cursor to the bottom left of the screen. */
+
+ if (SP->_restore == PDC_RESTORE_NONE)
+ {
+ SMALL_RECT win;
+
+ win.Left = orig_scr.srWindow.Left;
+ win.Right = orig_scr.srWindow.Right;
+ win.Top = 0;
+ win.Bottom = orig_scr.srWindow.Bottom - orig_scr.srWindow.Top;
+ SetConsoleWindowInfo(pdc_con_out, TRUE, &win);
+ PDC_gotoyx(win.Bottom, 0);
+ }
+}
+
+void PDC_scr_free(void)
+{
+ if (pdc_con_out != std_con_out)
+ {
+ CloseHandle(pdc_con_out);
+ pdc_con_out = std_con_out;
+ }
+
+ SetUnhandledExceptionFilter(xcpt_filter);
+ SetConsoleCtrlHandler(_ctrl_break, FALSE);
+}
+
+/* open the physical screen -- miscellaneous initialization, may save
+ the existing screen for later restoration */
+
+int PDC_scr_open(void)
+{
+ const char *str;
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ HMODULE h_kernel;
+ BOOL result;
+ int i;
+
+ PDC_LOG(("PDC_scr_open() - called\n"));
+
+ for (i = 0; i < 16; i++)
+ {
+ pdc_curstoreal[realtocurs[i]] = i;
+ pdc_curstoansi[ansitocurs[i]] = i;
+ }
+ _reset_old_colors();
+
+ std_con_out =
+ pdc_con_out = GetStdHandle(STD_OUTPUT_HANDLE);
+ pdc_con_in = GetStdHandle(STD_INPUT_HANDLE);
+
+ if (GetFileType(pdc_con_in) != FILE_TYPE_CHAR)
+ {
+ fprintf(stderr, "\nRedirection is not supported.\n");
+ exit(1);
+ }
+
+ is_nt = !(GetVersion() & 0x80000000);
+
+ pdc_wt = !!getenv("WT_SESSION");
+ str = pdc_wt ? NULL : getenv("ConEmuANSI");
+ pdc_conemu = !!str;
+ pdc_ansi = pdc_wt ? TRUE : pdc_conemu ? !strcmp(str, "ON") : FALSE;
+
+ GetConsoleScreenBufferInfo(pdc_con_out, &csbi);
+ GetConsoleScreenBufferInfo(pdc_con_out, &orig_scr);
+ GetConsoleMode(pdc_con_in, &old_console_mode);
+
+ /* preserve QuickEdit Mode setting for use in PDC_mouse_set() when
+ the mouse is not enabled -- other console input settings are
+ cleared */
+
+ pdc_quick_edit = old_console_mode & 0x0040;
+
+ SP->mouse_wait = PDC_CLICK_PERIOD;
+ SP->audible = TRUE;
+
+ SP->termattrs = A_COLOR | A_REVERSE;
+ if (pdc_ansi)
+ SP->termattrs |= A_UNDERLINE | A_ITALIC;
+
+ SP->orig_fore = csbi.wAttributes & 0x0f;
+ SP->orig_back = (csbi.wAttributes & 0xf0) >> 4;
+
+ SP->orig_attr = TRUE;
+
+ SP->_restore = PDC_RESTORE_NONE;
+
+ if ((str = getenv("PDC_RESTORE_SCREEN")) == NULL || *str != '0')
+ {
+ /* Create a new console buffer */
+
+ pdc_con_out =
+ CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
+
+ if (pdc_con_out == INVALID_HANDLE_VALUE)
+ {
+ PDC_LOG(("PDC_scr_open() - screen buffer failure\n"));
+
+ pdc_con_out = std_con_out;
+ }
+ else
+ SP->_restore = PDC_RESTORE_BUFFER;
+ }
+
+ xcpt_filter = SetUnhandledExceptionFilter(_restore_console);
+ SetConsoleCtrlHandler(_ctrl_break, TRUE);
+
+ SP->_preserve = (getenv("PDC_PRESERVE_SCREEN") != NULL);
+
+ /* ENABLE_LVB_GRID_WORLDWIDE */
+ result = SetConsoleMode(pdc_con_out, 0x0010);
+ if (result)
+ SP->termattrs |= A_UNDERLINE | A_LEFT | A_RIGHT;
+
+ PDC_reset_prog_mode();
+
+ SP->mono = FALSE;
+
+ h_kernel = GetModuleHandleA("kernel32.dll");
+ pGetConsoleScreenBufferInfoEx =
+ (GetConsoleScreenBufferInfoExFn)GetProcAddress(h_kernel,
+ "GetConsoleScreenBufferInfoEx");
+ pSetConsoleScreenBufferInfoEx =
+ (SetConsoleScreenBufferInfoExFn)GetProcAddress(h_kernel,
+ "SetConsoleScreenBufferInfoEx");
+
+ return OK;
+}
+
+ /* Calls SetConsoleWindowInfo with the given parameters, but fits them
+ if a scoll bar shrinks the maximum possible value. The rectangle
+ must at least fit in a half-sized window. */
+
+static BOOL _fit_console_window(HANDLE con_out, CONST SMALL_RECT *rect)
+{
+ SMALL_RECT run;
+ SHORT mx, my;
+
+ if (SetConsoleWindowInfo(con_out, TRUE, rect))
+ return TRUE;
+
+ run = *rect;
+ run.Right /= 2;
+ run.Bottom /= 2;
+
+ mx = run.Right;
+ my = run.Bottom;
+
+ if (!SetConsoleWindowInfo(con_out, TRUE, &run))
+ return FALSE;
+
+ for (run.Right = rect->Right; run.Right >= mx; run.Right--)
+ if (SetConsoleWindowInfo(con_out, TRUE, &run))
+ break;
+
+ if (run.Right < mx)
+ return FALSE;
+
+ for (run.Bottom = rect->Bottom; run.Bottom >= my; run.Bottom--)
+ if (SetConsoleWindowInfo(con_out, TRUE, &run))
+ return TRUE;
+
+ return FALSE;
+}
+
+/* the core of resize_term() */
+
+int PDC_resize_screen(int nlines, int ncols)
+{
+ SMALL_RECT rect;
+ COORD size, max;
+
+ bool prog_resize = nlines || ncols;
+
+ if (!prog_resize)
+ {
+ nlines = PDC_get_rows();
+ ncols = PDC_get_columns();
+ }
+
+ if (nlines < 2 || ncols < 2)
+ return ERR;
+
+ max = GetLargestConsoleWindowSize(pdc_con_out);
+
+ rect.Left = rect.Top = 0;
+ rect.Right = ncols - 1;
+
+ if (rect.Right > max.X)
+ rect.Right = max.X;
+
+ rect.Bottom = nlines - 1;
+
+ if (rect.Bottom > max.Y)
+ rect.Bottom = max.Y;
+
+ size.X = rect.Right + 1;
+ size.Y = rect.Bottom + 1;
+
+ _fit_console_window(pdc_con_out, &rect);
+ SetConsoleScreenBufferSize(pdc_con_out, size);
+
+ if (prog_resize)
+ {
+ _fit_console_window(pdc_con_out, &rect);
+ SetConsoleScreenBufferSize(pdc_con_out, size);
+ }
+ SetConsoleActiveScreenBuffer(pdc_con_out);
+
+ PDC_flushinp();
+
+ return OK;
+}
+
+void PDC_reset_prog_mode(void)
+{
+ PDC_LOG(("PDC_reset_prog_mode() - called.\n"));
+
+ if (pdc_con_out != std_con_out)
+ SetConsoleActiveScreenBuffer(pdc_con_out);
+ else if (is_nt)
+ {
+ COORD bufsize;
+ SMALL_RECT rect;
+
+ bufsize.X = orig_scr.srWindow.Right - orig_scr.srWindow.Left + 1;
+ bufsize.Y = orig_scr.srWindow.Bottom - orig_scr.srWindow.Top + 1;
+
+ rect.Top = rect.Left = 0;
+ rect.Bottom = bufsize.Y - 1;
+ rect.Right = bufsize.X - 1;
+
+ SetConsoleScreenBufferSize(pdc_con_out, bufsize);
+ SetConsoleWindowInfo(pdc_con_out, TRUE, &rect);
+ SetConsoleScreenBufferSize(pdc_con_out, bufsize);
+ SetConsoleActiveScreenBuffer(pdc_con_out);
+ }
+
+ PDC_mouse_set();
+}
+
+void PDC_reset_shell_mode(void)
+{
+ PDC_LOG(("PDC_reset_shell_mode() - called.\n"));
+
+ if (pdc_con_out != std_con_out)
+ SetConsoleActiveScreenBuffer(std_con_out);
+ else if (is_nt)
+ {
+ SetConsoleScreenBufferSize(pdc_con_out, orig_scr.dwSize);
+ SetConsoleWindowInfo(pdc_con_out, TRUE, &orig_scr.srWindow);
+ SetConsoleScreenBufferSize(pdc_con_out, orig_scr.dwSize);
+ SetConsoleWindowInfo(pdc_con_out, TRUE, &orig_scr.srWindow);
+ SetConsoleActiveScreenBuffer(pdc_con_out);
+ }
+
+ SetConsoleMode(pdc_con_in, old_console_mode | 0x0080);
+}
+
+void PDC_restore_screen_mode(int i)
+{
+}
+
+void PDC_save_screen_mode(int i)
+{
+}
+
+bool PDC_can_change_color(void)
+{
+ return is_nt;
+}
+
+int PDC_color_content(short color, short *red, short *green, short *blue)
+{
+ if (color < 16 && !(pdc_conemu || pdc_wt))
+ {
+ COLORREF *color_table = _get_colors();
+
+ if (color_table)
+ {
+ DWORD col = color_table[pdc_curstoreal[color]];
+
+ *red = DIVROUND(GetRValue(col) * 1000, 255);
+ *green = DIVROUND(GetGValue(col) * 1000, 255);
+ *blue = DIVROUND(GetBValue(col) * 1000, 255);
+ }
+ else
+ return ERR;
+ }
+ else
+ {
+ if (!pdc_color[color].mapped)
+ {
+ *red = *green = *blue = -1;
+ return ERR;
+ }
+
+ *red = pdc_color[color].r;
+ *green = pdc_color[color].g;
+ *blue = pdc_color[color].b;
+ }
+
+ return OK;
+}
+
+int PDC_init_color(short color, short red, short green, short blue)
+{
+ if (red == -1 && green == -1 && blue == -1)
+ {
+ pdc_color[color].mapped = FALSE;
+ return OK;
+ }
+
+ if (color < 16 && !(pdc_conemu || pdc_wt))
+ {
+ COLORREF *color_table = _get_colors();
+
+ if (color_table)
+ {
+ color_table[pdc_curstoreal[color]] =
+ RGB(DIVROUND(red * 255, 1000),
+ DIVROUND(green * 255, 1000),
+ DIVROUND(blue * 255, 1000));
+
+ return _set_colors();
+ }
+
+ return ERR;
+ }
+ else
+ {
+ pdc_color[color].r = red;
+ pdc_color[color].g = green;
+ pdc_color[color].b = blue;
+ pdc_color[color].mapped = TRUE;
+ }
+
+ return OK;
+}
diff --git a/Utilities/cmpdcurses/wincon/pdcsetsc.c b/Utilities/cmpdcurses/wincon/pdcsetsc.c
new file mode 100644
index 0000000..a2d1b6d
--- /dev/null
+++ b/Utilities/cmpdcurses/wincon/pdcsetsc.c
@@ -0,0 +1,130 @@
+/* PDCurses */
+
+#include "pdcwin.h"
+
+/*man-start**************************************************************
+
+pdcsetsc
+--------
+
+### Synopsis
+
+ int PDC_set_blink(bool blinkon);
+ int PDC_set_bold(bool boldon);
+ void PDC_set_title(const char *title);
+
+### Description
+
+ PDC_set_blink() toggles whether the A_BLINK attribute sets an actual
+ blink mode (TRUE), or sets the background color to high intensity
+ (FALSE). The default is platform-dependent (FALSE in most cases). It
+ returns OK if it could set the state to match the given parameter,
+ ERR otherwise.
+
+ PDC_set_bold() toggles whether the A_BOLD attribute selects an actual
+ bold font (TRUE), or sets the foreground color to high intensity
+ (FALSE). It returns OK if it could set the state to match the given
+ parameter, ERR otherwise.
+
+ PDC_set_title() sets the title of the window in which the curses
+ program is running. This function may not do anything on some
+ platforms.
+
+### Portability
+ X/Open ncurses NetBSD
+ PDC_set_blink - - -
+ PDC_set_title - - -
+
+**man-end****************************************************************/
+
+int PDC_curs_set(int visibility)
+{
+ CONSOLE_CURSOR_INFO cci;
+ int ret_vis;
+
+ PDC_LOG(("PDC_curs_set() - called: visibility=%d\n", visibility));
+
+ ret_vis = SP->visibility;
+
+ if (GetConsoleCursorInfo(pdc_con_out, &cci) == FALSE)
+ return ERR;
+
+ switch(visibility)
+ {
+ case 0: /* invisible */
+ cci.bVisible = FALSE;
+ break;
+ case 2: /* highly visible */
+ cci.bVisible = TRUE;
+ cci.dwSize = 95;
+ break;
+ default: /* normal visibility */
+ cci.bVisible = TRUE;
+ cci.dwSize = SP->orig_cursor;
+ break;
+ }
+
+ if (SetConsoleCursorInfo(pdc_con_out, &cci) == FALSE)
+ return ERR;
+
+ SP->visibility = visibility;
+ return ret_vis;
+}
+
+void PDC_set_title(const char *title)
+{
+#ifdef PDC_WIDE
+ wchar_t wtitle[512];
+#endif
+ PDC_LOG(("PDC_set_title() - called:<%s>\n", title));
+
+#ifdef PDC_WIDE
+ PDC_mbstowcs(wtitle, title, 511);
+ SetConsoleTitleW(wtitle);
+#else
+ SetConsoleTitleA(title);
+#endif
+}
+
+int PDC_set_blink(bool blinkon)
+{
+ if (!SP)
+ return ERR;
+
+ if (SP->color_started)
+ {
+ COLORS = 16;
+ if (PDC_can_change_color()) /* is_nt */
+ {
+ if (pdc_conemu || SetConsoleMode(pdc_con_out, 0x0004)) /* VT */
+ COLORS = PDC_MAXCOL;
+
+ if (!pdc_conemu)
+ SetConsoleMode(pdc_con_out, 0x0010); /* LVB */
+ }
+ }
+
+ if (blinkon)
+ {
+ if (!(SP->termattrs & A_BLINK))
+ {
+ SP->termattrs |= A_BLINK;
+ pdc_last_blink = GetTickCount();
+ }
+ }
+ else
+ {
+ if (SP->termattrs & A_BLINK)
+ {
+ SP->termattrs &= ~A_BLINK;
+ PDC_blink_text();
+ }
+ }
+
+ return OK;
+}
+
+int PDC_set_bold(bool boldon)
+{
+ return boldon ? ERR : OK;
+}
diff --git a/Utilities/cmpdcurses/wincon/pdcutil.c b/Utilities/cmpdcurses/wincon/pdcutil.c
new file mode 100644
index 0000000..a40cf45
--- /dev/null
+++ b/Utilities/cmpdcurses/wincon/pdcutil.c
@@ -0,0 +1,26 @@
+/* PDCurses */
+
+#include "pdcwin.h"
+
+void PDC_beep(void)
+{
+ PDC_LOG(("PDC_beep() - called\n"));
+
+/* MessageBeep(MB_OK); */
+ MessageBeep(0XFFFFFFFF);
+}
+
+void PDC_napms(int ms)
+{
+ PDC_LOG(("PDC_napms() - called: ms=%d\n", ms));
+
+ if ((SP->termattrs & A_BLINK) && (GetTickCount() >= pdc_last_blink + 500))
+ PDC_blink_text();
+
+ Sleep(ms);
+}
+
+const char *PDC_sysname(void)
+{
+ return "Windows";
+}
diff --git a/Utilities/cmpdcurses/wincon/pdcwin.h b/Utilities/cmpdcurses/wincon/pdcwin.h
new file mode 100644
index 0000000..08d3579
--- /dev/null
+++ b/Utilities/cmpdcurses/wincon/pdcwin.h
@@ -0,0 +1,27 @@
+/* PDCurses */
+
+#if defined(PDC_WIDE) && !defined(UNICODE)
+# define UNICODE
+#endif
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef MOUSE_MOVED
+#include <curspriv.h>
+
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
+# define _CRT_SECURE_NO_DEPRECATE 1 /* kill nonsense warnings */
+#endif
+
+typedef struct {short r, g, b; bool mapped;} PDCCOLOR;
+
+extern PDCCOLOR pdc_color[PDC_MAXCOL];
+
+extern HANDLE pdc_con_out, pdc_con_in;
+extern DWORD pdc_quick_edit;
+extern DWORD pdc_last_blink;
+extern short pdc_curstoreal[16], pdc_curstoansi[16];
+extern short pdc_oldf, pdc_oldb, pdc_oldu;
+extern bool pdc_conemu, pdc_wt, pdc_ansi;
+
+extern void PDC_blink_text(void);