home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / BBS / XSRC_117.ZIP / AWINDOW.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-11-18  |  20.9 KB  |  910 lines

  1. /*--------------------------------------------------------------------------*/
  2. /*                                                                          */
  3. /*   XBBS SOURCE CODE copyright (c) 1990 by M. Kimes                        */
  4. /*   All Rights Reserved                                                    */
  5. /*                                                                          */
  6. /*    For complete details of the licensing restrictions, please refer      */
  7. /*    to the License agreement, which is published in its entirety in       */
  8. /*    the in the file LICENSE.XBS.                                          */
  9. /*                                                                          */
  10. /*    USE OF THIS FILE IS SUBJECT TO THE RESTRICTIONS CONTAINED IN THE      */
  11. /*    XBBS LICENSING  AGREEMENT.  IF YOU DO NOT FIND THE TEXT OF            */
  12. /*    THIS AGREEMENT IN ANY OF THE AFOREMENTIONED FILES, OR IF YOU DO       */
  13. /*    NOT HAVE THESE FILES, YOU SHOULD IMMEDIATELY CONTACT M. KIMES         */
  14. /*    AT THE ADDRESS LISTED BELOW.  IN NO EVENT SHOULD YOU PROCEED TO USE   */
  15. /*    THIS FILE WITHOUT HAVING ACCEPTED THE TERMS OF THE XBBS LICENSING     */
  16. /*    AGREEMENT, OR SUCH OTHER AGREEMENT AS YOU ARE ABLE TO REACH WITH      */
  17. /*    M. KIMES                                                              */
  18. /*                                                                          */
  19. /*                                                                          */
  20. /* You can contact M. Kimes at the following address:                       */
  21. /*                                                                          */
  22. /* M. Kimes                         1:380/16.0@FidoNet                      */
  23. /* 542 Merrick                      (318)222-3455 data                      */
  24. /* Shreveport, LA  71104                                                    */
  25. /*                                                                          */
  26. /*                                                                          */
  27. /* Please feel free to contact me at any time to share your comments about  */
  28. /* my software and/or licensing policies.                                   */
  29. /*                                                                          */
  30. /*--------------------------------------------------------------------------*/
  31.  
  32. /* AWINDOW.C File */
  33.  
  34. #include <stdio.h>
  35. #include <ctype.h>
  36. #include <stdarg.h>
  37. #include <dos.h>
  38. #include <alloc.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include <conio.h>
  42. #include "awindow.h"
  43. #include "xkeys.h"
  44.  
  45. #define TABS         4
  46. #define ON           1
  47. #define OFF          0
  48. #define ERROR        -1
  49.  
  50. /* Local prototypes */
  51.  
  52. void pascal redraw(WINDOW *wnd);
  53. void pascal dtitle(WINDOW *wnd);
  54. int * pascal waddr(WINDOW *wnd,int x,int y);
  55. void pascal vswap(WINDOW *wnd);
  56. void pascal vsave(WINDOW *wnd);
  57. void pascal vrstr(WINDOW *wnd);
  58. void pascal add_list(WINDOW *wnd);
  59. void pascal beg_list(WINDOW *wnd);
  60. void pascal remove_list(WINDOW *wnd);
  61. void pascal insert_list(WINDOW *w1,WINDOW *w2);
  62. #ifndef FASTWINDOWS
  63. int pascal dget(WINDOW *wnd,int x,int y);
  64. int pascal verify_wnd(WINDOW **w1);
  65. #endif
  66.  
  67. #ifdef USEMOUSE
  68.     extern int hcount;
  69.     extern int vcount;
  70.     extern int hysterisis;
  71. #endif
  72.  
  73.  
  74. /* Array of border character sets */
  75.  
  76. struct {
  77.   int nw,ne,se,sw,side,line;
  78.   } wcs[]={
  79.     {218,191,217,192,179,196}, /* single line */
  80.     {201,187,188,200,186,205}, /* double line */
  81.     {214,183,189,211,186,196}, /* single top, double side */
  82.     {213,184,190,212,179,205}, /* double top, single side */
  83.     {194,194,217,192,179,196}, /* pop-down menu */
  84.     {'+','+','+','+','|','-'}, /* std ASCII chars */
  85.     {0,0,0,0,0,0}              /* No border */
  86.   };
  87.  
  88. /* Window structure linked list head & tail */
  89.  
  90. WINDOW *listhead = NULL;
  91. WINDOW *listtail = NULL;
  92.  
  93. WINDOW *ewnd=NULL;    /* Global error/note window */
  94.  
  95. int VSG;  /* video segment address */
  96.  
  97. unsigned int vbase=0;
  98. unsigned int maxx=80;
  99. unsigned int maxy=22;
  100. unsigned char current_color=7;
  101. unsigned int videomethod=0;
  102.  
  103. /*
  104.     SCREEN:
  105.           black=0 blue=1 green=2 aqua=3 red=4 magenta=5 yellow=6 white=7
  106.     ANSI:
  107.           30  black foreground          40  black background
  108.           31  red foreground            41  red background
  109.           32  green foreground          42  green background
  110.           33  yellow foreground         43  yellow background
  111.           34  blue foreground           44  blue background
  112.           35  magenta foreground        45  magenta foreground
  113.           36  cyan foreground           46  cyan background
  114.           37  white foreground          47  white background
  115. */
  116.  
  117. char ansifg[8][4]={"30;","34;","32;","36;","31;","35;","33;","37;"};
  118. char ansibg[8][4]={"40m","44m","42m","46m","41m","45m","43m","47m"};
  119.  
  120. extern char   cdecl  gprintf(char,char *,...);
  121. extern char   pascal printm(char *);
  122.  
  123. extern unsigned int baud;
  124.  
  125.  
  126.  
  127. /* Establish a new window */
  128.  
  129. WINDOW * pascal establish_window (int x,int y,int h,int w) {
  130.  
  131.   WINDOW *wnd;
  132.  
  133.   VSG=(vmode()==7 ? 0xb000: 0xb800);
  134.   if ((wnd=(WINDOW *) mmalloc(sizeof(WINDOW)))==NULL) return NULL;
  135.  
  136.   /* Adjust for out-of-bounds parameters */
  137.  
  138.   WTITLE="";
  139.   HEIGHT=min(h,maxy);
  140.   WIDTH=min(w,maxx);
  141.   COL=max(0,min(x,maxx-WIDTH));
  142.   ROW=max(0,min(y,maxy-HEIGHT));
  143.   WCURS=0;
  144.   SCROLL=0;
  145.   SELECT=1;
  146.   BTYPE=0;
  147.   VISIBLE=HIDDEN=0;
  148.   PREV=NEXT=NULL;
  149.   FHEAD=FTAIL=NULL;
  150.   WBORDER=WNORMAL=PNORMAL=WTITLEC=clr(BLACK,WHITE,BRIGHT);
  151.   WACCENT=clr(WHITE,BLACK,DIM);
  152.   if ((SAV=mmalloc(WIDTH * HEIGHT * 2))==(char *)0) {
  153.     ffree(wnd);
  154.     return NULL;
  155.   }
  156.   add_list(wnd);
  157.   #ifndef FASTWINDOWS
  158.     clear_window(wnd);
  159.     wframe(wnd);
  160.   #endif
  161.     return(wnd);
  162. }
  163.  
  164.  
  165. /* Establish screen as window */
  166.  
  167. WINDOW * pascal establish_screen (int x, int y, int h, int w) {
  168.  
  169.   WINDOW *wnd;
  170.  
  171.   VSG=(vmode()==7 ? 0xb000: 0xb800);
  172.   if ((wnd=(WINDOW *) mmalloc(sizeof(WINDOW)))==NULL) return NULL;
  173.   WTITLE="";
  174.   HEIGHT=min(h,maxy);
  175.   WIDTH=min(w,maxx);
  176.   COL=max(0,min(x,maxx-WIDTH));
  177.   ROW=max(0,min(y,maxy-HEIGHT));
  178.   WCURS=0;
  179.   SCROLL=min(h,maxy);
  180.   SCROLL-=2;
  181.   SELECT=0;
  182.   BTYPE=6;
  183.   VISIBLE=1;
  184.   HIDDEN=0;
  185.   PREV=NEXT=NULL;
  186.   FHEAD=FTAIL=NULL;
  187.   WBORDER=WNORMAL=PNORMAL=WTITLEC=clr(BLACK,WHITE,BRIGHT);
  188.   WACCENT=clr(WHITE,BLACK,DIM);
  189.   if ((SAV=mmalloc(WIDTH * HEIGHT * 2))==(char *)0) {
  190.         ffree(wnd);
  191.         return NULL;
  192.   }
  193.   add_list(wnd);
  194.   return(wnd);
  195. }
  196.  
  197.  
  198. /* Set the window's border */
  199.  
  200. void pascal set_border (WINDOW *wnd,int btype) {
  201.  
  202.   if (verify_wnd(&wnd)) {
  203.     BTYPE=btype;
  204.     redraw(wnd);
  205.   }
  206. }
  207.  
  208. /* Set colors */
  209.  
  210. void pascal set_colors (WINDOW *wnd,int area,int bg,int fg,int inten) {
  211.  
  212.   if (vmode()==7) {
  213.     if (bg != WHITE && bg !=BLACK) return;
  214.     if (fg !=WHITE && fg!=BLACK) return;
  215.   }
  216.   if(fg==bg) return;
  217.   if (verify_wnd(&wnd)) {
  218.     if (area==ALL){
  219.          while (area) WCOLOR[--area]=clr(bg,fg,inten);
  220.     }
  221.     else WCOLOR[area]=clr(bg,fg,inten);
  222.     redraw (wnd);
  223.   }
  224. }
  225.  
  226. /* Set intensity of window */
  227.  
  228. void pascal set_intensity (WINDOW *wnd,int inten) {
  229.  
  230.   int area=ALL;
  231.  
  232.   if (verify_wnd(&wnd)) {
  233.     while (area) {
  234.       WCOLOR[--area]&= ~BRIGHT;
  235.       WCOLOR[area] |= inten;
  236.     }
  237.     redraw(wnd);
  238.   }
  239. }
  240.  
  241. /* Set title */
  242.  
  243. void pascal set_title (WINDOW *wnd,char *title) {
  244.   if (verify_wnd(&wnd)) {
  245.     WTITLE=title;
  246.     redraw(wnd);
  247.   }
  248. }
  249.  
  250. /* Redraw a window when an attribute changes */
  251.  
  252. static void pascal redraw (WINDOW *wnd) {
  253.  
  254. #ifndef FASTWINDOWS
  255.   int x,y,chat,atr;
  256.  
  257.   for (y=1-(BTYPE==6);y<HEIGHT-(1-(BTYPE==6));y++)
  258.     for (x=1-(BTYPE==6);x<WIDTH-(1-(BTYPE==6));x++) {
  259.       chat=dget(wnd,x,y);
  260.       atr=(((chat>>8)&255) == PNORMAL ? WNORMAL : WACCENT);
  261.       displ(wnd,x,y,chat&255,atr);
  262.     }
  263.   wframe(wnd);
  264. #endif
  265.   PNORMAL=WNORMAL;
  266. }
  267.  
  268. /* Display an established window */
  269.  
  270. void pascal display_window (WINDOW *wnd) {
  271.  
  272.   if (verify_wnd(&wnd)&& !VISIBLE) {
  273.     VISIBLE=1;
  274. #ifdef FASTWINDOWS
  275.     if (HIDDEN) {
  276.       HIDDEN=0;
  277.       vrstr(wnd);
  278.       wframe(wnd);
  279.     }
  280.     else {
  281.       vsave (wnd);
  282.       clear_window(wnd);
  283.       wframe(wnd);
  284.     }
  285. #else
  286.     vswap(wnd);
  287. #endif
  288.   }
  289. }
  290.  
  291. /* Close all windows */
  292.  
  293. void pascal close_all() {
  294.  
  295.   WINDOW *sav,*wnd=listtail;
  296.  
  297.   while(wnd) {
  298.     sav=PREV;
  299.     delete_window(wnd);
  300.     wnd=sav;
  301.   }
  302. }
  303.  
  304. /* Remove a window */
  305.  
  306. void pascal delete_window (WINDOW *wnd) {
  307.  
  308.   if (verify_wnd(&wnd)) {
  309.     if(BTYPE!=6) hide_window(wnd);
  310.     ffree(SAV);
  311.     remove_list(wnd); /* remove window from list */
  312.     ffree(wnd);
  313.   }
  314. }
  315.  
  316. /* Hide a window */
  317.  
  318. void pascal hide_window (WINDOW *wnd) {
  319.  
  320.   if (verify_wnd(&wnd) && VISIBLE) {
  321. #ifndef FASTWINDOWS
  322.     vswap(wnd);
  323. #else
  324.     vrstr(wnd);
  325. #endif
  326.     HIDDEN=1;
  327.     VISIBLE=0;
  328.   }
  329. }
  330.  
  331. #ifndef FASTWINDOWS
  332.  
  333. /* Reposition the window in its 3-axis plane */
  334.  
  335. void pascal repos_wnd(WINDOW *wnd,int x,int y,int z) {
  336.  
  337.   WINDOW *twnd;
  338.   int x1,y1,chat;
  339.  
  340.   if (!verify_wnd(&wnd)) return;
  341.   twnd=establish_window(x+COL,y+ROW,HEIGHT,WIDTH);
  342.   twnd->_tl=WTITLE;
  343.   twnd->btype=BTYPE;
  344.   twnd->wcolor[BORDER]=WBORDER;
  345.   twnd->wcolor[TITLE]=WTITLEC;
  346.   twnd->wcolor[ACCENT]=WACCENT;
  347.   twnd->wcolor[NORMAL]=WNORMAL;
  348.   twnd->_wsp=SCROLL;
  349.   twnd->_cr=WCURS;
  350.   if (z!=1) {
  351.     remove_list(twnd);
  352.     if (z==0)
  353.       insert_list(twnd,wnd);
  354.     else
  355.       beg_list(twnd);
  356.   }
  357.   for(y1=0;y1<twnd->_wh;y1++)
  358.     for (x1=0;x1<twnd->_ww;x1++) {
  359.       chat = dget(wnd,x1,y1);
  360.       displ(twnd,x1,y1,chat&255,(chat>>8)&255);
  361.     }
  362.   twnd->_wv=1;
  363.   vswap(twnd);
  364.   hide_window(wnd);
  365.   ffree(SAV);
  366.   remove_list(wnd);
  367.   *wnd=*twnd;
  368.   insert_list(wnd,twnd);
  369.   remove_list(twnd);
  370.   ffree(twnd);
  371. }
  372. #endif
  373.  
  374. /* Clear window */
  375.  
  376. void pascal clear_window (WINDOW *wnd) {
  377.  
  378.   register int x1,y1;
  379.  
  380.   if (verify_wnd(&wnd))
  381.     for(y1=1-(BTYPE==6);y1<HEIGHT-(1-(BTYPE==6));y1++)
  382.       for(x1=1-(BTYPE==6);x1<WIDTH-(1-(BTYPE==6));x1++)
  383.     displ(wnd,x1,y1,' ',WNORMAL);
  384. }
  385.  
  386. /* Draw the window frame */
  387.  
  388. void pascal wframe (WINDOW *wnd) {
  389.  
  390.   register int x1,y1;
  391.  
  392.   if (!verify_wnd(&wnd)) return;
  393.   if (BTYPE==6) return;
  394.   /* Window title */
  395.   displ(wnd,0,0,NW,WBORDER);
  396.   dtitle(wnd);
  397.   displ(wnd,WIDTH-1,0,NE,WBORDER);
  398.   /* Window sides */
  399.   for (y1=1;y1<HEIGHT-1;y1++) {
  400.     displ(wnd,0,y1,SIDE,WBORDER);
  401.     displ(wnd,WIDTH-1,y1,SIDE,WBORDER);
  402.   }
  403.   /* Bottom of frame */
  404.   displ(wnd,0,y1,SW,WBORDER);
  405.   for(x1=1;x1<WIDTH-1;x1++)
  406.     displ(wnd,x1,y1,LINE,WBORDER);
  407.   displ(wnd,x1,y1,SE,WBORDER);
  408. }
  409.  
  410.  
  411. static void pascal dtitle (WINDOW *wnd) {
  412.  
  413.   int x1=1,i,ln;
  414.   char *s=WTITLE;
  415.  
  416.   if (!verify_wnd(&wnd)) return;
  417.   if (BTYPE==6) return;
  418.   if (s) {
  419.     ln=strlen(s);
  420.     if (ln>WIDTH-2) i=0;
  421.     else i=((WIDTH-2-ln)/2);
  422.     if (i>0) {
  423.         while (i--) displ(wnd,x1++,0,LINE,WBORDER);
  424.     }
  425.     while(*s && x1<WIDTH-1) displ(wnd,x1++,0,*s++,WTITLEC);
  426.   }
  427.   while(x1<WIDTH-1) displ(wnd,x1++,0,LINE,WBORDER);
  428. }
  429.  
  430. /* Window-oriented printf */
  431.  
  432. void cdecl wprintf (WINDOW *wnd,char *ln,...) {
  433.  
  434.   char dlin[100],*dl=dlin;
  435.  
  436.   if (verify_wnd(&wnd)) {
  437.     va_list ap;
  438.     va_start(ap,ln);
  439.     vsprintf(dlin,ln,ap);
  440.     va_end(ap);
  441.     while(*dl) wputchar(wnd,*dl++);
  442.   }
  443. }
  444.  
  445.  
  446. /* Window-oriented 'raw' printf */
  447.  
  448. void cdecl wprintfraw (WINDOW *wnd,char *ln,...) {
  449.  
  450.   char dlin[100],*dl=dlin;
  451.  
  452.   if (verify_wnd(&wnd)) {
  453.     va_list ap;
  454.     va_start(ap,ln);
  455.     vsprintf(dlin,ln,ap);
  456.     va_end(ap);
  457.     while(*dl) wputchar(wnd,*dl++);
  458.   }
  459. }
  460.  
  461. /* Write a character to the window */
  462.  
  463. void pascal wputchar (WINDOW *wnd,int c) {
  464.  
  465.   if (!verify_wnd(&wnd)) return;
  466.   switch(c) {
  467.     case '\n':
  468.       if (SCROLL==HEIGHT-(3-(BTYPE==6))) scroll(wnd,UP);
  469.       else SCROLL++;
  470.       WCURS=0;
  471.       break;
  472.     case '\t':
  473.       do displ(wnd,(WCURS++)+3,SCROLL+1,' ',WNORMAL);
  474.       while ((WCURS%TABS) && (WCURS+1)<WIDTH-1);
  475.       break;
  476.     default:
  477.       if ((WCURS+1)<WIDTH-(1*(BTYPE!=6))) {
  478.           displ(wnd,WCURS+(1-(BTYPE==6)),SCROLL+(1-(BTYPE==6)),c,WNORMAL);
  479.           WCURS++;
  480.       }
  481.       break;
  482.   }
  483. }
  484.  
  485.  
  486. /* Write a raw character to the window */
  487.  
  488. void pascal wputcharaw (WINDOW *wnd,int c) {
  489.  
  490.   if (!verify_wnd(&wnd)) return;
  491.   if ((WCURS+1)<WIDTH-1) {
  492.       displ(wnd,WCURS+(1-(BTYPE==6)),SCROLL+(1-(BTYPE==6)),c,WNORMAL);
  493.       WCURS++;
  494.   }
  495. }
  496.  
  497. /* Set window cursor */
  498.  
  499. void pascal wcursor (WINDOW *wnd,int x,int y) {
  500.  
  501.   if (verify_wnd(&wnd) && x<WIDTH-(1-(BTYPE==6)) && y<HEIGHT-(1-(BTYPE==6))) {
  502.     WCURS=x;
  503.     SCROLL=y;
  504.     if(!baud) cursor(COL+x+(1-(BTYPE==6)),ROW+y+(1-(BTYPE==6)));
  505.     else gprintf(0,"\x1b[%d;%dH",ROW+y+1+(1-(BTYPE==6)),COL+x+1+(1-(BTYPE==6)));
  506.   }
  507. }
  508.  
  509. /* Allow user to select from window */
  510.  
  511. int pascal get_selection (WINDOW *wnd,int s,char *keys) {
  512.  
  513.   int c=0,ky;
  514. #ifdef USEMOUSE
  515.   int temph,tempv;
  516. #endif
  517.  
  518.   if (!verify_wnd(&wnd)) return(0);
  519. #ifdef USEMOUSE
  520.   temph=hcount;
  521.   tempv=vcount;
  522.   hcount=2*hysterisis;
  523.   vcount=hysterisis;
  524. #endif
  525.   SELECT=s;
  526.   while (c !=ESC && c!='\r' && c !=BS && c!=FWD) {
  527.       accent(wnd);
  528.       c=get_char();
  529.       deaccent(wnd);
  530.       switch(c) {
  531.     case '8':
  532.     case UP:  if (SELECT > 1-(BTYPE==6)) SELECT --;
  533.               else SELECT = SCROLL+1;
  534.               break;
  535.     case '2':
  536.     case DN:  if (SELECT < SCROLL+1) SELECT++;
  537.               else SELECT=1-(BTYPE==6);
  538.               break;
  539.         case HOME:
  540.         case CTRL_HOME:
  541.         case END:
  542.         case CTRL_END:
  543.         case PGUP:
  544.         case PGDN:
  545. #ifdef USEMOUSE
  546.     hcount=temph;
  547.     vcount=tempv;
  548. #endif
  549.                     return c;
  550.         case FWD:
  551.         case '6':   return 205;
  552.         case BS:
  553.         case '4':   return 203;
  554.         case 0:     c='\r';
  555.         case '\r':
  556.         case ESC:
  557.         case CTRL_K:
  558.                     break;
  559.         default:    if (keys) {
  560.                       ky=0;
  561.                       while(*(keys+ky)) {
  562.                         if (*(keys+ky)==toupper(c) || *(keys+ky)==tolower(c)) {
  563. #ifdef USEMOUSE
  564.                             hcount=temph;
  565.                             vcount=tempv;
  566. #endif
  567.                             return ky+1;
  568.                         }
  569.                         ky++;
  570.                       }
  571.                     }
  572.                   break;
  573.       }
  574.     }
  575. #ifdef USEMOUSE
  576.     hcount=temph;
  577.     vcount=tempv;
  578. #endif
  579.     return (c=='\r' || c==0) ? (SELECT + (BTYPE==6)) : c==ESC ? 0 : c;
  580. }
  581.  
  582. union REGS rg;
  583.  
  584. /* Scroll a window's contents up or down */
  585.  
  586. void pascal scroll (WINDOW *wnd,int dir) {
  587.  
  588.   int row=HEIGHT-(1-(BTYPE==6)),col,chat;
  589.  
  590.   if (!verify_wnd(&wnd)) return;
  591.  
  592.     if (NEXT == NULL && HEIGHT > 3-((BTYPE==6)*2) && VISIBLE && !baud) {
  593.     rg.h.ah=dir==UP ? 6:7;
  594.     rg.h.al=1;
  595.     rg.h.bh=WNORMAL;
  596.     rg.h.cl=COL+(1-(BTYPE==6));
  597.     rg.h.ch=ROW+(1-(BTYPE==6));
  598.     rg.h.dl=COL+WIDTH-(2*(BTYPE!=6));
  599.     rg.h.dh=ROW+HEIGHT-(2*(BTYPE!=6));
  600.     int86(16,&rg,&rg);
  601.     return;
  602.   }
  603.  
  604.   if (dir==UP) {
  605.     for (row=(2*(BTYPE!=6));row<HEIGHT-(1+((BTYPE==6)* -2));row++)
  606.       for (col = 1-(BTYPE==6);col<WIDTH-(1+((BTYPE==6)* -2));col++) {
  607.         chat=dget(wnd,col,row);
  608.         displ(wnd,col,row-1,chat&255,(chat>>8)&255);
  609.       }
  610.     for (col=1-(BTYPE==6);col<WIDTH-(1+((BTYPE==6)* -2));col++)
  611.       displ(wnd,col,row-1,' ',WNORMAL);
  612.   }
  613.   else {
  614.     for (row=HEIGHT-(2*(BTYPE==6));row>1-(BTYPE==6);--row)
  615.       for(col=1-(BTYPE==6);col<WIDTH-(1+(BTYPE==6)* -2);col++) {
  616.         chat=dget(wnd,col,row-1);
  617.         displ(wnd,col,row,chat&255,(chat>>8)&255);
  618.       }
  619.     for (col=1-(BTYPE==6);col < WIDTH-(1+(BTYPE==6)* -2);col++)
  620.       displ(wnd,col,row,' ',WNORMAL);
  621.   }
  622. }
  623.  
  624. #ifndef FASTWINDOWS
  625.  
  626. /* Compute address of a window's display character */
  627.  
  628. static int * pascal waddr (WINDOW *wnd,int x,int y) {
  629.  
  630.   WINDOW *nxt=NEXT;
  631.   int *vp;
  632.  
  633.   if (!VISIBLE) return(int *) (SAV+y*(WIDTH*2)+x*2);
  634.   x+=COL;
  635.   y+=ROW;
  636.   while(nxt) {
  637.     if (nxt->_wv) {
  638.       if (x>=nxt->_wx && x<= nxt->_wx+nxt->_ww-1)
  639.         if (y>=nxt->_wy && y<=nxt->_wy +nxt->_wh-1) {
  640.             x-=nxt->_wx;
  641.             y-=nxt->_wy;
  642.             vp=(int *) ((nxt->_ws)+y*(nxt->_ww*2)+x*2);
  643.             return vp;
  644.       }
  645.     }
  646.     nxt=nxt->_nx;
  647.   }
  648.   return NULL;
  649. }
  650.  
  651. #endif
  652.  
  653. /* Display a character to a window */
  654.  
  655. void pascal displ (WINDOW *wnd,int x,int y,int ch,int at) {
  656.  
  657.     int *vp;
  658.     int vch = (ch & 255) | (at<<8);
  659.     int fg,bg,in,fl;
  660.     char s[24];
  661.     static int last_at=0;
  662.     static int last_x=0;
  663.     static int last_y=0;
  664.  
  665. #ifndef FASTWINDOWS
  666.  
  667.     if((vp=waddr(wnd,x,y))!=NULL) *vp=vch;
  668.     else {
  669.  
  670. #endif
  671.      if(!baud) {
  672.         vpoke(VSG,vad(x+COL,y+ROW),vch);
  673.         return;
  674.      }
  675.      else {
  676.         if(last_x!=x+COL+1 || last_y!=y+ROW+1)
  677.             gprintf(0,"\x1b[%d;%dH",y+ROW+1,x+COL+1);
  678.         if(last_at!=at) {
  679.             fg=at & 7;              /* Foreground */
  680.             bg=((at & (~7))>>4);    /* Background */
  681.             in=at & 8;              /* Intensity  */
  682.             fl=at & 128;            /* Flash      */
  683.             strcpy(s,"\x1b[0;");
  684.             if(in) {
  685.                 strcat(s,"1;");
  686.             }
  687.             else strcat(s,"2;");
  688.             if(fl) {
  689.                 strcat(s,"5;");
  690.             }
  691.             strcat(s,ansifg[fg]);
  692.             strcat(s,ansibg[bg]);
  693.             printm(s);
  694.         }
  695.         gprintf(0,"%c",(char)ch);
  696.      }
  697.  
  698. #ifndef FASTWINDOWS
  699.  
  700.     }
  701.  
  702. #endif
  703.  
  704.     last_x=wherex();
  705.     last_y=wherey();
  706.     last_at=at;
  707.  
  708. }
  709.  
  710. #ifndef FASTWINDOWS
  711.  
  712. /* Get a displayed character from a window */
  713.  
  714. static int pascal dget (WINDOW *wnd,int x,int y) {
  715.  
  716.   int *vp;
  717.  
  718.   if((vp=waddr(wnd,x,y))!=NULL) return *vp;
  719.   return vpeek(VSG,vad(x+COL,y+ROW));
  720. }
  721.  
  722. /* Low-level video functions */
  723.  
  724. /* Swap the video image with the save buffer */
  725.  
  726. static void pascal vswap (WINDOW *wnd) {
  727.  
  728.   int x,y,chat;
  729.   int *bf=(int *)SAV;
  730.  
  731.   for (y=0;y<HEIGHT;y++)
  732.     for (x=0;x<WIDTH;x++) {
  733.       chat=*bf;
  734.       *bf++=dget(wnd,x,y);
  735.       displ(wnd,x,y,chat&255,(chat>>8)&255);
  736.     }
  737. }
  738.  
  739. #else
  740.  
  741. /* Save video memory into the save buffer */
  742.  
  743. static void pascal vsave (WINDOW *wnd) {
  744.  
  745.   int x,y;
  746.   int *bf=(int *) SAV;
  747.  
  748.   for(y=0;y<HEIGHT;y++)
  749.     for(x=0;x<WIDTH;x++)
  750.       *bf++=vpeek(VSG,vad(x+COL,y+ROW));
  751. }
  752.  
  753. /* Restore video memory from the save buffer */
  754.  
  755. static void pascal vrstr (WINDOW *wnd) {
  756.  
  757.   int x,y;
  758.   int *bf=(int *)SAV;
  759.  
  760.   for(y=0;y<HEIGHT;y++) {
  761.     for (x=0;x<WIDTH;x++) {
  762.       if(!baud) vpoke(VSG,vad(x+COL,y+ROW),*bf++);
  763.       else {
  764.         displ(wnd,x,y,*bf&255,(*bf>>8)&255);
  765.         bf++;
  766.       }
  767.     }
  768.   }
  769. }
  770.  
  771. #endif
  772.  
  773. /* (de)Accent the line where SELECT points */
  774.  
  775. void pascal acline (WINDOW *wnd,int set) {
  776.  
  777.   int x,ch;
  778.   int at;
  779.   char al,ah;
  780.  
  781.   if (!verify_wnd(&wnd)) return;
  782.   for(x=1-(BTYPE==6);x<WIDTH-(1-(BTYPE==6));x++) {
  783.     if(BTYPE!=6) {
  784.         ch=dget(wnd,x,SELECT) & 255;
  785.         displ(wnd,x,SELECT,ch,set);
  786.     }
  787.     else {
  788.         ch=dget(wnd,x,SELECT);
  789.         at=(ch>>8)&255; /* Invert attribute */
  790.         al=(at>>4)&255;
  791.         ah=(at<<4)&255;
  792.         at=al+ah;
  793.         displ(wnd,x,SELECT,ch&255,at&255);
  794.  
  795.     }
  796.   }
  797. }
  798.  
  799. /* Linked List functions */
  800.  
  801. /* Add a window to the end of the list */
  802.  
  803. static void pascal add_list (WINDOW *wnd) {
  804.  
  805.   if(listtail) {
  806.     PREV=listtail;
  807.     listtail->_nx=wnd;
  808.   }
  809.   listtail=wnd;
  810.   if (!listhead)
  811.     listhead=wnd;
  812. }
  813.  
  814. /* Add a window to the beginning of the list */
  815.  
  816. static void pascal beg_list(WINDOW *wnd) {
  817.  
  818.   if(listhead) {
  819.     NEXT=listhead;
  820.     listhead->_pv=wnd;
  821.   }
  822.   listhead=wnd;
  823.   if(!listtail) listtail=wnd;
  824. }
  825.  
  826. /* Remove a window from the list */
  827.  
  828. static void pascal remove_list (WINDOW *wnd) {
  829.  
  830.   if(NEXT) NEXT->_pv=PREV;
  831.   if(PREV) PREV->_nx=NEXT;
  832.   if (listhead==wnd) listhead=NEXT;
  833.   if (listtail==wnd) listtail=PREV;
  834.   NEXT=PREV=NULL;
  835. }
  836.  
  837. /* Insert w1 after w2 */
  838.  
  839. static void pascal insert_list (WINDOW *w1,WINDOW *w2) {
  840.  
  841.   w1->_pv=w2;
  842.   w1->_nx=w2->_nx;
  843.   w2->_nx=w1;
  844.   if (w1->_nx==NULL) listtail=w1;
  845.   else w1->_nx->_pv=w1;
  846. }
  847.  
  848. #ifndef FASTWINDOWS
  849.  
  850. /* Verify the presence of a window in the list */
  851.  
  852. static int pascal verify_wnd (WINDOW **w1) {
  853.  
  854.   WINDOW *wnd;
  855.  
  856.   wnd=listhead;
  857.   if(*w1==NULL) *w1=listtail;
  858.   else {
  859.      while(wnd !=NULL) {
  860.        if(*w1==wnd) break;
  861.        wnd=NEXT;
  862.      }
  863.   }
  864.   return wnd != NULL;
  865. }
  866.  
  867. #endif
  868.  
  869.  
  870. /* Error/misc messages */
  871.  
  872. void pascal error_message (char *s) {
  873.  
  874.   clear_message();
  875.   ewnd=establish_window(50,(maxy-3),3,max(10,strlen(s)+2));
  876.   set_colors(ewnd,ALL,RED,YELLOW,BRIGHT);
  877.   set_colors(ewnd,TITLE,RED,YELLOW,BRIGHT|128);
  878.   set_title(ewnd," ERROR! ");
  879.   display_window(ewnd);
  880.   wprintf(ewnd,s);
  881. }
  882.  
  883. void pascal any_message (char *s) {
  884.  
  885.   clear_message();
  886.   ewnd=establish_window(65,(maxy-4),3,max(9,strlen(s)+2));
  887.   set_border(ewnd,2);
  888.   set_colors(ewnd,ALL,AQUA,BLACK,DIM);
  889.   set_title(ewnd," NOTE: ");
  890.   display_window(ewnd);
  891.   wprintf(ewnd,s);
  892. }
  893.  
  894. void pascal _anymsg (char *t,char *s) {
  895.  
  896.   clear_message();
  897.   ewnd=establish_window(65,(maxy-4),3,max(strlen(s),strlen(t))+2);
  898.   set_border(ewnd,2);
  899.   set_colors(ewnd,ALL,AQUA,BLACK,DIM);
  900.   set_title(ewnd,t);
  901.   display_window(ewnd);
  902.   wprintf(ewnd,s);
  903. }
  904.  
  905. void pascal clear_message() {
  906.  
  907.   if (ewnd) delete_window(ewnd);
  908.   ewnd=NULL;
  909. }
  910.