1 /*
2 * OS2SCR.C
3 *
4 * Written on 10-Jul-94 by John Dennis and released to the public domain.
5 *
6 * Screen definitions & routines for the IBM PC under OS/2 only. There
7 * are three threads of execution in this module; the mouse, keyboard
8 * and the main thread.
9 *
10 * The mouse thread polls the OS/2 mouse subsystem - I know it *should*
11 * be blocked, but unfortunately a thread that is blocked cannot be
12 * killed and we have to explicitly release the mouse control for the
13 * current screen group (when we exit), if another application wants to
14 * be able to use the mouse.
15 *
16 * The keyboard thread is blocked and only sends events when a key is
17 * pressed.
18 */
19
20 #include "winsys.h"
21 #include "memextra.h"
22 #include "specch.h"
23
24 #define TERMDEF 1
25
26 #define NCOL 80
27 #define NROW 25
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <stdarg.h>
33
34 #define EBUFSZ 25
35 #define INCL_VIO
36 #define INCL_AVIO
37 #define INCL_KBD
38 #define INCL_MOU
39 #define INCL_DOSPROCESS
40 #define INCL_DOSINFOSEG
41 #include <os2.h>
42
43 #include "mcompile.h"
44
45 #ifndef KBDTRF_FINAL_CHAR_IN
46 #define KBDTRF_FINAL_CHAR_IN FINAL_CHAR_IN
47 #endif
48
49 /* codepage 437 / 850 block graphics */
50 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";
51
52 TERM term =
53 {
54 NCOL - 1,
55 NROW - 1,
56 0
57 };
58
59 int vcol, vrow; /* cursor position */
60 int color; /* current color on screen */
61 int cur_start = 0;
62 int cur_end = 0;
63
64 static VIOMODEINFO fossil_data;
65
66 static MOUEVENTINFO *pMouEvent = 0; /* Mouse Event storage */
67 static USHORT MouHandle; /* handle for the mouse */
68 static USHORT MouAvail = 0; /* mouse services available ? */
69 static MOU mstatus = {0, 39, 12, 0, 0, 1, 1, 0};
70 static EVT EVent[EBUFSZ]; /* event circular queue */
71 static int ebufin = 0; /* event in */
72 static int ebufout = 0; /* event out */
73
74 static int mykbhit(void);
75 static int FullBuffer(void);
76 static unsigned long hsec_time(void);
77
TTBeginOutput(void)78 void TTBeginOutput(void) {}
TTEndOutput(void)79 void TTEndOutput(void) {}
80
TTScolor(unsigned int Attr)81 int TTScolor(unsigned int Attr)
82 {
83 color = Attr & 0xFF; /* we don't need the F_ALTERNATE attribute! */
84 return 1;
85 }
86
TTCurSet(int st)87 int TTCurSet(int st)
88 {
89 static USHORT oldstart = 0, oldstop = 0;
90 VIOCURSORINFO *pcur = xmalloc16(sizeof(VIOCURSORINFO));
91
92 if (oldstart == 0)
93 {
94 if (cur_start != 0 && cur_end != 0)
95 {
96 /* save a user-defined cursor shape */
97 oldstart = (USHORT) cur_start;
98 oldstop = (USHORT) cur_end;
99 }
100 else
101 {
102 /* save the default cursor shape */
103 VioGetCurType((PVIOCURSORINFO) pcur, 0);
104 oldstart = pcur->yStart;
105 oldstop = pcur->cEnd;
106 }
107 }
108
109 if (st)
110 {
111 pcur->yStart = oldstart;
112 pcur->cEnd = oldstop;
113 pcur->attr = 0;
114 pcur->cx = 0;
115 VioSetCurType((PVIOCURSORINFO) pcur, 0);
116 }
117 else
118 {
119 pcur->yStart = oldstart;
120 pcur->cEnd = oldstop;
121 pcur->attr = 0xFFFF;
122 pcur->cx = 0;
123 VioSetCurType((PVIOCURSORINFO) pcur, 0);
124 }
125
126 xfree16(pcur);
127
128 return 0;
129 }
130
TTgotoxy(int row,int col)131 int TTgotoxy(int row, int col)
132 {
133 vrow = row;
134 vcol = col;
135 VioSetCurPos((short)row, (short)col, 0);
136 return 1;
137 }
138
TTgetxy(int * row,int * col)139 int TTgetxy(int *row, int *col)
140 {
141 *row = vrow;
142 *col = vcol;
143 return 1;
144 }
145
TTPutChr(unsigned int Ch)146 int TTPutChr(unsigned int Ch)
147 {
148 unsigned int *d = xmalloc16(sizeof(unsigned int));
149
150 *d = ((unsigned)Ch & 0xFF) | (color << 8);
151 VioWrtCellStr((PCH) d, 2, (short)vrow, (short)vcol, 0);
152
153 xfree16(d);
154
155 return 1;
156 }
157
TTWriteStr(unsigned long * b,int len,int row,int col)158 int TTWriteStr(unsigned long *b, int len, int row, int col)
159 {
160 unsigned short *ptr16;
161 int i;
162
163 if (len == 0)
164 {
165 return 1;
166 }
167
168 ptr16 = xmalloc16((short)(len * 2));
169
170 for (i = 0; i < len; i++)
171 {
172 ptr16[i] =
173 (unsigned short)((b[i] & 0xFFUL) | ((b[i] >> 8) & 0xFF00UL));
174 }
175
176 VioWrtCellStr((PCH) ptr16, (short)(len * 2), (short)row, (short)col & 0xFF, 0);
177 xfree16(ptr16);
178
179 return 1;
180 }
181
TTStrWr(unsigned char * s,int row,int col,int len)182 int TTStrWr(unsigned char *s, int row, int col, int len)
183 {
184 char *ptr16;
185
186 if (len < 0)
187 len = strlen((char *)s);
188
189 if (len == 0)
190 {
191 return 0;
192 }
193 ptr16 = xmalloc16(len);
194
195 memmove(ptr16, s, len);
196 VioWrtCharStrAtt((char *)ptr16, (short)len, (short)row, (short)col,
197 (PBYTE) &color, 0);
198 xfree16(ptr16);
199
200 return 1;
201 }
202
TTReadStr(unsigned long * b,int len,int row,int col)203 int TTReadStr(unsigned long *b, int len, int row, int col)
204 {
205 unsigned short l = (short)(len * 2);
206 unsigned short *ptr16;
207 int i;
208
209 if (l == 0)
210 {
211 return 1;
212 }
213 ptr16 = xmalloc16(l);
214 VioReadCellStr((PCH) ptr16, &l, (short)row, (short)col, 0);
215 for (i = 0; i < len; i++)
216 {
217 b[i] = MAKECELL((ptr16[i] & 0xFF), ((ptr16[i] >> 8) & 0xFF));
218 }
219 xfree16(ptr16);
220
221 return 1;
222 }
223
TTScroll(int x1,int y1,int x2,int y2,int lines,int Dir)224 int TTScroll(int x1, int y1, int x2, int y2, int lines, int Dir)
225 {
226 unsigned char *scroll_fill = xmalloc16(2);
227
228 if (Dir)
229 {
230 y2 = min(y2, term.NRow);
231 y1 = min(y1, term.NRow);
232 x1 = min(x1, term.NCol);
233 x2 = min(x2, term.NCol);
234 scroll_fill[0] = ' ';
235 scroll_fill[1] = (unsigned char)color;
236 if (lines == 0)
237 {
238 lines = -1;
239 }
240 VioScrollUp((short)y1, (short)x1, (short)y2, (short)x2,
241 (short)lines, (char *)scroll_fill, 0);
242 }
243 else
244 {
245 y2 = min(y2, term.NRow);
246 y1 = min(y1, term.NRow);
247 x1 = min(x1, term.NCol);
248 x2 = min(x2, term.NCol);
249 scroll_fill[0] = ' ';
250 scroll_fill[1] = (unsigned char)color;
251 if (lines == 0)
252 {
253 lines = -1;
254 }
255 VioScrollDn((short)y1, (short)x1, (short)y2, (short)x2,
256 (short)lines, (char *)scroll_fill, 0);
257 }
258 xfree16(scroll_fill);
259 return 1;
260 }
261
TTClear(int x1,int y1,int x2,int y2)262 int TTClear(int x1, int y1, int x2, int y2)
263 {
264 TTScroll(x1, y1, x2, y2, 0, 1);
265 return 1;
266 }
267
TTEeol(void)268 int TTEeol(void)
269 {
270 TTScroll(vcol, vrow, term.NCol - 1, vrow, 0, 1);
271 return 1;
272 }
273
TTdelay(int mil)274 int TTdelay(int mil)
275 {
276 DosSleep((long)mil);
277 return (0);
278 }
279
TTGetKey(void)280 unsigned int TTGetKey(void)
281 {
282 KBDKEYINFO *pki = xmalloc16(sizeof(KBDKEYINFO));
283 int retval;
284
285 pki->chChar = pki->chScan = 0;
286 KbdCharIn(pki, IO_WAIT, 0);
287
288 if (pki->chChar == 0xe0 && (pki->fbStatus & 2))
289 {
290 if (pki->chScan)
291 {
292 pki->chChar = 0; /* Force Scan return */
293 }
294 else
295 { /* Get next block */
296 pki->chChar = 0;
297 KbdCharIn(pki, IO_WAIT, 0);
298 if (!pki->chScan)
299 { /* Still no scan? */
300 pki->chScan = pki->chChar; /* Move new char over */
301 pki->chChar = 0; /* Force its return */
302 }
303 else
304 {
305 pki->chChar = 0; /* Force new scan */
306 }
307 }
308 }
309 if (pki->chScan == 0xe0 && (pki->fbStatus & 2))
310 {
311 if (!pki->chChar)
312 {
313 pki->chScan = 0;
314 KbdCharIn(pki, IO_WAIT, 0);
315 if (!pki->chScan)
316 { /* Still no scan? */
317 pki->chScan = pki->chChar; /* Move new char over */
318 pki->chChar = 0; /* Force its return */
319 }
320 else
321 {
322 pki->chChar = 0; /* Force new scan */
323 }
324 }
325 else
326 {
327 pki->chScan = 0; /* Handle 0xe00d case */
328 }
329 }
330 if (pki->chChar)
331 {
332 pki->chScan = 0;
333 }
334
335 retval = (unsigned int)((pki->chScan << 8) + (pki->chChar));
336 xfree16(pki);
337 return retval;
338 }
339
TTSendMsg(unsigned int msg,int x,int y,unsigned int msgtype)340 void TTSendMsg(unsigned int msg, int x, int y, unsigned int msgtype)
341 {
342 if (((ebufin + 1) % EBUFSZ) != ebufout)
343 {
344 EVent[ebufin].msg = msg;
345 EVent[ebufin].x = x;
346 EVent[ebufin].y = y;
347 EVent[ebufin].msgtype = msgtype;
348 ebufin = (ebufin + 1) % EBUFSZ;
349 }
350 }
351
352 #define CLICKMAX 50 /* second max */
353 #define PULSE_PAUSE 2
354 #define REPEAT_PAUSE 800
355
356 static unsigned long rtimer = 0;
357 static unsigned long ltimer = 0;
358 static unsigned long lpulse = 0;
359 static unsigned long rpulse = 0;
360
collect_events(int delay)361 int collect_events(int delay)
362 {
363 USHORT wait = MOU_NOWAIT;
364 static int oy = 0, ox = 0;
365 int moved = 0;
366 int evt = 0;
367 int temp1, temp2;
368
369
370 if (MouAvail)
371 {
372 MouReadEventQue(pMouEvent, &wait, MouHandle);
373
374 if (pMouEvent->time == 0)
375 {
376 if (mstatus.lbutton || mstatus.rbutton)
377 {
378 if (mstatus.lbutton && hsec_time() > ltimer && hsec_time() > lpulse)
379 {
380 lpulse = hsec_time() + PULSE_PAUSE;
381 TTSendMsg(LMOU_RPT, ox, oy, WND_WM_MOUSE);
382 }
383 else if (delay)
384 {
385 DosSleep(1L);
386 }
387
388 if (mstatus.rbutton && hsec_time() > rtimer && hsec_time() > rpulse)
389 {
390 rpulse = hsec_time() + PULSE_PAUSE;
391 TTSendMsg(RMOU_RPT, ox, oy, WND_WM_MOUSE);
392 }
393 else if (delay)
394 {
395 DosSleep(1L);
396 }
397 }
398 else if (delay)
399 {
400 DosSleep(1L);
401 }
402 }
403 else
404 {
405 temp1 = ((pMouEvent->fs & MOUSE_BN1_DOWN) || (pMouEvent->fs & MOUSE_MOTION_WITH_BN1_DOWN));
406 temp2 = ((pMouEvent->fs & MOUSE_BN2_DOWN) || (pMouEvent->fs & MOUSE_MOTION_WITH_BN2_DOWN));
407 evt = 0;
408
409 if (pMouEvent->col != ox || pMouEvent->row != oy)
410 {
411 ox = mstatus.x = pMouEvent->col;
412 oy = mstatus.y = pMouEvent->row;
413 }
414 moved = 1;
415
416 if (mstatus.lrelease && temp1)
417 {
418 evt = 1;
419 mstatus.lbutton = 1;
420 mstatus.lrelease = 0;
421 lpulse = hsec_time() + PULSE_PAUSE;
422 ltimer = hsec_time() + CLICKMAX;
423 TTSendMsg(MOU_LBTDN, ox, oy, WND_WM_MOUSE);
424 }
425 if (mstatus.lbutton && !temp1)
426 {
427 evt = 1;
428 mstatus.lbutton = 0;
429 mstatus.lrelease = 1;
430 TTSendMsg(MOU_LBTUP, ox, oy, WND_WM_MOUSE);
431
432 if (hsec_time() < ltimer)
433 {
434 TTSendMsg(LMOU_CLCK, ox, oy, WND_WM_MOUSE);
435 }
436
437 ltimer = 0;
438 }
439 if (mstatus.rrelease && temp2)
440 {
441 evt = 1;
442 mstatus.rbutton = 1;
443 mstatus.rrelease = 0;
444 rpulse = hsec_time() + PULSE_PAUSE;
445 rtimer = hsec_time() + CLICKMAX;
446 TTSendMsg(MOU_RBTDN, ox, oy, WND_WM_MOUSE);
447 }
448 if (mstatus.rbutton && !temp2)
449 {
450 evt = 1;
451 mstatus.rbutton = 0;
452 mstatus.rrelease = 1;
453 TTSendMsg(MOU_RBTUP, ox, oy, WND_WM_MOUSE);
454
455 if (hsec_time() < rtimer)
456 {
457 TTSendMsg(RMOU_CLCK, ox, oy, WND_WM_MOUSE);
458 }
459
460 rtimer = 0;
461 }
462 if ((moved && evt) || ((mstatus.rbutton || mstatus.lbutton) && moved))
463 {
464 TTSendMsg(MOUSE_EVT, ox, oy, WND_WM_MOUSE);
465 }
466 }
467 if (mykbhit())
468 {
469 TTSendMsg(TTGetKey(), 0, 0, WND_WM_CHAR);
470 }
471 else if (delay)
472 {
473 if (MouAvail)
474 {
475 DosSleep(1L);
476 }
477 else
478 {
479 DosSleep(50L);
480 }
481 }
482 }
483 else
484 {
485 if (mykbhit())
486 {
487 TTSendMsg(TTGetKey(), 0, 0, WND_WM_CHAR);
488 }
489 else if (delay)
490 {
491 if (MouAvail)
492 {
493 DosSleep(1L);
494 }
495 else
496 {
497 DosSleep(50L);
498 }
499 }
500 }
501 return 0;
502 }
503
TTkopen(void)504 int TTkopen(void)
505 {
506 return (0);
507 }
508
TTkclose(void)509 int TTkclose(void)
510 {
511 return (0);
512 }
513
MouseOFF(void)514 void MouseOFF(void)
515 {
516 NOPTRRECT *pmouRect = xmalloc16(sizeof(NOPTRRECT));
517
518 if (!MouAvail)
519 {
520 return;
521 }
522
523 pmouRect->row = 0;
524 pmouRect->col = 0;
525 pmouRect->cRow = (short)(term.NRow - 1);
526 pmouRect->cCol = (short)(term.NCol - 1);
527 MouRemovePtr(pmouRect, MouHandle);
528 xfree16(pmouRect);
529 }
530
MouseON(void)531 void MouseON(void)
532 {
533 if (!MouAvail)
534 {
535 return;
536 }
537 MouDrawPtr(MouHandle);
538 }
539
MouseInit(void)540 void MouseInit(void)
541 {
542 USHORT MouMask = MOUSE_MOTION | MOUSE_MOTION_WITH_BN1_DOWN | MOUSE_BN1_DOWN | MOUSE_MOTION_WITH_BN2_DOWN | MOUSE_BN2_DOWN | MOUSE_MOTION_WITH_BN3_DOWN | MOUSE_BN3_DOWN;
543
544 if (term.Abil & NOMOUSE)
545 {
546 return;
547 }
548
549 if (MouOpen(0L, &MouHandle))
550 {
551 MouAvail = 0;
552 return;
553 }
554
555 MouAvail = 1;
556 if (pMouEvent == 0)
557 {
558 pMouEvent = xmalloc16(sizeof(MOUEVENTINFO));
559 }
560
561 MouSetEventMask(&MouMask, MouHandle);
562 }
563
GetMouInfo(int * x,int * y)564 int GetMouInfo(int *x, int *y)
565 {
566 if (!MouAvail)
567 {
568 return 0;
569 }
570 collect_events(0);
571 *x = mstatus.x;
572 *y = mstatus.y;
573 return 0;
574 }
575
TTGetMsg(EVT * e)576 int TTGetMsg(EVT * e)
577 {
578 while (ebufin == ebufout)
579 {
580 collect_events(1);
581 }
582 e->msg = EVent[ebufout].msg;
583 e->x = EVent[ebufout].x;
584 e->y = EVent[ebufout].y;
585 e->msgtype = EVent[ebufout].msgtype;
586 e->id = 0;
587 ebufout = (ebufout + 1) % EBUFSZ;
588 return e->msg;
589 }
590
TTPeekQue(void)591 int TTPeekQue(void)
592 {
593 collect_events(0);
594 return (ebufin != ebufout);
595 }
596
TTClearQue(void)597 void TTClearQue(void)
598 {
599 ebufin = ebufout;
600 }
601
TTGetChr(void)602 int TTGetChr(void)
603 {
604 EVT e;
605 TTGetMsg(&e);
606 return e.msg;
607 }
608
TTopen(void)609 int TTopen(void)
610 {
611 KBDINFO *pki = xmalloc16(sizeof(KBDINFO));
612 fossil_data.cb = 2 * sizeof(fossil_data);
613 VioGetMode(&fossil_data, 0); /* Get mode info */
614 term.NCol = fossil_data.col; /* Maximum 'X' value */
615 term.NRow = fossil_data.row; /* Maximum 'Y' value */
616 pki->cb = sizeof(KBDINFO); /* Set binary keyboard mode */
617 pki->fsMask = KEYBOARD_BINARY_MODE;
618 KbdSetStatus(pki, 0);
619 vcol = vrow = 0;
620 color = 0x07;
621 TTkopen();
622 MouseInit();
623 xfree16(pki);
624 return 1;
625 }
626
TTclose(void)627 int TTclose(void)
628 {
629 TTkclose();
630 if (MouAvail)
631 {
632 if (pMouEvent != 0)
633 {
634 xfree16(pMouEvent);
635 pMouEvent = 0;
636 }
637
638 MouClose(MouHandle);
639 }
640 return 1;
641 }
642
643
644 #pragma warn -par
645
646 /*
647 * Configure the terminal. This must be called *before* TTopen!
648 *
649 * The OS/2 VIO terminal does not need any configuration.
650 *
651 */
652
TTconfigure(const char * keyword,const char * value)653 int TTconfigure(const char *keyword, const char *value)
654 {
655 return 0;
656 }
657
658 #pragma warn +par
659
660
mykbhit(void)661 static int mykbhit(void)
662 {
663 KBDKEYINFO *pki;
664 int retval;
665
666 if (FullBuffer())
667 {
668 return (0);
669 }
670
671 pki = xmalloc16(sizeof(KBDKEYINFO));
672 pki->fbStatus = 0;
673 KbdPeek(pki, 0);
674 retval = pki->fbStatus & KBDTRF_FINAL_CHAR_IN ? 1 : 0;
675 xfree16(pki);
676 return retval;
677 }
678
dv_running(void)679 int dv_running(void)
680 {
681 return 0;
682 }
683
FullBuffer(void)684 static int FullBuffer(void)
685 {
686 if (((ebufin + 1) % EBUFSZ) != ebufout)
687 {
688 return 0;
689 }
690 else
691 {
692 return 1;
693 }
694 }
695
hsec_time(void)696 static unsigned long hsec_time(void)
697 {
698 DATETIME pdt;
699 DosGetDateTime(&pdt);
700 return (pdt.year * 3214080000UL) + (pdt.month * 267840000L) +
701 (pdt.day * 8640000L) + (pdt.hours * 360000L) +
702 (pdt.minutes * 6000L) + (pdt.seconds * 100L) +
703 pdt.hundredths;
704 }
705