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