/* * WINNTSCR.C * * Written in August 1996 by Andrew Clarke and released to the public domain. * * Screen definitions & routines for Windows NT. */ #include #include #include #include "winsys.h" #include "unused.h" #include "specch.h" #define TERMDEF 1 #ifdef KEYDEBUG #include static FILE *fTrace = NULL; #endif int vcol, vrow; /* cursor position */ int color; /* current color on screen */ int cur_start = 0; int cur_end = 0; TERM term = { 80, 25, 0, }; #define EBUFSZ 25 static int ebufin = 0; /* event in */ static int ebufout = 0; /* event out */ static EVT EVent[EBUFSZ]; /* event circular queue */ static HANDLE HInput = INVALID_HANDLE_VALUE; static HANDLE HOutput = INVALID_HANDLE_VALUE; static unsigned long key_hit = 0xFFFFFFFFUL; static int FullBuffer(void); /* codepage 437 / 850 block graphics */ char *tt_specials="\272\315\311\273\310\274\263\304\332\277\300\331\261\020\021\334\337\030\031\024\035\000"; int tt_graphics = 0; void TTBeginOutput(void) {} void TTEndOutput(void) {} int TTopen(void) { CONSOLE_SCREEN_BUFFER_INFO csbi; TTkopen(); GetConsoleScreenBufferInfo(HOutput, &csbi); vcol = (int) csbi.dwCursorPosition.X; vrow = (int) csbi.dwCursorPosition.Y; term.NCol = (short) csbi.dwSize.X; term.NRow = (short) csbi.dwSize.Y; color = 0x07; return 1; } int TTclose(void) { return 1; } #pragma warn -par /* * Configure the terminal. This must be called *before* TTopen! * * The Windows NT console terminal does not need any configuration. * */ int TTconfigure(const char *keyword, const char *value) { return 0; } #pragma warn +par int TTgotoxy(int row, int col) { COORD coord; coord.X = (SHORT) col; coord.Y = (SHORT) row; SetConsoleCursorPosition(HOutput, coord); vcol = col; vrow = row; return 1; } int TTPutChr(unsigned int Ch) { DWORD len; COORD coord; WORD wattr; unsigned char wch; coord.X = (SHORT) vcol; coord.Y = (SHORT) vrow; wattr = (WORD) color; wch = (unsigned char) Ch; WriteConsoleOutputCharacterA(HOutput, &wch, 1, coord, &len); WriteConsoleOutputAttribute(HOutput, &wattr, 1, coord, &len); TTgotoxy(vrow, vcol + 1); return 1; } static int mykbhit(int block) { int iKey = 0; INPUT_RECORD irBuffer; DWORD pcRead; if (FullBuffer()) { return 0; } if (key_hit != 0xFFFFFFFFUL) { return (int)key_hit; } memset(&irBuffer, 0, sizeof irBuffer); if (WaitForSingleObject(HInput, (block)? INFINITE : 0L) == 0) { ReadConsoleInput(HInput, &irBuffer, 1, &pcRead); #ifdef KEYDEBUG if (irBuffer.EventType == KEY_EVENT) { fprintf(fTrace, "bKD=%d wRC=%hd wVKC=%hd wVSC=%hd c=%d dwCKS=%lx\n", irBuffer.Event.KeyEvent.bKeyDown, irBuffer.Event.KeyEvent.wRepeatCount, irBuffer.Event.KeyEvent.wVirtualKeyCode, irBuffer.Event.KeyEvent.wVirtualScanCode, #ifdef __MINGW32__ irBuffer.Event.KeyEvent.AsciiChar; #else irBuffer.Event.KeyEvent.uChar.AsciiChar; #endif irBuffer.Event.KeyEvent.dwControlKeyState); } #endif if (irBuffer.EventType == KEY_EVENT && irBuffer.Event.KeyEvent.bKeyDown != 0 && irBuffer.Event.KeyEvent.wRepeatCount <= 1) { WORD vk, vs, uc; BOOL fShift, fAlt, fCtrl; vk = irBuffer.Event.KeyEvent.wVirtualKeyCode; vs = irBuffer.Event.KeyEvent.wVirtualScanCode; #ifdef __MINGW32__ uc = irBuffer.Event.KeyEvent.AsciiChar; #else uc = irBuffer.Event.KeyEvent.uChar.AsciiChar; #endif fShift = (irBuffer.Event.KeyEvent.dwControlKeyState & (SHIFT_PRESSED)); fAlt = (irBuffer.Event.KeyEvent.dwControlKeyState & (RIGHT_ALT_PRESSED + LEFT_ALT_PRESSED)); fCtrl = (irBuffer.Event.KeyEvent.dwControlKeyState & (RIGHT_CTRL_PRESSED + LEFT_CTRL_PRESSED)); if (uc == 0) /* function keys */ { switch (vk) { case 0x21: /* PgUp */ if (fCtrl) { vs = 0x84; /* Ctrl+PgUp */ } break; case 0x22: /* PgDn */ if (fCtrl) { vs = 0x76; /* Ctrl+PgDn */ } break; case 0x23: /* End */ if (fCtrl) { vs = 0x75; /* Ctrl+End */ } break; case 0x24: /* Home */ if (fCtrl) { vs = 0x77; /* Ctrl+Home */ } break; case 0x25: /* Left Arrow */ if (fCtrl) { vs = 0x73; /* Ctrl+Left Arrow */ } break; case 0x26: /* Up Arrow */ if (fCtrl) { vs = 0x8d; /* Ctrl+Up Arrow */ } break; case 0x27: /* Right Arrow */ if (fCtrl) { vs = 0x74; /* Ctrl+Right Arrow */ } break; case 0x28: /* Down Arrow */ if (fCtrl) { vs = 0x91; /* Ctrl+Down Arrow */ } break; case 0x70: /* F-Keys */ case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: case 0x78: case 0x79: if (fAlt != 0) { vs += 0x2D; /* Alt+F-Key */ } else if (fShift != 0) { vs += 0x19; /* Shift+F-Key */ } break; } if (vk > 0x20 && vk < 0x92) /* If it's OK use scan code */ { iKey = vs << 8; } } else { if (fAlt && (!fCtrl)) /* Alt+Key */ { iKey = vs << 8; } else if (fCtrl && (!fAlt)) /* Ctrl+Key */ { iKey = vk & 0xBF; } else { iKey = uc; } } } } if (iKey != 0) { key_hit = iKey; } return (int)iKey; } unsigned int TTGetKey(void) { int iKey; while (key_hit == 0xFFFFFFFFUL) { mykbhit(1); } iKey = key_hit; key_hit = 0xFFFFFFFFUL; return (unsigned int)iKey; } int TTScolor(unsigned int Attr) { color = Attr; return 1; } int TTCurSet(int st) { CONSOLE_CURSOR_INFO cci; GetConsoleCursorInfo(HOutput, &cci); cci.bVisible = st; SetConsoleCursorInfo(HOutput, &cci); return 0; } int TTgetxy(int *row, int *col) { *row = vrow; *col = vcol; return 1; } int TTdelay(int mil) { Sleep((DWORD) mil); return 0; } void TTSendMsg(unsigned int msg, int x, int y, unsigned int msgtype) { if (((ebufin + 1) % EBUFSZ) != ebufout) { EVent[ebufin].msg = msg; EVent[ebufin].x = x; EVent[ebufin].y = y; EVent[ebufin].msgtype = msgtype; ebufin = (ebufin + 1) % EBUFSZ; } } int collect_events(int delay) { if (mykbhit(0)) { TTSendMsg(TTGetKey(), 0, 0, WND_WM_CHAR); } else if (delay) { TTdelay(50); } return 0; } int TTkopen(void) { DWORD cmode; HInput = GetStdHandle(STD_INPUT_HANDLE); HOutput = GetStdHandle(STD_OUTPUT_HANDLE); GetConsoleMode(HInput, (LPDWORD)&cmode); SetConsoleMode(HInput, cmode & (~ENABLE_PROCESSED_INPUT)); #ifdef KEYDEBUG fTrace = fopen("ntkeys.trc", "w"); if (fTrace == NULL) { abort(); } #endif return 0; } int TTkclose(void) { CloseHandle(HInput); HInput = INVALID_HANDLE_VALUE; CloseHandle(HOutput); HOutput = INVALID_HANDLE_VALUE; #ifdef KEYDEBUG fclose(fTrace); #endif return 0; } void MouseOFF(void) { } void MouseON(void) { } void MouseInit(void) { } int GetMouInfo(int *x, int *y) { unused(x); unused(y); return 0; } int TTGetMsg(EVT * e) { while (ebufin == ebufout) { collect_events(1); } e->msg = EVent[ebufout].msg; e->x = EVent[ebufout].x; e->y = EVent[ebufout].y; e->msgtype = EVent[ebufout].msgtype; e->id = 0; ebufout = (ebufout + 1) % EBUFSZ; return e->msg; } int TTPeekQue(void) { collect_events(0); return ebufin != ebufout; } void TTClearQue(void) { ebufin = ebufout; } int TTGetChr(void) { EVT e; TTGetMsg(&e); return e.msg; } int dv_running(void) { return 0; } static int FullBuffer(void) { if (((ebufin + 1) % EBUFSZ) != ebufout) { return 0; } else { return 1; } } int TTStrWr(unsigned char *s, int row, int col, int len) { DWORD i; COORD coord; LPWORD pwattr; DWORD ntlen; if (len < 0) len = strlen((char *)s); ntlen = len; if (len == 0) return 1; pwattr = (LPWORD) malloc(len * sizeof *pwattr); if (pwattr == NULL) { return 0; } coord.X = (SHORT) col; coord.Y = (SHORT) row; for (i = 0; i < len; i++) { *(pwattr + i) = color; } WriteConsoleOutputCharacterA(HOutput, s, (DWORD) len, coord, &ntlen); WriteConsoleOutputAttribute(HOutput, pwattr, (DWORD) len, coord, &ntlen); free(pwattr); TTgotoxy(row, col + ntlen); return 1; } static void clearbox(int x1, int y1, int x2, int y2) { COORD coord; LPWORD pwattr; char y, *pstr; DWORD i, len, width; width = x2 - x1 + 1; pwattr = malloc(width * sizeof *pwattr); if (pwattr == NULL) { return; } pstr = malloc(width); if (pstr == NULL) { free(pwattr); return; } for (i = 0; i < width; i++) { *(pwattr + i) = color; *(pstr + i) = ' '; } for (y = y1; y <= y2; y++) { coord.X = (SHORT) x1; coord.Y = (SHORT) y; WriteConsoleOutputCharacterA(HOutput, pstr, width, coord, &len); WriteConsoleOutputAttribute(HOutput, pwattr, width, coord, &len); } free(pwattr); free(pstr); } int TTClear(int x1, int y1, int x2, int y2) { clearbox(x1, y1, x2, y2); TTgotoxy(y1, x1); return 1; } int TTEeol(void) { clearbox(vcol, vrow, term.NCol -1, vrow); TTgotoxy(vcol, vrow); return 1; } int TTWriteStr(unsigned long *b, int len, int row, int col) { DWORD i, wlen; COORD coord; LPWORD pwattr; unsigned char *pstr; pwattr = malloc(len * sizeof *pwattr); if (pwattr == NULL) { return 0; } pstr = malloc(len); if (pstr == NULL) { free(pwattr); return 0; } for (i = 0; i < len; i++) { *(pstr + i) = *b & 0xff; *(pwattr + i) = ((*b) >> 16) & 0xff; b++; } coord.X = (SHORT) col; coord.Y = (SHORT) row; WriteConsoleOutputCharacterA(HOutput, pstr, len, coord, &wlen); WriteConsoleOutputAttribute(HOutput, pwattr, len, coord, &wlen); free(pwattr); free(pstr); TTgotoxy(row, col + len); return 1; } int TTReadStr(unsigned long *b, int len, int row, int col) { DWORD i, wlen; COORD coord; LPWORD pwattr; unsigned char *pstr; pwattr = malloc(len * sizeof *pwattr); if (pwattr == NULL) { return 0; } pstr = malloc(len); if (pstr == NULL) { free(pwattr); return 0; } coord.X = (SHORT) col; coord.Y = (SHORT) row; ReadConsoleOutputCharacterA(HOutput, pstr, len, coord, &wlen); ReadConsoleOutputAttribute(HOutput, pwattr, len, coord, &wlen); for (i = 0; i < len; i++) { b[i] = MAKECELL(pstr[i] & 0xFF, pwattr[i] & 0xFF); } free(pwattr); free(pstr); return 1; } static void gettext(int x1, int y1, int x2, int y2, char *dest) { DWORD i, len, width; COORD coord; LPWORD pwattr; char y, *pstr; width = x2 - x1 + 1; pwattr = malloc(width * sizeof *pwattr); if (pwattr == NULL) { return; } pstr = malloc(width); if (pstr == NULL) { free(pwattr); return; } for (y = y1; y <= y2; y++) { coord.X = (SHORT) x1; coord.Y = (SHORT) y; ReadConsoleOutputCharacterA(HOutput, pstr, width, coord, &len); ReadConsoleOutputAttribute(HOutput, pwattr, width, coord, &len); for (i = 0; i < width; i++) { *((unsigned char *)dest) = *(pstr + i); dest++; *((unsigned char *)dest) = (char)*(pwattr + i); dest++; } } free(pwattr); free(pstr); } static void puttext(int x1, int y1, int x2, int y2, char *srce) { DWORD i, len, width; COORD coord; LPWORD pwattr; char y, *pstr; width = x2 - x1 + 1; pwattr = malloc(width * sizeof *pwattr); if (pwattr == NULL) { return; } pstr = malloc(width); if (pstr == NULL) { free(pwattr); return; } for (y = y1; y <= y2; y++) { for (i = 0; i < width; i++) { *(pstr + i) = *((unsigned char *)srce); srce++; *(pwattr + i) = *((unsigned char *)srce); srce++; } coord.X = (SHORT) x1; coord.Y = (SHORT) y; WriteConsoleOutputCharacterA(HOutput, pstr, width, coord, &len); WriteConsoleOutputAttribute(HOutput, pwattr, width, coord, &len); } free(pwattr); free(pstr); } int TTScroll(int x1, int y1, int x2, int y2, int lines, int Dir) { int width, height; char *buf; width = x2 - x1 + 1; height = y2 - y1 + 1; buf = malloc(width * height * 2); if (buf == NULL) { return 0; } if (Dir) { gettext(x1, y1, x2, y2, buf); puttext(x1, y1, x2, y2 - lines, buf + (width * 2)); } else { gettext(x1, y1, x2, y2, buf); puttext(x1, y1 + lines, x2, y2, buf); } free(buf); return 1; }