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: gvidinit.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. Initialise class GVid.
28 // ------------------------------------------------------------------
29
30 #include <cassert>
31 #include <cstdio>
32 #include <cstdlib>
33 #include <cstdarg>
34 #include <gmemall.h>
35 #include <gmemdbg.h>
36 #include <gstrall.h>
37 #if defined(__WATCOMC__) || defined(__DJGPP__)
38 #include <conio.h>
39 #endif
40 #include <gvidall.h>
41
42 #if defined(__OS2__)
43 #define INCL_BASE
44 #include <os2.h>
45 #endif
46
47 #if defined(__WIN32__)
48 #include <windows.h>
49 #endif
50
51 #if !defined(__USE_NCURSES__) && defined(__UNIX__)
52 #include <sys/ioctl.h>
53 #include <termios.h>
54 #include <unistd.h>
55 #include <errno.h>
56 #endif
57
58 #if defined(__DJGPP__)
59 #include <sys/farptr.h>
60 #include <go32.h>
61 #endif
62
63
64 // ------------------------------------------------------------------
65 // Check if Borland C++ for OS/2 1.0 header has been fixed
66
67 #if defined(__OS2__) && defined(__BORLANDC__)
68 #if __BORLANDC__ <= 0x400
69 #ifndef BCOS2_BSESUB_FIXED
70 #error There is a bug in the BSESUB.H header. Please fix it.
71 //
72 // Add/change the following in BSESUB.H:
73 //
74 // #define BCOS2_BSESUB_FIXED
75 // APIRET16 APIENTRY16 VioGetState (PVOID16 pState, HVIO hvio);
76 // APIRET16 APIENTRY16 VioSetState (PVOID16 pState, HVIO hvio);
77 //
78 // Borland forgot this (was only PVOID) ^^
79 //
80 #endif
81 #endif
82 #endif
83
84
85 // ------------------------------------------------------------------
86 // Global video data
87
88 GVid *gvid;
89
90 #if defined(__USE_NCURSES__)
91
92 // add statics here
93
94 #elif defined(__UNIX__)
95
96 int gvid_stdout = -1;
97 const char* gvid_acs_enable;
98 const char* gvid_acs_disable;
99
100 void _vputx(int row, int col, int atr, char chr, uint len);
101 void gvid_printf(const char* fmt, ...) __attribute__ ((format (printf, 1, 2)));
102
103 #elif defined(__WIN32__)
104
105 HANDLE gvid_hout = INVALID_HANDLE_VALUE;
106
107 #elif defined(__MSDOS__)
108
109 int __gdvdetected = false;
110
111 #endif
112
113
114 // ------------------------------------------------------------------
115 // Video Class constructor
116
GVid()117 GVid::GVid() {
118
119 #ifdef __DJGPP__
120 dmaptr = dmadir = 0;
121 #else
122 dmaptr = dmadir = NULL;
123 #endif
124 bufchr = NULL;
125 bufwrd = NULL;
126 bufansi = NULL;
127
128 init();
129 }
130
131
132 // ------------------------------------------------------------------
133 // Video Class destructor
134
~GVid()135 GVid::~GVid() {
136
137 #if defined(__USE_NCURSES__)
138
139 attrset(A_NORMAL);
140 if(0 == (--curses_initialized))
141 endwin();
142
143 #elif defined(__UNIX__)
144
145 // "\033<" Enter ANSI mode
146 // "\033[?5l" Normal screen
147 // "\033[0m" Normal character attributes
148
149 gvid_printf("\033<\033[?5l\033[0m");
150
151 #endif
152 #ifndef __DJGPP__
153 if(dmaptr != dmadir) throw_xfree(dmaptr);
154 #endif
155 throw_xfree(bufwrd);
156 throw_xfree(bufchr);
157 throw_xfree(bufansi);
158 }
159
160
161 // ------------------------------------------------------------------
162
init()163 void GVid::init() {
164
165 #if defined(__USE_NCURSES__)
166 // Both display and keyboard will be initialized at once
167 if(0 == (curses_initialized++)) {
168 initscr();
169 raw();
170 noecho();
171 nonl();
172 intrflush(stdscr, FALSE);
173 keypad(stdscr, TRUE);
174 }
175 #endif
176
177 // Detect video adapter
178 detectadapter();
179
180 // Detect original video information
181 detectinfo(&orig);
182 memcpy(&curr, &orig, sizeof(GVidInfo));
183
184 #if defined(__MSDOS__)
185 device = GVID_DMA;
186 #elif defined(__OS2__)
187 device = GVID_OS2;
188 #elif defined(__WIN32__)
189 device = GVID_W32;
190 #endif
191
192 #if defined(__USE_NCURSES__)
193 dmaptr = dmadir = NULL;
194 #elif defined(__WATCOMC__) && defined(__386__)
195 dmaptr = dmadir = (gdma)(videoseg << 4);
196 #elif defined(__DJGPP__)
197 dmaptr = dmadir = ScreenPrimary;
198 #elif defined(__OS2__) || defined(__WIN32__)
199 dmaptr = dmadir = NULL;
200 #elif defined(__UNIX__)
201 dmaptr = (gdma)throw_xcalloc((orig.screen.rows+1)*orig.screen.columns, sizeof(word));
202 dmadir = NULL;
203 #else
204 dmaptr = dmadir = (gdma)MK_FP(videoseg, 0);
205 #endif
206
207 bufchr = NULL;
208 bufwrd = NULL;
209 bufansi = NULL;
210
211 resetcurr();
212 }
213
214 // ------------------------------------------------------------------
215 // Video adapter detect
216
detectadapter()217 int GVid::detectadapter() {
218
219 // Initialize to a valid value
220 adapter = GV_NONE;
221
222 #if defined(__USE_NCURSES__)
223
224 start_color();
225
226 setcolorpairs();
227
228 adapter = V_VGA;
229
230 #elif defined(__MSDOS__)
231
232 i86 cpu;
233
234 // Get video mode
235 cpu.ah(V_GET_MODE);
236 cpu.genint(0x10);
237 int _got_mode = cpu.al();
238
239 // Check for PS/2 compatible video BIOS by calling the get
240 // video configuration function. If it exists, the video
241 // configuration code will be returned in BL.
242
243 cpu.ax(0x1A00);
244 cpu.genint(0x10);
245
246 if(cpu.al() == 0x1A) {
247
248 switch(cpu.bl()) {
249 case 0x00:
250 adapter = GV_NONE;
251 break;
252 case 0x01:
253 adapter = V_MDA;
254 break;
255 case 0x02:
256 adapter = V_CGA;
257 break;
258 case 0x04:
259 adapter = V_EGA;
260 break;
261 case 0x05:
262 adapter = V_EGAMONO;
263 break;
264 case 0x07:
265 adapter = (_got_mode == 7) ? V_VGAMONO : V_VGA;
266 break;
267 case 0x08:
268 adapter = (_got_mode == 7) ? V_VGAMONO : V_VGA;
269 break;
270 case 0x0A:
271 case 0x0C:
272 adapter = V_MCGA;
273 break;
274 case 0x0B:
275 adapter = V_MCGAMONO;
276 break;
277 default:
278 adapter = V_VGA; // We hope it is VGA compatible!
279 }
280 }
281 else {
282
283 // OK, we know that it's not a PS/2 BIOS, so check for an EGA.
284 // If an EGA is not present, BH will be unchanged on return.
285
286 cpu.ah(0x12);
287 cpu.bl(0x10);
288 cpu.genint(0x10);
289
290 if(cpu.bl() - 0x10) {
291 adapter = cpu.bh() ? V_EGAMONO : V_EGA;
292 }
293 else {
294
295 // Now we know it's not an EGA. Get the BIOS equipment
296 // flag and test for CGA, MDA, or no video adapter.
297
298 cpu.genint(0x11);
299
300 switch(cpu.al() & 0x30) {
301 case 0x00:
302 adapter = (_got_mode == 7) ? V_VGAMONO : V_VGA; // EGA, VGA, or PGA
303 break;
304 case 0x10:
305 adapter = GV_NONE; // 40x25 color
306 break;
307 case 0x20:
308 adapter = V_CGA; // 80x25 color
309 break;
310 case 0x30:
311 adapter = V_MDA; // 80x25 monochrome
312 break;
313 }
314 }
315 }
316
317 #ifndef __DJGPP__
318
319 // Set video segment
320 #if defined(__BORLANDC__) && defined(__DPMI32__)
321 videoseg = (word)((adapter & V_MONO) ? __SegB000 : __SegB800);
322 #else
323 videoseg = (word)((adapter & V_MONO) ? 0xB000 : 0xB800);
324 #endif
325
326 // check for presence of DESQview by using the DOS Set
327 // System Date function and trying to set an invalid date
328
329 cpu.ax(0x2B01); // DOS Set System Date
330 cpu.ch('D');
331 cpu.cl('E');
332 cpu.dh('S');
333 cpu.dl('Q');
334 cpu.genint(0x21);
335
336 // if error, then DESQview not present
337 if(cpu.al() != 0xFF) {
338
339 __gdvdetected = true;
340
341 #if defined(__WATCOMC__) && defined(__386__)
342 memset(&RMI, 0, sizeof(RMI));
343 RMI.EAX = 0x0000FE00;
344 RMI.ES = videoseg;
345 cpu.ax(0x0300);
346 cpu.bl(0x10);
347 cpu.bh(0);
348 cpu.cx(0);
349 cpu.es(FP_SEG(&RMI));
350 cpu.edi(FP_OFF(&RMI));
351 cpu.genint(0x31);
352 videoseg = RMI.ES;
353 #else
354 cpu.ah(0xFE); // DV get alternate video buffer
355 cpu.es(videoseg);
356 cpu.di(0x0000);
357 cpu.genint(0x10);
358 videoseg = cpu.es();
359 #endif
360 }
361
362 #endif // __DJGPP__
363
364 #elif defined(__OS2__)
365
366 {
367 VIOCONFIGINFO vioconfiginfo;
368 memset(&vioconfiginfo, 0, sizeof(VIOCONFIGINFO));
369 vioconfiginfo.cb = sizeof(VIOCONFIGINFO);
370 VioGetConfig(0, &vioconfiginfo, 0);
371 switch(vioconfiginfo.adapter) {
372 case DISPLAY_MONOCHROME:
373 adapter = V_MDA;
374 break;
375 case DISPLAY_CGA:
376 adapter = V_CGA;
377 break;
378 case DISPLAY_EGA:
379 adapter = V_EGA;
380 break;
381 case DISPLAY_VGA:
382 adapter = V_VGA;
383 break;
384 default:
385 adapter = V_VGA; // We hope it is VGA compatible!
386 }
387 if(vioconfiginfo.display == DISPLAY_MONOCHROME)
388 adapter |= V_MONO;
389 }
390
391 #elif defined(__WIN32__)
392
393 gvid_hout = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE,
394 FILE_SHARE_WRITE | FILE_SHARE_READ, NULL,
395 OPEN_EXISTING,
396 FILE_FLAG_NO_BUFFERING|FILE_FLAG_WRITE_THROUGH, NULL);
397
398 adapter = V_VGA;
399
400 #elif defined(__linux__)
401
402 for(int n=0; n<8; n++)
403 __box_table[n] = __box_table[8];
404
405 gvid_acs_enable = "\016";
406 gvid_acs_disable = "\017";
407
408 gvid_stdout = fileno(stdout);
409
410 adapter = V_VGA;
411
412 #elif defined(__UNIX__) // code below should not be normally used...
413
414 bool gvid_xterm = false;
415 const char* term = getenv("TERM");
416
417 if(term and strneql(term, "xterm", 5)) {
418 gvid_xterm = true;
419 for(int n=0; n<8; n++)
420 __box_table[n] = __box_table[8];
421 }
422
423 gvid_acs_enable = gvid_xterm ? "\033)0\033(B\016" : "\033[11m";
424 gvid_acs_disable = gvid_xterm ? "\033(B\033)B\017" : "\033[10m";
425
426 gvid_stdout = fileno(stdout);
427
428 adapter = V_VGA;
429
430 #endif
431
432 return adapter;
433 }
434
setcolorpairs(bool enabletransparent)435 void GVid::setcolorpairs(bool enabletransparent) {
436 #if defined(__USE_NCURSES__)
437 /* init colors */
438 short mycolors[] = { COLOR_BLACK, COLOR_BLUE, COLOR_GREEN, COLOR_CYAN,
439 COLOR_RED, COLOR_MAGENTA, COLOR_YELLOW, COLOR_WHITE };
440
441 if(enabletransparent)
442 use_default_colors();
443 for(int i = 1; i < 64 and i < COLOR_PAIRS; i++) {
444 short bg=mycolors[(i>>3)&0x07];
445 init_pair(i, mycolors[(~i)&0x07], ((bg==COLOR_BLACK) && enabletransparent)?-1:bg);
446 }
447 #endif
448 }
449
450 // ------------------------------------------------------------------
451 // Video info detect
452
detectinfo(GVidInfo * _info)453 void GVid::detectinfo(GVidInfo* _info)
454 {
455 // Reset all original values
456 memset(_info, 0, sizeof(GVidInfo));
457
458 #if defined(__USE_NCURSES__)
459
460 _info->screen.mode = 0;
461 _info->screen.rows = LINES;
462 _info->screen.columns = COLS;
463 getyx(stdscr, _info->cursor.row, _info->cursor.column);
464 _info->color.textattr = 7;
465 _info->cursor.start = 11;
466 _info->cursor.end = 12;
467 _info->cursor.attr = 7;
468 _info->color.intensity = 1;
469 _info->color.overscan = 0;
470
471 #elif defined(__MSDOS__)
472
473 i86 cpu;
474
475 // Get video mode and number of columns
476 cpu.ah(V_GET_MODE);
477 cpu.genint(0x10);
478 _info->screen.mode = cpu.al();
479 _info->screen.columns = cpu.ah();
480
481 // Get the number of screen rows
482 if(adapter >= V_EGA) {
483 cpu.ax(V_GET_FONT_INFO);
484 cpu.dx(0);
485 cpu.genint(0x10);
486 _info->screen.rows = cpu.dl() + ((adapter & V_EGA) ? 0 : 1);
487 if(_info->screen.rows == 24) // Normally nonsense
488 _info->screen.rows++;
489 //_info->screen.cheight = cpu.cx();
490 _info->screen.cheight = 8;
491 _info->screen.cwidth = 8;
492 }
493 else {
494 _info->screen.rows = 25;
495 _info->screen.cheight = 8;
496 _info->screen.cwidth = 8;
497 }
498
499 // Get character attribute under the cursor
500 cpu.ah(V_RD_CHAR_ATTR);
501 cpu.bh(0);
502 cpu.genint(0x10);
503 _info->color.textattr = cpu.ah();
504
505 // Get cursor position and form
506 cpu.ah(V_GET_CURSOR_POS);
507 cpu.bh(0);
508 cpu.genint(0x10);
509 _info->cursor.row = cpu.dh();
510 _info->cursor.column = cpu.dl();
511 _info->cursor.start = cpu.ch();
512 _info->cursor.end = cpu.cl();
513 _info->cursor.attr = (word)_info->color.textattr;
514 // Get overscan color
515 if(adapter & V_VGA) {
516 cpu.ax(0x1008);
517 cpu.bh(0xFF);
518 cpu.genint(0x10);
519 _info->color.overscan = cpu.bh();
520 }
521
522 // Get intensity state
523 {
524 // Check bit 5 at 0000:0465
525 #if defined(__DJGPP__)
526 _info->color.intensity = (_farpeekb (_dos_ds, 0x465) & 0x20) ? 0 : 1;
527 #else
528 byte* _bptr = (byte*)0x0465;
529 _info->color.intensity = (*_bptr & 0x20) ? 0 : 1;
530 #endif
531
532 }
533
534 #elif defined(__OS2__)
535
536 // Get video mode and number of rows and columns
537 {
538 VIOMODEINFO viomodeinfo;
539 memset(&viomodeinfo, 0, sizeof(VIOMODEINFO));
540 viomodeinfo.cb = sizeof(VIOMODEINFO);
541 VioGetMode(&viomodeinfo, 0);
542 _info->screen.mode = viomodeinfo.fbType;
543 _info->screen.rows = viomodeinfo.row;
544 _info->screen.columns = viomodeinfo.col;
545 _info->screen.cheight = viomodeinfo.vres / viomodeinfo.row;
546 _info->screen.cwidth = viomodeinfo.hres / viomodeinfo.col;
547 }
548
549 // Get cursor position and character attribute under the cursor
550 {
551 USHORT usRow, usColumn;
552 VioGetCurPos(&usRow, &usColumn, 0);
553 _info->cursor.row = usRow;
554 _info->cursor.column = usColumn;
555 BYTE chat[2];
556 USHORT len = 2;
557 #if defined(__EMX__)
558 VioReadCellStr((PCH)chat, &len, usRow, usColumn, 0);
559 #else
560 VioReadCellStr((CHAR*)chat, &len, usRow, usColumn, 0);
561 #endif
562 _info->color.textattr = chat[1];
563 }
564
565 // Get cursor form
566 {
567 VIOCURSORINFO viocursorinfo;
568 memset(&viocursorinfo, 0, sizeof(VIOCURSORINFO));
569 VioGetCurType(&viocursorinfo, 0);
570 _info->cursor.start = viocursorinfo.yStart;
571 _info->cursor.end = viocursorinfo.cEnd;
572 _info->cursor.attr = viocursorinfo.attr;
573 }
574
575 // Get intensity state
576 {
577 VIOINTENSITY viointensity;
578 memset(&viointensity, 0, sizeof(VIOINTENSITY));
579 viointensity.cb = sizeof(VIOINTENSITY);
580 viointensity.type = 0x0002;
581 VioGetState(&viointensity, 0);
582 _info->color.intensity = viointensity.fs ? 1 : 0;
583 }
584
585 // Get overscan color
586 {
587 VIOOVERSCAN viooverscan;
588 memset(&viooverscan, 0, sizeof(VIOOVERSCAN));
589 viooverscan.cb = sizeof(VIOOVERSCAN);
590 viooverscan.type = 0x0001;
591 VioGetState(&viooverscan, 0);
592 _info->color.overscan = (int)viooverscan.color;
593 }
594
595 #elif defined(__WIN32__)
596
597 // Get video mode and number of rows and columns
598 CONSOLE_SCREEN_BUFFER_INFO csbi;
599 int result = GetConsoleScreenBufferInfo(gvid_hout, &csbi);
600 assert(result != 0);
601
602 _info->screen.mode = 0;
603 _info->screen.rows = csbi.dwSize.Y;
604 _info->screen.columns = csbi.dwSize.X;
605
606 // Get cursor position and character attribute under the cursor
607 _info->cursor.row = csbi.dwCursorPosition.Y;
608 _info->cursor.column = csbi.dwCursorPosition.X;
609 _info->color.textattr = csbi.wAttributes;
610
611 if(_info->screen.rows > 100) {
612 _info->screen.rows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
613 _info->screen.columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
614 _info->cursor.row = csbi.dwCursorPosition.Y - csbi.srWindow.Top + 1;
615 _info->cursor.column = csbi.dwCursorPosition.X - csbi.srWindow.Left + 1;
616 }
617
618 // Get cursor form
619 CONSOLE_CURSOR_INFO cci;
620 GetConsoleCursorInfo(gvid_hout, &cci);
621
622 _info->cursor.start = (int) 1;
623 _info->cursor.end = cci.bVisible ? (int) 15 : 0;
624 _info->cursor.attr = (word)(cci.bVisible ? 7 : 0);
625
626 // Get intensity state
627 _info->color.intensity = 1;
628
629 // Get overscan color
630 _info->color.overscan = 0;
631
632 #elif defined(__UNIX__)
633
634 int r = 0, c = 0;
635
636 if(r <= 0) {
637 char *s = getenv("LINES");
638 if(s) {
639 //printf("getenv(\"LINES\") = %s\n", s);
640 r = atoi(s);
641 }
642 }
643
644 if(c <= 0) {
645 char *s = getenv("COLUMNS");
646 if(s) {
647 //printf("getenv(\"COLUMNS\") = %s\n", s);
648 c = atoi(s);
649 }
650 }
651
652 //printf("init1: c=%i, r=%i\n", c, r);
653
654 #if defined(TIOCGSIZE)
655 if(r <= 0 or c <= 0) {
656 struct ttysize sz;
657
658 do {
659 if((ioctl(1,TIOCGSIZE,&sz) == 0) or (ioctl(0, TIOCGSIZE, &sz) == 0) or (ioctl(2, TIOCGSIZE, &sz) == 0)) {
660 c = (int)sz.ts_cols;
661 r = (int)sz.ts_lines;
662 break;
663 }
664 } while(errno == EINTR);
665 }
666 //printf("init2: c=%i, r=%i\n", c, r);
667 #elif defined(TIOCGWINSZ)
668 if(r <= 0 or c <= 0) {
669 struct winsize wind_struct;
670
671 do {
672 if((ioctl(1,TIOCGWINSZ,&wind_struct) == 0) or (ioctl(0, TIOCGWINSZ, &wind_struct) == 0) or (ioctl(2, TIOCGWINSZ, &wind_struct) == 0)) {
673 c = (int)wind_struct.ws_col;
674 r = (int)wind_struct.ws_row;
675 break;
676 }
677 } while(errno == EINTR);
678 }
679 //printf("init3: c=%i, r=%i\n", c, r);
680 #endif
681
682
683 if((r <= 0) or (r > 200))
684 r = 24;
685 if((c <= 0) or (c > 250))
686 c = 80;
687
688 //printf("init4: c=%i, r=%i\n", c, r);
689
690 //*dmadir = 0;
691
692 _info->screen.mode = 0;
693 _info->screen.rows = r;
694 _info->screen.columns = c;
695 _info->cursor.row = 0;
696 _info->cursor.column = 0;
697 _info->color.textattr = 7;
698 _info->cursor.start = 11;
699 _info->cursor.end = 12;
700 _info->cursor.attr = 7;
701 _info->color.intensity = 1;
702 _info->color.overscan = 0;
703
704 #endif
705
706 getpalette(_info->color.palette);
707 }
708
709
710 // ------------------------------------------------------------------
711 // Reset current video info
712
resetcurr()713 void GVid::resetcurr() {
714
715 currow = curr.cursor.row;
716 curcol = curr.cursor.column;
717
718 numrows = curr.screen.rows;
719 numcols = curr.screen.columns;
720
721 throw_xfree(bufchr);
722 throw_xfree(bufwrd);
723 throw_xfree(bufansi);
724
725 bufchr = (vchar*)throw_xcalloc(sizeof(vchar), numcols+1);
726 bufwrd = (vatch*)throw_xcalloc(sizeof(vatch), numcols+1);
727 bufansi = (vchar*)throw_xcalloc(sizeof(vchar), (11*numcols)+1);
728
729 setdevice(device);
730 }
731
732
733 // ------------------------------------------------------------------
734 // Sets video output device
735
setdevice(int _device)736 void GVid::setdevice(int _device) {
737
738 device = _device;
739 }
740
741
742 // ------------------------------------------------------------------
743 // Sets video mode
744
setmode(int _mode)745 void GVid::setmode(int _mode) {
746
747 if(_mode) {
748 #if defined(__MSDOS__)
749
750 i86 cpu;
751 cpu.ah(0x00);
752 cpu.al((byte)_mode);
753 cpu.genint(0x10);
754
755 #endif
756 }
757
758 detectinfo(&curr);
759 resetcurr();
760 }
761
762
763 // ------------------------------------------------------------------
764 // Sets screen rows
765
setrows(int _rows)766 void GVid::setrows(int _rows) {
767
768 int origrows = curr.screen.rows;
769
770 #if defined(__USE_NCURSES__)
771
772 NW(_rows);
773
774 #elif defined(__MSDOS__)
775 i86 cpu;
776
777 // Set video mode 3 (80xNN)
778 if(curr.screen.mode != 3) {
779 cpu.ax(0x0003);
780 cpu.genint(0x10);
781 }
782
783 if(adapter >= V_EGA) {
784 if((_rows == 28) and (adapter >= V_VGA)) { // vga-only
785 cpu.ax(0x1202);
786 cpu.bl(0x30);
787 cpu.genint(0x10);
788 cpu.ax(0x1111);
789 cpu.bl(0);
790 cpu.genint(0x10);
791 }
792 else if(_rows >= 43) {
793 cpu.ax(0x1112); // Load 8x8 character set
794 cpu.bl(0x00);
795 cpu.genint(0x10);
796 cpu.ax(0x1200); // Select alternate print-screen routine
797 cpu.bl(0x20);
798 cpu.genint(0x10);
799 if(adapter & V_EGA) {
800 // Disable cursor size emulation
801 byte* _bptr = (byte*)0x0487;
802 *_bptr |= (byte)0x01;
803 // Set cursor size
804 cpu.ah(0x01);
805 cpu.al((byte)orig.screen.mode);
806 cpu.cx(0x0600);
807 cpu.genint(0x10);
808 }
809 }
810 else {
811 if(adapter & V_EGA) {
812 // Enable cursor size emulation
813 byte* _bptr = (byte*)0x0487;
814 *_bptr &= (byte)0xFE;
815 }
816 // Set cursor size
817 cpu.ah(0x01);
818 cpu.al((byte)orig.screen.mode);
819 cpu.cx(0x0607);
820 cpu.genint(0x10);
821 }
822 }
823
824 #elif defined(__OS2__)
825
826 VIOMODEINFO viomodeinfo;
827 memset(&viomodeinfo, 0, sizeof(VIOMODEINFO));
828 viomodeinfo.cb = sizeof(VIOMODEINFO);
829 VioGetMode(&viomodeinfo, 0);
830 viomodeinfo.row = (USHORT)_rows;
831 VioSetMode(&viomodeinfo, 0);
832
833 #elif defined(__WIN32__) || defined(__UNIX__)
834
835 NW(_rows);
836
837 #endif
838
839 if(origrows < _rows)
840 vfill(origrows, 0, _rows, 80, ' ', LGREY_|_BLACK);
841
842 detectinfo(&curr);
843 resetcurr();
844 }
845
846
847 // ------------------------------------------------------------------
848 // Set the screen border (overscan) color
849
setoverscan(vattr _overscan)850 void GVid::setoverscan(vattr _overscan)
851 {
852 #if defined(__USE_NCURSES__)
853
854 NW (_overscan);
855
856 #elif defined(__MSDOS__)
857
858 i86 cpu;
859 cpu.ah(0x0B);
860 cpu.bh(0x00);
861 cpu.bl((byte)_overscan);
862 cpu.genint(0x10);
863
864 #elif defined(__OS2__)
865
866 VIOOVERSCAN viooverscan;
867 memset(&viooverscan, 0, sizeof(VIOOVERSCAN));
868 viooverscan.cb = sizeof(VIOOVERSCAN);
869 viooverscan.type = 0x0001;
870 VioGetState(&viooverscan, 0);
871 viooverscan.color = (BYTE)_overscan;
872 VioSetState(&viooverscan, 0);
873
874 #elif defined(__WIN32__) || defined(__UNIX__)
875
876 NW(_overscan);
877
878 #endif
879 }
880
881
882 // ------------------------------------------------------------------
883 // Set intensity/blinking state
884
setintensity(int _intensity)885 void GVid::setintensity(int _intensity)
886 {
887 #if defined(__USE_NCURSES__)
888
889 NW(_intensity);
890
891 #elif defined(__MSDOS__)
892
893 #ifdef __DJGPP__
894
895 if(_intensity)
896 intensevideo();
897 else
898 blinkvideo();
899
900 #else
901
902 if(adapter & V_CGA) {
903 word* _wptr = (word*)0x0463;
904 byte* _bptr = (byte*)0x0465;
905 uint port = *_wptr + 4;
906 uint reg = *_bptr;
907 if(_intensity)
908 reg &= 0xDF;
909 else
910 reg |= 0x20;
911 outp(port, reg);
912 }
913 else {
914 i86 cpu;
915 cpu.ax(0x1003);
916 cpu.bh(0x00);
917 cpu.bl((byte)(_intensity ? 0 : 1));
918 cpu.genint(0x10);
919 }
920
921 #endif // __DJGPP__
922
923 #elif defined(__OS2__)
924
925 VIOINTENSITY viointensity;
926 memset(&viointensity, 0, sizeof(VIOINTENSITY));
927 viointensity.cb = sizeof(VIOINTENSITY);
928 viointensity.fs = (USHORT)(_intensity ? 1 : 0);
929 viointensity.type = 0x0002;
930 VioSetState(&viointensity, 0);
931
932 #elif defined(__WIN32__) || defined(__UNIX__)
933
934 NW(_intensity);
935
936 #endif
937 }
938
939
940 // ------------------------------------------------------------------
941
getpalette(int * _palette)942 void GVid::getpalette(int* _palette)
943 {
944 #if defined(__USE_NCURSES__)
945
946 NW(_palette);
947
948 #elif defined(__MSDOS__)
949
950 // Get palette state
951 if(adapter & V_VGA) {
952 i86 cpu;
953 for(byte n=0; n<16; n++) {
954 cpu.ax(0x1007); // GET INDIVIDUAL PALETTE REGISTER
955 cpu.bh(0xFF);
956 cpu.bl(n);
957 cpu.genint(0x10);
958 _palette[n] = cpu.bh();
959 }
960 }
961 else {
962 // Set to standard palette colors
963 for(byte n=0; n<16; n++)
964 _palette[n] = n + ((n > 7) ? 48 : 0);
965 }
966
967 #elif defined(__OS2__)
968
969 // Get palette state
970 BYTE viopalstate[38];
971 PVIOPALSTATE pviopalstate;
972 memset(viopalstate, 0, sizeof(viopalstate));
973 pviopalstate = (PVIOPALSTATE)viopalstate;
974 pviopalstate->cb = sizeof(viopalstate);
975 pviopalstate->type = 0;
976 pviopalstate->iFirst = 0;
977 VioGetState(pviopalstate, 0);
978 for(byte n=0; n<16; n++)
979 _palette[n] = pviopalstate->acolor[n];
980
981 #elif defined(__WIN32__) || defined(__UNIX__)
982
983 NW(_palette);
984
985 #endif
986 }
987
988
989 // ------------------------------------------------------------------
990
setpalette(int * _palette)991 void GVid::setpalette(int* _palette)
992 {
993 #if defined(__USE_NCURSES__)
994
995 NW(_palette);
996
997 #elif defined(__MSDOS__)
998
999 if(adapter & (V_EGA|V_MCGA|V_VGA)) {
1000 i86 cpu;
1001 for(byte n=0; n<16; n++) {
1002 if(_palette[n] != -1) {
1003 cpu.ax(0x1000);
1004 cpu.bl(n);
1005 cpu.bh((byte)_palette[n]);
1006 cpu.genint(0x10);
1007 }
1008 }
1009 }
1010
1011 #elif defined(__OS2__)
1012
1013 BYTE viopalstate[38];
1014 PVIOPALSTATE pviopalstate;
1015 memset(viopalstate, 0, sizeof(viopalstate));
1016 pviopalstate = (PVIOPALSTATE)viopalstate;
1017 pviopalstate->cb = sizeof(viopalstate);
1018 pviopalstate->type = 0;
1019 pviopalstate->iFirst = 0;
1020 VioGetState(pviopalstate, 0);
1021 for(byte n=0; n<16; n++)
1022 if(_palette[n] != -1)
1023 pviopalstate->acolor[n] = (USHORT)_palette[n];
1024 VioSetState(pviopalstate, 0);
1025
1026 #elif defined(__WIN32__) || defined(__UNIX__)
1027
1028 NW(_palette);
1029
1030 #endif
1031 }
1032
1033
1034 // ------------------------------------------------------------------
1035
restore_cursor()1036 void GVid::restore_cursor() {
1037
1038 vcurset(orig.cursor.start, orig.cursor.end);
1039 vcurshow();
1040 vposset(orig.cursor.row-1, 0);
1041 }
1042
1043
1044 // ------------------------------------------------------------------
1045
resize_screen(int columns,int rows)1046 void GVid::resize_screen(int columns, int rows) {
1047
1048 numcols = curr.screen.columns = columns;
1049 numrows = curr.screen.rows = rows;
1050
1051 bufchr = (vchar*)throw_xrealloc(bufchr, numcols+1);
1052 bufwrd = (vatch*)throw_xrealloc(bufwrd, (numcols+1)*sizeof(vatch));
1053 bufansi = (vchar*)throw_xrealloc(bufansi, 1+(11*numcols));
1054
1055 #if defined(__UNIX__) && !defined(__USE_NCURSES__) && !defined(__DJGPP__)
1056 dmaptr = (gdma)throw_xrealloc(dmaptr, (rows+1)*columns*sizeof(word));
1057 #endif
1058 }
1059
1060
1061 // ------------------------------------------------------------------
1062