1 // This may look like C code, but it is really -*- C++ -*-
2
3 // ------------------------------------------------------------------
4 // The Goldware Library
5 // Copyright (C) 1990-1999 Odinn Sorensen
6 // Copyright (C) 1999-2000 Alexander S. Aganichev
7 // Copyright (C) 2000 Jacobo Tarrio
8 // ------------------------------------------------------------------
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Library General Public
11 // License as published by the Free Software Foundation; either
12 // version 2 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Library General Public License for more details.
18 //
19 // You should have received a copy of the GNU Library General Public
20 // License along with this program; if not, write to the Free
21 // Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22 // MA 02111-1307, USA
23 // ------------------------------------------------------------------
24 // $Id: gvidbase.cpp,v 1.1 2011/02/18 19:46:02 stas_degteff Exp $
25 // ------------------------------------------------------------------
26 // GCUI: Golded+ Character-oriented User Interface.
27 // Device-independent video functions.
28 // ------------------------------------------------------------------
29
30 #include <cstdio>
31 #include <cstdlib>
32 #include <cstdarg>
33 #include <gmemall.h>
34 #include <gmemdbg.h>
35 #include <gstrall.h>
36 #include <gvidall.h>
37
38 #if defined(__OS2__)
39 #define INCL_BASE
40 #include <os2.h>
41 #ifndef __EMX__
42 #define PCCH CHAR*
43 #endif
44 #endif
45
46 #ifdef __WIN32__
47 #include <windows.h>
48 #endif
49
50 #ifdef __GNUC__
51 #include <unistd.h>
52 #endif
53
54 #if defined(__DJGPP__)
55 #include <sys/farptr.h>
56 #endif
57
58
59 // ------------------------------------------------------------------
60 // Check if Borland C++ for OS/2 1.0 header has been fixed
61
62 #if defined(__OS2__) && defined(__BORLANDC__)
63 #if __BORLANDC__ <= 0x400
64 #ifndef BCOS2_BSESUB_FIXED
65 #error There is a bug in the BSESUB.H header. Please fix it.
66 //
67 // Add/change the following in BSESUB.H:
68 //
69 // #define BCOS2_BSESUB_FIXED
70 // APIRET16 APIENTRY16 VioGetState (PVOID16 pState, HVIO hvio);
71 // APIRET16 APIENTRY16 VioSetState (PVOID16 pState, HVIO hvio);
72 //
73 // Borland forgot this (was only PVOID) ^^
74 //
75 #endif
76 #endif
77 #endif
78
79
80 // ------------------------------------------------------------------
81
82 static bool __vcurhidden = false;
83 #if defined(__UNIX__) || defined(__USE_NCURSES__)
84 static uint32_t gvid_boxcvtc(char);
85 #endif
86
87 #if !defined(__USE_NCURSES__)
88
89 // ------------------------------------------------------------------
90
91 #ifdef __WIN32__
92 extern HANDLE gvid_hout;
93 extern OSVERSIONINFO WinVer; // defined in gutlwin.cpp
94 extern WCHAR oem2unicode[]; // defined in gutlwin.cpp
95
96 // ------------------------------------------------------------------
97 // Transform character < 32 into printable Unicode equivalent
98
99
gvid_tcpr(vchar chr)100 inline WCHAR gvid_tcpr(vchar chr) {
101
102 return oem2unicode[chr & 0xff];
103 }
104
105 #endif
106
107
108 // ------------------------------------------------------------------
109
110 #if defined(__MSDOS__) || defined(__UNIX__)
111
112 #if defined(__MSDOS__)
113 extern int __gdvdetected;
114 #endif
115
116 #ifndef __DJGPP__
117 const uint16_t _dos_ds = 0;
118
_my_ds(void)119 inline uint16_t _my_ds(void) {
120
121 return 0;
122 }
123
_farpokew(uint16_t s,gdma ptr,word chat)124 inline void _farpokew(uint16_t s, gdma ptr, word chat) {
125
126 NW(s);
127 *ptr = chat;
128 }
129
_farnspokew(gdma ptr,word chat)130 inline void _farnspokew(gdma ptr, word chat) {
131
132 *ptr = chat;
133 }
134
_farpeekw(uint16_t s,gdma ptr)135 inline word _farpeekw(uint16_t s, gdma ptr) {
136
137 NW(s);
138 return *ptr;
139 }
140
_farnspokeb(byte * ptr,byte chr)141 inline void _farnspokeb(byte *ptr, byte chr) {
142
143 *ptr = chr;
144 }
145
_farsetsel(uint16_t s)146 inline void _farsetsel(uint16_t s) {
147
148 NW(s);
149 }
150 #endif
151
152 #ifdef __DJGPP__
153 const int ATTRSIZE = sizeof(word);
154 #else
155 const int ATTRSIZE = 1;
156 #endif
157
gdmacpy(uint16_t seg_d,gdma sel_d,uint16_t seg_s,gdma sel_s,int len)158 inline void gdmacpy(uint16_t seg_d, gdma sel_d, uint16_t seg_s, gdma sel_s, int len) {
159
160 #ifdef __DJGPP__
161 movedata(seg_s, sel_s, seg_d, sel_d, len);
162 #else
163 NW(seg_d);
164 NW(seg_s);
165 memcpy(sel_d, sel_s, len);
166 #endif
167 }
168
gdmaptr(int col,int row)169 inline gdma gdmaptr(int col, int row) {
170
171 return gvid->dmaptr+ATTRSIZE*((row*gvid->numcols)+col);
172 }
173 #endif
174
175
176 // ------------------------------------------------------------------
177
178 #if defined(__UNIX__)
179
180
181 // ------------------------------------------------------------------
182
183 extern int gvid_stdout;
184 extern const char* gvid_acs_enable;
185 extern const char* gvid_acs_disable;
186 int gvid_last_attr = 0;
187
188
189 // ------------------------------------------------------------------
190
gvid_printf(const char * fmt,...)191 void gvid_printf(const char* fmt, ...) {
192
193 char buf[1024];
194 va_list argptr;
195 va_start(argptr, fmt);
196 int n = vsprintf(buf, fmt, argptr);
197 va_end(argptr);
198
199 write(gvid_stdout, buf, n);
200 }
201
202
203 // ------------------------------------------------------------------
204 // Control chars 01234567890123456789012345678901
205
206 const char* gvid_x0 = "x@xxxxxxxxxxxxxx><xxxxxx^vxxxx^v";
207
208
209 // ------------------------------------------------------------------
210
gvid_cvtchr(char & ch)211 inline void gvid_cvtchr(char& ch) {
212
213 register const char* x0 = gvid_x0;
214
215 if(ch < ' ')
216 ch = x0[ch];
217 }
218
219
220 // ------------------------------------------------------------------
221
gvid_cvtstr(char * s,int len)222 void gvid_cvtstr(char* s, int len) {
223
224 register char* p = s;
225
226 for(int n=0; n<len; n++,p++)
227 gvid_cvtchr(*p);
228 }
229
230
231 // ------------------------------------------------------------------
232
gvid_cvtstr(word * ws,int len)233 void gvid_cvtstr(word* ws, int len) {
234
235 register word* wp = ws;
236
237 for(int n=0; n<len; n++,wp++)
238 gvid_cvtchr(*(char*)wp);
239 }
240
241
242 // ------------------------------------------------------------------
243
244 static int _atr_to_ans[8] = {
245 0, // BLACK 0
246 4, // BLUE 1
247 2, // GREEN 2
248 6, // CYAN 3
249 1, // RED 4
250 5, // MAGENTA 5
251 3, // BROWN 6
252 7 // WHITE 7
253 };
254
255
256 // ------------------------------------------------------------------
257
vatr2ansin(int x)258 inline int vatr2ansin(int x) {
259
260 return (x & 8) ? 1 : 0;
261 }
262
263
264 // ------------------------------------------------------------------
265
vatr2ansfg(int x)266 inline int vatr2ansfg(int x) {
267
268 return _atr_to_ans[x & 7];
269 }
270
271
272 // ------------------------------------------------------------------
273
vatr2ansbg(int x)274 inline int vatr2ansbg(int x) {
275
276 return _atr_to_ans[(x>>4) & 7];
277 }
278
279
280 // ------------------------------------------------------------------
281
vputansi(int row,int col,word * buf,int len)282 void vputansi(int row, int col, word* buf, int len) {
283
284 char ch;
285 int in, fg, bg, acs;
286 int atr = gvid_last_attr;
287 int in0 = vatr2ansin(atr);
288 int fg0 = vatr2ansfg(atr);
289 int bg0 = vatr2ansbg(atr);
290 int acs0 = atr & ACSET;
291
292 // Get pointer to ANSI line buffer
293 char* ptr = gvid->bufansi;
294
295 // Get pointer to video memory image
296 byte* p = (byte*)buf;
297
298 for(int n=0; n<len; n++,p+=2) { // For each screen element
299
300 if(p[1] != atr) { // If attribute is different
301
302 atr = p[1]; // Store new attribute
303 gvid_last_attr = atr;
304
305 in = vatr2ansin(atr); // Get intensity
306 fg = vatr2ansfg(atr); // Get foreground color
307 bg = vatr2ansbg(atr); // Get background color
308 acs = atr & ACSET; // Get Alt Color Set
309
310 if(acs != acs0) {
311 ptr = stpcpy(ptr, acs ? gvid_acs_enable : gvid_acs_disable);
312 acs0 = acs;
313 }
314
315 *ptr++ = 0x1B; // Start ANSI color sequence
316 *ptr++ = '[';
317
318 if(in != in0) { // Set intensity if different
319 if(in)
320 *ptr++ = '1'; // Intense
321 else {
322 *ptr++ = '0'; // Reset
323 fg0 = bg0 = -1;
324 }
325 in0 = in;
326 if((fg != fg0) or (bg != bg0))
327 *ptr++ = ';';
328 }
329
330 if(fg != fg0) { // Set foreground if different
331 *ptr++ = '3';
332 *ptr++ = (char)('0' + fg);
333 fg0 = fg;
334 if(bg != bg0)
335 *ptr++ = ';';
336 }
337
338 if(bg != bg0) { // Set background if different
339 *ptr++ = '4';
340 *ptr++ = (char)('0' + bg);
341 bg0 = bg;
342 }
343
344 *ptr++ = 'm'; // End ANSI color sequence
345 }
346
347 ch = p[0];
348 gvid_cvtchr(ch);
349 *ptr++ = ch; // Output the character
350 }
351
352 *ptr = NUL; // Terminate string
353
354 // Print complete ANSI string at the specified position
355 gvid_printf("\x1B[%u;%uH%s", row+1, col+1, gvid->bufansi);
356 }
357
358
359 // ------------------------------------------------------------------
360
361 #endif
362
363 #endif // !defined(__USE_NCURSES__)
364
365
366 // ------------------------------------------------------------------
367 // Converts an attribute to monochrome equivalent
368
mapattr(vattr attr)369 vattr mapattr(vattr attr)
370 {
371 switch(attr&112) { // test for a light background
372
373 case _LGREY:
374 case _GREEN:
375 case _CYAN:
376 case _BROWN:
377 attr &= 240; // foreground = black
378 attr |= 112; // background = light grey
379 break;
380
381 default:
382 if((attr&15)==8) // if foreground = dark grey
383 attr &= 247; // clear intensity bit
384 attr |= 7; // foreground = light grey
385 attr &= 143; // background = black
386 }
387
388 return attr; // return converted attribute
389 }
390
391
392 // ------------------------------------------------------------------
393 // Reverses the attribute given
394
revsattr(vattr attr)395 vattr revsattr(vattr attr)
396 {
397 return (vattr)(((attr>>4)&0x07)|((attr<<4)&0x70)|(attr&0x80)|(attr&0x08));
398 }
399
400 #if !defined(__USE_NCURSES__)
401
402
403 // ------------------------------------------------------------------
404
405 #if defined(__UNIX__)
gvid_newattr(int & attr)406 char* gvid_newattr(int& attr) {
407
408 // 12345678901234567890
409 // E[1;33;44mE[11m
410 static char newattr[20];
411 *newattr = NUL;
412 if(attr != gvid_last_attr) {
413 if((attr & ~ACSET) != (gvid_last_attr & ~ACSET)) {
414 sprintf(newattr, "\033[%c;3%u;4%um",
415 vatr2ansin(attr) ? '1' : '0',
416 vatr2ansfg(attr),
417 vatr2ansbg(attr)
418 );
419 }
420 if((attr & ACSET) != (gvid_last_attr & ACSET))
421 strcat(newattr, (attr & ACSET) ? gvid_acs_enable : gvid_acs_disable);
422 gvid_last_attr = attr;
423 }
424
425 return newattr;
426 }
427 #endif
428
429
430 // ------------------------------------------------------------------
431 // OS/2 Vio* wrappers for prevent 16-bit segment overrun
432
433 #if defined(__OS2__)
434
435 #ifndef _THUNK_PTR_SIZE_OK
436 #define _THUNK_PTR_SIZE_OK(ptr,size) (((ULONG)(ptr) & ~0xffff) == (((ULONG)(ptr) + (size) - 1) & ~0xffff))
437 #endif
438
VioReadCellStr_(PCH str,PUSHORT pcb,USHORT row,USHORT col,HVIO hvio)439 static USHORT VioReadCellStr_(PCH str, PUSHORT pcb, USHORT row, USHORT col, HVIO hvio) {
440 USHORT rc, cb = *pcb;
441
442 if(_THUNK_PTR_SIZE_OK(str, cb))
443 return VioReadCellStr(str, pcb, row, col, hvio);
444 PCH newstr = (PCH)throw_xmalloc(cb * 2);
445 if(_THUNK_PTR_SIZE_OK(newstr, cb)) {
446 rc = VioReadCellStr(newstr, pcb, row, col, hvio);
447 if(rc == 0)
448 memcpy(str, newstr, *pcb);
449 }
450 else {
451 rc = VioReadCellStr(newstr + cb, pcb, row, col, hvio);
452 if(rc == 0)
453 memcpy(str, newstr + cb, *pcb);
454 }
455 throw_xfree(newstr);
456 return rc;
457 }
458
459
VioWrtCellStr_(PCCH str,USHORT cb,USHORT row,USHORT col,HVIO hvio)460 static USHORT VioWrtCellStr_(PCCH str, USHORT cb, USHORT row, USHORT col, HVIO hvio) {
461 USHORT rc;
462
463 if(_THUNK_PTR_SIZE_OK(str, cb ))
464 return VioWrtCellStr(str, cb, row, col, hvio);
465 PCH newstr = (PCH)throw_xmalloc(cb * 2);
466 if(_THUNK_PTR_SIZE_OK(newstr, cb)) {
467 memcpy(newstr, str, cb);
468 rc = VioWrtCellStr(newstr, cb, row, col, hvio);
469 }
470 else {
471 memcpy(newstr + cb, str, cb);
472 rc = VioWrtCellStr(newstr + cb, cb, row, col, hvio);
473 }
474 throw_xfree(newstr);
475 return rc;
476 }
477
478
VioWrtCharStrAtt_(PCCH str,USHORT cb,USHORT row,USHORT col,PBYTE attr,HVIO hvio)479 static USHORT VioWrtCharStrAtt_(PCCH str, USHORT cb, USHORT row, USHORT col, PBYTE attr, HVIO hvio) {
480 USHORT rc;
481
482 if(_THUNK_PTR_SIZE_OK(str, cb))
483 return VioWrtCharStrAtt(str, cb, row, col, attr, hvio);
484 PCH newstr = (PCH)throw_xmalloc(cb * 2);
485 if(_THUNK_PTR_SIZE_OK(newstr, cb)) {
486 memcpy(newstr, str, cb);
487 rc = VioWrtCharStrAtt(newstr, cb, row, col, attr, hvio);
488 }
489 else {
490 memcpy(newstr + cb, str, cb);
491 rc = VioWrtCharStrAtt(newstr + cb, cb, row, col, attr, hvio);
492 }
493 throw_xfree(newstr);
494 return rc;
495 }
496
497 #define VioReadCellStr VioReadCellStr_
498 #define VioWrtCellStr VioWrtCellStr_
499 #define VioWrtCharStrAtt VioWrtCharStrAtt_
500
501 #endif
502
503 // ------------------------------------------------------------------
504 // ncurses support functions
505
506 #else // defined(__USE_NCURSES__)
507
508 // ------------------------------------------------------------------
509 // Compute our attributes from DOS attributes
510
gvid_attrcalc(int dosattr)511 int gvid_attrcalc(int dosattr) {
512
513 // DOS attrs: XRGBxrgb
514 // color pair definition: 00RGBrgb, with last 3 bits negated
515 int attr;
516 attr = COLOR_PAIR(((dosattr & 0x70) >> 1) | ((~dosattr) & 0x07));
517 if(dosattr & 0x08)
518 attr |= A_BOLD;
519 // if(dosattr & 0x80)
520 // attr |= A_BLINK;
521
522 return attr;
523 }
524
525 // ------------------------------------------------------------------
526 // Compute DOS attributes from our attributes
527
gvid_dosattrcalc(int ourattr)528 int gvid_dosattrcalc(int ourattr) {
529
530 int attr = 0;
531 attr = PAIR_NUMBER(ourattr);
532 attr = ((attr & 0x38) << 1) | ((~attr) & 0x07);
533 if(ourattr & A_BLINK)
534 attr |= 0x80;
535 if(ourattr & A_BOLD)
536 attr |= 0x08;
537
538 return attr;
539 }
540
541 // ------------------------------------------------------------------
542 // Transform character < 32 into printable equivalent
543
544
gvid_tcpr(vchar chr)545 chtype gvid_tcpr(vchar chr) {
546
547 const chtype gvid_cpr[] = {
548 (chtype)' ', (chtype)'@', (chtype)'@', (chtype)'x',
549 (chtype) ACS_DIAMOND, (chtype)'x', (chtype)'x', ACS_BULLET,
550 ACS_BULLET, ACS_BULLET, ACS_BULLET, (chtype)'x',
551 (chtype)'x', (chtype)'x', (chtype)'x', ACS_LANTERN,
552 (chtype)ACS_RARROW, ACS_LARROW, (chtype)'x', (chtype)'!',
553 (chtype)'x', (chtype)'x', ACS_S1, (chtype)'x',
554 ACS_UARROW, ACS_DARROW, ACS_LARROW, (chtype)ACS_RARROW,
555 (chtype)'x', (chtype)'x', ACS_UARROW, ACS_DARROW
556 };
557
558 chtype ch = chr & A_CHARTEXT;
559 chtype at = chr & (~A_CHARTEXT);
560
561 if(ch<' ')
562 return gvid_cpr[ch] | at;
563 else
564 return ch | at;
565 }
566
567
568 // ------------------------------------------------------------------
569
570 #endif // defined(__USE_NCURSES__)
571
572
573 // ------------------------------------------------------------------
574 // Print character and attribute at specfied location
575
576 #if (defined(__MSDOS__) || defined(__UNIX__)) && !defined(__USE_NCURSES__)
_vputw(int row,int col,word chat)577 inline void _vputw(int row, int col, word chat) {
578
579 _farpokew(_dos_ds, gdmaptr(col, row), chat);
580 }
581 #endif
582
583
vputw(int row,int col,vatch chat)584 void vputw(int row, int col, vatch chat) {
585
586 #if defined(__USE_NCURSES__)
587
588 mvaddch(row, col, chat);
589 refresh();
590
591 #elif defined(__MSDOS__)
592
593 if(gvid->isdma()) {
594 _vputw(row, col, chat);
595 }
596 else if(gvid->isbios() or gvid->iscga()) {
597 i86 cpu;
598 cpu.ah(2);
599 cpu.bh(0);
600 cpu.dh((byte)row);
601 cpu.dl((byte)col);
602 cpu.genint(0x10);
603 cpu.ah(9);
604 cpu.al(vgchar(chat));
605 cpu.bh(0);
606 cpu.bl(vgattr(chat));
607 cpu.cx(1);
608 cpu.genint(0x10);
609 }
610
611 #elif defined(__OS2__)
612
613 VioWrtNCell((BYTE *)&chat, 1, (USHORT)row, (USHORT)col, 0);
614
615 #elif defined(__WIN32__)
616
617 const COORD coord = {0, 0};
618 const COORD size = {1, 1};
619 SMALL_RECT rect;
620
621 rect.Top = row;
622 rect.Left = col;
623 rect.Bottom = row+size.Y-1;
624 rect.Right = col+size.X-1;
625 if(WinVer.dwPlatformId == VER_PLATFORM_WIN32_NT) {
626 chat.Char.UnicodeChar = gvid_tcpr(vgchar(chat));
627 WriteConsoleOutputW(gvid_hout, &chat, size, coord, &rect);
628 }
629 else
630 WriteConsoleOutputA(gvid_hout, &chat, size, coord, &rect);
631
632 #elif defined(__UNIX__)
633
634 char chr = vgchar(chat);
635 int atr = vgattr(chat);
636 char* color = gvid_newattr(atr);
637
638 gvid_cvtstr(&chat, 1);
639 _vputw(row, col, chat);
640
641 gvid_printf("\033[%u;%uH%s%c", row+1, col+1, color, chr);
642
643 #endif
644 }
645
646
647 // ------------------------------------------------------------------
648 // Print attrib/char buffer at specfied location
649
vputws(int row,int col,vatch * buf,uint len)650 void vputws(int row, int col, vatch* buf, uint len) {
651
652 #if defined(__USE_NCURSES__)
653
654 move(row, col);
655 for(int counter = 0; counter < len; counter++)
656 addch(buf[counter]);
657 refresh();
658
659 #elif defined(__MSDOS__)
660
661 if(gvid->isdma()) {
662 gdmacpy(_dos_ds, (gdma)gdmaptr(col, row), _my_ds(), (gdma)buf, len*sizeof(word));
663 }
664 else if(gvid->isbios() or gvid->iscga()) {
665 i86 cpu;
666 byte* p = (byte*)buf;
667 for(uint n=0; n<len; n++) {
668 cpu.ah(2);
669 cpu.bh(0);
670 cpu.dh((byte)row);
671 cpu.dl((byte)col++);
672 cpu.genint(0x10);
673 cpu.ah(9);
674 cpu.al(*p++);
675 cpu.bh(0);
676 cpu.bl(*p++);
677 cpu.cx(1);
678 cpu.genint(0x10);
679 }
680 }
681
682 #elif defined(__OS2__)
683
684 VioWrtCellStr((PCCH)buf, (USHORT)(len*2), (USHORT)row, (USHORT)col, 0);
685
686 #elif defined(__WIN32__)
687
688 const COORD coord = {0, 0};
689 COORD size = {len, 1};
690 SMALL_RECT rect;
691
692 rect.Top = row;
693 rect.Left = col;
694 rect.Bottom = row+size.Y-1;
695 rect.Right = col+size.X-1;
696 if(WinVer.dwPlatformId == VER_PLATFORM_WIN32_NT) {
697 for(int i = 0; i < len; i++) {
698 buf[i].Char.UnicodeChar = gvid_tcpr(vgchar(buf[i]));
699 }
700 WriteConsoleOutputW(gvid_hout, buf, size, coord, &rect);
701 }
702 else
703 WriteConsoleOutputA(gvid_hout, buf, size, coord, &rect);
704
705 #elif defined(__UNIX__)
706
707 gvid_cvtstr(buf, len);
708 gdmacpy(_dos_ds, (gdma)gdmaptr(col, row), _my_ds(), (gdma)buf, len*sizeof(word));
709 vputansi(row, col, buf, len);
710
711 #endif
712 }
713
714
715 // ------------------------------------------------------------------
716 // Print character and attribute at specfied location
717
vputc(int row,int col,vattr atr,vchar chr)718 void vputc(int row, int col, vattr atr, vchar chr) {
719
720 #if defined(__USE_NCURSES__)
721
722 mvaddch(row, col, vcatch(gvid_tcpr(chr), atr));
723 refresh();
724
725 #elif defined(__MSDOS__)
726
727 if(gvid->isdma()) {
728 _vputw(row, col, vcatch(chr, atr));
729 }
730 else if(gvid->isbios() or gvid->iscga()) {
731 i86 cpu;
732 cpu.ah(2);
733 cpu.bh(0);
734 cpu.dh((byte)row);
735 cpu.dl((byte)col);
736 cpu.genint(0x10);
737 cpu.ah(9);
738 cpu.al(chr);
739 cpu.bh(0);
740 cpu.bl((byte)atr);
741 cpu.cx(1);
742 cpu.genint(0x10);
743 }
744
745 #elif defined(__OS2__) || defined(__WIN32__)
746
747 vputw(row, col, vcatch(chr, atr));
748
749 #elif defined(__UNIX__)
750
751 char* color = gvid_newattr(atr);
752 gvid_cvtstr(&chr, 1);
753 _vputw(row, col, vcatch(chr, atr));
754
755 gvid_printf("\033[%u;%uH%s%c", row+1, col+1, color, chr);
756
757 #endif
758 }
759
760
761 // ------------------------------------------------------------------
762 // Print string with attribute at specfied location
763
vputvs(int row,int col,vattr atr,const vchar * str)764 void vputvs(int row, int col, vattr atr, const vchar* str) {
765
766 #if defined(__USE_NCURSES__)
767
768 uint counter;
769 int attr = gvid_attrcalc(atr);
770 move(row, col);
771 for(counter = 0; str[counter] != 0; counter++)
772 addch(gvid_tcpr(str[counter]) | attr);
773 refresh();
774
775 #else
776
777 vputs(row, col, atr, str);
778
779 #endif
780 }
781
782
783 // ------------------------------------------------------------------
784 // Print string with attribute at specfied location
785
vputs_box(int row,int col,vattr atr,const char * str)786 void vputs_box(int row, int col, vattr atr, const char* str) {
787 #if defined(__USE_NCURSES__)
788 uint counter;
789 int len = strlen(str);
790 int attr = gvid_attrcalc(atr);
791 move(row, col);
792 for(counter = 0; counter < len; counter++)
793 addch(gvid_tcpr(gvid_boxcvtc(str[counter])) | attr);
794 refresh();
795 #else
796 vputs(row, col, atr, str);
797 #endif
798 }
799
vputs(int row,int col,vattr atr,const char * str)800 void vputs(int row, int col, vattr atr, const char* str) {
801
802 #if defined(__USE_NCURSES__)
803
804 uint counter;
805 int len = strlen(str);
806 int attr = gvid_attrcalc(atr);
807 move(row, col);
808 for(counter = 0; counter < len; counter++)
809 addch(gvid_tcpr(str[counter]) | attr);
810 refresh();
811
812 #elif defined(__MSDOS__)
813
814 if(gvid->isdma()) {
815 gdma p = gdmaptr(col, row);
816 _farsetsel(_dos_ds);
817 while(*str) {
818 _farnspokew(p, vcatch(*str++, atr));
819 p += ATTRSIZE;
820 }
821 }
822 else if(gvid->isbios() or gvid->iscga()) {
823 i86 cpu;
824 for(const char* q=str; *q; q++) {
825 // Write as fast as possible on XT bios...
826 cpu.ah(2);
827 cpu.bh(0);
828 cpu.dh((byte)row);
829 cpu.dl((byte)(col++));
830 cpu.genint(0x10);
831 cpu.ah(9);
832 cpu.al(*q);
833 cpu.bh(0);
834 cpu.bl((byte)atr);
835 cpu.cx(1);
836 cpu.genint(0x10);
837 }
838 }
839
840 #elif defined(__OS2__)
841
842 VioWrtCharStrAtt((PCCH)str, (USHORT)strlen(str), (USHORT)row, (USHORT)col, (PBYTE)&atr, 0);
843
844 #elif defined(__WIN32__)
845
846 int i;
847
848 for(i = 0; *str && (i < gvid->numcols); i++)
849 gvid->bufwrd[i] = vcatch(*str++, atr);
850 if(i)
851 vputws(row, col, gvid->bufwrd, i);
852
853 #elif defined(__UNIX__)
854
855 char buf[1024];
856 strcpy(buf, str);
857 char* color = gvid_newattr(atr);
858 gvid_cvtstr(buf, strlen(buf));
859 gdma p = gdmaptr(col, row);
860 _farsetsel(_dos_ds);
861 while(*str) {
862 _farnspokew(p, vcatch(*str++, atr));
863 p += ATTRSIZE;
864 }
865
866 gvid_printf("\033[%u;%uH%s%s", row+1, col+1, color, buf);
867
868 #endif
869 }
870
871
872 // ------------------------------------------------------------------
873 // Print string with attribute at specfied location
874
875 #if (defined(__MSDOS__) || defined(__UNIX__)) && !defined(__USE_NCURSES__)
_vputns(int row,int col,int atr,const char * str,uint width)876 static void _vputns(int row, int col, int atr, const char* str, uint width) {
877
878 char fillchar = ' ';
879
880 gdma p = gdmaptr(col, row);
881 _farsetsel(_dos_ds);
882 while(width--) {
883 _farnspokew(p, (atr << 8) | (*str ? *str++ : fillchar));
884 p += ATTRSIZE;
885 }
886 }
887 #endif
888
889
890 // ------------------------------------------------------------------
891 // Print string with attribute at specfied location
892
vputns(int row,int col,vattr atr,const char * str,uint width)893 void vputns(int row, int col, vattr atr, const char* str, uint width) {
894
895 char fillchar = ' ';
896
897 #if defined(__USE_NCURSES__)
898
899 uint counter;
900 int len = strlen(str);
901 int attr = gvid_attrcalc(atr);
902 move(row, col);
903 for(counter = 0; counter < width; counter++) {
904 if(counter<len)
905 addch(gvid_tcpr(str[counter]) | attr);
906 else
907 addch(gvid_tcpr(fillchar) | attr);
908 }
909 refresh();
910
911 #elif defined(__MSDOS__)
912
913 if(gvid->isdma()) {
914 _vputns(row, col, atr, str, width);
915 }
916 else if(gvid->isbios() or gvid->iscga()) {
917 i86 cpu;
918 while(width--) {
919 // Write as fast as possible on XT bios...
920 cpu.ah(2);
921 cpu.bh(0);
922 cpu.dh((byte)row);
923 cpu.dl((byte)(col++));
924 cpu.genint(0x10);
925 cpu.ah(9);
926 cpu.al(*str ? *str++ : fillchar);
927 cpu.bh(0);
928 cpu.bl((byte)atr);
929 cpu.cx(1);
930 cpu.genint(0x10);
931 }
932 }
933
934 #elif defined(__OS2__)
935
936 uint len = strlen(str);
937
938 VioWrtCharStrAtt((PCCH)str, (USHORT)minimum_of_two(len,width), (USHORT)row, (USHORT)col, (PBYTE)&atr, 0);
939
940 if(width > len) {
941 vatch filler = vcatch(fillchar, atr);
942 VioWrtNCell((BYTE *)&filler, (USHORT)(width-len), (USHORT)row, (USHORT)(col+len), 0);
943 }
944
945 #elif defined(__WIN32__)
946
947 int i;
948
949 if (width > gvid->numcols)
950 width = gvid->numcols;
951
952 for(i = 0; (i < width) and *str; i++)
953 gvid->bufwrd[i] = vcatch(*str++, atr);
954 vatch filler = vcatch(fillchar, atr);
955 for(; i < width; i++)
956 gvid->bufwrd[i] = filler;
957 vputws(row, col, gvid->bufwrd, width);
958
959 #elif defined(__UNIX__)
960
961 char* color = gvid_newattr(atr);
962
963 uint len = strlen(str);
964 uint min_len = minimum_of_two(len, width);
965 char buf[1024];
966 strcpy(buf, str);
967 gvid_cvtstr(buf, len);
968
969 _vputns(row, col, atr, buf, width);
970
971 char fillbuf[256];
972 if(width > len) {
973 memset(fillbuf, fillchar, width-len);
974 fillbuf[width-len] = NUL;
975 }
976 else {
977 *fillbuf = NUL;
978 }
979
980 gvid_printf("\033[%u;%uH%s%*.*s%s", row+1, col+1, color,
981 min_len, min_len, buf, fillbuf
982 );
983
984 #endif
985 }
986
987
988 // ------------------------------------------------------------------
989 // Print horizontal line of character and attribute
990
991 #if (defined(__MSDOS__) || defined(__UNIX__)) && !defined(__USE_NCURSES__)
_vputx(int row,int col,int atr,char chr,uint len)992 void _vputx(int row, int col, int atr, char chr, uint len) {
993
994 gdma p = gdmaptr(col, row);
995 word tmp = vcatch(chr, atr);
996 _farsetsel(_dos_ds);
997 for(uint n=0; n<len; n++) {
998 _farnspokew(p, tmp);
999 p += ATTRSIZE;
1000 }
1001 }
1002 #endif
1003
1004
1005 // ------------------------------------------------------------------
1006 // Print horizontal line of character and attribute
1007
vputx(int row,int col,vattr atr,vchar chr,uint len)1008 void vputx(int row, int col, vattr atr, vchar chr, uint len) {
1009
1010 #if defined(__USE_NCURSES__)
1011
1012 mvhline(row, col, vcatch(gvid_tcpr(chr), atr), len);
1013 refresh();
1014
1015 #elif defined(__MSDOS__)
1016
1017 if(gvid->isdma()) {
1018 _vputx(row, col, atr, chr, len);
1019 }
1020 else if(gvid->isbios() or gvid->iscga()) {
1021 i86 cpu;
1022 cpu.ah(2);
1023 cpu.bh(0);
1024 cpu.dh((byte)row);
1025 cpu.dl((byte)col);
1026 cpu.genint(0x10);
1027 cpu.ah(9);
1028 cpu.al(chr);
1029 cpu.bh(0);
1030 cpu.bl((byte)atr);
1031 cpu.cx((word)len);
1032 cpu.genint(0x10);
1033 }
1034
1035 #elif defined(__OS2__)
1036
1037 vatch filler = vcatch(chr, atr);
1038 VioWrtNCell((BYTE *)&filler, (USHORT)len, (USHORT)row, (USHORT)col, 0);
1039
1040 #elif defined(__WIN32__)
1041
1042 if (len > gvid->numcols)
1043 len = gvid->numcols;
1044
1045 vatch filler = vcatch(chr, atr);
1046 for(int i = 0; i < len; i++)
1047 gvid->bufwrd[i] = filler;
1048 vputws(row, col, gvid->bufwrd, len);
1049
1050 #elif defined(__UNIX__)
1051
1052 char buf[256];
1053 char* color = gvid_newattr(atr);
1054 gvid_cvtchr(chr);
1055 _vputx(row, col, atr, chr, len);
1056 memset(buf, chr, len);
1057 buf[len] = NUL;
1058 gvid_printf("\033[%u;%uH%s%s", row+1, col+1, color, buf);
1059
1060 #endif
1061 }
1062
1063
1064 // ------------------------------------------------------------------
1065 // Print vertical line of character and attribute
1066
1067 #if (defined(__MSDOS__) || defined(__UNIX__)) && !defined(__USE_NCURSES__)
_vputy(int row,int col,int atr,char chr,uint len)1068 inline void _vputy(int row, int col, int atr, char chr, uint len) {
1069
1070 gdma p = gdmaptr(col, row);
1071 word tmp = vcatch(chr, atr);
1072 _farsetsel(_dos_ds);
1073 for(uint n=0; n<len; n++) {
1074 _farnspokew(p, tmp);
1075 p += ATTRSIZE*gvid->numcols;
1076 }
1077 }
1078 #endif
1079
1080
1081 // ------------------------------------------------------------------
1082 // Print vertical line of character and attribute
1083
vputy(int row,int col,vattr atr,vchar chr,uint len)1084 void vputy(int row, int col, vattr atr, vchar chr, uint len) {
1085
1086 #if defined(__USE_NCURSES__)
1087
1088 mvvline(row, col, vcatch(gvid_tcpr(chr), atr), len);
1089 refresh();
1090
1091 #elif defined(__MSDOS__)
1092
1093 if(gvid->isdma()) {
1094 _vputy(row, col, atr, chr, len);
1095 }
1096 else if(gvid->isbios() or gvid->iscga()) {
1097 for(uint n=0; n<len; n++) {
1098 i86 cpu;
1099 cpu.ah(2);
1100 cpu.bh(0);
1101 cpu.dh((byte)row++);
1102 cpu.dl((byte)col);
1103 cpu.genint(0x10);
1104 cpu.ah(9);
1105 cpu.al(chr);
1106 cpu.bh(0);
1107 cpu.bl((byte)atr);
1108 cpu.cx(1);
1109 cpu.genint(0x10);
1110 }
1111 }
1112
1113 #elif defined(__OS2__)
1114
1115 vatch filler = vcatch(chr, atr);
1116 for(int n=0; n<len; n++)
1117 VioWrtNCell((BYTE *)&filler, 1, (USHORT)row++, (USHORT)col, 0);
1118
1119 #elif defined(__WIN32__)
1120
1121 vatch filler = vcatch(chr, atr);
1122 for(int i=0; i < len; i++)
1123 vputw(row++, col, filler);
1124
1125 #elif defined(__UNIX__)
1126
1127 char* color = gvid_newattr(atr);
1128 gvid_cvtchr(chr);
1129 _vputy(row, col, atr, chr, len);
1130
1131 char buf[2048];
1132 sprintf(buf, "\033[%u;%uH%s", row+1, col+1, color);
1133
1134 char* p = buf + strlen(buf);
1135 for(uint n=0; n<(len-1); n++) {
1136 *p++ = chr;
1137 if(col == gvid->numcols-1) {
1138 sprintf(p, "\033[%u;%uH", row+n+2, col+1);
1139 p += strlen(p);
1140 }
1141 else {
1142 strcpy(p, "\033[D\033[B");
1143 p += 6;
1144 }
1145 }
1146 *p++ = chr;
1147 *p = NUL;
1148 gvid_printf("%s", buf);
1149
1150 #endif
1151 }
1152
1153
1154 // ------------------------------------------------------------------
1155 // Get character and attribute at cursor position
1156
1157 #if (defined(__MSDOS__) || defined(__UNIX__)) && !defined(__USE_NCURSES__)
_vgetw(int row,int col)1158 inline word _vgetw(int row, int col) {
1159
1160 return _farpeekw(_dos_ds, gdmaptr(col, row));
1161 }
1162 #endif
1163
1164
1165 // ------------------------------------------------------------------
1166 // Get character and attribute at cursor position
1167
vgetw(int row,int col)1168 vatch vgetw(int row, int col) {
1169
1170 #if defined(__USE_NCURSES__)
1171
1172 return mvinch(row, col);
1173
1174 #elif defined(__MSDOS__)
1175
1176 if(gvid->isdma()) {
1177 return _vgetw(row, col);
1178 }
1179 else if(gvid->isbios() or gvid->iscga()) {
1180 i86 cpu;
1181 cpu.ah(2);
1182 cpu.bh(0);
1183 cpu.dh((byte)row);
1184 cpu.dl((byte)col);
1185 cpu.genint(0x10);
1186 cpu.ah(8);
1187 cpu.bh(0);
1188 cpu.genint(0x10);
1189 return cpu.ax();
1190 }
1191 return 0;
1192
1193 #elif defined(__OS2__)
1194
1195 vatch chat;
1196 USHORT len=sizeof(chat);
1197
1198 VioReadCellStr((BYTE *)&chat, &len, (USHORT)row, (USHORT)col, 0);
1199
1200 return chat;
1201
1202 #elif defined(__WIN32__)
1203
1204 vatch chat;
1205 const COORD coord = {0, 0};
1206 const COORD size = {1, 1};
1207 SMALL_RECT rect;
1208
1209 rect.Top = row;
1210 rect.Left = col;
1211 rect.Bottom = row+size.Y-1;
1212 rect.Right = col+size.X-1;
1213 ReadConsoleOutput(gvid_hout, &chat, size, coord, &rect);
1214
1215 return chat;
1216
1217 #elif defined(__UNIX__)
1218
1219 return _vgetw(row, col);
1220
1221 #endif
1222 }
1223
1224
1225 // ------------------------------------------------------------------
1226 // Get character and attribute at cursor position
1227
vgetc(int row,int col,vattr * atr,vchar * chr)1228 void vgetc(int row, int col, vattr* atr, vchar* chr) {
1229
1230 if((row < 0) or (row > gvid->numrows-1) or (col < 0) or (col > gvid->numcols-1)) {
1231 *chr = ' ';
1232 *atr = BLACK_|_BLACK;
1233 }
1234 else {
1235 vatch tmp = vgetw(row, col);
1236
1237 *chr = vgchar(tmp);
1238 *atr = vgattr(tmp);
1239 }
1240 }
1241
1242
1243 // ------------------------------------------------------------------
1244 // Scroll screen area
1245
1246 #if (defined(__MSDOS__) || defined(__UNIX__)) && !defined(__USE_NCURSES__)
_vscroll(int srow,int scol,int erow,int ecol,int atr,int lines)1247 static void _vscroll(int srow, int scol, int erow, int ecol, int atr, int lines) {
1248
1249 word empty = (atr << 8) | ' ';
1250 if(lines > 0) {
1251 while(lines--) {
1252 int nrow = srow;
1253 int l = ((ecol - scol) + 1);
1254 gdma scrptr = gdmaptr(scol, srow);
1255 while(nrow++ < erow) {
1256 gdmacpy(_dos_ds, (gdma)scrptr, _dos_ds, (gdma)(scrptr+ATTRSIZE*gvid->numcols), l*sizeof(word));
1257 scrptr += ATTRSIZE*gvid->numcols;
1258 }
1259 _farsetsel(_dos_ds);
1260 for(l *= ATTRSIZE; l>0;) {
1261 l -= ATTRSIZE;
1262 _farnspokew(scrptr+l, empty);
1263 }
1264 }
1265 }
1266 else {
1267 while(lines++) {
1268 int nrow = erow;
1269 int l = ((ecol - scol) + 1);
1270 gdma scrptr = gdmaptr(scol, erow);
1271 while(nrow-- >= (srow + 1)) {
1272 gdmacpy(_dos_ds, (gdma)scrptr, _dos_ds, (gdma)(scrptr-ATTRSIZE*gvid->numcols), l*sizeof(word));
1273 scrptr -= ATTRSIZE*gvid->numcols;
1274 }
1275 _farsetsel(_dos_ds);
1276 for(l *= ATTRSIZE; l>0;) {
1277 l -= ATTRSIZE;
1278 _farnspokew(scrptr+l, empty);
1279 }
1280 }
1281 }
1282 }
1283 #endif
1284
1285
1286 // ------------------------------------------------------------------
1287 // Scroll screen area
1288
vscroll(int srow,int scol,int erow,int ecol,vattr atr,int lines)1289 void vscroll(int srow, int scol, int erow, int ecol, vattr atr, int lines) {
1290
1291 #if defined(__USE_NCURSES__)
1292
1293 vatch filler = vcatch(' ', atr);
1294
1295 // Currently implemented with vsave/vrestore
1296 // Does anyone know a better solution?
1297
1298 if(lines >= 0) {
1299 if(lines <= 1 + erow - srow) {
1300 vsavebuf *buf = vsave(srow + lines, scol, erow, ecol);
1301 vrestore(buf, srow, scol, erow - lines, ecol);
1302 throw_xfree(buf);
1303 }
1304 else
1305 lines = 1 + erow - srow;
1306
1307 for(int counter = 0; counter < lines; counter++)
1308 mvhline(1 + erow + counter - lines, scol, filler, 1 + ecol - scol);
1309 refresh();
1310 }
1311 else {
1312 lines*=-1;
1313 if(lines <= 1 + erow - srow) {
1314 vsavebuf *buf = vsave(srow, scol, erow - lines, ecol);
1315 vrestore(buf, srow + lines, scol, erow, ecol);
1316 throw_xfree(buf);
1317 }
1318 else
1319 lines = 1 + erow - srow;
1320
1321 for(int counter = 0; counter < lines; counter++)
1322 mvhline(srow + counter, scol, filler, 1 + ecol - scol);
1323 refresh();
1324 }
1325
1326 #elif defined(__MSDOS__)
1327
1328 if(gvid->isdma()) {
1329 _vscroll(srow, scol, erow, ecol, atr, lines);
1330 }
1331 else if(gvid->isbios() or gvid->iscga()) {
1332 i86 cpu;
1333 cpu.ah((byte)(lines > 0 ? 6 : 7));
1334 cpu.al((byte)absolute(lines));
1335 cpu.bh((byte)atr);
1336 cpu.ch((byte)srow);
1337 cpu.cl((byte)scol);
1338 cpu.dh((byte)erow);
1339 cpu.dl((byte)ecol);
1340 cpu.genint(0x10);
1341 }
1342
1343 #elif defined(__OS2__)
1344
1345 vatch filler = vcatch(' ', atr);
1346
1347 if(lines > 0)
1348 VioScrollUp((USHORT)srow, (USHORT)scol, (USHORT)erow, (USHORT)ecol, (USHORT)lines, (BYTE *)&filler, 0);
1349 else
1350 VioScrollDn((USHORT)srow, (USHORT)scol, (USHORT)erow, (USHORT)ecol, (USHORT)-lines, (BYTE *)&filler, 0);
1351
1352 #elif defined(__WIN32__)
1353
1354 SMALL_RECT r;
1355 COORD c = {scol, srow - lines};
1356 vatch filler = vcatch(' ', atr);
1357
1358 r.Left = (SHORT)scol;
1359 r.Top = (SHORT)srow;
1360 r.Right = (SHORT)ecol;
1361 r.Bottom = (SHORT)erow;
1362
1363 ScrollConsoleScreenBuffer(gvid_hout, &r, &r, c, &filler);
1364
1365 #elif defined(__UNIX__)
1366
1367 _vscroll(srow, scol, erow, ecol, atr, lines);
1368
1369 gdma ptr = gdmaptr(scol, srow);
1370 int len = ecol-scol+1;
1371 for(int nrow=srow; nrow<=erow; nrow++) {
1372 vputansi(nrow, scol, ptr, len);
1373 ptr += ATTRSIZE*gvid->numcols;
1374 }
1375
1376 #endif
1377 }
1378
1379
1380 // ------------------------------------------------------------------
1381 // Returns true if cursor invisible
1382
vcurhidden()1383 bool vcurhidden() {
1384
1385 return __vcurhidden;
1386 }
1387
1388 // ------------------------------------------------------------------
1389 // Get cursor position
1390
vposget(int * row,int * col)1391 void vposget(int* row, int* col) {
1392
1393 #if defined(__USE_NCURSES__)
1394
1395 getyx(stdscr, gvid->currow, gvid->curcol);
1396
1397 #elif defined(__MSDOS__)
1398
1399 i86 cpu;
1400 cpu.ah(3);
1401 cpu.bh(0);
1402 cpu.genint(0x10);
1403 gvid->currow = cpu.dh();
1404 gvid->curcol = cpu.dl();
1405
1406 #elif defined(__OS2__)
1407
1408 USHORT _getrow, _getcol;
1409 VioGetCurPos(&_getrow, &_getcol, 0);
1410 gvid->currow = _getrow;
1411 gvid->curcol = _getcol;
1412
1413 #elif defined(__WIN32__)
1414
1415 CONSOLE_SCREEN_BUFFER_INFO i;
1416 GetConsoleScreenBufferInfo(gvid_hout, &i);
1417 gvid->currow = i.dwCursorPosition.Y;
1418 gvid->curcol = i.dwCursorPosition.X;
1419
1420 #elif defined(__UNIX__)
1421
1422 // Not available
1423
1424 #endif
1425
1426 *row = gvid->currow;
1427 *col = gvid->curcol;
1428 }
1429
1430
1431 // ------------------------------------------------------------------
1432 // Set cursor position
1433
vposset(int row,int col)1434 void vposset(int row, int col) {
1435
1436 gvid->currow = row;
1437 gvid->curcol = col;
1438
1439 #if defined(__USE_NCURSES__)
1440
1441 move(row, col);
1442 refresh();
1443
1444 #elif defined(__MSDOS__)
1445
1446 i86 cpu;
1447 cpu.ah(2);
1448 cpu.bh(0);
1449 cpu.dh((byte)row);
1450 cpu.dl((byte)col);
1451 cpu.genint(0x10);
1452
1453 #elif defined(__OS2__)
1454
1455 VioSetCurPos((USHORT)row, (USHORT)col, 0);
1456
1457 #elif defined(__WIN32__)
1458
1459 // No need to set the cursor position if its not visible
1460 // Strangely, this is a major speedup to screen-output
1461
1462 if(__vcurhidden)
1463 return;
1464
1465 COORD c = {col, row};
1466 SetConsoleCursorPosition(gvid_hout, c);
1467
1468 #elif defined(__UNIX__)
1469
1470 gvid_printf("\x1B[%u;%uH", row+1, col+1);
1471
1472 #endif
1473 }
1474
1475
1476 // ------------------------------------------------------------------
1477 // Clears the screen and homes the cursor
1478
vclrscr()1479 void vclrscr() {
1480
1481 vclrscr(vgattr(vgetw(gvid->currow, gvid->curcol)));
1482 }
1483
1484
1485 // ------------------------------------------------------------------
1486 // Clears the screen using given attribute and homes the cursor
1487
1488 #if (defined(__MSDOS__) || defined(__UNIX__)) && !defined(__USE_NCURSES__)
_vclrscr(vattr atr)1489 static void _vclrscr(vattr atr) {
1490
1491 int len = gvid->numrows * gvid->numcols;
1492
1493 _vputx(0, 0, atr, ' ', len);
1494 }
1495 #endif
1496
1497
1498
1499 // ------------------------------------------------------------------
1500 // Clears the screen using given attribute and homes the cursor
1501
vclrscr(vattr atr)1502 void vclrscr(vattr atr) {
1503
1504 #if defined(__USE_NCURSES__)
1505
1506 clearok(stdscr, TRUE);
1507 vatch filler = vcatch(' ', atr);
1508 for(int row = 0; row < LINES; row++)
1509 mvhline(row, 0, filler, COLS);
1510 move(0, 0);
1511 refresh();
1512
1513 #elif defined(__MSDOS__)
1514
1515 if(gvid->isdma()) {
1516 _vclrscr(atr);
1517 }
1518 else if(gvid->isbios() or gvid->iscga()) {
1519 i86 cpu;
1520 cpu.ax(0x0600); // clear screen by scrolling it
1521 cpu.bh((byte)atr);
1522 cpu.cx(0);
1523 cpu.dh((byte)(gvid->numrows - 1));
1524 cpu.dl((byte)(gvid->numcols - 1));
1525 cpu.genint(0x10);
1526 }
1527
1528 #elif defined(__OS2__)
1529
1530 vatch filler = vcatch(' ', atr);
1531 VioScrollUp(0, 0, 0xFFFF, 0xFFFF, 0xFFFF, (BYTE *)&filler, 0);
1532
1533 #elif defined(__WIN32__)
1534
1535 COORD c = {0, 0};
1536 DWORD wr, len = gvid->numrows * gvid->numcols;
1537 // Filling with space seems to work for both Unicode and regular functions
1538 FillConsoleOutputCharacter(gvid_hout, ' ', len, c, &wr);
1539 FillConsoleOutputAttribute(gvid_hout, (WORD)atr, len, c, &wr);
1540
1541 #elif defined(__UNIX__)
1542
1543 _vclrscr(atr);
1544
1545 gvid_printf("%s\x1B[2J", gvid_newattr(atr));
1546
1547 #endif
1548
1549 vposset(0,0);
1550 }
1551
1552
1553 // ------------------------------------------------------------------
1554 // Saves the current screen and returns pointer to buffer
1555
1556 #if (defined(__MSDOS__) || defined(__UNIX__)) && !defined(__USE_NCURSES__)
_vsave(word * buf,int len1,int srow,int scol,int erow)1557 static void _vsave(word* buf, int len1, int srow, int scol, int erow) {
1558
1559 const int len2 = len1*sizeof(word);
1560 gdma p = gdmaptr(scol, srow);
1561 for(int nrow=srow; nrow<=erow; nrow++) {
1562 gdmacpy(_my_ds(), (gdma)buf, _dos_ds, (gdma)p, len2);
1563 p += ATTRSIZE*gvid->numcols;
1564 buf += len1;
1565 }
1566 }
1567 #endif
1568
1569
1570 // ------------------------------------------------------------------
1571 // Saves the current screen and returns pointer to buffer
1572
vsave(int srow,int scol,int erow,int ecol)1573 vsavebuf* vsave(int srow, int scol, int erow, int ecol) {
1574
1575 if(srow == -1) srow = 0;
1576 if(scol == -1) scol = 0;
1577 if(erow == -1) erow = gvid->numrows-1;
1578 if(ecol == -1) ecol = gvid->numcols-1;
1579
1580 vsavebuf* sbuf = (vsavebuf*)throw_xmalloc(sizeof(vsavebuf) + (erow - srow + 1) * (ecol - scol + 1) * sizeof(vatch));
1581
1582 if(sbuf) {
1583
1584 vatch* buf = sbuf->data;
1585
1586 sbuf->top = srow;
1587 sbuf->left = scol;
1588 sbuf->bottom = erow;
1589 sbuf->right = ecol;
1590
1591 #if defined(__USE_NCURSES__)
1592
1593 for(int row=srow; row<=erow; row++)
1594 for(int col=scol; col<=ecol; col++)
1595 *buf++ = mvinch(row, col);
1596
1597 #elif defined(__MSDOS__)
1598
1599 int len1 = ecol-scol+1;
1600
1601 if(gvid->isdma()) {
1602 _vsave(buf, len1, srow, scol, erow);
1603 }
1604 else if(gvid->isbios() or gvid->iscga()) {
1605 i86 cpu;
1606 byte* p = (byte*)buf;
1607 for(byte row=(byte)srow; row<=erow; row++) {
1608 for(byte col=(byte)scol; col<=ecol; col++) {
1609 cpu.ah(2);
1610 cpu.bh(0);
1611 cpu.dh(row);
1612 cpu.dl(col);
1613 cpu.genint(0x10);
1614 cpu.ah(8);
1615 cpu.bh(0);
1616 cpu.genint(0x10);
1617 *p++ = cpu.al();
1618 *p++ = cpu.ah();
1619 }
1620 }
1621 }
1622
1623 #elif defined(__OS2__)
1624
1625 int len1 = (int)(ecol-scol+1);
1626
1627 #if defined(__BORLANDC__)
1628 PCHAR16 ptr = (PCHAR16)buf;
1629 #else
1630 PCH ptr = (PCH)buf;
1631 #endif
1632
1633 USHORT len2 = (USHORT)(len1*sizeof(word));
1634 for(int nrow=srow; nrow<=erow; nrow++) {
1635 VioReadCellStr(ptr, &len2, nrow, scol, 0);
1636 ptr += len2;
1637 }
1638
1639 #elif defined(__WIN32__)
1640
1641 const COORD coord = {0, 0};
1642 COORD size = {ecol-scol+1, erow-srow+1};
1643 SMALL_RECT r;
1644
1645 // Set the source rectangle.
1646 r.Top = srow;
1647 r.Left = scol;
1648 r.Bottom = erow;
1649 r.Right = ecol;
1650
1651 if(WinVer.dwPlatformId == VER_PLATFORM_WIN32_NT)
1652 ReadConsoleOutputW(gvid_hout, buf, size, coord, &r);
1653 else
1654 ReadConsoleOutputA(gvid_hout, buf, size, coord, &r);
1655
1656 #elif defined(__UNIX__)
1657
1658 int len1 = ecol-scol+1;
1659
1660 _vsave(buf, len1, srow, scol, erow);
1661
1662 #endif
1663 }
1664
1665 return sbuf;
1666 }
1667
1668
1669 // ------------------------------------------------------------------
1670 // Redraws a previously saved screen
1671
1672 #if (defined(__MSDOS__) || defined(__UNIX__)) && !defined(__USE_NCURSES__)
_vredraw(word * buf,int len1,int srow,int scol,int erow)1673 static void _vredraw(word* buf, int len1, int srow, int scol, int erow) {
1674
1675 const int len2 = len1*sizeof(word);
1676 gdma p = gdmaptr(scol, srow);
1677 for(int nrow=srow; nrow<=erow; nrow++) {
1678 gdmacpy(_dos_ds, (gdma)p, _my_ds(), (gdma)buf, len2);
1679 p += ATTRSIZE*gvid->numcols;
1680 buf += len1;
1681 }
1682 }
1683 #endif
1684
1685
1686 // ------------------------------------------------------------------
1687 // Redraws a previously saved screen
1688
vrestore(vsavebuf * sbuf,int srow,int scol,int erow,int ecol)1689 void vrestore(vsavebuf* sbuf, int srow, int scol, int erow, int ecol) {
1690
1691 if(srow != -1) sbuf->top = srow;
1692 if(scol != -1) sbuf->left = scol;
1693 if(erow != -1) sbuf->bottom = erow;
1694 if(ecol != -1) sbuf->right = ecol;
1695
1696 srow = sbuf->top;
1697 scol = sbuf->left;
1698 erow = sbuf->bottom;
1699 ecol = sbuf->right;
1700
1701 vatch *buf = sbuf->data;
1702
1703 #if defined(__USE_NCURSES__)
1704
1705 for(int row=srow; row<=erow; row++)
1706 for(int col=scol; col<=ecol; col++)
1707 mvaddch(row, col, *buf++);
1708
1709 refresh();
1710
1711 #elif defined(__MSDOS__)
1712
1713 int len1 = ecol-scol+1;
1714
1715 if(gvid->isdma()) {
1716 _vredraw(buf, len1, srow, scol, erow);
1717 }
1718 else if(gvid->isbios() or gvid->iscga()) {
1719 i86 cpu;
1720 byte* p = (byte*)buf;
1721 for(byte row=(byte)srow; row<=erow; row++) {
1722 for(byte col=(byte)scol; col<=ecol; col++) {
1723 cpu.ah(2);
1724 cpu.bh(0);
1725 cpu.dh(row);
1726 cpu.dl(col);
1727 cpu.genint(0x10);
1728 cpu.ah(9);
1729 cpu.al(*p++);
1730 cpu.bh(0);
1731 cpu.bl(*p++);
1732 cpu.cx(1);
1733 cpu.genint(0x10);
1734 }
1735 }
1736 }
1737
1738 #elif defined(__OS2__)
1739
1740 USHORT len1 = (USHORT)(ecol-scol+1);
1741 USHORT len2 = (USHORT)(len1*sizeof(word));
1742
1743 #if defined(__BORLANDC__)
1744 PCHAR16 ptr = (PCHAR16)buf;
1745 #else
1746 PCH ptr = (PCH)buf;
1747 #endif
1748
1749 for(USHORT nrow=srow; nrow<=erow; nrow++) {
1750 VioWrtCellStr(ptr, len2, nrow, scol, 0);
1751 ptr += len2;
1752 }
1753
1754 #elif defined(__WIN32__)
1755
1756 const COORD coord = {0, 0};
1757 COORD size = {ecol-scol+1, erow-srow+1};
1758 SMALL_RECT r;
1759
1760 // Set the source rectangle.
1761 r.Top = srow;
1762 r.Left = scol;
1763 r.Bottom = erow;
1764 r.Right = ecol;
1765
1766 if(WinVer.dwPlatformId == VER_PLATFORM_WIN32_NT)
1767 WriteConsoleOutputW(gvid_hout, buf, size, coord, &r);
1768 else
1769 WriteConsoleOutputA(gvid_hout, buf, size, coord, &r);
1770
1771 #elif defined(__UNIX__)
1772
1773 int len1 = ecol-scol+1;
1774
1775 _vredraw(buf, len1, srow, scol, erow);
1776
1777 int atr = vgattr(*buf);
1778 char* color = gvid_newattr(atr);
1779 gvid_printf("%s", color);
1780
1781 for(int nrow=srow; nrow<=erow; nrow++) {
1782 vputansi(nrow, scol, buf, len1);
1783 buf += len1;
1784 }
1785
1786 #endif
1787 }
1788
1789
1790 // ------------------------------------------------------------------
1791 // Sets the cursor shape/size
1792
vcurset(int sline,int eline)1793 void vcurset(int sline, int eline) {
1794
1795 if(eline) {
1796 gvid->curr.cursor.start = sline;
1797 gvid->curr.cursor.end = eline;
1798 __vcurhidden = false;
1799 }
1800
1801 #if defined(__USE_NCURSES__)
1802
1803 if((sline == 0) and (eline == 0))
1804 curs_set(0);
1805 else if((eline - sline) <= 4)
1806 curs_set(1);
1807 else
1808 curs_set(2);
1809
1810 #elif defined(__MSDOS__)
1811
1812 if(eline == 0) {
1813 int _dvhide = __gdvdetected ? 0x01 : 0x30;
1814 sline = ((gvid->adapter>=V_HGC) and (gvid->adapter<=V_INCOLOR)) ? 0x3F : _dvhide;
1815 }
1816
1817 i86 cpu;
1818 cpu.ah(1);
1819 cpu.ch((byte)sline);
1820 cpu.cl((byte)eline);
1821 cpu.genint(0x10);
1822
1823 #elif defined(__OS2__)
1824
1825 VIOCURSORINFO vioci;
1826 VioGetCurType(&vioci, 0);
1827 vioci.yStart = (USHORT)sline;
1828 vioci.cEnd = (USHORT)eline;
1829 vioci.attr = (USHORT)((eline == 0) ? 0xFFFF : gvid->curr.color.textattr);
1830 VioSetCurType(&vioci, 0);
1831
1832 #elif defined(__WIN32__)
1833
1834 CONSOLE_CURSOR_INFO cci;
1835
1836 if(eline)
1837 vposset(gvid->currow, gvid->curcol);
1838 else /* Move cursor to bottom right corner (workaround of the win9x console bug) */
1839 vposset(gvid->numrows-1, gvid->numcols-1);
1840
1841 cci.dwSize = (eline and sline) ? sline : 100;
1842 cci.bVisible = make_bool(eline);
1843
1844 // To hide cursor in w98 needs change byte sequnce in compiled gedcyg.exe:
1845 // 0F 95 C0 89 45 FC
1846 // B0 01 90 -- -- --
1847
1848 SetConsoleCursorInfo(gvid_hout, &cci);
1849
1850 #elif defined(__UNIX__)
1851
1852 gvid_printf("\033[?25%c", eline ? 'h' : 'l');
1853
1854 #endif
1855 }
1856
1857
1858 // ------------------------------------------------------------------
1859 // Hides the cursor
1860
vcurhide()1861 void vcurhide() {
1862
1863 if(not __vcurhidden) {
1864 #if defined(__USE_NCURSES__)
1865 curs_set(0);
1866 #else
1867 vcurset(0,0);
1868 #endif
1869 __vcurhidden = true;
1870 }
1871 }
1872
1873
1874 // ------------------------------------------------------------------
1875 // Reveals the cursor
1876
vcurshow()1877 void vcurshow() {
1878
1879 if(__vcurhidden) {
1880 vcurset(gvid->curr.cursor.start, gvid->curr.cursor.end);
1881 __vcurhidden = false;
1882 }
1883 }
1884
1885
1886 // ------------------------------------------------------------------
1887 // Sets a large cursor
1888
vcurlarge()1889 void vcurlarge() {
1890
1891 #if defined(__USE_NCURSES__)
1892 curs_set(2);
1893 #else
1894 vcurshow();
1895
1896 #if defined(__MSDOS__)
1897
1898 switch(gvid->adapter) {
1899 case V_CGA:
1900 vcurset(1,7);
1901 break;
1902 case V_EGA:
1903 if(gvid->numrows == 25) {
1904 vcurset(1,7);
1905 }
1906 else {
1907 word* p = (word*)0x0463; // video BIOS data area
1908 outpw(*p,0x000A); // update cursor start register
1909 outpw(*p,0x0A0B); // update cursor end register
1910 }
1911 break;
1912 case V_VGA:
1913 vcurset(1,7);
1914 break;
1915 default: // one of the monochrome cards
1916 vcurset(1,12);
1917 }
1918
1919 #elif defined(__OS2__)
1920
1921 vcurset(1, gvid->curr.screen.cheight-1);
1922
1923 #elif defined(__WIN32__)
1924
1925 vcurset(90, true);
1926
1927 #endif
1928 #endif
1929 }
1930
1931
1932 // ------------------------------------------------------------------
1933 // Sets a small cursor
1934
vcursmall()1935 void vcursmall() {
1936
1937 #if defined(__USE_NCURSES__)
1938 curs_set(1);
1939 #else
1940 vcurshow();
1941
1942 #if defined(__MSDOS__)
1943
1944 switch(gvid->adapter) {
1945 case V_CGA:
1946 vcurset(6,7);
1947 break;
1948 case V_EGA:
1949 if(gvid->numrows == 25) {
1950 vcurset(6,7);
1951 }
1952 else {
1953 word* p = (word*)0x0463; // video BIOS data area
1954 outpw(*p,0x060A); // update cursor start register
1955 outpw(*p,0x000B); // update cursor end register
1956 }
1957 break;
1958 case V_VGA:
1959 vcurset(6,7);
1960 break;
1961 default: // one of the monochrome cards
1962 vcurset(11,12);
1963 }
1964
1965 #elif defined(__OS2__)
1966
1967 vcurset(gvid->curr.screen.cheight-2, gvid->curr.screen.cheight-1);
1968
1969 #elif defined(__WIN32__)
1970
1971 vcurset(13, true);
1972
1973 #endif
1974 #endif
1975 }
1976
1977
1978 // ------------------------------------------------------------------
1979 // Table of characters used to display boxes
1980 //
1981 // Access box table characters via:
1982 // _box_table(boxtype, x)
1983 //
1984 // where:
1985 // boxtype is the number of the box type you want to use (0 - 5)
1986 //
1987 // x will be one of the following:
1988 // 0 - upper left corner
1989 // 1 - upper horizontal line
1990 // 2 - upper right corner
1991 // 3 - left vertical line
1992 // 4 - right vertical line
1993 // 5 - lower left corner
1994 // 6 - lower horizontal line
1995 // 7 - lower right corner
1996 // 8 - middle junction
1997 // 9 - left vertical junction
1998 // 10 - right vertical junction
1999 // 11 - upper horizontal junction
2000 // 12 - lower horizontal junction
2001 // 13 - checkerboard
2002 // 14 - solid block
2003 // ------------------------------------------------------------------
2004
2005 #if !defined(__USE_NCURSES__)
2006
2007 char* __box_table[] = {
2008
2009 #if defined(__UNIX__) // This table will be actually patched at startup...
2010
2011 ".-.||`-'+||-- #", // box type 0 Single border
2012 ".-.||`-'+||-- #", // box type 1 Double border
2013 ".-.||`-'+||-- #", // box type 2 Single top
2014 ".-.||`-'+||-- #", // box type 3 Double top
2015 " #", // box type 4 With empty border
2016 ".-.||`-'+||-- #", // box type 5 No border at all
2017 ".-.||`-'+||-- #", // box type 6 Blocky border
2018 ".-.||`-'+||-- #", // box type 7 ASCII border
2019 "lqkxxmqjntuwvaa", // box type 8 xterm single border
2020
2021 #else
2022
2023 "�Ŀ������ô����", // box type 0 Single border
2024 "�ͻ���ͼ�̹�ʰ�", // box type 1 Double border
2025 "�ķ���Ľ�Ƕ�а�", // box type 2 Single top
2026 "����;�Ƶ�ϰ�", // box type 3 Double top
2027 " ��", // box type 4 With empty border
2028 "�Ŀ������ô����", // box type 5 No border at all
2029 "������������ݰ�", // box type 6 Blocky border
2030 ".-.||`-'+||--##", // box type 7 ASCII border
2031 "lqkxxmqjntuwvaa", // box type 8 xterm single border
2032
2033 #endif
2034 };
2035 #else
2036
2037 // ncurses ACS_nnn characters are usually computed at runtime, so
2038 // we cannot use a static array
2039
_box_table(int type,int c)2040 chtype _box_table(int type, int c) {
2041
2042 char asciiborder[] = ".-.||-'+||--##";
2043
2044 switch(type) {
2045 case 4:
2046 switch(c) {
2047 case 13:
2048 return ACS_BOARD;
2049 case 14:
2050 return ACS_BLOCK;
2051 default:
2052 return (chtype) ' ';
2053 }
2054 case 6:
2055 switch(c) {
2056 case 13:
2057 return ACS_BOARD;
2058 default:
2059 return ACS_BLOCK;
2060 }
2061 case 7:
2062 return (chtype) (asciiborder[c]);
2063 default:
2064 switch (c) {
2065 case 0:
2066 return ACS_ULCORNER;
2067 case 1:
2068 case 6:
2069 return ACS_HLINE;
2070 case 2:
2071 return ACS_URCORNER;
2072 case 3:
2073 case 4:
2074 return ACS_VLINE;
2075 case 5:
2076 return ACS_LLCORNER;
2077 case 7:
2078 return ACS_LRCORNER;
2079 case 8:
2080 return ACS_PLUS;
2081 case 9:
2082 return ACS_LTEE;
2083 case 10:
2084 return ACS_RTEE;
2085 case 11:
2086 return ACS_TTEE;
2087 case 12:
2088 return ACS_BTEE;
2089 case 13:
2090 return ACS_BOARD;
2091 default:
2092 return ACS_BLOCK;
2093 }
2094 }
2095 }
2096
2097 #endif
2098
2099
2100 // ------------------------------------------------------------------
2101
2102 #if defined(__UNIX__)
gvid_boxcvt(char * s)2103 void gvid_boxcvt(char* s) {
2104 while(*s)
2105 *s++ = (char)gvid_boxcvtc(*s);
2106 }
2107
gvid_boxcvtc(char c)2108 static uint32_t gvid_boxcvtc(char c) {
2109 switch(c) {
2110 #if 0
2111 case '�': return _box_table(8, 0);
2112 case '�': return _box_table(8, 1);
2113 case '�': return _box_table(8, 2);
2114 case '�': return _box_table(8, 4);
2115 case '�': return _box_table(8, 5);
2116 case '�': return _box_table(8, 7);
2117 case '�': return _box_table(8, 8);
2118 case '�': return _box_table(8, 9);
2119 case '�': return _box_table(8, 10);
2120 case '�': return _box_table(8, 11);
2121 case '�': return _box_table(8, 12);
2122 #else
2123 case '�': return _box_table(0, 0);
2124 case '�': return _box_table(0, 1);
2125 case '�': return _box_table(0, 2);
2126 case '�': return _box_table(0, 4);
2127 case '�': return _box_table(0, 5);
2128 case '�': return _box_table(0, 7);
2129 case '�': return _box_table(0, 8);
2130 case '�': return _box_table(0, 9);
2131 case '�': return _box_table(0, 10);
2132 case '�': return _box_table(0, 11);
2133 case '�': return _box_table(0, 12);
2134 case '�': return _box_table(1, 0);
2135 case '�': return _box_table(1, 1);
2136 case '�': return _box_table(1, 2);
2137 case '�': return _box_table(1, 4);
2138 case '�': return _box_table(1, 5);
2139 case '�': return _box_table(1, 7);
2140 case '�': return _box_table(1, 8);
2141 case '�': return _box_table(1, 9);
2142 case '�': return _box_table(1, 10);
2143 case '�': return _box_table(1, 11);
2144 case '�': return _box_table(1, 12);
2145 #endif
2146 }
2147 return c;
2148 }
2149 #endif
2150
2151
2152 // ------------------------------------------------------------------
2153 // Draws a text box on the screen
2154
vbox(int srow,int scol,int erow,int ecol,int box,vattr hiattr,vattr loattr)2155 void vbox(int srow, int scol, int erow, int ecol, int box, vattr hiattr, vattr loattr)
2156 {
2157 if (loattr == DEFATTR)
2158 loattr = hiattr;
2159 else if(loattr == -2)
2160 loattr = (int)((hiattr & 0x08) ? (hiattr & 0xF7) : (hiattr | 0x08));
2161
2162 #if defined(__UNIX__)
2163 hiattr |= ACSET;
2164 loattr |= ACSET;
2165 #endif
2166
2167 vputc(srow, scol, hiattr, _box_table(box, 0)); // Top left corner
2168 vputx(srow, scol+1, hiattr, _box_table(box, 1), ecol-scol-1); // Top border
2169 vputc(srow, ecol, loattr, _box_table(box, 2)); // Top right corner
2170 vputy(srow+1, scol, hiattr, _box_table(box, 3), erow-srow-1); // Left border
2171 vputy(srow+1, ecol, loattr, _box_table(box, 4), erow-srow-1); // Right border
2172 vputc(erow, scol, hiattr, _box_table(box, 5)); // Bottom left corner
2173 vputx(erow, scol+1, loattr, _box_table(box, 6), ecol-scol-1); // Bottom border
2174 vputc(erow, ecol, loattr, _box_table(box, 7)); // Bottom right corner
2175 }
2176
2177
2178 // ------------------------------------------------------------------
2179 // Fills an area of screen with a character & attribute
2180
vfill(int srow,int scol,int erow,int ecol,vchar chr,vattr atr)2181 void vfill(int srow, int scol, int erow, int ecol, vchar chr, vattr atr) {
2182
2183 int width = ecol-scol+1;
2184 for(int crow=srow; crow<=erow; crow++)
2185 vputx(crow, scol, atr, chr, width);
2186 }
2187
2188
2189 // ------------------------------------------------------------------
2190