home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / BBS / MISC / HSRC_117.ZIP / TWINDOW.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-11-09  |  20.6 KB  |  1,046 lines

  1. /* TWINDOW.C File */
  2.  
  3. #include <stdio.h>
  4. #include <ctype.h>
  5. #include <stdarg.h>
  6. #include <dos.h>
  7. #include <alloc.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <conio.h>
  11. #include "twindow.h"
  12. #include "keys.h"
  13.  
  14. #define TABS         4
  15. #define ON        1
  16. #define OFF        0
  17. #define ERROR        -1
  18.  
  19. /* Local prototypes */
  20.  
  21. void pascal redraw(WINDOW *wnd);
  22. void pascal dtitle(WINDOW *wnd);
  23. int * pascal waddr(WINDOW *wnd,int x,int y);
  24. void pascal vswap(WINDOW *wnd);
  25. void pascal vsave(WINDOW *wnd);
  26. void pascal vrstr(WINDOW *wnd);
  27. void pascal add_list(WINDOW *wnd);
  28. void pascal beg_list(WINDOW *wnd);
  29. void pascal remove_list(WINDOW *wnd);
  30. void pascal insert_list(WINDOW *w1,WINDOW *w2);
  31. #ifndef FASTWINDOWS
  32.  int pascal dget(WINDOW *wnd,int x,int y);
  33.  int pascal verify_wnd(WINDOW **w1);
  34. #endif
  35. #ifdef USECLOCK
  36.  extern void pascal print_clock(void);
  37. #endif
  38.  
  39. /* Array of border character sets */
  40.  
  41. struct {
  42.   int nw,ne,se,sw,side,line;
  43.   } wcs[]={
  44.     {254,24,217,25,179,196},     /* single line */
  45.     {254,24,188,25,186,205},     /* double line */
  46.     {254,24,189,25,186,196},     /* single top, double side */
  47.     {254,24,190,25,179,205},     /* double top, single side */
  48.     {194,26,217,27,179,196},     /* pop-down menu */
  49.     {201,187,188,200,186,205},    /* double line no cues*/
  50.     {254,183,189,211,186,196}   /* horizontal menu of pull-down */
  51.   };
  52.  
  53. /* Window structure linked list head & tail */
  54.  
  55. WINDOW *listhead = NULL;
  56. WINDOW *listtail = NULL;
  57.  
  58. WINDOW *ewnd=NULL;    /* Global error/note window */
  59.  
  60. int VSG;  /* video segment address */
  61.  
  62. /* Variables which should be set by external functions */
  63.  
  64. unsigned int vbase=0;              /* for pd direct screen funcs if used */
  65. unsigned int maxx=0;            /* # columns on screen */
  66. unsigned int maxy=0;            /* # rows on screen */
  67. unsigned char current_color=7;  /* for pd direct screen funcs if used */
  68. unsigned int videomethod=0;     /* for pd direct screen funcs if used */
  69. unsigned char usemouse=0;       /* mouse used if non-zero */
  70. int oldmousex=-1,oldmousey,oldmousevid;
  71. int wasconfinedx1=-1,wasconfinedy1,wasconfinedx2,wasconfinedy2;
  72.  
  73. /* Establish a new window */
  74.  
  75. WINDOW * pascal establish_window (x,y,h,w) {
  76.  
  77.   WINDOW *wnd;
  78.  
  79.   VSG=(vmode()==7 ? 0xb000: 0xb800);
  80.   if ((wnd=(WINDOW *) malloc(sizeof(WINDOW)))==NULL)
  81.     return NULL;
  82.  
  83.   /* Adjust for out-of-bounds parameters */
  84.  
  85.   WTITLE="";
  86.   HEIGHT=min(h,maxy);
  87.   WIDTH=min(w,maxx);
  88.   COL=max(0,min(x,maxx-WIDTH));
  89.   ROW=max(0,min(y,maxy-HEIGHT));
  90.   WCURS=0;
  91.   SCROLL=0;
  92.   SELECT=1;
  93.   BTYPE=0;
  94.   VISIBLE=HIDDEN=0;
  95.   PREV=NEXT=NULL;
  96.   FHEAD=FTAIL=NULL;
  97.   WBORDER=WNORMAL=PNORMAL=WTITLEC=clr(BLACK,WHITE,BRIGHT);
  98.   WACCENT=clr(WHITE,BLACK,DIM);
  99.     if ((SAV=malloc(WIDTH * HEIGHT * 2))==(char *)0) return NULL;
  100.     add_list(wnd);
  101.   #ifndef FASTWINDOWS
  102.     clear_window(wnd);
  103.     wframe(wnd);
  104.   #endif
  105.     return(wnd);
  106. }
  107.  
  108.  
  109. /* Set the window's border */
  110.  
  111. void pascal set_border (WINDOW *wnd,int btype) {
  112.  
  113.   if (verify_wnd(&wnd)) {
  114.     BTYPE=btype;
  115.     redraw(wnd);
  116.   }
  117. }
  118.  
  119. /* Set colors */
  120.  
  121. void pascal set_colors (WINDOW *wnd,int area,int bg,int fg,int inten) {
  122.  
  123.   if (vmode()==7) {
  124.     if (bg != WHITE && bg !=BLACK) return;
  125.     if (fg !=WHITE && fg!=BLACK) return;
  126.   }
  127.   if(fg==bg) return;
  128.   if (verify_wnd(&wnd)) {
  129.     if (area==ALL)
  130.       while (area)
  131.         WCOLOR[--area]=clr(bg,fg,inten);
  132.     else WCOLOR[area]=clr(bg,fg,inten);
  133.     redraw (wnd);
  134.   }
  135. }
  136.  
  137. /* Set intensity of window */
  138.  
  139. void pascal set_intensity (WINDOW *wnd,int inten) {
  140.  
  141.   int area=ALL;
  142.  
  143.   if (verify_wnd(&wnd)) {
  144.     while (area) {
  145.       WCOLOR[--area]&= ~BRIGHT;
  146.       WCOLOR[area] |= inten;
  147.     }
  148.     redraw(wnd);
  149.   }
  150. }
  151.  
  152. /* Set title */
  153.  
  154. void pascal set_title (WINDOW *wnd,char *title) {
  155.   if (verify_wnd(&wnd)) {
  156.     WTITLE=title;
  157.     redraw(wnd);
  158.   }
  159. }
  160.  
  161. /* Redraw a window when an attribute changes */
  162.  
  163. static void pascal redraw (WINDOW *wnd) {
  164.  
  165. #ifndef FASTWINDOWS
  166.   int x,y,chat,atr;
  167.  
  168.   for (y=1;y<HEIGHT-1;y++)
  169.     for (x=1;x<WIDTH-1;x++) {
  170.       chat=dget(wnd,x,y);
  171.       atr=(((chat>>8)&255) ==
  172.     PNORMAL ? WNORMAL : WACCENT);
  173.       displ(wnd,x,y,chat&255,atr);
  174.     }
  175.   wframe(wnd);
  176. #endif
  177.   PNORMAL=WNORMAL;
  178. }
  179.  
  180. /* Display an established window */
  181.  
  182. void pascal display_window (WINDOW *wnd) {
  183.  
  184.   if (verify_wnd(&wnd)&& !VISIBLE) {
  185.     VISIBLE=1;
  186. #ifdef FASTWINDOWS
  187.     if (HIDDEN) {
  188.       HIDDEN=0;
  189.       vrstr(wnd);
  190.       wframe(wnd);
  191.     }
  192.     else {
  193.       vsave (wnd);
  194.       clear_window(wnd);
  195.       wframe(wnd);
  196.     }
  197. #else
  198.     vswap(wnd);
  199. #endif
  200.   }
  201. }
  202.  
  203. /* Close all windows */
  204.  
  205. void pascal close_all() {
  206.  
  207.   WINDOW *sav,*wnd=listtail;
  208.  
  209.   while(wnd) {
  210.     sav=PREV;
  211.     delete_window(wnd);
  212.     wnd=sav;
  213.   }
  214. }
  215.  
  216. /* Remove a window */
  217.  
  218. void pascal delete_window (WINDOW *wnd) {
  219.  
  220.   if (verify_wnd(&wnd)) {
  221.     hide_window(wnd);
  222.     free(SAV);
  223.     remove_list(wnd); /* remove window from list */
  224.     free(wnd);
  225.   }
  226. }
  227.  
  228. /* Hide a window */
  229.  
  230. void pascal hide_window (WINDOW *wnd) {
  231.  
  232.   if (verify_wnd(&wnd) && VISIBLE) {
  233. #ifndef FASTWINDOWS
  234.     vswap(wnd);
  235. #else
  236.     vrstr(wnd);
  237. #endif
  238.     HIDDEN=1;
  239.     VISIBLE=0;
  240.   }
  241. }
  242.  
  243. #ifndef FASTWINDOWS
  244.  
  245. /* Reposition the window in its 3-axis plane */
  246.  
  247. void pascal repos_wnd(WINDOW *wnd,int x,int y,int z) {
  248.  
  249.   WINDOW *twnd;
  250.   int x1,y1,chat;
  251.   if (!verify_wnd(&wnd))
  252.     return;
  253.   twnd=establish_window(x+COL,y+ROW,HEIGHT,WIDTH);
  254.   twnd->_tl=WTITLE;
  255.   twnd->btype=BTYPE;
  256.   twnd->wcolor[BORDER]=WBORDER;
  257.   twnd->wcolor[TITLE]=WTITLEC;
  258.   twnd->wcolor[ACCENT]=WACCENT;
  259.   twnd->wcolor[NORMAL]=WNORMAL;
  260.   twnd->_wsp=SCROLL;
  261.   twnd->_cr=WCURS;
  262.   if (z!=1) {
  263.     remove_list(twnd);
  264.     if (z==0)
  265.       insert_list(twnd,wnd);
  266.     else
  267.       beg_list(twnd);
  268.   }
  269.   for(y1=0;y1<twnd->_wh;y1++)
  270.     for (x1=0;x1<twnd->_ww;x1++) {
  271.       chat = dget(wnd,x1,y1);
  272.       displ(twnd,x1,y1,chat&255,(chat>>8)&255);
  273.     }
  274.   twnd->_wv=1;
  275.   vswap(twnd);
  276.   hide_window(wnd);
  277.   free(SAV);
  278.   remove_list(wnd);
  279.   *wnd=*twnd;
  280.   insert_list(wnd,twnd);
  281.   remove_list(twnd);
  282.   free(twnd);
  283. }
  284. #endif
  285.  
  286. /* Clear window */
  287.  
  288. void pascal clear_window (WINDOW *wnd) {
  289.  
  290.   register int x1,y1;
  291.  
  292.   if (verify_wnd(&wnd))
  293.     for(y1=1;y1<HEIGHT-1;y1++)
  294.       for(x1=1;x1<WIDTH-1;x1++)
  295.     displ(wnd,x1,y1,' ',WNORMAL);
  296. }
  297.  
  298. /* Draw the window frame */
  299.  
  300. void pascal wframe (WINDOW *wnd) {
  301.  
  302.   register int x1,y1;
  303.  
  304.   if (!verify_wnd(&wnd)) return;
  305.   /* Window title */
  306.   displ(wnd,0,0,NW,WBORDER);
  307.   dtitle(wnd);
  308.   displ(wnd,WIDTH-1,0,NE,WBORDER);
  309.   /* Window sides */
  310.   for (y1=1;y1<HEIGHT-1;y1++) {
  311.     displ(wnd,0,y1,SIDE,WBORDER);
  312.     displ(wnd,WIDTH-1,y1,SIDE,WBORDER);
  313.   }
  314.   /* Bottom of frame */
  315.   displ(wnd,0,y1,SW,WBORDER);
  316.   for(x1=1;x1<WIDTH-1;x1++)
  317.     displ(wnd,x1,y1,LINE,WBORDER);
  318.   displ(wnd,x1,y1,SE,WBORDER);
  319. }
  320.  
  321.  
  322. static void pascal dtitle (WINDOW *wnd) {
  323.  
  324.   int x1=1,i,ln;
  325.   char *s=WTITLE;
  326.  
  327.   if (!verify_wnd(&wnd)) return;
  328.   if (s) {
  329.     ln=strlen(s);
  330.     if (ln>WIDTH-2)
  331.       i=0;
  332.     else
  333.       i=((WIDTH-2-ln)/2);
  334.     if (i>0)
  335.       while (i--)
  336.     displ(wnd,x1++,0,LINE,WBORDER);
  337.     while(*s && x1<WIDTH-1)
  338.       displ(wnd,x1++,0,*s++,WTITLEC);
  339.   }
  340.   while(x1<WIDTH-1)
  341.     displ(wnd,x1++,0,LINE,WBORDER);
  342. }
  343.  
  344. /* Window-oriented printf */
  345.  
  346. void cdecl wprintf (WINDOW *wnd,char *ln,...) {
  347.  
  348.   char dlin[100],*dl=dlin;
  349.  
  350.   if (verify_wnd(&wnd)) {
  351.     va_list ap;
  352.     va_start(ap,ln);
  353.     vsprintf(dlin,ln,ap);
  354.     va_end(ap);
  355.     while(*dl)
  356.       wputchar(wnd,*dl++);
  357.   }
  358. }
  359.  
  360.  
  361. /* Window-oriented 'raw' printf */
  362.  
  363. void cdecl wprintfraw (WINDOW *wnd,char *ln,...) {
  364.  
  365.   char dlin[100],*dl=dlin;
  366.  
  367.   if (verify_wnd(&wnd)) {
  368.     va_list ap;
  369.     va_start(ap,ln);
  370.     vsprintf(dlin,ln,ap);
  371.     va_end(ap);
  372.     while(*dl)
  373.       wputchar(wnd,*dl++);
  374.   }
  375. }
  376.  
  377. /* Write a character to the window */
  378.  
  379. void pascal wputchar (WINDOW *wnd,int c) {
  380.  
  381.   if (!verify_wnd(&wnd)) return;
  382.   switch(c) {
  383.     case '\n':
  384.       if (SCROLL==HEIGHT-3)
  385.     scroll(wnd,UP);
  386.       else
  387.     SCROLL++;
  388.       WCURS=0;
  389.       break;
  390.     case '\t':
  391.       do displ(wnd,(WCURS++)+3,SCROLL+1,' ',WNORMAL);
  392.     while ((WCURS%TABS) && (WCURS+1)<WIDTH-1);
  393.       break;
  394.     default:
  395.       if ((WCURS+1)<WIDTH-1) {
  396.           displ(wnd,WCURS+1,SCROLL+1,c,WNORMAL);
  397.           WCURS++;
  398.       }
  399.       break;
  400.   }
  401. }
  402.  
  403.  
  404. /* Write a raw character to the window */
  405.  
  406. void pascal wputcharaw (WINDOW *wnd,int c) {
  407.  
  408.   if (!verify_wnd(&wnd)) return;
  409.   if ((WCURS+1)<WIDTH-1) {
  410.       displ(wnd,WCURS+1,SCROLL+1,c,WNORMAL);
  411.       WCURS++;
  412.   }
  413. }
  414.  
  415. /* Set window cursor */
  416.  
  417. void pascal wcursor (WINDOW *wnd,int x,int y) {
  418.  
  419.   if (verify_wnd(&wnd) && x<WIDTH-1 && y<HEIGHT-1) {
  420.     WCURS=x;
  421.     SCROLL=y;
  422.     cursor(COL+x+1,ROW+y+1);
  423.   }
  424. }
  425.  
  426. /* Allow user to select window */
  427.  
  428. int pascal get_selection (WINDOW *wnd,int s,char *keys) {
  429.  
  430.   int c=0,ky;
  431.  
  432.   if (!verify_wnd(&wnd)) return(0);
  433.     SHOWMOUSE;
  434.     CONFINEMOUSE(wnd);
  435.     SELECT=s;
  436.     while (c !=ESC && c!='\r' && c !=BS && c!=FWD) {
  437.       HIDEMOUSE;
  438.       accent(wnd);
  439.       SHOWMOUSE;
  440.       c=0;
  441.       while(!kbhit()) {
  442.           if(usemouse) {
  443.  
  444.                 union REGS rg;
  445.  
  446.                 rg.x.ax=3;
  447.                 int86(0x33,&rg,&rg);
  448.                 move_mouse(rg.x.cx/8,rg.x.dx/8);
  449.                 rg.x.ax=5;
  450.                 rg.x.bx=0;          /* Check left button */
  451.                 int86(0x33,&rg,&rg);
  452.                 rg.x.cx/=8;
  453.                 rg.x.dx/=8;
  454.                 if(rg.x.bx) {       /* Button pressed */
  455.                     if(rg.x.cx==COL && rg.x.dx==ROW) {
  456.                         c=ESC;
  457.                         break;
  458.                     }
  459.                     if(rg.x.dx==ROW && rg.x.cx==COL+WIDTH-1) {
  460.                         c=PGUP;
  461.                         break;
  462.                     }
  463.                     if(rg.x.cx==COL && rg.x.dx==ROW+HEIGHT-1) {
  464.                         c=PGDN;
  465.                         break;
  466.                     }
  467.                     if(rg.x.cx==COL+WIDTH-1 && rg.x.cx==ROW+HEIGHT-1) {
  468.                         c=END;
  469.                         break;
  470.                     }
  471.                     if(rg.x.cx==COL+WIDTH-1) {
  472.                         c=FWD;
  473.                         break;
  474.                     }
  475.                     if(rg.x.cx==COL) {
  476.                         c=BS;
  477.                         break;
  478.                     }
  479.                     if(rg.x.dx==ROW+HEIGHT-1) {
  480.                         c=DN;
  481.                         break;
  482.                     }
  483.                     if(rg.x.dx==ROW) {
  484.                         c=UP;
  485.                         break;
  486.                     }
  487.                     if(rg.x.cx>COL && rg.x.dx>ROW && rg.x.cx<((COL+WIDTH)-1) && rg.x.dx<((ROW+HEIGHT)-1)) {
  488.                         rg.x.cx=rg.x.dx-ROW;    /* rg.x.cx = window y pos of mouse */
  489.                         if(rg.x.cx<=SCROLL+1) {    /* In valid area */
  490.                             c='\r';
  491.                             HIDEMOUSE;
  492.                             deaccent(wnd);
  493.                             SELECT=rg.x.cx;
  494.                             SHOWMOUSE;
  495.                             accent(wnd);
  496.                             break;
  497.                         }
  498.                     }
  499.                 }
  500.                 rg.x.ax=3;
  501.                 int86(0x33,&rg,&rg);
  502.                 move_mouse(rg.x.cx/8,rg.x.dx/8);
  503.                 rg.x.ax=5;
  504.                 rg.x.bx=1;
  505.                 int86(0x33,&rg,&rg);
  506.                 if(rg.x.bx) {
  507.                     c=ESC;
  508.                     break;
  509.                 }
  510.           }
  511. #ifdef USECLOCK
  512.           print_clock();
  513. #endif
  514.       }
  515.       HIDEMOUSE;
  516.       if(!c)c=get_char();
  517.       deaccent(wnd);
  518.       SHOWMOUSE;
  519.       switch(c) {
  520.         case UP:  if (SELECT > 1) SELECT --;
  521.                   else SELECT = SCROLL+1;
  522.                   break;
  523.         case DN:  if (SELECT < SCROLL+1) SELECT++;
  524.                   else SELECT=1;
  525.                   break;
  526.         case HOME:
  527.         case END:
  528.         case PGUP:
  529.         case PGDN:
  530.         case F10:
  531.         case ALT_F1:
  532.         case ALT_F2:
  533.         case ALT_F3:
  534.         case ALT_F4:
  535.         case ALT_F5:
  536.         case ALT_F6:
  537.         case ALT_F7:
  538.         case ALT_F8:
  539.         case ALT_F9:
  540.         case ALT_F10:   HIDEMOUSE;
  541.                         return c;
  542.         case '\r':
  543.         case ESC:
  544.         case FWD:
  545.         case BS:      break;
  546.         default:      if (keys) {
  547.                           ky=0;
  548.                           while(*(keys+ky)) {
  549.                             if (*(keys+ky)==toupper(c) || *(keys+ky)==tolower(c)) {
  550.                                 HIDEMOUSE;
  551.                                 return ky+1;
  552.                             }
  553.                             ky++;
  554.                           }
  555.                       }
  556.                       break;
  557.       }
  558.     }
  559.     HIDEMOUSE;
  560.     return c=='\r' ? SELECT : c==ESC ? 0 : c;
  561. }
  562.  
  563. /* Scroll a window's contents up or down */
  564.  
  565. void pascal scroll (WINDOW *wnd,int dir) {
  566.  
  567.   int row=HEIGHT-1,col,chat;
  568.   union REGS rg;
  569.  
  570.   if (!verify_wnd(&wnd)) return;
  571.   if (NEXT == NULL && HEIGHT > 3 && VISIBLE) {
  572.     rg.h.ah=dir==UP ? 6:7;
  573.     rg.h.al=1;
  574.     rg.h.bh=WNORMAL;
  575.     rg.h.cl=COL+1;
  576.     rg.h.ch=ROW+1;
  577.     rg.h.dl=COL+WIDTH-2;
  578.     rg.h.dh=ROW+HEIGHT-2;
  579.     int86(16,&rg,&rg);
  580.     return;
  581.   }
  582.   if (dir==UP) {
  583.     for (row=2;row<HEIGHT-1;row++)
  584.       for (col = 1;col<WIDTH-1;col++) {
  585.         chat=dget(wnd,col,row);
  586.         displ(wnd,col,row-1,chat&255,(chat>>8)&255);
  587.       }
  588.     for (col=1;col<WIDTH-1;col++)
  589.       displ(wnd,col,row-1,' ',WNORMAL);
  590.   }
  591.   else {
  592.     for (row=HEIGHT-2;row>1;--row)
  593.       for(col=1;col<WIDTH-1;col++) {
  594.         chat=dget(wnd,col,row-1);
  595.         displ(wnd,col,row,chat&255,(chat>>8)&255);
  596.       }
  597.     for (col=1;col < WIDTH-1;col++)
  598.       displ(wnd,col,row,' ',WNORMAL);
  599.   }
  600. }
  601.  
  602. #ifndef FASTWINDOWS
  603.  
  604. /* Compute address of a window's display character */
  605.  
  606. static int * pascal waddr (WINDOW *wnd,int x,int y) {
  607.  
  608.   WINDOW *nxt=NEXT;
  609.   int *vp;
  610.  
  611.   if (!VISIBLE) return(int *)(SAV+y*(WIDTH*2)+x*2);
  612.   x+=COL;
  613.   y+=ROW;
  614.   while(nxt) {
  615.     if (nxt->_wv)
  616.       if (x>=nxt->_wx && x<= nxt->_wx+nxt->_ww-1)
  617.         if (y>=nxt->_wy && y<=nxt->_wy +nxt->_wh-1) {
  618.             x-=nxt->_wx;
  619.             y-=nxt->_wy;
  620.             vp=(int *)((nxt->_ws)+y*(nxt->_ww*2)+x*2);
  621.             return vp;
  622.         }
  623.         nxt=nxt->_nx;
  624.   }
  625.   return NULL;
  626. }
  627.  
  628. /* Display a character to a window */
  629.  
  630. void pascal displ (WINDOW *wnd,int x,int y,int ch,int at) {
  631.  
  632.     int *vp;
  633.     int vch = ch + (at<<8);
  634.  
  635.     if((vp=waddr(wnd,x,y))!=NULL) *vp=vch;
  636.     else vpoke(VSG,vad(x+COL,y+ROW),vch);
  637. }
  638.  
  639. /* Get a displayed character from a window */
  640.  
  641. static int pascal dget (WINDOW *wnd,int x,int y) {
  642.  
  643.   int *vp;
  644.  
  645.   if((vp=waddr(wnd,x,y))!=NULL) return *vp;
  646.   return vpeek(VSG,vad(x+COL,y+ROW));
  647. }
  648.  
  649. /* Low-level video functions */
  650.  
  651. /* Swap the video image with the save buffer */
  652.  
  653. static void pascal vswap (WINDOW *wnd) {
  654.  
  655.   int x,y,chat;
  656.   int *bf=(int *)SAV;
  657.  
  658.   for (y=0;y<HEIGHT;y++)
  659.     for (x=0;x<WIDTH;x++) {
  660.       chat=*bf;
  661.       *bf++=dget(wnd,x,y);
  662.       displ(wnd,x,y,chat&255,(chat>>8)&255);
  663.     }
  664. }
  665.  
  666. #else
  667.  
  668. /* Save video memory into the save buffer */
  669.  
  670. static void pascal vsave (WINDOW *wnd) {
  671.  
  672.   int x,y;
  673.   int *bf=(int *) SAV;
  674.  
  675.   for(y=0;y<HEIGHT;y++)
  676.     for(x=0;x<WIDTH;x++)
  677.       *bf++=vpeek(VSG,vad(x+COL,y+ROW));
  678. }
  679.  
  680. /* Restore video memory from the save buffer */
  681.  
  682. static void pascal vrstr (WINDOW *wnd) {
  683.  
  684.   int x,y;
  685.   int *bf=(int *)SAV;
  686.  
  687.   for(y=0;y<HEIGHT;y++)
  688.     for (x=0;x<WIDTH;x++)
  689.       vpoke(VSG,vad(x+COL,y+ROW),*bf++);
  690. }
  691.  
  692. #endif
  693.  
  694. /* (de)Accent the line where SELECT points */
  695.  
  696. void pascal acline(WINDOW *wnd,int set) {
  697.  
  698.   int x,ch;
  699.  
  700.   if (!verify_wnd(&wnd)) return;
  701.   for(x=1;x<WIDTH-1;x++) {
  702.     ch=dget(wnd,x,SELECT) & 255;
  703.     displ(wnd,x,SELECT,ch,set);
  704.   }
  705. }
  706.  
  707. /* Linked List functions */
  708.  
  709. /* Add a window to the end of the list */
  710.  
  711. static void pascal add_list (WINDOW *wnd) {
  712.  
  713.   if(listtail) {
  714.     PREV=listtail;
  715.     listtail->_nx=wnd;
  716.   }
  717.   listtail=wnd;
  718.   if (!listhead)
  719.     listhead=wnd;
  720. }
  721.  
  722. /* Add a window to the beginning of the list */
  723.  
  724. static void pascal beg_list(WINDOW *wnd) {
  725.  
  726.   if(listhead) {
  727.     NEXT=listhead;
  728.     listhead->_pv=wnd;
  729.   }
  730.   listhead=wnd;
  731.   if(!listtail)
  732.     listtail=wnd;
  733. }
  734.  
  735. /* Remove a window from the list */
  736.  
  737. static void pascal remove_list (WINDOW *wnd) {
  738.  
  739.   if(NEXT)
  740.     NEXT->_pv=PREV;
  741.   if(PREV)
  742.     PREV->_nx=NEXT;
  743.   if (listhead==wnd)
  744.     listhead=NEXT;
  745.   if (listtail==wnd)
  746.     listtail=PREV;
  747.   NEXT=PREV=NULL;
  748. }
  749.  
  750. /* Insert w1 after w2 */
  751.  
  752. static void pascal insert_list (WINDOW *w1,WINDOW *w2) {
  753.  
  754.   w1->_pv=w2;
  755.   w1->_nx=w2->_nx;
  756.   w2->_nx=w1;
  757.   if (w1->_nx==NULL)
  758.     listtail=w1;
  759.   else
  760.     w1->_nx->_pv=w1;
  761. }
  762.  
  763. #ifndef FASTWINDOWS
  764.  
  765. /* Verify the presence of a window in the list */
  766.  
  767. static int pascal verify_wnd (WINDOW **w1) {
  768.  
  769.   WINDOW *wnd;
  770.  
  771.   wnd=listhead;
  772.   if(*w1==NULL)
  773.      *w1=listtail;
  774.   else {
  775.      while(wnd !=NULL) {
  776.        if(*w1==wnd)
  777.      break;
  778.        wnd=NEXT;
  779.      }
  780.   }
  781.   return wnd != NULL;
  782. }
  783.  
  784. #endif
  785.  
  786. /* Error messages */
  787.  
  788. void pascal error_message(char *s) {
  789.  
  790.   clear_message();
  791.   ewnd=establish_window(50,(maxy-3),3,max(10,strlen(s)+2));
  792.   set_colors(ewnd,ALL,RED,YELLOW,BRIGHT);
  793.   set_colors(ewnd,TITLE,RED,YELLOW,BRIGHT|128);
  794.   set_border(ewnd,5);
  795.   set_title(ewnd," ERROR! ");
  796.   display_window(ewnd);
  797.   wprintf(ewnd,s);
  798. }
  799.  
  800.  
  801. void pascal any_message (char *s) {
  802.  
  803.   clear_message();
  804.   ewnd=establish_window(65,(maxy-4),3,max(9,strlen(s)+2));
  805.   set_border(ewnd,5);
  806.   set_colors(ewnd,ALL,AQUA,BLACK,DIM);
  807.   set_colors(ewnd,TITLE,AQUA,BLACK,BRIGHT);
  808.   set_title(ewnd," NOTE: ");
  809.   display_window(ewnd);
  810.   wprintf(ewnd,s);
  811. }
  812.  
  813.  
  814. void pascal _anymsg (char *t,char *s) {
  815.  
  816.   clear_message();
  817.   ewnd=establish_window(65,(maxy-4),3,max(strlen(s),strlen(t))+2);
  818.   set_border(ewnd,5);
  819.   set_colors(ewnd,ALL,GREEN,BLACK,DIM);
  820.   set_colors(ewnd,TITLE,GREEN,BLACK,BRIGHT);
  821.   set_title(ewnd,t);
  822.   display_window(ewnd);
  823.   wprintf(ewnd,s);
  824. }
  825.  
  826. void pascal clear_message() {
  827.  
  828.   if (ewnd) delete_window(ewnd);
  829.   ewnd=NULL;
  830. }
  831.  
  832.  
  833. void pascal hide_mouse () {
  834.  
  835.     union REGS rg;
  836.  
  837.     if(usemouse) {
  838.        rg.x.ax=2;  /* Hide mouse cursor */
  839.        int86(0x33,&rg,&rg);
  840.        if(oldmousex!=-1)vpoke(VSG,vad(oldmousex,oldmousey),oldmousevid);
  841.        oldmousex=-1;
  842.     }
  843. }
  844.  
  845.  
  846. void pascal show_mouse () {
  847.  
  848.     union REGS rg;
  849.  
  850.     if(usemouse) {
  851.         rg.x.ax=1;
  852.         int86(0x33,&rg,&rg);    /* Mouse cursor on */
  853.         rg.x.ax=10;
  854.         rg.x.bx=0;
  855.         rg.x.cx=0xffff;
  856.         rg.x.dx=0x7700;
  857.         int86(0x33,&rg,&rg);    /* Software cursor (not really used) */
  858.     }
  859. }
  860.  
  861.  
  862. void pascal pause_msg () {
  863.  
  864.     union REGS rg;
  865.     int temp=0;
  866.  
  867.     while(!kbhit()) {
  868.         rg.x.ax=5;
  869.         rg.x.bx=0;
  870.         int86(0x33,&rg,&rg);
  871.         temp+=rg.x.bx;
  872.         rg.x.ax=5;
  873.         rg.x.bx=1;
  874.         int86(0x33,&rg,&rg);
  875.         temp+=rg.x.bx;
  876.         rg.x.ax=5;
  877.         rg.x.bx=2;
  878.         int86(0x33,&rg,&rg);
  879.         temp+=rg.x.bx;
  880.         if(temp) {
  881.             clear_message();
  882.             return;
  883.         }
  884. #ifdef USECLOCK
  885.         print_clock();
  886. #endif
  887.     }
  888.     get_char();
  889.     clear_message();
  890. }
  891.  
  892.  
  893. void pascal nopause_msg () {
  894.  
  895.     union REGS rg;
  896.     int temp=0;
  897.  
  898.     while(!kbhit()) {
  899.         if(usemouse) {
  900.             rg.x.ax=5;
  901.             rg.x.bx=0;
  902.             int86(0x33,&rg,&rg);
  903.             temp+=rg.x.bx;
  904.             rg.x.ax=5;
  905.             rg.x.bx=1;
  906.             int86(0x33,&rg,&rg);
  907.             temp+=rg.x.bx;
  908.             rg.x.ax=5;
  909.             rg.x.bx=2;
  910.             int86(0x33,&rg,&rg);
  911.             temp+=rg.x.bx;
  912.             if(temp) {
  913.                 break;
  914.             }
  915.         }
  916. #ifdef USECLOCK
  917.         print_clock();
  918. #endif
  919.     }
  920.     clear_message();
  921. }
  922.  
  923.  
  924. void pascal confine_mouse (WINDOW *wnd) {
  925.  
  926.     if(usemouse) {          /* Confine mouse to window */
  927.  
  928.         union REGS rg;
  929.  
  930.         rg.x.ax=7;
  931.         rg.x.cx=COL*8;
  932.         rg.x.dx=(COL+WIDTH-1)*8;
  933.         int86(0x33,&rg,&rg);
  934.         rg.x.ax=8;
  935.         rg.x.cx=ROW*8;
  936.         rg.x.dx=(ROW+HEIGHT-1)*8;
  937.         int86(0x33,&rg,&rg);
  938.         wasconfinedx1=COL;
  939.         wasconfinedy1=ROW;
  940.         wasconfinedx2=COL+WIDTH-1;
  941.         wasconfinedy2=ROW+HEIGHT-1;
  942.     }
  943. }
  944.  
  945.  
  946.  
  947. int pascal get_screen_char (int x,int y) {
  948.  
  949.     return vpeek(VSG,vad(x,y))&255;
  950. }
  951.  
  952.  
  953. int pascal generic_mouse_input (WINDOW *wnd) {
  954.  
  955.     union REGS rg;
  956.     int c=0;
  957.  
  958.     SHOWMOUSE;
  959.     if(usemouse) {
  960.         rg.x.ax=7;
  961.         rg.x.cx=COL*8;
  962.         rg.x.dx=(COL+WIDTH-1)*8;
  963.         int86(0x33,&rg,&rg);
  964.         rg.x.ax=8;
  965.         rg.x.cx=ROW*8;
  966.         rg.x.dx=(ROW+HEIGHT-1)*8;
  967.         int86(0x33,&rg,&rg);
  968.         if(wnd)vpoke(VSG,vad(COL,ROW),254+((WBORDER & 255)<<8));
  969.     }
  970.     while(!kbhit()) {
  971.         c=0;
  972.         if(usemouse) {
  973.             rg.x.ax=3;
  974.             int86(0x33,&rg,&rg);
  975.             move_mouse(rg.x.cx/8,rg.x.dx/8);
  976.             rg.x.ax=5;
  977.             rg.x.bx=0;
  978.             int86(0x33,&rg,&rg);
  979.             if(rg.x.bx) {
  980.                 rg.x.cx/=8;
  981.                 rg.x.dx/=8;
  982.                 if(rg.x.cx==COL && rg.x.dx==ROW) c=ESC;
  983.                 else if(rg.x.cx==COL+WIDTH-1 && rg.x.dx==ROW) c=PGUP;
  984.                 else if(rg.x.cx==COL && rg.x.dx==ROW+HEIGHT-1) c=PGDN;
  985.                 else if(rg.x.cx==COL+WIDTH-1 && rg.x.dx==ROW+HEIGHT-1) c='\r';
  986.                 else c=get_screen_char(rg.x.cx,rg.x.dx);
  987.                 if(c!=' ' && c)break;
  988.             }
  989.             rg.x.ax=3;
  990.             int86(0x33,&rg,&rg);
  991.             move_mouse(rg.x.cx/8,rg.x.dx/8);
  992.             rg.x.ax=5;
  993.             rg.x.bx=1;
  994.             int86(0x33,&rg,&rg);
  995.             if(rg.x.bx) {
  996.                 c=ESC;
  997.                 break;
  998.             }
  999.             rg.x.ax=5;
  1000.             rg.x.bx=2;
  1001.             int86(0x33,&rg,&rg);
  1002.             if(rg.x.bx) {
  1003.                 c='\r';
  1004.                 break;
  1005.             }
  1006.         }
  1007.     }
  1008.     HIDEMOUSE;
  1009.     reconfine_mouse();
  1010.     if(!c) c=get_char();
  1011.     return c;
  1012. }
  1013.  
  1014.  
  1015.  
  1016.  
  1017. void pascal move_mouse (int x,int y) {
  1018.  
  1019.     if(usemouse) {
  1020.         if(oldmousex==x && oldmousey==y) return;    /* No change */
  1021.         if(oldmousex!=-1) {
  1022.             vpoke(VSG,vad(oldmousex,oldmousey),oldmousevid);
  1023.         }
  1024.         oldmousevid=vpeek(VSG,vad(x,y));
  1025.         vpoke(VSG,vad(x,y),oldmousevid ^ 0x7700);
  1026.         oldmousex=x;
  1027.         oldmousey=y;
  1028.     }
  1029. }
  1030.  
  1031.  
  1032. void pascal reconfine_mouse (void) {
  1033.  
  1034.     union REGS rg;
  1035.  
  1036.     if(!usemouse || wasconfinedx1==-1) return;
  1037.  
  1038.     rg.x.ax=7;
  1039.     rg.x.cx=wasconfinedx1;
  1040.     rg.x.dx=wasconfinedy1;
  1041.     int86(0x33,&rg,&rg);
  1042.     rg.x.ax=8;
  1043.     rg.x.cx=wasconfinedx2;
  1044.     rg.x.dx=(wasconfinedy2)*8;
  1045.     int86(0x33,&rg,&rg);
  1046. }