1 /*
2 * WINNTSCR.C
3 *
4 * Written in August 1996 by Andrew Clarke and released to the public domain.
5 *
6 * Screen definitions & routines for Windows NT.
7 */
8
9 #include <stdlib.h>
10 #include <string.h>
11 #include <windows.h>
12 #include "winsys.h"
13 #include "unused.h"
14 #include "specch.h"
15
16 #define TERMDEF 1
17
18 #ifdef KEYDEBUG
19 #include <stdio.h>
20 static FILE *fTrace = NULL;
21 #endif
22
23 int vcol, vrow; /* cursor position */
24 int color; /* current color on screen */
25 int cur_start = 0;
26 int cur_end = 0;
27
28 TERM term =
29 {
30 80,
31 25,
32 0,
33 };
34
35 #define EBUFSZ 25
36
37 static int ebufin = 0; /* event in */
38 static int ebufout = 0; /* event out */
39 static EVT EVent[EBUFSZ]; /* event circular queue */
40
41 static HANDLE HInput = INVALID_HANDLE_VALUE;
42 static HANDLE HOutput = INVALID_HANDLE_VALUE;
43 static unsigned long key_hit = 0xFFFFFFFFUL;
44
45 static int FullBuffer(void);
46
47 /* codepage 437 / 850 block graphics */
48 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";
49
50 int tt_graphics = 0;
51
TTBeginOutput(void)52 void TTBeginOutput(void) {}
TTEndOutput(void)53 void TTEndOutput(void) {}
54
TTopen(void)55 int TTopen(void)
56 {
57 CONSOLE_SCREEN_BUFFER_INFO csbi;
58 TTkopen();
59 GetConsoleScreenBufferInfo(HOutput, &csbi);
60 vcol = (int) csbi.dwCursorPosition.X;
61 vrow = (int) csbi.dwCursorPosition.Y;
62 term.NCol = (short) csbi.dwSize.X;
63 term.NRow = (short) csbi.dwSize.Y;
64 color = 0x07;
65 return 1;
66 }
67
TTclose(void)68 int TTclose(void)
69 {
70 return 1;
71 }
72
73 #ifdef __GNUC__
74 #pragma warn -par
75 #endif
76
77 /*
78 * Configure the terminal. This must be called *before* TTopen!
79 *
80 * The Windows NT console terminal does not need any configuration.
81 *
82 */
83
TTconfigure(const char * keyword,const char * value)84 int TTconfigure(const char *keyword, const char *value)
85 {
86 return 0;
87 }
88
89 #ifdef __GNUC__
90 #pragma warn +par
91 #endif
92
TTgotoxy(int row,int col)93 int TTgotoxy(int row, int col)
94 {
95 COORD coord;
96 coord.X = (SHORT) col;
97 coord.Y = (SHORT) row;
98 SetConsoleCursorPosition(HOutput, coord);
99 vcol = col;
100 vrow = row;
101 return 1;
102 }
103
TTPutChr(unsigned int Ch)104 int TTPutChr(unsigned int Ch)
105 {
106 DWORD len;
107 COORD coord;
108 WORD wattr;
109 unsigned char wch;
110 coord.X = (SHORT) vcol;
111 coord.Y = (SHORT) vrow;
112 wattr = (WORD) color;
113 wch = (unsigned char) Ch;
114 WriteConsoleOutputCharacterA(HOutput, &wch, 1, coord, &len);
115 WriteConsoleOutputAttribute(HOutput, &wattr, 1, coord, &len);
116 TTgotoxy(vrow, vcol + 1);
117 return 1;
118 }
119
mykbhit(int block)120 static int mykbhit(int block)
121 {
122 int iKey = 0;
123 INPUT_RECORD irBuffer;
124 DWORD pcRead;
125
126 if (FullBuffer())
127 {
128 return 0;
129 }
130
131 if (key_hit != 0xFFFFFFFFUL)
132 {
133 return (int)key_hit;
134 }
135
136 memset(&irBuffer, 0, sizeof irBuffer);
137
138 if (WaitForSingleObject(HInput, (block)? INFINITE : 0L) == 0)
139 {
140 ReadConsoleInput(HInput, &irBuffer, 1, &pcRead);
141
142 #ifdef KEYDEBUG
143 if (irBuffer.EventType == KEY_EVENT)
144 {
145 fprintf(fTrace, "bKD=%d wRC=%hd wVKC=%hd wVSC=%hd c=%d dwCKS=%lx\n",
146 irBuffer.Event.KeyEvent.bKeyDown,
147 irBuffer.Event.KeyEvent.wRepeatCount,
148 irBuffer.Event.KeyEvent.wVirtualKeyCode,
149 irBuffer.Event.KeyEvent.wVirtualScanCode,
150 #ifdef __MINGW32__
151 irBuffer.Event.KeyEvent.AsciiChar;
152 #else
153 irBuffer.Event.KeyEvent.uChar.AsciiChar;
154 #endif
155 irBuffer.Event.KeyEvent.dwControlKeyState);
156 }
157 #endif
158
159
160 if (irBuffer.EventType == KEY_EVENT && irBuffer.Event.KeyEvent.bKeyDown != 0 && irBuffer.Event.KeyEvent.wRepeatCount <= 1)
161 {
162 WORD vk, vs, uc;
163 BOOL fShift, fAlt, fCtrl;
164
165 vk = irBuffer.Event.KeyEvent.wVirtualKeyCode;
166 vs = irBuffer.Event.KeyEvent.wVirtualScanCode;
167 #ifdef __MINGW32__
168 uc = irBuffer.Event.KeyEvent.AsciiChar;
169 #else
170 uc = irBuffer.Event.KeyEvent.uChar.AsciiChar;
171 #endif
172 fShift = (irBuffer.Event.KeyEvent.dwControlKeyState & (SHIFT_PRESSED));
173 fAlt = (irBuffer.Event.KeyEvent.dwControlKeyState & (RIGHT_ALT_PRESSED + LEFT_ALT_PRESSED));
174 fCtrl = (irBuffer.Event.KeyEvent.dwControlKeyState & (RIGHT_CTRL_PRESSED + LEFT_CTRL_PRESSED));
175
176 if (uc == 0) /* function keys */
177 {
178 switch (vk)
179 {
180 case 0x21: /* PgUp */
181 if (fCtrl)
182 {
183 vs = 0x84; /* Ctrl+PgUp */
184 }
185 break;
186
187 case 0x22: /* PgDn */
188 if (fCtrl)
189 {
190 vs = 0x76; /* Ctrl+PgDn */
191 }
192 break;
193
194 case 0x23: /* End */
195 if (fCtrl)
196 {
197 vs = 0x75; /* Ctrl+End */
198 }
199 break;
200
201 case 0x24: /* Home */
202 if (fCtrl)
203 {
204 vs = 0x77; /* Ctrl+Home */
205 }
206 break;
207
208 case 0x25: /* Left Arrow */
209 if (fCtrl)
210 {
211 vs = 0x73; /* Ctrl+Left Arrow */
212 }
213 break;
214
215 case 0x26: /* Up Arrow */
216 if (fCtrl)
217 {
218 vs = 0x8d; /* Ctrl+Up Arrow */
219 }
220 break;
221
222 case 0x27: /* Right Arrow */
223 if (fCtrl)
224 {
225 vs = 0x74; /* Ctrl+Right Arrow */
226 }
227 break;
228
229 case 0x28: /* Down Arrow */
230 if (fCtrl)
231 {
232 vs = 0x91; /* Ctrl+Down Arrow */
233 }
234 break;
235
236 case 0x70: /* F-Keys */
237 case 0x71:
238 case 0x72:
239 case 0x73:
240 case 0x74:
241 case 0x75:
242 case 0x76:
243 case 0x77:
244 case 0x78:
245 case 0x79:
246 if (fAlt != 0)
247 {
248 vs += 0x2D; /* Alt+F-Key */
249 }
250 else if (fShift != 0)
251 {
252 vs += 0x19; /* Shift+F-Key */
253 }
254 break;
255 }
256
257 if (vk > 0x20 && vk < 0x92) /* If it's OK use scan code */
258 {
259 iKey = vs << 8;
260 }
261 }
262 else
263 {
264 if (fAlt && (!fCtrl)) /* Alt+Key */
265 {
266 iKey = vs << 8;
267 }
268 else if (fCtrl && (!fAlt)) /* Ctrl+Key */
269 {
270 iKey = vk & 0xBF;
271 }
272 else
273 {
274 iKey = uc;
275 }
276 }
277 }
278 }
279
280 if (iKey != 0)
281 {
282 key_hit = iKey;
283 }
284
285 return (int)iKey;
286 }
287
TTGetKey(void)288 unsigned int TTGetKey(void)
289 {
290 int iKey;
291 while (key_hit == 0xFFFFFFFFUL)
292 {
293 mykbhit(1);
294 }
295 iKey = key_hit;
296 key_hit = 0xFFFFFFFFUL;
297 return (unsigned int)iKey;
298 }
299
TTScolor(unsigned int Attr)300 int TTScolor(unsigned int Attr)
301 {
302 color = Attr;
303 return 1;
304 }
305
TTCurSet(int st)306 int TTCurSet(int st)
307 {
308 CONSOLE_CURSOR_INFO cci;
309 GetConsoleCursorInfo(HOutput, &cci);
310 cci.bVisible = st;
311 SetConsoleCursorInfo(HOutput, &cci);
312 return 0;
313 }
314
TTgetxy(int * row,int * col)315 int TTgetxy(int *row, int *col)
316 {
317 *row = vrow;
318 *col = vcol;
319 return 1;
320 }
321
TTdelay(int mil)322 int TTdelay(int mil)
323 {
324 Sleep((DWORD) mil);
325 return 0;
326 }
327
TTSendMsg(unsigned int msg,int x,int y,unsigned int msgtype)328 void TTSendMsg(unsigned int msg, int x, int y, unsigned int msgtype)
329 {
330 if (((ebufin + 1) % EBUFSZ) != ebufout)
331 {
332 EVent[ebufin].msg = msg;
333 EVent[ebufin].x = x;
334 EVent[ebufin].y = y;
335 EVent[ebufin].msgtype = msgtype;
336 ebufin = (ebufin + 1) % EBUFSZ;
337 }
338 }
339
collect_events(int delay)340 int collect_events(int delay)
341 {
342 if (mykbhit(0))
343 {
344 TTSendMsg(TTGetKey(), 0, 0, WND_WM_CHAR);
345 }
346 else if (delay)
347 {
348 TTdelay(50);
349 }
350 return 0;
351 }
352
TTkopen(void)353 int TTkopen(void)
354 {
355 DWORD cmode;
356
357 HInput = GetStdHandle(STD_INPUT_HANDLE);
358 HOutput = GetStdHandle(STD_OUTPUT_HANDLE);
359
360 GetConsoleMode(HInput, (LPDWORD)&cmode);
361 SetConsoleMode(HInput, cmode & (~ENABLE_PROCESSED_INPUT));
362
363 #ifdef KEYDEBUG
364 fTrace = fopen("ntkeys.trc", "w");
365 if (fTrace == NULL)
366 {
367 abort();
368 }
369 #endif
370
371 return 0;
372 }
373
TTkclose(void)374 int TTkclose(void)
375 {
376 CloseHandle(HInput);
377 HInput = INVALID_HANDLE_VALUE;
378 CloseHandle(HOutput);
379 HOutput = INVALID_HANDLE_VALUE;
380
381 #ifdef KEYDEBUG
382 fclose(fTrace);
383 #endif
384
385 return 0;
386 }
387
MouseOFF(void)388 void MouseOFF(void)
389 {
390 }
391
MouseON(void)392 void MouseON(void)
393 {
394 }
395
MouseInit(void)396 void MouseInit(void)
397 {
398 }
399
GetMouInfo(int * x,int * y)400 int GetMouInfo(int *x, int *y)
401 {
402 unused(x);
403 unused(y);
404 return 0;
405 }
406
TTGetMsg(EVT * e)407 int TTGetMsg(EVT * e)
408 {
409 while (ebufin == ebufout)
410 {
411 collect_events(1);
412 }
413 e->msg = EVent[ebufout].msg;
414 e->x = EVent[ebufout].x;
415 e->y = EVent[ebufout].y;
416 e->msgtype = EVent[ebufout].msgtype;
417 e->id = 0;
418 ebufout = (ebufout + 1) % EBUFSZ;
419 return e->msg;
420 }
421
TTPeekQue(void)422 int TTPeekQue(void)
423 {
424 collect_events(0);
425 return ebufin != ebufout;
426 }
427
TTClearQue(void)428 void TTClearQue(void)
429 {
430 ebufin = ebufout;
431 }
432
TTGetChr(void)433 int TTGetChr(void)
434 {
435 EVT e;
436 TTGetMsg(&e);
437 return e.msg;
438 }
439
dv_running(void)440 int dv_running(void)
441 {
442 return 0;
443 }
444
FullBuffer(void)445 static int FullBuffer(void)
446 {
447 if (((ebufin + 1) % EBUFSZ) != ebufout)
448 {
449 return 0;
450 }
451 else
452 {
453 return 1;
454 }
455 }
456
TTStrWr(unsigned char * s,int row,int col,int len)457 int TTStrWr(unsigned char *s, int row, int col, int len)
458 {
459 DWORD i;
460 COORD coord;
461 LPWORD pwattr;
462 DWORD ntlen;
463
464 if (len < 0)
465 len = strlen((char *)s);
466
467 ntlen = len;
468
469 if (len == 0)
470 return 1;
471
472 pwattr = (LPWORD) malloc(len * sizeof *pwattr);
473 if (pwattr == NULL)
474 {
475 return 0;
476 }
477 coord.X = (SHORT) col;
478 coord.Y = (SHORT) row;
479 for (i = 0; i < len; i++)
480 {
481 *(pwattr + i) = color;
482 }
483 WriteConsoleOutputCharacterA(HOutput, s, (DWORD) len, coord, &ntlen);
484 WriteConsoleOutputAttribute(HOutput, pwattr, (DWORD) len, coord, &ntlen);
485 free(pwattr);
486 TTgotoxy(row, col + ntlen);
487 return 1;
488 }
489
clearbox(int x1,int y1,int x2,int y2)490 static void clearbox(int x1, int y1, int x2, int y2)
491 {
492 COORD coord;
493 LPWORD pwattr;
494 char y, *pstr;
495 DWORD i, len, width;
496 width = x2 - x1 + 1;
497 pwattr = malloc(width * sizeof *pwattr);
498 if (pwattr == NULL)
499 {
500 return;
501 }
502 pstr = malloc(width);
503 if (pstr == NULL)
504 {
505 free(pwattr);
506 return;
507 }
508 for (i = 0; i < width; i++)
509 {
510 *(pwattr + i) = color;
511 *(pstr + i) = ' ';
512 }
513 for (y = y1; y <= y2; y++)
514 {
515 coord.X = (SHORT) x1;
516 coord.Y = (SHORT) y;
517 WriteConsoleOutputCharacterA(HOutput, pstr, width, coord, &len);
518 WriteConsoleOutputAttribute(HOutput, pwattr, width, coord, &len);
519 }
520 free(pwattr);
521 free(pstr);
522 }
523
TTClear(int x1,int y1,int x2,int y2)524 int TTClear(int x1, int y1, int x2, int y2)
525 {
526 clearbox(x1, y1, x2, y2);
527 TTgotoxy(y1, x1);
528 return 1;
529 }
530
TTEeol(void)531 int TTEeol(void)
532 {
533 clearbox(vcol, vrow, term.NCol -1, vrow);
534 TTgotoxy(vcol, vrow);
535 return 1;
536 }
537
TTWriteStr(unsigned long * b,int len,int row,int col)538 int TTWriteStr(unsigned long *b, int len, int row, int col)
539 {
540 DWORD i, wlen;
541 COORD coord;
542 LPWORD pwattr;
543 unsigned char *pstr;
544
545 pwattr = malloc(len * sizeof *pwattr);
546 if (pwattr == NULL)
547 {
548 return 0;
549 }
550 pstr = malloc(len);
551 if (pstr == NULL)
552 {
553 free(pwattr);
554 return 0;
555 }
556 for (i = 0; i < len; i++)
557 {
558 *(pstr + i) = *b & 0xff;
559 *(pwattr + i) = ((*b) >> 16) & 0xff;
560 b++;
561 }
562 coord.X = (SHORT) col;
563 coord.Y = (SHORT) row;
564 WriteConsoleOutputCharacterA(HOutput, pstr, len, coord, &wlen);
565 WriteConsoleOutputAttribute(HOutput, pwattr, len, coord, &wlen);
566 free(pwattr);
567 free(pstr);
568 TTgotoxy(row, col + len);
569 return 1;
570 }
571
TTReadStr(unsigned long * b,int len,int row,int col)572 int TTReadStr(unsigned long *b, int len, int row, int col)
573 {
574 DWORD i, wlen;
575 COORD coord;
576 LPWORD pwattr;
577 unsigned char *pstr;
578
579 pwattr = malloc(len * sizeof *pwattr);
580 if (pwattr == NULL)
581 {
582 return 0;
583 }
584 pstr = malloc(len);
585 if (pstr == NULL)
586 {
587 free(pwattr);
588 return 0;
589 }
590 coord.X = (SHORT) col;
591 coord.Y = (SHORT) row;
592 ReadConsoleOutputCharacterA(HOutput, pstr, len, coord, &wlen);
593 ReadConsoleOutputAttribute(HOutput, pwattr, len, coord, &wlen);
594 for (i = 0; i < len; i++)
595 {
596 b[i] = MAKECELL(pstr[i] & 0xFF, pwattr[i] & 0xFF);
597 }
598 free(pwattr);
599 free(pstr);
600 return 1;
601 }
602
gettext(int x1,int y1,int x2,int y2,char * dest)603 static void gettext(int x1, int y1, int x2, int y2, char *dest)
604 {
605 DWORD i, len, width;
606 COORD coord;
607 LPWORD pwattr;
608 char y, *pstr;
609 width = x2 - x1 + 1;
610 pwattr = malloc(width * sizeof *pwattr);
611 if (pwattr == NULL)
612 {
613 return;
614 }
615 pstr = malloc(width);
616 if (pstr == NULL)
617 {
618 free(pwattr);
619 return;
620 }
621 for (y = y1; y <= y2; y++)
622 {
623 coord.X = (SHORT) x1;
624 coord.Y = (SHORT) y;
625 ReadConsoleOutputCharacterA(HOutput, pstr, width, coord, &len);
626 ReadConsoleOutputAttribute(HOutput, pwattr, width, coord, &len);
627 for (i = 0; i < width; i++)
628 {
629 *((unsigned char *)dest) = *(pstr + i);
630 dest++;
631 *((unsigned char *)dest) = (char)*(pwattr + i);
632 dest++;
633 }
634 }
635 free(pwattr);
636 free(pstr);
637 }
638
puttext(int x1,int y1,int x2,int y2,char * srce)639 static void puttext(int x1, int y1, int x2, int y2, char *srce)
640 {
641 DWORD i, len, width;
642 COORD coord;
643 LPWORD pwattr;
644 char y, *pstr;
645 width = x2 - x1 + 1;
646 pwattr = malloc(width * sizeof *pwattr);
647 if (pwattr == NULL)
648 {
649 return;
650 }
651 pstr = malloc(width);
652 if (pstr == NULL)
653 {
654 free(pwattr);
655 return;
656 }
657 for (y = y1; y <= y2; y++)
658 {
659 for (i = 0; i < width; i++)
660 {
661 *(pstr + i) = *((unsigned char *)srce);
662 srce++;
663 *(pwattr + i) = *((unsigned char *)srce);
664 srce++;
665 }
666 coord.X = (SHORT) x1;
667 coord.Y = (SHORT) y;
668 WriteConsoleOutputCharacterA(HOutput, pstr, width, coord, &len);
669 WriteConsoleOutputAttribute(HOutput, pwattr, width, coord, &len);
670 }
671 free(pwattr);
672 free(pstr);
673 }
674
TTScroll(int x1,int y1,int x2,int y2,int lines,int Dir)675 int TTScroll(int x1, int y1, int x2, int y2, int lines, int Dir)
676 {
677 int width, height;
678 char *buf;
679
680 width = x2 - x1 + 1;
681 height = y2 - y1 + 1;
682 buf = malloc(width * height * 2);
683 if (buf == NULL)
684 {
685 return 0;
686 }
687
688 if (Dir)
689 {
690 gettext(x1, y1, x2, y2, buf);
691 puttext(x1, y1, x2, y2 - lines, buf + (width * 2));
692 }
693 else
694 {
695 gettext(x1, y1, x2, y2, buf);
696 puttext(x1, y1 + lines, x2, y2, buf);
697 }
698
699 free(buf);
700 return 1;
701 }
702