home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / WINDO21.ZIP / WINDO.INC next >
Encoding:
Text File  |  1986-03-04  |  25.8 KB  |  494 lines

  1. { ===================================================================== }
  2. {  WINDO - Windowing routines for Turbo PASCAL                          }
  3. {                                                                       }
  4. {     Author:   Michael Burton                                          }
  5. {               15540 Boot Hill Rd.                                     }
  6. {               Hayden Lake, ID 83835                                   }
  7. {               (208) 772-9347 (after 1800 PST)                         }
  8. {     Revision: 2.1                                                     }
  9. {     Date:     04 March 1986                                           }
  10. {                                                                       }
  11. {  Execute the WINTUTOR program for an explanation of use.              }
  12. {                                                                       }
  13. {  This is a 'Shareware' program.  If you find it to be of significant  }
  14. {  use to you, a $10 donation to the above address would be greatly     }
  15. {  appreciated.  This would also place you on our mailing list to keep  }
  16. {  you informed of upgrades to Windo and of new programs.               }
  17. {                                                                       }
  18. { Modifications:                                                        }
  19. { DATE      Rev  Description                                            }
  20. { 04 Mar 86 2.1  Make the heap available check properly                 }
  21. { ===================================================================== }
  22. type
  23.      windimtype = record
  24.                      colb,rowb,cole,rowe,attrib,bordr,lastx,lasty : byte;
  25.                   end;
  26.      charptr = ^char;
  27.      winstr = string[80];
  28.      brdtype = record
  29.                   ul,ur,ll,lr,hz,vtl,vtr: char;
  30.                end;
  31.  
  32. const maxwin  = 30;        { Total number of windows on screen at any time }
  33.       noneb   = 0;         { No border           }
  34.       singleb = 1;         { Single border       }
  35.       doubleb = 2;         { Double border       }
  36.       mixedb  = 3;         { Mixed border        }
  37.       solidb  = 4;         { Solid border        }
  38.       dimondb = 5;         { Diamond border      }
  39.       circleb = 6;         { Circles border      }
  40.       lhatchb = 7;         { light hatch border  }
  41.       mhatchb = 8;         { medium hatch border }
  42.       dhatchb = 9;         { dense hatch border  }
  43.       brd: array[1..9] of brdtype =  (
  44.           (ul:'┌';ur:'┐';ll:'└';lr:'┘';hz:'─';vtl:'│';vtr:'│'),  { single }
  45.           (ul:'╔';ur:'╗';ll:'╚';lr:'╝';hz:'═';vtl:'║';vtr:'║'),  { double }
  46.           (ul:'╒';ur:'╕';ll:'╘';lr:'╛';hz:'═';vtl:'│';vtr:'│'),  { mixed  }
  47.           (ul:'█';ur:'█';ll:'█';lr:'█';hz:'█';vtl:'▌';vtr:'▐'),  { solid  }
  48.           (ul:' ';ur:' ';ll:' ';lr:' ';hz:' ';vtl:' ';vtr:' '),  { diamond}
  49.           (ul:' ';ur:' ';ll:' ';lr:' ';hz:' ';vtl:' ';vtr:' '),  { circle }
  50.           (ul:'░';ur:'░';ll:'░';lr:'░';hz:'░';vtl:'░';vtr:'░'),  { lhatch }
  51.           (ul:'▒';ur:'▒';ll:'▒';lr:'▒';hz:'▒';vtl:'▒';vtr:'▒'),  { mhatch }
  52.           (ul:'▓';ur:'▓';ll:'▓';lr:'▓';hz:'▓';vtl:'▓';vtr:'▓')); { dhatch }
  53.  
  54. var
  55.      wndo    : Array [0..maxwin] of windimtype; { window attributes      }
  56.      wndoptr : Array [1..maxwin] of charptr; { pointer to window on heap }
  57.      tmpptr  : charptr;                      { temporary pointer         }
  58.      l_i  : byte;                            { level index               }
  59.      wndostr : winstr;                       { string for building wndos }
  60.  
  61. { ===================================================================== }
  62. { GETDISP - Get an array of characters from the CRT display and store   }
  63. {           them in tostrng.                                            }
  64. {           The row and column inputs are relative to zero and are      }
  65. {           also relative to the entire screen, not any open window.    }
  66. {                                                                       }
  67. {    Inputs:                                                            }
  68. {       colb      : byte;    Starting column (0 - 79)                   }
  69. {       rowb      : byte;    Starting row    (0 - 24)                   }
  70. {       len       : byte;    length of array                            }
  71. {       tostrng   : charptr; Pointer to character storage               }
  72. { ===================================================================== }
  73. Procedure GetDisp(colb,rowb,len : byte; tostrng : charptr);
  74. Begin
  75.    Inline(
  76.       $1E/                    {           PUSH   DS               }
  77.       $8A/$86/rowb/           {           MOV    AL,rowb[BP]      }
  78.       $B3/$50/                {           MOV    BL,80            }
  79.       $F6/$E3/                {           MUL    BL               }
  80.       $2B/$DB/                {           SUB    BX,BX            }
  81.       $8A/$9E/colb/           {           MOV    BL,colb[BP]      }
  82.       $03/$C3/                {           ADD    AX,BX            }
  83.       $03/$C0/                {           ADD    AX,AX            }
  84.       $8B/$F8/                {           MOV    DI,AX            }
  85.       $C4/$B6/tostrng/        {           LES    SI,tostrng[BP]   }
  86.       $8A/$8E/len/            {           MOV    CL,len[BP]       }
  87.       $03/$C9/                {           ADD    CX,CX            }
  88.       $2B/$C0/                {           ADD    AX,AX            }
  89.       $8E/$D8/                {           MOV    DS,AX            }
  90.       $A0/$49/$04/            {           MOV    AL,DS:[0449H]    }
  91.       $22/$C9/                {           AND    CL,CL            }
  92.       $74/$32/                {           JZ     DONE             }
  93.       $2C/$07/                {           SUB    AL,7             }
  94.       $74/$20/                {           JZ     MONO             }
  95.       $BA/$00/$B8/            {           MOV    DX,0B800H        }
  96.       $8E/$DA/                {           MOV    DS,DX            }
  97.       $BA/$DA/$03/            {           MOV    DX,03DAH         }
  98.       $EC/                    { TESTLOW:  IN     AL,DX            }
  99.       $A8/$01/                {           TEST   AL,1             }
  100.       $75/$FB/                {           JNZ    TESTLOW          }
  101.       $FA/                    {           CLI                     }
  102.       $EC/                    { TESTHI:   IN     AL,DX            }
  103.       $A8/$01/                {           TEST   AL,1             }
  104.       $74/$FB/                {           JZ     TESTHI           }
  105.       $8A/$1D/                {           MOV    BL,DS:[DI]       }
  106.       $26/$88/$1C/            {           MOV    ES:[SI],BL       }
  107.       $47/                    {           INC    DI               }
  108.       $46/                    {           INC    SI               }
  109.       $E2/$EC/                {           LOOP   GETCHAR          }
  110.       $2A/$C0/                {           SUB    AL,AL            }
  111.       $74/$0E/                {           JZ     DONE             }
  112.       $BA/$00/$B0/            { MONO:     MOV    DX,0B000H        }
  113.       $8E/$DA/                {           MOV    DS,DX            }
  114.       $8A/$1D/                { MONO1:    MOV    BL,DS:[DI]       }
  115.       $26/$88/$1C/            {           MOV    ES:[SI],BL       }
  116.       $47/                    {           INC    DI               }
  117.       $46/                    {           INC    SI               }
  118.       $E2/$F7/                {           LOOP   MONO1            }
  119.       $1F);                   { DONE:     POP    DS               }
  120. End;
  121.  
  122. { ===================================================================== }
  123. { DISPALL - Display an array of characters and attributes on the CRT.   }
  124. {           The array is usually one that has been created using the    }
  125. {           GetDisp procedure.                                          }
  126. {           The row and column inputs are relative to zero and are      }
  127. {           also relative to the entire screen, not any open window.    }
  128. {                                                                       }
  129. {    Inputs:                                                            }
  130. {       colb      : byte;    Starting column  (0 - 79)                  }
  131. {       rowb      : byte;    Starting row     (0 - 24)                  }
  132. {       len       : byte;    length of array  (not including attributes)}
  133. {       fromstrng : charptr; Pointer to array to display                }
  134. { ===================================================================== }
  135. Procedure DispAll(colb,rowb,len : byte; fromstrng : charptr);
  136. Begin
  137.    Inline(
  138.       $1E/                    {           PUSH   DS               }
  139.       $8A/$86/rowb/           {           MOV    AL,rowb[BP]      }
  140.       $B3/$50/                {           MOV    BL,80            }
  141.       $F6/$E3/                {           MUL    BL               }
  142.       $2B/$DB/                {           SUB    BX,BX            }
  143.       $8A/$9E/colb/           {           MOV    BL,colb[BP]      }
  144.       $03/$C3/                {           ADD    AX,BX            }
  145.       $03/$C0/                {           ADD    AX,AX            }
  146.       $8B/$F8/                {           MOV    DI,AX            }
  147.       $C4/$B6/fromstrng/      {           LES    SI,fromstrng[BP] }
  148.       $8A/$8E/len/            {           MOV    CL,len[BP]       }
  149.       $03/$C9/                {           ADD    CX,CX            }
  150.       $2B/$C0/                {           ADD    AX,AX            }
  151.       $8E/$D8/                {           MOV    DS,AX            }
  152.       $A0/$49/$04/            {           MOV    AL,DS:[0449H]    }
  153.       $22/$C9/                {           AND    CL,CL            }
  154.       $74/$32/                {           JZ     DONE             }
  155.       $2C/$07/                {           SUB    AL,7             }
  156.       $74/$20/                {           JZ     MONO             }
  157.       $BA/$00/$B8/            {           MOV    DX,0B800H        }
  158.       $8E/$DA/                {           MOV    DS,DX            }
  159.       $BA/$DA/$03/            {           MOV    DX,03DAH         }
  160.       $26/$8A/$1C/            { GETCHAR:  MOV    BL,ES:[SI]       }
  161.       $EC/                    { TESTLOW:  IN     AL,DX            }
  162.       $A8/$01/                {           TEST   AL,1             }
  163.       $75/$FB/                {           JNZ    TESTLOW          }
  164.       $FA/                    {           CLI                     }
  165.       $EC/                    { TESTHI:   IN     AL,DX            }
  166.       $A8/$01/                {           TEST   AL,1             }
  167.       $74/$FB/                {           JZ     TESTHI           }
  168.       $88/$1D/                {           MOV    DS:[DI],BL       }
  169.       $47/                    {           INC    DI               }
  170.       $46/                    {           INC    SI               }
  171.       $E2/$EC/                {           LOOP   GETCHAR          }
  172.       $2A/$C0/                {           SUB    AL,AL            }
  173.       $74/$0E/                {           JZ     DONE             }
  174.       $BA/$00/$B0/            { MONO:     MOV    DX,0B000H        }
  175.       $8E/$DA/                {           MOV    DS,DX            }
  176.       $26/$8A/$1C/            { MONO1:    MOV    BL,ES:[SI]       }
  177.       $88/$1D/                {           MOV    DS:[DI],BL       }
  178.       $47/                    {           INC    DI               }
  179.       $46/                    {           INC    SI               }
  180.       $E2/$F7/                {           LOOP   MONO1            }
  181.       $1F);                   { DONE:     POP    DS               }
  182. End;
  183.  
  184. { ===================================================================== }
  185. { DISPLINE - Display a string of characters on the CRT (with the same   }
  186. {            attributes)                                                }
  187. {           The row and column inputs are relative to zero and are      }
  188. {           also relative to the entire screen, not any open window.    }
  189. {                                                                       }
  190. {    Inputs:                                                            }
  191. {       colb      : byte;       Starting column  (0 - 79)               }
  192. {       rowb      : byte;       Starting row     (0 - 24)               }
  193. {       attrib    : byte;       Line attributes                         }
  194. {       fromstrng : string[80]; String to display                       }
  195. { ===================================================================== }
  196. Procedure DispLine(colb,rowb,attrib : byte; VAR fromstrng : winstr);
  197. Begin
  198.    Inline(
  199.       $1E/                    {           PUSH   DS               }
  200.       $8A/$86/rowb/           {           MOV    AL,rowb[BP]      }
  201.       $B3/$50/                {           MOV    BL,80            }
  202.       $F6/$E3/                {           MUL    BL               }
  203.       $2B/$DB/                {           SUB    BX,BX            }
  204.       $8A/$9E/colb/           {           MOV    BL,colb[BP]      }
  205.       $03/$C3/                {           ADD    AX,BX            }
  206.       $03/$C0/                {           ADD    AX,AX            }
  207.       $8B/$F8/                {           MOV    DI,AX            }
  208.       $8A/$BE/attrib/         {           MOV    BH,attrib[BP]    }
  209.       $C4/$B6/fromstrng/      {           LES    SI,fromstrng[BP] }
  210.       $2B/$C9/                {           SUB    CX,CX            }
  211.       $26/$8A/$0C/            {           MOV    CL,ES:[SI]       }
  212.       $2B/$C0/                {           ADD    AX,AX            }
  213.       $8E/$D8/                {           MOV    DS,AX            }
  214.       $A0/$49/$04/            {           MOV    AL,DS:[0449H]    }
  215.       $22/$C9/                {           AND    CL,CL            }
  216.       $74/$34/                {           JZ     DONE             }
  217.       $2C/$07/                {           SUB    AL,7             }
  218.       $74/$21/                {           JZ     MONO             }
  219.       $BA/$00/$B8/            {           MOV    DX,0B800H        }
  220.       $8E/$DA/                {           MOV    DS,DX            }
  221.       $BA/$DA/$03/            {           MOV    DX,03DAH         }
  222.       $46/                    { GETCHAR:  INC    SI               }
  223.       $26/$8A/$1C/            {           MOV    BL,ES:[SI]       }
  224.       $EC/                    { TESTLOW:  IN     AL,DX            }
  225.       $A8/$01/                {           TEST   AL,1             }
  226.       $75/$FB/                {           JNZ    TESTLOW          }
  227.       $FA/                    {           CLI                     }
  228.       $EC/                    { TESTHI:   IN     AL,DX            }
  229.       $A8/$01/                {           TEST   AL,1             }
  230.       $74/$FB/                {           JZ     TESTHI           }
  231.       $89/$1D/                {           MOV    DS:[DI],BX       }
  232.       $47/                    {           INC    DI               }
  233.       $47/                    {           INC    DI               }
  234.       $E2/$EB/                {           LOOP   GETCHAR          }
  235.       $2A/$C0/                {           SUB    AL,AL            }
  236.       $74/$0F/                {           JZ     DONE             }
  237.       $BA/$00/$B0/            { MONO:     MOV    DX,0B000H        }
  238.       $8E/$DA/                {           MOV    DS,DX            }
  239.       $46/                    { MONO1:    INC    SI               }
  240.       $26/$8A/$1C/            {           MOV    BL,ES:[SI]       }
  241.       $89/$1D/                {           MOV    DS:[DI],BX       }
  242.       $47/                    {           INC    DI               }
  243.       $47/                    {           INC    DI               }
  244.       $E2/$F6/                {           LOOP   MONO1            }
  245.       $1F);                   { DONE:     POP    DS               }
  246. End;
  247.  
  248. { ======================================================================== }
  249. { NAME: Normalize                   VERSION: 1.0   DATE: 23 January 1986   }
  250. { AUTHOR: Michael Burton                                                   }
  251. { DESCRIPTION: Normalize coordinates                                       }
  252. { INPUTS: s,e : byte;  start and end coordinates                           }
  253. { OUTPUTS: s,e : byte; coordinates with s < e                              }
  254. {                                                                          }
  255. { ======================================================================== }
  256. Procedure Normalize(VAR s,e: byte);
  257. Var temp: byte;
  258. Begin
  259.    If s > e Then
  260.    Begin
  261.       temp := s;
  262.       s    := e;
  263.       e    := temp;
  264.    End;
  265. End;
  266.  
  267. { ======================================================================== }
  268. { NAME: Bleep                       VERSION: 1.0   DATE: 14 January 1986   }
  269. { AUTHOR: Michael Burton                                                   }
  270. { DESCRIPTION: Produce a bleeping sound times number of times              }
  271. { INPUTS: times : byte;  The number of bleeps required                     }
  272. {                                                                          }
  273. { ======================================================================== }
  274. Procedure Bleep(times : byte);
  275. Var i : byte;
  276. Begin
  277.    For i := 1 To times Do
  278.    Begin
  279.       Nosound;
  280.       Sound(880);
  281.       Delay(60);
  282.       Sound(440);
  283.       Delay(60);
  284.       Nosound;
  285.    End;
  286. End;
  287.  
  288. { ======================================================================== }
  289. { NAME: Set_Cursor                  VERSION: 1.0   DATE: 27 January 1986   }
  290. { AUTHOR:                                                                  }
  291. { DESCRIPTION: Set the cursor size                                         }
  292. { INPUTS: The number of cursor lines to display (0 -7, 0-14)               }
  293. {                                                                          }
  294. { ======================================================================== }
  295. Procedure Set_Cursor (n: byte);
  296. Type
  297.    regrec = Record
  298.               ax,bx,cx,dx,bp,si,di,ds,es,flags: integer
  299.             End;
  300. Var regpak: regrec;
  301. Begin
  302.    regpak.ax:= $100;
  303.    If Not n In [1..8] Then regpak.cx:= $0800
  304.    Else regpak.cx:= ((8-n) shl 8) or 7;
  305.    Intr($10,regpak)
  306. End;
  307.  
  308. { ===================================================================== }
  309. { INITWINDO - Initialize the window variables                           }
  310. {                                                                       }
  311. { Use this routine before using MAKEWINDO, REMOVEWINDO or TITLEWINDO    }
  312. {                                                                       }
  313. {    Inputs:                                                            }
  314. {       txtcolor  : byte;    Starting text color                        }
  315. {       bkgndclr  : byte;    Starting background color                  }
  316. { ===================================================================== }
  317. Procedure InitWindo(txtcolor,bkgndclr : byte);
  318. Begin
  319.    brd[5].ul  := chr(08);   { Set up circle border constants    }
  320.    brd[5].ur  := chr(08);
  321.    brd[5].ll  := chr(08);
  322.    brd[5].lr  := chr(08);
  323.    brd[5].hz  := chr(08);
  324.    brd[5].vtl := chr(08);
  325.    brd[5].vtr := chr(08);
  326.    brd[6].ul  := chr(10);   { Set up diamond border constants   }
  327.    brd[6].ur  := chr(10);
  328.    brd[6].ll  := chr(10);
  329.    brd[6].lr  := chr(10);
  330.    brd[6].hz  := chr(10);
  331.    brd[6].vtl := chr(10);
  332.    brd[6].vtr := chr(10);
  333.    textcolor(txtcolor);
  334.    textbackground(bkgndclr);
  335.    wndo[0].rowb   := 0;       { Initialize non-window zero }
  336.    wndo[0].rowe   := 24;
  337.    wndo[0].colb   := 0;
  338.    wndo[0].cole   := 79;
  339.    wndo[0].attrib := (bkgndclr * 16) + txtcolor;
  340.    wndo[0].bordr  := noneb;
  341.    wndo[0].lastx  := Wherex;
  342.    wndo[0].lasty  := Wherey;
  343.    l_i := 0;
  344. End;
  345.  
  346. { ===================================================================== }
  347. { MAKEWINDO - Create a window                                           }
  348. {                                                                       }
  349. {    Inputs:                                                            }
  350. {         colb     : byte;   Start column     (1 - 80)                  }
  351. {         rowb     : byte;   Start row        (1 - 25)                  }
  352. {         cole     : byte;   End column       (1 - 80)                  }
  353. {         rowe     : byte;   End row          (1 - 25)                  }
  354. {         tcolor   : byte;   Text color       (0 - 15)                  }
  355. {         tback    : byte;   Text background  (0 - 7, > 7 for blinking) }
  356. {         bordr    : boolean;   Border indicator (0 - 9)                }
  357. { ===================================================================== }
  358. Procedure MakeWindo(colb,rowb,cole,rowe,tcolor,tback:byte;bordr:byte);
  359. Var i     : byte;
  360.     wsize : integer;
  361.     pseg  : integer;
  362.     pofs  : integer;
  363.     mema  : real;
  364. Begin
  365.    rowb := rowb - 1;  { Set coordinates relative to zero }
  366.    rowe := rowe - 1;
  367.    colb := colb - 1;
  368.    cole := cole - 1;
  369.    Normalize(rowb,rowe);
  370.    Normalize(colb,cole);
  371.    wsize := 2 * ((cole - colb + 1) * (rowe - rowb + 1));  { Total size of area }
  372.                                                      { needed to store display }
  373.    If l_i + 1 > maxwin Then
  374.    Begin
  375.       Writeln('Too many Windows!');
  376.       Bleep(4);
  377.    End
  378.    Else
  379.    Begin
  380.       If memavail < 0 then mema := 65536.0 + memavail
  381.       else mema := memavail;
  382.       If (wsize DIV 16 + 1) > mema Then
  383.       Begin
  384.          Writeln('Not enough Heap space!');
  385.          Bleep(4);
  386.       End
  387.       Else
  388.       Begin
  389.          wndo[l_i].lastx  := Wherex;   { Store old cursor coordinates }
  390.          wndo[l_i].lasty  := Wherey;
  391.          l_i := l_i + 1;        { Go to next window level }
  392.          Textcolor(tcolor);
  393.          Textbackground(tback);
  394.          wndo[l_i].rowb := rowb;   { Store all variables for this window }
  395.          wndo[l_i].rowe := rowe;
  396.          wndo[l_i].colb := colb;
  397.          wndo[l_i].cole := cole;
  398.          wndo[l_i].attrib := (tback * 16) + tcolor;
  399.          wndo[l_i].bordr  := bordr;
  400.          GetMem(wndoptr[l_i],wsize);   { Get enough heap to store old display }
  401.          tmpptr := wndoptr[l_i];
  402.          For i := rowb To rowe Do  { Store old display one row at a time }
  403.          Begin
  404.             GetDisp(colb,i,(cole-colb+1),tmpptr);
  405.             pseg   := Seg(tmpptr^);
  406.             pofs   := Ofs(tmpptr^);
  407.             pofs   := pofs + 2 * (cole - colb + 1);
  408.             tmpptr := Ptr(pseg,pofs);
  409.          End;
  410.          wndostr[0] := chr(cole - colb + 1);  { Set up String length }
  411.          If bordr = noneb Then
  412.          Begin
  413.             FillChar(wndostr[1],cole-colb+1,' '); { Do no border }
  414.             For i := rowb To rowe Do DispLine(colb,i,wndo[l_i].attrib,wndostr);
  415.             Window(colb+1,rowb+1,cole+1,rowe+1); { Create actual Turbo window }
  416.          End
  417.          Else
  418.          Begin
  419.             wndostr[1] := brd[bordr].ul;      { Do border top line }
  420.             wndostr[cole-colb+1] := brd[bordr].ur;
  421.             FillChar(wndostr[2],cole-colb-1,brd[bordr].hz);
  422.             DispLine(colb,rowb,wndo[l_i].attrib,wndostr);
  423.             wndostr[1] := brd[bordr].vtl;     { Do border middle lines }
  424.             wndostr[cole-colb+1] := brd[bordr].vtr;
  425.             FillChar(wndostr[2],cole-colb-1,' ');
  426.             For i := rowb+1 To rowe-1 Do DispLine(colb,i,wndo[l_i].attrib,wndostr);
  427.             wndostr[1] := brd[bordr].ll;      { Do border bottom line }
  428.             wndostr[cole-colb+1] := brd[bordr].lr;
  429.             FillChar(wndostr[2],cole-colb-1,brd[bordr].hz);
  430.             DispLine(colb,rowe,wndo[l_i].attrib,wndostr);
  431.             Window(colb+2,rowb+2,cole,rowe);  { Create actual Turbo window }
  432.          End;
  433.          Gotoxy(1,1);
  434.       End;
  435.    End;
  436. End;
  437.  
  438. { ===================================================================== }
  439. { REMOVEWINDO - Remove the last window created from the screen.  To     }
  440. {               get back to the original screen, there must be as many  }
  441. {               Removewindos as there are Makewindos.                   }
  442. {                                                                       }
  443. {    Inputs:                                                            }
  444. {         None                                                          }
  445. { ===================================================================== }
  446. Procedure RemoveWindo;
  447. Var i    : byte;
  448.     wsize: integer;
  449.     pseg : integer;
  450.     pofs : integer;
  451. Begin
  452.    If l_i = 0 Then
  453.    Begin
  454.       Writeln('No Window To Remove!');
  455.       Bleep(4);
  456.    End
  457.    Else
  458.    Begin
  459.       wsize  := wndo[l_i].cole - wndo[l_i].colb + 1;
  460.       tmpptr := wndoptr[l_i];
  461.       For i  := wndo[l_i].rowb To wndo[l_i].rowe Do   { Put back old display }
  462.       Begin
  463.          DispAll(wndo[l_i].colb,i,wsize,tmpptr);
  464.          pseg   := Seg(tmpptr^);
  465.          pofs   := Ofs(tmpptr^);
  466.          pofs   := pofs + 2 * wsize;
  467.          tmpptr := Ptr(pseg,pofs);
  468.       End;
  469.       wsize := 2 * ((wndo[l_i].cole - wndo[l_i].colb + 1) * (wndo[l_i].rowe - wndo[l_i].rowb + 1));
  470.       FreeMem(wndoptr[l_i],wsize);      { Release heap space }
  471.       l_i := l_i - 1;                   { Go to next lower level }
  472.       Textcolor(wndo[l_i].attrib AND $0F); { Set up all for this level }
  473.       Textbackground(wndo[l_i].attrib DIV 16);
  474.       If wndo[l_i].bordr = noneb Then
  475.          Window(wndo[l_i].colb+1,wndo[l_i].rowb+1,wndo[l_i].cole+1,wndo[l_i].rowe+1)
  476.       Else
  477.          Window(wndo[l_i].colb+2,wndo[l_i].rowb+2,wndo[l_i].cole,wndo[l_i].rowe);
  478.       Gotoxy(wndo[l_i].lastx,wndo[l_i].lasty);
  479.    End;
  480. End;
  481.  
  482. { ===================================================================== }
  483. { TITLEWINDO - Place a centered title in the top border of a window.    }
  484. {                                                                       }
  485. {    Inputs:                                                            }
  486. {         title  : string[80]; The title of the window                  }
  487. { ===================================================================== }
  488. Procedure TitleWindo (title: winstr);
  489. Var i : byte;
  490. Begin
  491.    i := (((wndo[l_i].cole-wndo[l_i].colb) - length(title)) DIV 2 + 1) + wndo[l_i].colb;
  492.    DispLine(i,wndo[l_i].rowb,wndo[l_i].attrib,title);
  493. End;
  494.