1 #include <string.h>
2 #ifdef NCURSES
3 #include <curses.h>
4 #else
5 #include "xfcurses.h"
6 #endif
7 #include "port.h"
8 #include "prototyp.h"
9 /*
10  * This file contains Unix versions of the routines in video.asm
11  * Copyright 1992 Ken Shirriff
12  */
13 
14 extern WINDOW *curwin;
15 
16 extern unsigned char *xgetfont (void);
17 extern int startdisk (void);
18 extern int waitkeypressed (int);
19 extern int ctrl_window;
20 
21 #ifndef NCURSES
22 extern unsigned long pixel[48];
23 #endif
24 
25 int fake_lut = 0;
26 int istruecolor = 0;
27 int daclearn = 0;
28 int dacnorm = 0;
29 int daccount = 0;
30 int ShadowColors;
31 int goodmode = 0;		/* if non-zero, OK to read/write pixels */
32 void (*dotwrite) (int, int, int);
33 				/* write-a-dot routine */
34 int (*dotread) (int, int);	/* read-a-dot routine */
35 void (*linewrite) ();		/* write-a-line routine */
36 void (*lineread) ();		/* read-a-line routine */
37 int andcolor = 0;		/* "and" value used for color selection */
38 int diskflag = 0;		/* disk video active flag */
39 
40 int videoflag = 0;		/* special "your-own-video" flag */
41 
42 void (*swapsetup) (void) = NULL;	/* setfortext/graphics setup routine */
43 int color_dark = 0;		/* darkest color in palette */
44 int color_bright = 0;		/* brightest color in palette */
45 int color_medium = 0;		/* nearest to medbright grey in palette
46 				   Zoom-Box values (2K x 2K screens max) */
47 extern int boxcolor;		/* Zoom-Box color */
48 int reallyega = 0;		/* 1 if its an EGA posing as a VGA */
49 int gotrealdac = 0;		/* 1 if loaddac has a dacbox */
50 int rowcount = 0;		/* row-counter for decoder and out_line */
51 int video_type = 0;		/* actual video adapter type:
52 				   0  = type not yet determined
53 				   1  = Hercules
54 				   2  = CGA (assumed if nothing else)
55 				   3  = EGA
56 				   4  = MCGA
57 				   5  = VGA
58 				   6  = VESA (not yet checked)
59 				   11  = 8514/A (not yet checked)
60 				   12  = TIGA   (not yet checked)
61 				   13  = TARGA  (not yet checked)
62 				   100 = x monochrome
63 				   101 = x 256 colors
64 				 */
65 int svga_type = 0;		/*  (forced) SVGA type
66 				   1 = ahead "A" type
67 				   2 = ATI
68 				   3 = C&T
69 				   4 = Everex
70 				   5 = Genoa
71 				   6 = Ncr
72 				   7 = Oak-Tech
73 				   8 = Paradise
74 				   9 = Trident
75 				   10 = Tseng 3000
76 				   11 = Tseng 4000
77 				   12 = Video-7
78 				   13 = ahead "B" type
79 				   14 = "null" type (for testing only) */
80 int mode7text = 0;		/* nonzero for egamono and hgc */
81 int textaddr = 0xb800;		/* b800 for mode 3, b000 for mode 7 */
82 int textsafe = 0;		/* 0 = default, runup chgs to 1
83 				   1 = yes
84 				   2 = no, use 640x200
85 				   3 = bios, yes plus use int 10h-1Ch
86 				   4 = save, save entire image */
87 #ifdef NCURSES
88 int text_type = 1;
89 #else
90 int text_type = 0;
91 #endif
92 				/* current mode's type of text:
93 				   0  = real text, mode 3 (or 7)
94 				   1  = 640x200x2, mode 6
95 				   2  = some other mode, graphics */
96 int textrow = 0;		/* for putstring(-1,...) */
97 int textcol = 0;		/* for putstring(..,-1,...) */
98 int textrbase = 0;		/* textrow is relative to this */
99 int textcbase = 0;		/* textcol is relative to this */
100 
101 int vesa_detect = 1;		/* set to 0 to disable VESA-detection */
102 int virtual = 0;                /* no virtual screens, it's a DOS thing */
103 int video_scroll = 0;
104 int video_startx = 0;
105 int video_starty = 0;
106 int vesa_xres;
107 int vesa_yres;
108 int chkd_vvs = 0;
109 int video_vram = 0;
110 
111 /*
112 
113 ;		|--Adapter/Mode-Name------|-------Comments-----------|
114 
115 ;		|------INT 10H------|Dot-|--Resolution---|
116 ;	    |key|--AX---BX---CX---DX|Mode|--X-|--Y-|Color|
117 */
118 
119 struct videoinfo videotable[MAXVIDEOTABLE] = {
120   {"xfractint mode           ", "                         ",
121    999, 0, 0, 0, 0, 19, 800, 600, 256},
122   {"unused  mode             ", "                         ",
123    0, 0, 0, 0, 0, 0, 0, 0, 0},
124 };
125 
126 void setforgraphics ();
127 
128 void
nullwrite(a,b,c)129 nullwrite (a, b, c)
130      int a, b, c;
131 {
132 }
133 
134 int
nullread(a,b)135 nullread (a, b)
136      int a, b;
137 {
138   return 0;
139 }
140 
141 void
setnullvideo(void)142 setnullvideo (void)
143 {
144   dotwrite = nullwrite;
145   dotread = nullread;
146 }
147 
148 void normalineread ();
149 void normaline ();
150 
151 void
putprompt(void)152 putprompt (void)
153 {
154   wclear (curwin);		/* ???? */
155 #ifdef NCURSES
156   putstring (0, 0, 15, "Press operation key ('d' = redraw), or <Esc> to return to Main Menu");
157   wrefresh (curwin);
158 #else
159   if (ctrl_window)
160      putstring (0, 0, 15, "Press operation key ('d' = redraw), or <Esc> to return to Main Menu");
161 #endif
162   return;
163 }
164 
165 /*
166 ; ********************** Function setvideotext() ************************
167 
168 ;       Sets video to text mode, using setvideomode to do the work.
169 */
170 void
setvideotext(void)171 setvideotext (void)
172 {
173   initmode = adapter;
174   dotmode = 0;
175   setvideomode (3, 0, 0, 0);
176 }
177 
178 void
loaddac(void)179 loaddac (void)
180 {
181   readvideopalette ();
182 }
183 
184 /*
185 ; **************** Function setvideomode(ax, bx, cx, dx) ****************
186 ;       This function sets the (alphanumeric or graphic) video mode
187 ;       of the monitor.   Called with the proper values of AX thru DX.
188 ;       No returned values, as there is no particular standard to
189 ;       adhere to in this case.
190 
191 ;       (SPECIAL "TWEAKED" VGA VALUES:  if AX==BX==CX==0, assume we have a
192 ;       genuine VGA or register compatable adapter and program the registers
193 ;       directly using the coded value in DX)
194 
195 ; Unix: We ignore ax,bx,cx,dx.  dotmode is the "mode" field in the video
196 ; table.  We use mode 19 for the X window.
197 */
198 void
setvideomode(ax,bx,cx,dx)199 setvideomode (ax, bx, cx, dx)
200      int ax, bx, cx, dx;
201 {
202   if (diskflag)
203     {
204       enddisk ();
205     }
206   if (videoflag)
207     {
208       endvideo ();
209       videoflag = 0;
210     }
211   goodmode = 1;
212   switch (dotmode)
213     {
214     case 0:			/* text */
215       clear ();
216       /*
217          touchwin(curwin);
218        */
219       wrefresh (curwin);
220       break;
221     case 11:
222       startdisk ();
223       dotwrite = writedisk;
224       dotread = readdisk;
225       lineread = normalineread;
226       linewrite = normaline;
227       break;
228     case 19:			/* X window */
229       putprompt ();
230       dotwrite = writevideo;
231       dotread = readvideo;
232       lineread = readvideoline;
233       linewrite = writevideoline;
234       videoflag = 1;
235       startvideo ();
236       setforgraphics ();
237       break;
238     default:
239       printf ("Bad mode %d\n", dotmode);
240       exit (-1);
241     }
242   if (dotmode != 0)
243     {
244       loaddac ();
245       andcolor = colors - 1;
246       boxcount = 0;
247     }
248   vesa_xres = sxdots;
249   vesa_yres = sydots;
250 }
251 
252 
253 /*
254 ; **************** Function getcolor(xdot, ydot) *******************
255 
256 ;       Return the color on the screen at the (xdot,ydot) point
257 */
258 int
getcolor(xdot,ydot)259 getcolor (xdot, ydot)
260      int xdot, ydot;
261 {
262   int x1, y1;
263   x1 = xdot + sxoffs;
264   y1 = ydot + syoffs;
265   if (x1 < 0 || y1 < 0 || x1 >= sxdots || y1 >= sydots)
266     return 0;
267   return dotread (x1, y1);
268 }
269 
270 /*
271 ; ************** Function putcolor_a(xdot, ydot, color) *******************
272 
273 ;       write the color on the screen at the (xdot,ydot) point
274 */
275 void
putcolor_a(xdot,ydot,color)276 putcolor_a (xdot, ydot, color)
277      int xdot, ydot, color;
278 {
279   dotwrite (xdot + sxoffs, ydot + syoffs, color & andcolor);
280 }
281 
282 /*
283 ; **************** Function movecursor(row, col)  **********************
284 
285 ;       Move the cursor (called before printfs)
286 */
287 void
movecursor(row,col)288 movecursor (row, col)
289      int row, col;
290 {
291   if (row == -1)
292     {
293       row = textrow;
294     }
295   else
296     {
297       textrow = row;
298     }
299   if (col == -1)
300     {
301       col = textcol;
302     }
303   else
304     {
305       textcol = col;
306     }
307   wmove (curwin, row, col);
308 }
309 
310 /*
311 ; **************** Function keycursor(row, col)  **********************
312 
313 ;       Subroutine to wait cx ticks, or till keystroke pending
314 */
315 int
keycursor(row,col)316 keycursor (row, col)
317      int row, col;
318 {
319   movecursor (row, col);
320   wrefresh (curwin);
321   waitkeypressed (0);
322   return getakey ();
323 }
324 
325 /*
326 ; PUTSTR.asm puts a string directly to video display memory. Called from C by:
327 ;    putstring(row, col, attr, string) where
328 ;         row, col = row and column to start printing.
329 ;         attr = color attribute.
330 ;         string = far pointer to the null terminated string to print.
331 ;    Written for the A86 assembler (which has much less 'red tape' than MASM)
332 ;    by Bob Montgomery, Orlando, Fla.             7-11-88
333 ;    Adapted for MASM 5.1 by Tim Wegner          12-11-89
334 ;    Furthur mucked up to handle graphics
335 ;       video modes by Bert Tyler                 1-07-90
336 ;    Reworked for:  row,col update/inherit;
337 ;       620x200x2 inverse video;  far ptr to string;
338 ;       fix to avoid scrolling when last posn chgd;
339 ;       divider removed;  newline ctl chars;  PB  9-25-90
340 */
341 void
putstring(row,col,attr,msg)342 putstring (row, col, attr, msg)
343      int row, col, attr;
344      CHAR far *msg;
345 {
346   int so = 0;
347   if (row != -1)
348     textrow = row;
349   if (col != -1)
350     textcol = col;
351 
352 #ifndef NCURSES
353   curwin->_cur_attr = attr;
354 #endif
355 
356   if (attr & INVERSE || attr & BRIGHT)
357     {
358       wstandout (curwin);
359       so = 1;
360     }
361 
362   wmove (curwin, textrow + textrbase, textcol + textcbase);
363   while (1)
364     {
365       if (*msg == '\0')
366 	break;
367       if (*msg == '\n')
368 	{
369 	  textcol = 0;
370 	  textrow++;
371 	  wmove (curwin, textrow + textrbase, textcol + textcbase);
372 	}
373       else
374 	{
375 	  char *ptr;
376 	  ptr = strchr (msg, '\n');
377 	  if (ptr == NULL)
378 	    {
379 	      waddstr (curwin, msg);
380 	      break;
381 	    }
382 	  else
383 	    {
384 	      waddch (curwin, *msg);
385 	    }
386 	}
387       msg++;
388     }
389   if (so)
390     {
391       wstandend (curwin);
392     }
393 
394 #ifdef NCURSES
395   wrefresh (curwin);
396   fflush (stdout);
397 #else
398   XFlush(Xdp);
399 #endif
400   getyx (curwin, textrow, textcol);
401   textrow -= textrbase;
402   textcol -= textcbase;
403 }
404 
405 /*
406 ; setattr(row, col, attr, count) where
407 ;         row, col = row and column to start printing.
408 ;         attr = color attribute.
409 ;         count = number of characters to set
410 ;         This routine works only in real color text mode.
411 */
412 void
setattr(row,col,attr,count)413 setattr (row, col, attr, count)
414      int row, col, attr, count;
415 {
416   int i;
417   int so = 0;
418   if (row != -1)
419     textrow = row;
420   if (col != -1)
421     textcol = col;
422 
423   if (attr & INVERSE || attr & BRIGHT)
424     {
425       wstandout (curwin);
426       so = 1;
427     }
428 
429   wmove (curwin, textrow + textrbase, textcol + textcbase);
430 
431 #ifndef NCURSES
432   curwin->_cur_attr = attr;
433   for (i=0; i<count; i++)
434     waddch (curwin, '\0');
435 #endif
436   if (so)
437     {
438       wstandend (curwin);
439     }
440 
441 }
442 
443 /*
444 ; **************** Function home()  ********************************
445 
446 ;       Home the cursor (called before printfs)
447 */
448 void
home(void)449 home (void)
450 {
451   wmove (curwin, 0, 0);
452   textrow = 0;
453   textcol = 0;
454 }
455 
456 
457 /*
458 ; ************* Function scrollup(toprow, botrow) ******************
459 
460 ;       Scroll the screen up (from toprow to botrow)
461 */
462 void
scrollup(top,bot)463 scrollup (top, bot)
464      int top, bot;
465 {
466   wmove (curwin, top, 0);
467   wdeleteln (curwin);
468   wmove (curwin, bot, 0);
469   winsertln (curwin);
470 #ifdef NCURSES
471   wrefresh (curwin);
472 #else
473   refresh(top, bot+1);
474 #endif
475 }
476 
477 /*
478 ; *************** Function spindac(direction, rstep) ********************
479 
480 ;       Rotate the MCGA/VGA DAC in the (plus or minus) "direction"
481 ;       in "rstep" increments - or, if "direction" is 0, just replace it.
482 */
483 void
spindac(dir,inc)484 spindac (dir, inc)
485      int dir, inc;
486 {
487   int i, top;
488   unsigned char tmp[3];
489   unsigned char *dacbot;
490   int len;
491   if (colors < 16)
492     return;
493   if (!(gotrealdac || fake_lut))
494     return;
495   if (istruecolor)
496     return;
497   if (dir != 0 && rotate_lo < colors && rotate_lo < rotate_hi)
498     {
499       top = rotate_hi > colors ? colors - 1 : rotate_hi;
500       dacbot = (unsigned char *) dacbox + 3 * rotate_lo;
501       len = (top - rotate_lo) * 3 * sizeof (unsigned char);
502       if (dir > 0)
503 	{
504 	  for (i = 0; i < inc; i++)
505 	    {
506 	      bcopy (dacbot, tmp, 3 * sizeof (unsigned char));
507 	      bcopy (dacbot + 3 * sizeof (unsigned char), dacbot, len);
508 	      bcopy (tmp, dacbot + len, 3 * sizeof (unsigned char));
509 	    }
510 	}
511       else
512 	{
513 	  for (i = 0; i < inc; i++)
514 	    {
515 	      bcopy (dacbot + len, tmp, 3 * sizeof (unsigned char));
516 	      bcopy (dacbot, dacbot + 3 * sizeof (unsigned char), len);
517 	      bcopy (tmp, dacbot, 3 * sizeof (unsigned char));
518 	    }
519 	}
520     }
521   writevideopalette ();
522   delay (colors - daccount - 1);
523 }
524 
525 /*
526 ; ---- Help (Video) Support
527 ; ********* Functions setfortext() and setforgraphics() ************
528 
529 ;       setfortext() resets the video for text mode and saves graphics data
530 ;       setforgraphics() restores the graphics mode and data
531 ;       setclear() clears the screen after setfortext()
532 */
533 void
setfortext(void)534 setfortext (void)
535 {
536 }
537 
538 void
setclear(void)539 setclear (void)
540 {
541   wclear (curwin);
542   wrefresh (curwin);
543 }
544 
545 void
setforgraphics()546 setforgraphics ()
547 {
548   startvideo ();
549   spindac (0, 1);
550 }
551 
552 unsigned char *fontTab = NULL;
553 
554 /*
555 ; ************** Function findfont(n) ******************************
556 
557 ;       findfont(0) returns far pointer to 8x8 font table if it can
558 ;                   find it, NULL otherwise;
559 ;                   nonzero parameter reserved for future use
560 */
561 BYTE *
findfont(fontparm)562 findfont (fontparm)
563      int fontparm;
564 {
565   if (fontTab == NULL)
566     {
567       fontTab = xgetfont ();
568     }
569   return (BYTE *) fontTab;
570 }
571 
572 /*
573 ; ******************** Zoombox functions **************************
574 */
575 
576 /*
577  * The IBM method is that boxx[],boxy[] is a set of locations, and boxvalues
578  * is the values in these locations.
579  * Instead of using this box save/restore technique, we'll put the corners
580  * in boxx[0],boxy[0],1,2,3 and then use xor.
581  */
582 
583 void
dispbox(void)584 dispbox (void)
585 {
586   if (boxcount)
587     {
588       setlinemode (1);
589       drawline (boxx[0], boxy[0], boxx[1], boxy[1]);
590       drawline (boxx[1], boxy[1], boxx[2], boxy[2]);
591       drawline (boxx[2], boxy[2], boxx[3], boxy[3]);
592       drawline (boxx[3], boxy[3], boxx[0], boxy[0]);
593       setlinemode (0);
594       xsync ();
595     }
596 }
597 
598 void
clearbox(void)599 clearbox (void)
600 {
601   dispbox ();
602 }
603 
604 int
CheckForTPlus(void)605 CheckForTPlus (void)
606 {
607   return 0;
608 }
609 
610 /*
611 ; Passing this routine 0 turns off shadow, nonzero turns it on.
612 */
613 int
ShadowVideo(on)614 ShadowVideo (on)
615      int on;
616 {
617   return 0;
618 }
619 
620 int
SetupShadowVideo(void)621 SetupShadowVideo (void)
622 {
623   return 0;
624 }
625 
626 /*
627 ; adapter_detect:
628 ;       This routine performs a few quick checks on the type of
629 ;       video adapter installed.
630 ;       It sets variables video_type and textsafe,
631 ;       and fills in a few bank-switching routines.
632 */
633 int done_detect = 0;
634 
635 void
adapter_detect(void)636 adapter_detect (void)
637 {
638   if (done_detect)
639     return;
640   done_detect = 1;
641   textsafe = 2;
642   if (colors == 2)
643     {
644       video_type = 100;
645     }
646   else
647     {
648       video_type = 101;
649     }
650 }
651 
652 /*
653 ; **************** internal Read/Write-a-line routines *********************
654 ;
655 ;       These routines are called by out_line(), put_line() and get_line().
656 */
657 
658 void
normaline(y,x,lastx,pixels)659 normaline (y, x, lastx, pixels)
660      int x, y, lastx;
661      BYTE *pixels;
662 {
663   int i, width;
664   width = lastx - x + 1;
665   for (i = 0; i < width; i++)
666     {
667       dotwrite (x + i, y, pixels[i]);
668     }
669 }
670 
671 void
normalineread(y,x,lastx,pixels)672 normalineread (y, x, lastx, pixels)
673      int x, y, lastx;
674      BYTE *pixels;
675 {
676   int i, width;
677   width = lastx - x + 1;
678   for (i = 0; i < width; i++)
679     {
680       pixels[i] = dotread (x + i, y);
681     }
682 }
683 
684 /*
685 ; *************** Function find_special_colors ********************
686 
687 ;       Find the darkest and brightest colors in palette, and a medium
688 ;       color which is reasonably bright and reasonably grey.
689 */
690 void
find_special_colors(void)691 find_special_colors (void)
692 {
693   int maxb = 0;
694   int minb = 9999;
695   int med = 0;
696   int maxgun, mingun;
697   int brt;
698   int i;
699 
700   color_dark = 0;
701   color_medium = 7;
702   color_bright = 15;
703 
704   if (colors == 2)
705     {
706       color_medium = 1;
707       color_bright = 1;
708       return;
709     }
710 
711   if (!(gotrealdac || fake_lut))
712     return;
713 
714   for (i = 0; i < colors; i++)
715     {
716       brt = (int) dacbox[i][0] + (int) dacbox[i][1] + (int) dacbox[i][2];
717       if (brt > maxb)
718 	{
719 	  maxb = brt;
720 	  color_bright = i;
721 	}
722       if (brt < minb)
723 	{
724 	  minb = brt;
725 	  color_dark = i;
726 	}
727       if (brt < 150 && brt > 80)
728 	{
729 	  maxgun = mingun = (int) dacbox[i][0];
730 	  if ((int) dacbox[i][1] > (int) dacbox[i][0])
731 	    {
732 	      maxgun = (int) dacbox[i][1];
733 	    }
734 	  else
735 	    {
736 	      mingun = (int) dacbox[i][1];
737 	    }
738 	  if ((int) dacbox[i][2] > maxgun)
739 	    {
740 	      maxgun = (int) dacbox[i][2];
741 	    }
742 	  if ((int) dacbox[i][2] < mingun)
743 	    {
744 	      mingun = (int) dacbox[i][2];
745 	    }
746 	  if (brt - (maxgun - mingun) / 2 > med)
747 	    {
748 	      color_medium = i;
749 	      med = brt - (maxgun - mingun) / 2;
750 	    }
751 	}
752     }
753 }
754 
755 /*
756 ; *************** Functions get_a_char, put_a_char ********************
757 
758 ;       Get and put character and attribute at cursor
759 ;       Hi nybble=character, low nybble attribute. Text mode only
760 */
761 char
get_a_char(void)762 get_a_char (void)
763 {
764   return (char) getakey ();
765 }
766 
767 void
put_a_char(ch)768 put_a_char (ch)
769      int ch;
770 {
771 }
772 
773 /*
774 ; ***Function get_line(int row,int startcol,int stopcol, unsigned char *pixels)
775 
776 ;       This routine is a 'line' analog of 'getcolor()', and gets a segment
777 ;       of a line from the screen and stores it in pixels[] at one byte per
778 ;       pixel
779 ;       Called by the GIF decoder
780 */
781 
782 void
get_line(row,startcol,stopcol,pixels)783 get_line (row, startcol, stopcol, pixels)
784      int row, startcol, stopcol;
785      BYTE *pixels;
786 {
787   if (startcol + sxoffs >= sxdots || row + syoffs >= sydots)
788     return;
789   lineread (row + syoffs, startcol + sxoffs, stopcol + sxoffs, pixels);
790 }
791 
792 /*
793 ; ***Function put_line(int row,int startcol,int stopcol, unsigned char *pixels)
794 
795 ;       This routine is a 'line' analog of 'putcolor()', and puts a segment
796 ;       of a line from the screen and stores it in pixels[] at one byte per
797 ;       pixel
798 ;       Called by the GIF decoder
799 */
800 
801 void
put_line(row,startcol,stopcol,pixels)802 put_line (row, startcol, stopcol, pixels)
803      int row, startcol, stopcol;
804      BYTE *pixels;
805 {
806   if (startcol + sxoffs >= sxdots || row + syoffs > sydots)
807     return;
808   linewrite (row + syoffs, startcol + sxoffs, stopcol + sxoffs, pixels);
809 }
810 
811 /*
812 ; ***************Function out_line(pixels,linelen) *********************
813 
814 ;       This routine is a 'line' analog of 'putcolor()', and sends an
815 ;       entire line of pixels to the screen (0 <= xdot < xdots) at a clip
816 ;       Called by the GIF decoder
817 */
818 int
out_line(pixels,linelen)819 out_line (pixels, linelen)
820      BYTE *pixels;
821      int linelen;
822 {
823   if (rowcount + syoffs >= sydots)
824     return 0;
825   linewrite (rowcount + syoffs, sxoffs, linelen + sxoffs - 1, pixels);
826   rowcount++;
827   return 0;
828 }
829 
830 /*
831 ; far move routine for savegraphics/restoregraphics
832 */
833 void
movewords(len,fromptr,toptr)834 movewords (len, fromptr, toptr)
835      int len;
836      BYTE *fromptr, *toptr;
837 {
838   bcopy (fromptr, toptr, len);
839 }
840 
841 void
swapnormread(void)842 swapnormread (void)
843 {
844 }
845 void
swapnormwrite(void)846 swapnormwrite (void)
847 {
848 }
849 
850 /*
851  * Implement stack and unstack window functions by using multiple curses
852  * windows.
853  */
854 void
savecurses(ptr)855 savecurses (ptr)
856      WINDOW **ptr;
857 {
858   ptr[0] = curwin;
859 #ifdef NCURSES
860   curwin = newwin (0, 0, 0, 0);
861 #else
862   curwin = newwin (LINES, COLS, 0, 0);
863 #endif
864   touchwin (curwin);
865   wrefresh (curwin);
866 }
867 
868 void
restorecurses(ptr)869 restorecurses (ptr)
870      WINDOW **ptr;
871 {
872   delwin (curwin);
873   curwin = ptr[0];
874   touchwin (curwin);
875   wrefresh (curwin);
876 #ifndef NCURSES
877   refresh(0, LINES);
878 #endif
879 }
880 
881 /* Moved the following from realdos.c to more cleanly separate the XFRACT
882  * code.  Now curses.h is only required in the unix directory. JCO 11/26/2005
883  */
884 
885 /*
886  * The stackscreen()/unstackscreen() functions were originally
887  * ported to Xfractint.
888  * These functions are useful for switching between different text screens.
889  * For example, looking at a parameter entry using F2.
890  */
891 
892 int screenctr = 0;
893 
894 #define MAXSCREENS 3
895 
896 static BYTE far *savescreen[MAXSCREENS];
897 static int saverc[MAXSCREENS+1];
898 
stackscreen()899 void stackscreen()
900 {
901    int i;
902    BYTE far *ptr;
903    saverc[screenctr+1] = textrow*80 + textcol;
904    if (++screenctr) { /* already have some stacked */
905          static char far msg[]={"stackscreen overflow"};
906       if ((i = screenctr - 1) >= MAXSCREENS) { /* bug, missing unstack? */
907          stopmsg(1,msg);
908          exit(1);
909          }
910       if ((ptr = (savescreen[i] = (BYTE far *)farmemalloc(sizeof(int *)))))
911          savecurses((WINDOW **)ptr);
912       else {
913          stopmsg(1,msg);
914          exit(1);
915         }
916       setclear();
917       }
918    else
919       setfortext();
920 }
921 
unstackscreen()922 void unstackscreen()
923 {
924    BYTE far *ptr;
925    textrow = saverc[screenctr] / 80;
926    textcol = saverc[screenctr] % 80;
927    if (--screenctr >= 0) { /* unstack */
928       ptr = savescreen[screenctr];
929       restorecurses((WINDOW **)ptr);
930       farmemfree(ptr);
931       }
932    else
933       setforgraphics();
934    movecursor(-1,-1);
935 }
936 
discardscreen()937 void discardscreen()
938 {
939    if (--screenctr >= 0) { /* unstack */
940       if (savescreen[screenctr]) {
941          farmemfree(savescreen[screenctr]);
942       }
943    }
944    else
945       discardgraphics();
946 }
947