home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 14 / CDACTUAL.iso / cdactual / demobin / share / program / Pascal / TJOCK50.ZIP / SOURCE.ARC / WINTTT5.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1989-03-05  |  27.9 KB  |  986 lines

  1. {--------------------------------------------------------------------------}
  2. {                         TechnoJock's Turbo Toolkit                       }
  3. {                                                                          }
  4. {                              Version   5.00a                             }
  5. {                                                                          }
  6. {                                                                          }
  7. {              Copyright 1986, 1989 TechnoJock Software, Inc.              }
  8. {                           All Rights Reserved                            }
  9. {                          Restricted by License                           }
  10. {--------------------------------------------------------------------------}
  11.  
  12.                      {--------------------------------}
  13.                      {       Unit:   WinTTT5          }
  14.                      {--------------------------------}
  15.  
  16. {History:    03/05/89   5.00a  corrected Get_ScreenWord procedure
  17.  
  18. }
  19.  
  20. {$S-,R-,V-,D-}       
  21.  
  22. unit  WinTTT5;
  23.  
  24. interface
  25.  
  26. uses CRT,DOS,FastTTT5,KeyTTT5;
  27.  
  28. Type
  29.  Direction = (Up, Down, Left, Right);
  30. Const
  31.     Shadow = 5;
  32. Var
  33.     Shadcolor    : byte;
  34.     DisplayLines : byte;
  35.  
  36. Procedure MoveFromScreen(var Source,Dest;Length:Word);
  37. Procedure MoveToScreen(var Source,Dest; Length:Word);
  38. Procedure SizeCursor(Top,Bot:byte);
  39. Procedure FindCursor(var X,Y,Top,Bot:byte);
  40. Procedure PosCursor(X,Y: integer);
  41. Procedure Fullcursor;
  42. Procedure HalfCursor;
  43. Procedure OnCursor;
  44. Procedure OffCursor;
  45. Procedure GotoXY(X,Y : byte);
  46. Function  WhereX: byte;
  47. Function  WhereY: byte;
  48. Function  GetScreenChar(X,Y:byte):char;
  49. Function  GetScreenAttr(X,Y:byte):byte;
  50. Procedure GetScreenStr(X1,X2,Y:byte;var  St:StrScreen);
  51. Procedure CreateScreen(Page:byte;Lines:byte);
  52. Procedure SaveScreen(Page:byte);
  53. Procedure RestoreScreen(Page:byte);
  54. Procedure PartRestoreScreen(Page,X1,Y1,X2,Y2,X,Y:byte);
  55. Procedure SlideRestoreScreen(Page:byte;Way:Direction);
  56. Procedure PartSlideRestoreScreen(Page:byte;Way:Direction;X1,Y1,X2,Y2:byte);
  57. Procedure DisposeScreen(Page:byte);
  58. Procedure SetCondensedLines;
  59. Procedure Set25Lines;
  60. Procedure CopyScreenBlock(X1,Y1,X2,Y2,X,Y:byte);
  61. Procedure MoveScreenBlock(X1,Y1,X2,Y2,X,Y:byte);
  62. Procedure Scroll(Way:direction;X1,Y1,X2,Y2:byte);
  63. Procedure PartSave(X1,Y1,X2,Y2:byte; VAR Dest);
  64. Procedure PartRestore(X1,Y1,X2,Y2:byte; VAR Source);
  65. Procedure Mkwin(x1,y1,x2,y2,F,B,boxtype:integer);
  66. Procedure GrowMkwin(x1,y1,x2,y2,F,B,boxtype:integer);
  67. Procedure Rmwin;
  68. Procedure FillScreen(X1,Y1,X2,Y2:byte; F,B:byte; C:char);
  69. Procedure TempMessageCh(X,Y,F,B:integer;St:strscreen;var Ch : char);
  70. Procedure TempMessage(X,Y,F,B:integer;St:strscreen);
  71. Procedure TempMessageBoxCh(X1,Y1,F,B,BoxType:integer;St:strscreen;var Ch : char);
  72. Procedure TempMessageBox(X1,Y1,F,B,BoxType:integer;St:strscreen);
  73. Procedure Activate_Visible_Screen;
  74. Procedure Activate_Virtual_Screen(Page:byte);
  75. Procedure Reset_StartUp_Mode;
  76.  
  77. Const
  78.     Max_Windows = 10;          {Change this constant as necessary}
  79.     Max_Screens = 10;          {Change this constant as necessary}
  80.     WindowCounter : byte = 0;
  81.     ScreenCounter : byte = 0;
  82.     ActiveVScreen: byte = 0;
  83.  
  84. Type
  85.     ScreenImage = record
  86.                        CursorX : byte;
  87.                        CursorY : byte;
  88.                        ScanTop : byte;
  89.                        ScanBot : byte;
  90.                        SavedLines:byte;
  91.                        ScreenPtr: pointer;
  92.                   end;
  93.     ScreenPtr = ^ScreenImage;
  94.     WindowImage = record
  95.                        ScreenPtr: Pointer;             {pointer to screen data}
  96.                        Coord    : array[1..4] of byte; {window coords}
  97.                        CursorX  : byte;                {cursor location}
  98.                        CursorY  : byte;
  99.                        ScanTop  : byte;                {cursor shape}
  100.                        ScanBot  : byte;
  101.                   end;
  102.     WindowPtr = ^WindowImage;
  103.  
  104. Var
  105.     Screen : array[1..Max_Screens] of ScreenPtr;
  106.     Win    : array[1..Max_Windows] of WindowPtr;
  107.     W_error: integer;     {Global error to report winTTT errors}
  108.     W_fatal: boolean;
  109.  
  110. IMPLEMENTATION
  111.  
  112. CONST
  113.     MonoAdr =$b000;
  114. VAR
  115.     StartTop,      {used to record initial screen state when program is run}
  116.     StartBot   : Byte;
  117.     StartMode  : word;
  118.  
  119. {$L WINTTT5}
  120.  
  121. {$F+}
  122.   Procedure MoveFromScreen(var Source,Dest;Length:Word); external;
  123.   Procedure MoveToScreen(var Source,Dest; Length:Word); external;
  124. {$F-}
  125.  
  126. Procedure WinTTT_Error(No : byte);
  127. {Updates W_error and optionally displays error message then halts program}
  128. var Msg : String;
  129. begin
  130.     W_error := No;
  131.     If W_fatal = true then
  132.     begin
  133.         Case No of
  134.         1 :  Msg := 'Max screens exceeded';
  135.         2 :  Msg := 'Max Windows Exceeded';
  136.         3 :  Msg := 'Insufficient memory to create screen';
  137.         4 :  Msg := 'Screen not saved cannot activate.';
  138.         5 :  Msg := 'Screen has not been created - cannot activate';
  139.         6 :  Msg := 'Screen has not been created - cannot dispose';
  140.         7 :  Msg := 'Screen has not been created - cannot restore';
  141.         8 :  Msg := 'Screen does not exist cannot clear';
  142.         9 :  Msg := 'Insufficient memory for Screen Copy/Move';
  143.         10:  Msg := 'Visible screen must be active for Window operations';
  144.         11:  Msg := 'Visible screen must be active for Message operations';
  145.         12:; {reserved for non-fatal error settings condensed mode}
  146.         13:  Msg := 'Can only save 25 screen lines - check CONST SavedLines';
  147.         else Msg := '?) -- Utterly confused';
  148.         end; {Case}
  149.         Msg := 'Fatal Error (WinTTT -- '+Msg;
  150.         Writeln(Msg);
  151.         Delay(5000);    {display long enough to read if child process}
  152.         Halt;
  153.     end;
  154. end;
  155.  
  156. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  157. {                                                                     }
  158. {     V I S I B L E    a n d    V I R T U A L  P R O C E D U R E S    }
  159. {                                                                     }
  160. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  161. Procedure PartSave (X1,Y1,X2,Y2:byte; VAR Dest);
  162. {transfers data from active virtual screen to Dest}
  163. var
  164.    I,width : byte;
  165.    ScreenAdr: integer;
  166. begin
  167.     width := succ(X2- X1);
  168.     For I :=  Y1 to Y2 do
  169.     begin
  170.      ScreenAdr := Vofs + Pred(I)*160 + Pred(X1)*2;
  171.      MoveFromScreen(Mem[Vseg:ScreenAdr],
  172.                     Mem[seg(Dest):ofs(dest)+(I-Y1)*width*2],
  173.                     width);
  174.     end;
  175. end;
  176.  
  177. Procedure PartRestore (X1,Y1,X2,Y2:byte; VAR Source);
  178. {restores data from Source and transfers to active virtual screen}
  179. var
  180.    I,width : byte;
  181.    ScreenAdr: integer;
  182. begin
  183.     width := succ(X2- X1);
  184.     For I :=  Y1 to Y2 do
  185.     begin
  186.      ScreenAdr := Vofs + Pred(I)*160 + Pred(X1)*2;
  187.      MoveToScreen(Mem[Seg(Source):ofs(Source)+(I-Y1)*width*2],
  188.                   Mem[Vseg:ScreenAdr],
  189.                   width);
  190.     end;
  191. end;
  192.  
  193. Procedure FillScreen(X1,Y1,X2,Y2:byte; F,B:byte; C:char);
  194. var
  195.    I : integer;
  196.    S : string;
  197. begin
  198.     W_error := 0;
  199.     Attrib(X1,Y1,X2,Y2,F,B);
  200.     S := Replicate(Succ(X2-x1),C);
  201.     For I := Y1 to Y2 do
  202.         PlainWrite(X1,I,S);
  203. end;
  204.  
  205. Procedure GetScreenWord(X,Y:byte;var Attr:byte; var Ch : char);
  206. {updates vars Attr and Ch with attribute and character bytes in screen
  207.  location (X,Y) of the active screen}
  208. Type
  209.     ScreenWordRec = record
  210.                          Ch   : char;   {5.00a}
  211.                          Attr : byte;
  212.                     end;
  213. var
  214.    ScreenAdr: integer;
  215.    SW : ScreenWordRec;
  216. begin
  217.     ScreenAdr := Vofs + Pred(Y)*160 + Pred(X)*2;
  218.     MoveFromScreen(Mem[Vseg:ScreenAdr],mem[seg(SW):ofs(SW)],1);
  219.     Attr := SW.Attr;
  220.     Ch   := SW.Ch;
  221. end;
  222.  
  223. Function GetScreenChar(X,Y:byte):char;
  224. var
  225.    A : byte;
  226.    C : char;
  227. begin
  228.     GetScreenWord(X,Y,A,C);
  229.     GetScreenChar := C;
  230. end;
  231.  
  232. Function GetScreenAttr(X,Y:byte):byte;
  233. var
  234.    A : byte;
  235.    C : char;
  236. begin
  237.     GetScreenWord(X,Y,A,C);
  238.     GetScreenAttr := A;
  239. end;
  240.  
  241. Procedure GetScreenStr(X1,X2,Y:byte;var  St:StrScreen);
  242. var
  243.    I : integer;
  244. begin
  245.     St := '';
  246.     For I := X1 to X2 do
  247.         St := St + GetScreenChar(I,Y);
  248. end;
  249.  
  250. {++++++++++++++++++++++++++++++++++++++++++++++}
  251. {                                              }
  252. {         C U R S O R    R O U T I N E S       }
  253. {                                              }
  254. {++++++++++++++++++++++++++++++++++++++++++++++}
  255.  
  256. Procedure GotoXY(X,Y : byte);
  257. {intercepts normal Turbo GotoXY procedure, in case a virtual screen
  258.  is active.
  259. }
  260. begin
  261.     If VSeg = BaseOfScreen then
  262.        CRT.GotoXY(X,Y)
  263.     else
  264.        with Screen[ActiveVScreen]^ do
  265.        begin
  266.            CursorX := X;
  267.            CursorY := Y;
  268.        end; {with}
  269. end;  {proc GotoXY}
  270.  
  271. Function WhereX: byte;
  272. {intercepts normal Turbo WhereX procedure, in case a virtual screen
  273.  is active.
  274. }
  275. begin
  276.     If VSeg = BaseOfScreen then
  277.        WhereX := CRT.WhereX
  278.     else
  279.        with Screen[ActiveVScreen]^ do
  280.            WhereX := CursorX;
  281. end; {of func WhereX}
  282.  
  283. Function WhereY: byte;
  284. {intercepts normal Turbo WhereX procedure, in case a virtual screen
  285.  is active.
  286. }
  287. begin
  288.     If VSeg = BaseOfScreen then
  289.        WhereY := CRT.WhereY
  290.     else
  291.        with Screen[ActiveVScreen]^ do
  292.            WhereY := CursorY;
  293. end; {of func WhereY}
  294.  
  295. Procedure FindCursor(var X,Y,Top,Bot:byte);
  296. var
  297.    Reg : registers;
  298. begin
  299.   If VSeg = BaseOfScreen then    {visible screen is active}
  300.   begin   
  301.       Reg.Ax := $0F00;              {get page in Bx}
  302.       Intr($10,Reg);
  303.       Reg.Ax := $0300;
  304.       Intr($10,Reg);
  305.       With Reg do
  306.       begin
  307.         X := lo(Dx) + 1;
  308.         Y := hi(Dx) + 1;
  309.         Top := Hi(Cx) and $0F;
  310.         Bot := Lo(Cx) and $0F;
  311.       end;
  312.   end
  313.   else                            {virtual screen active}
  314.      with Screen[ActiveVScreen]^ do
  315.      begin
  316.          X := CursorX;
  317.          Y := CursorY;
  318.          Top := ScanTop;
  319.          Bot := ScanBot;
  320.      end;
  321. end;
  322.  
  323. Procedure PosCursor(X,Y: integer);
  324. var Reg : registers;
  325. begin
  326.     If VSeg = BaseOfScreen then    {visible screen is active}
  327.     begin   
  328.         Reg.Ax := $0F00;              {get page in Bx}
  329.         Intr($10,Reg);
  330.         with Reg do
  331.         begin
  332.           Ax := $0200;
  333.           Dx := ((Y-1) shl 8) or ((X-1) and $00FF);
  334.         end;
  335.         Intr($10,Reg);
  336.     end
  337.     else                           {virtual screen active}
  338.        with Screen[ActiveVScreen]^ do
  339.        begin
  340.            CursorX := X;
  341.            CursorY := Y;
  342.        end;
  343. end;
  344.  
  345. Procedure SizeCursor(Top,Bot:byte);
  346. var Reg : registers;
  347. begin
  348.     If VSeg = BaseOfScreen then    {visible screen is active}
  349.        with Reg do
  350.        begin
  351.          ax := 1 shl 8;
  352.          cx := Top shl 8 + Bot;
  353.          INTR($10,Reg);
  354.        end
  355.     else                           {virtual screen active}
  356.        with Screen[ActiveVScreen]^ do
  357.        begin
  358.            ScanTop := Top;
  359.            ScanBot := Bot;
  360.        end;
  361. end;
  362.  
  363. Procedure HalfCursor;
  364. begin
  365.     If BaseOfScreen = MonoAdr then    
  366.        SizeCursor(8,13)    
  367.     else
  368.        SizeCursor(4,7);    
  369. end; {Proc HalfCursor}
  370.  
  371. Procedure Fullcursor;
  372. begin
  373.     If BaseOfScreen = MonoAdr then
  374.        SizeCursor(0,13)
  375.     else
  376.        SizeCursor(0,7);
  377. end;
  378.  
  379. Procedure OnCursor;
  380. begin
  381.     If BaseOfScreen = MonoAdr then
  382.        SizeCursor(12,13)
  383.     else
  384.        SizeCursor(6,7);
  385. end;
  386.  
  387. Procedure OffCursor;
  388. begin
  389.     Sizecursor(14,0);
  390. end;
  391.  
  392. {++++++++++++++++++++++++++++++++++++++++++++++++++++}
  393. {                                                    }
  394. {   S C R E E N   S A V I N G  R O U T I N E S       }
  395. {                                                    }
  396. {++++++++++++++++++++++++++++++++++++++++++++++++++++}
  397.  
  398. Procedure DisposeScreen(Page:byte);
  399. {Free memory and set pointer to nil}
  400. begin
  401.     If Screen[Page] = nil then
  402.     begin
  403.        WinTTT_Error(6);
  404.        exit;
  405.     end
  406.     else
  407.        W_error := 0;
  408.     FreeMem(Screen[Page]^.ScreenPtr,Screen[Page]^.SavedLines*160);
  409.     Freemem(Screen[Page],SizeOf(Screen[Page]^));
  410.     Screen[page] := nil;
  411.     If ActiveVscreen = Page then
  412.        Activate_Visible_Screen;
  413.     dec(ScreenCounter);
  414. end;
  415.  
  416. Procedure SaveScreen(Page:byte);
  417. {Save screen display and cursor details}
  418. begin
  419.     If (Page > Max_Screens) then
  420.     begin
  421.       WinTTT_Error(1);
  422.       exit;
  423.     end;
  424.     If ((Screen[Page] <> nil) and (DisplayLines <> Screen[Page]^.SavedLines)) then
  425.         DisposeScreen(Page);
  426.     If Screen[Page] = nil then            {need to allocate memory}
  427.     begin
  428.         If MaxAvail < SizeOf(Screen[Page]^) then
  429.         begin
  430.             WinTTT_Error(3);
  431.             exit;
  432.         end;
  433.         GetMem(Screen[Page],SizeOf(Screen[Page]^));
  434.         If MaxAvail < DisplayLines*160 then     {do check in two parts 'cos Maxavail is not same as MemAvail}
  435.         begin
  436.             WinTTT_Error(3);
  437.             Freemem(Screen[Page],SizeOf(Screen[Page]^));
  438.             Screen[Page] := nil;
  439.             exit;
  440.         end;
  441.         GetMem(Screen[Page]^.ScreenPtr,DisplayLines*160);
  442.         Inc(ScreenCounter);
  443.     end;
  444.     With Screen[Page]^ do
  445.     begin
  446.        FindCursor(CursorX,CursorY,ScanTop,ScanBot);     {Save Cursor posn. and shape}
  447.        SavedLines := DisplayLines;
  448.        MoveFromScreen(Mem[BaseOfScreen:0],Screen[Page]^.ScreenPtr^,DisplayLines*80);
  449.     end;
  450.     W_error := 0;
  451. end;
  452.  
  453. Procedure RestoreScreen(Page:byte);
  454. {Display a screen that was previously saved}
  455. begin
  456.     If Screen[Page] = nil then
  457.     begin
  458.        WinTTT_Error(7);
  459.        exit;
  460.     end
  461.     else
  462.        W_error := 0;
  463.     With Screen[Page]^ do
  464.     begin
  465.         MoveToScreen(ScreenPtr^,mem[BaseOfScreen:0], 80*SavedLines);
  466.         PosCursor(CursorX,CursorY);
  467.         SizeCursor(ScanTop,ScanBot);
  468.     end;
  469. end;  {Proc RestoreScreen}
  470.  
  471.  
  472. Procedure PartRestoreScreen(Page,X1,Y1,X2,Y2,X,Y:byte);
  473. {Move from heap to screen, part of saved screen}
  474. Var
  475.    I,width     : byte;
  476.    ScreenAdr,
  477.    PageAdr     : integer;
  478. begin
  479.     If Screen[Page] = nil then
  480.     begin
  481.        WinTTT_Error(7);
  482.        exit;
  483.     end
  484.     else
  485.        W_error := 0;
  486.     Width := succ(X2- X1);
  487.     For I :=  Y1 to Y2 do
  488.     begin
  489.         ScreenAdr := pred(Y+I-Y1)*160 + Pred(X)*2;
  490.         PageAdr   := Pred(I)*160 + Pred(X1)*2;
  491.         MoveToScreen(Mem[Seg(Screen[Page]^.ScreenPtr^):ofs(Screen[Page]^.ScreenPtr^)+PageAdr],
  492.                      Mem[BaseOfScreen:ScreenAdr],
  493.                      width);
  494.     end;
  495. end;
  496.  
  497. Procedure SlideRestoreScreen(Page:byte;Way:Direction);
  498. {Display a screen that was previously saved, with fancy slide}
  499. Var I : byte;
  500. begin
  501.     If Screen[Page] = nil then
  502.     begin
  503.        WinTTT_Error(7);
  504.        exit;
  505.     end
  506.     else
  507.        W_error := 0;
  508.     Case Way of
  509.     Up    : begin
  510.                 For I := DisplayLines downto 1 do
  511.                 begin
  512.                     PartRestoreScreen(Page,
  513.                                       1,1,80,succ(DisplayLines -I),
  514.                                       1,I);
  515.                     Delay(50);
  516.                 end;
  517.             end;
  518.     Down  : begin
  519.                 For I := 1 to DisplayLines do
  520.                 begin
  521.                     PartRestoreScreen(Page,
  522.                                       1,succ(DisplayLines -I),80,DisplayLines,
  523.                                       1,1);
  524.                     Delay(50);  {savor the moment!}
  525.                 end;
  526.             end;
  527.     Left  : begin
  528.                 For I := 1 to 80 do
  529.                 begin
  530.                     PartRestoreScreen(Page,
  531.                                       1,1,I,DisplayLines,
  532.                                       succ(80-I),1);
  533.                 end;
  534.             end;
  535.     Right : begin
  536.                 For I := 80 downto 1 do
  537.                 begin
  538.                     PartRestoreScreen(Page,
  539.                                       I,1,80,DisplayLines,
  540.                                       1,1);
  541.                 end;
  542.             end;
  543.     end; {case}
  544.     PosCursor(Screen[Page]^.CursorX,Screen[Page]^.CursorY);
  545.     SizeCursor(Screen[Page]^.ScanTop,Screen[Page]^.ScanBot);
  546. end;   {Proc SlideRestoreScreen}
  547.  
  548.  
  549. Procedure PartSlideRestoreScreen(Page:byte;Way:Direction;X1,Y1,X2,Y2:byte);
  550. {Display a screen that was previously saved, with fancy slide}
  551. Var I : byte;
  552. begin
  553.     If Screen[Page] = nil then
  554.     begin
  555.        WinTTT_Error(7);
  556.        exit;
  557.     end
  558.     else
  559.        W_error := 0;
  560.     Case Way of
  561.     Up    : begin
  562.                 For I := Y2 downto Y1 do
  563.                 begin
  564.                     PartRestoreScreen(Page,
  565.                                       X1,Y1,X2,Y1+Y2-I,
  566.                                       X1,I);
  567.                     Delay(50);
  568.                 end;
  569.             end;
  570.     Down  : begin
  571.                 For I := Y1 to Y2 do
  572.                 begin
  573.                     PartRestoreScreen(Page,
  574.                                       X1,Y1+Y2 -I,X2,Y2,
  575.                                       X1,Y1);
  576.                     Delay(50);  {savor the moment!}
  577.                 end;
  578.             end;
  579.     Left  : begin
  580.                 For I := X1 to X2 do
  581.                 begin
  582.                     PartRestoreScreen(Page,
  583.                                       X1,Y1,I,Y2,
  584.                                       X1+X2-I,Y1);
  585.                 end;
  586.             end;
  587.     Right : begin
  588.                 For I := X2 downto X1 do
  589.                 begin
  590.                     PartRestoreScreen(Page,
  591.                                       I,Y1,X2,Y2,
  592.                                       X1,Y1);
  593.                 end;
  594.             end;
  595.     end; {case}
  596. end;   {Proc PartSlideRestoreScreen}
  597.  
  598.  
  599. {++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  600. {                                                                              }
  601. {     V I R T U A L    S C R E E N    S P E C I F I C   P R O C E D U R E S    }
  602. {                                                                              }
  603. {++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  604.  
  605. Procedure Clear_Vscreen(page:byte);
  606. var
  607.    Tseg, Tofs : word;
  608. begin
  609.     If Screen[Page] = nil then
  610.     begin
  611.        WinTTT_Error(8);
  612.        exit;
  613.     end
  614.     else
  615.        W_error := 0;
  616.     Tseg := Vseg;
  617.     Tofs := Vofs;
  618.     Vseg := Seg(Screen[Page]^.ScreenPtr^);
  619.     Vofs := Ofs(Screen[Page]^.ScreenPtr^);
  620.     ClearText(1,1,80,Screen[Page]^.SavedLines,yellow,black);
  621.     Vseg := Tseg;
  622.     Vofs := Tofs;
  623. end;
  624.  
  625. Procedure CreateScreen(Page:byte;Lines:byte);
  626. begin
  627.     W_error := 0;
  628.     If (Page > Max_Screens) then
  629.     begin
  630.        WinTTT_Error(1);
  631.        exit;
  632.     end;
  633.     If ((Screen[Page] <> nil) and (Lines <> Screen[Page]^.SavedLines)) then
  634.         DisposeScreen(Page);
  635.     If Screen[Page] = nil then            {need to allocate memory}
  636.     begin
  637.         If MaxAvail < SizeOf(Screen[Page]^) then
  638.         begin
  639.             WinTTT_Error(3);
  640.             exit;
  641.         end;
  642.         GetMem(Screen[Page],SizeOf(Screen[Page]^));
  643.         If MaxAvail < Lines*160 then     {do check in two parts 'cos Maxavail is not same as MemAvail}
  644.         begin
  645.             WinTTT_Error(3);
  646.             Freemem(Screen[Page],SizeOf(Screen[Page]^));
  647.             Screen[Page] := nil;
  648.             exit;
  649.         end;
  650.         GetMem(Screen[Page]^.ScreenPtr,Lines*160);
  651.         Inc(ScreenCounter);
  652.     end;
  653.     With Screen[Page]^ do
  654.     begin
  655.         If BaseOfScreen = $B000 then
  656.         begin
  657.             ScanTop := 12;
  658.             ScanBot := 13;
  659.         end
  660.         else
  661.         begin
  662.             ScanTop := 6;
  663.             ScanBot := 7;
  664.         end;
  665.         CursorX := 1;
  666.         CursorY := 1;
  667.         SavedLines := Lines;
  668.         Clear_Vscreen(Page);
  669.     end;
  670. end;
  671.  
  672. Procedure Activate_Visible_Screen;
  673. begin
  674.     VSeg := BaseOfScreen;
  675.     VOfs := 0;
  676.     ActiveVscreen := 0;
  677. end;
  678.  
  679. Procedure Activate_Virtual_Screen(Page:byte);
  680. {Page zero signifies the visible screen}
  681. begin
  682.     If Screen[Page] = nil then
  683.        WinTTT_Error(4)
  684.     else
  685.     begin
  686.        W_error := 0;
  687.        If Page = 0 then
  688.           Activate_Visible_Screen
  689.        else
  690.        begin
  691.            VSeg := Seg(Screen[Page]^.ScreenPtr^);
  692.            VOfs := Ofs(Screen[Page]^.ScreenPtr^);
  693.            ActiveVScreen := page;
  694.        end;
  695.     end;
  696. end;
  697.  
  698. {++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  699. {                                                                              }
  700. {     V I S I B L E    S C R E E N    S P E C I F I C   P R O C E D U R E S    }
  701. {                                                                              }
  702. {++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  703.  
  704. Procedure SetCondensedLines;
  705. begin
  706.     If EGAVGASystem then
  707.     begin
  708.         W_Error := 0;
  709.         TextMode(Lo(LastMode)+Font8x8);
  710.         DisplayLines := succ(Hi(WindMax));
  711.     end
  712.     else
  713.         W_Error := 12;
  714. end;  {proc SetCondensedDisplay}
  715.  
  716. Procedure Set25Lines;
  717. begin
  718.     TextMode(Lo(LastMode));
  719.     DisplayLines := succ(Hi(WindMax));
  720. end;
  721.  
  722.  
  723. Procedure CopyScreenBlock(X1,Y1,X2,Y2,X,Y:byte);
  724. {copies text and attributes from one part of screen to another}
  725. Var
  726.    S : word;
  727.    SPtr : pointer;
  728. begin
  729.     W_error := 0;
  730.     S := succ(Y2-Y1)*succ(X2-X1)*2;
  731.     If Maxavail < S then
  732.        WinTTT_Error(9)
  733.     else
  734.     begin
  735.         GetMem(SPtr,S);
  736.         PartSave(X1,Y1,X2,Y2,SPtr^);
  737.         PartRestore(X,Y,X+X2-X1,Y+Y2-Y1,SPtr^);
  738.         FreeMem(Sptr,S);
  739.     end;
  740. end; {CopyScreenBlock}
  741.  
  742. Procedure MoveScreenBlock(X1,Y1,X2,Y2,X,Y:byte);
  743. {Moves text and attributes from one part of screen to another,
  744.  replacing with Replace_Char}
  745. const
  746.   Replace_Char = ' ';
  747. Var
  748.    S : word;
  749.    SPtr : pointer;
  750.    I : Integer;
  751.    ST : string;
  752. begin
  753.     W_error := 0;
  754.     S := succ(Y2-Y1)*succ(X2-X1)*2;
  755.     If Maxavail < S then
  756.        WinTTT_Error(9)
  757.     else
  758.     begin
  759.         GetMem(SPtr,S);
  760.         PartSave(X1,Y1,X2,Y2,SPtr^);
  761.         St := Replicate(succ(X2-X1),Replace_Char);
  762.         For I := Y1 to Y2 do
  763.             PlainWrite(X1,I,St);
  764.         PartRestore(X,Y,X+X2-X1,Y+Y2-Y1,SPtr^);
  765.         FreeMem(Sptr,S);
  766.     end;
  767. end; {Proc MoveScreenBlock}
  768.  
  769. Procedure Scroll(Way:direction;X1,Y1,X2,Y2:byte);
  770. {used for screen scrolling, uses Copy & Plainwrite for speed}
  771. const
  772.   Replace_Char = ' ';
  773. var
  774.   I : integer;
  775. begin
  776.     W_error := 0;
  777.     Case Way of
  778.     Up   : begin
  779.                CopyScreenBlock(X1,succ(Y1),X2,Y2,X1,Y1);
  780.                PlainWrite(X1,Y2,replicate(succ(X2-X1),Replace_Char));
  781.            end;
  782.     Down : begin
  783.                CopyScreenBlock(X1,Y1,X2,pred(Y2),X1,succ(Y1));
  784.                PlainWrite(X1,Y1,replicate(succ(X2-X1),Replace_Char));
  785.            end;
  786.     Left : begin
  787.                CopyScreenBlock(succ(X1),Y1,X2,Y2,X1,Y1);
  788.                For I := Y1 to Y2 do
  789.                    PlainWrite(X2,1,Replace_Char);
  790.            end;
  791.     Right: begin
  792.                CopyScreenBlock(X1,Y1,pred(X2),Y2,succ(X1),Y1);
  793.                For I := Y1 to Y2 do
  794.                    PlainWrite(X1,1,Replace_Char);
  795.            end;
  796.     end; {case}
  797. end;
  798.  
  799. procedure CreateWin(x1,y1,x2,y2,F,B,boxtype:integer);
  800. {called by MkWin and GrowMkWin}
  801. begin
  802.     If WindowCounter >= Max_Windows then
  803.     begin
  804.        WinTTT_Error(2);
  805.        exit;
  806.     end;
  807.     If MaxAvail < sizeOf(Win[WindowCounter]^) then
  808.     begin
  809.        WinTTT_Error(3);
  810.        exit;
  811.     end
  812.     else
  813.        W_error := 0;
  814.     Inc(WindowCounter);
  815.     GetMem(Win[WindowCounter],sizeof(Win[WindowCounter]^));    {allocate space}
  816.     If (BoxType in [5..9]) and (X1 > 1) then     {is there a drop shadow}
  817.     begin
  818.         X1 := pred(X1);    {increase dimensions for the box}
  819.         Y2 := succ(Y2);
  820.     end;
  821.     If MaxAvail < succ(Y2-Y1)*succ(X2-X1)*2 then
  822.     begin
  823.        WinTTT_Error(3);
  824.        exit;
  825.     end;
  826.     GetMem(Win[WindowCounter]^.ScreenPtr,succ(Y2-Y1)*succ(X2-X1)*2);
  827.     PartSave(X1,Y1,X2,Y2,Win[WindowCounter]^.ScreenPtr^);
  828.     with Win[WindowCounter]^ do
  829.     begin
  830.       Coord[1] := X1;
  831.       Coord[2] := Y1;
  832.       Coord[3] := X2;
  833.       Coord[4] := Y2;
  834.       FindCursor(CursorX,CursorY,ScanTop,ScanBot);
  835.     end;  {with}
  836. end; {Proc CreateWin}
  837.  
  838. procedure mkwin(x1,y1,x2,y2,F,B,boxtype:integer);
  839. {Main procedure for creating window}
  840. var I : integer;
  841. begin
  842.     If ActiveVscreen <> 0 then
  843.     begin
  844.         W_error := 10;
  845.         exit;
  846.     end
  847.     else
  848.         W_error := 0;
  849.     CreateWin(X1,Y1,X2,Y2,F,B,Boxtype);
  850.     If (BoxType in [5..9]) and (X1 > 1) then
  851.        FBox(x1,y1,x2,y2,F,B,boxtype-shadow)
  852.     else
  853.        FBox(x1,y1,x2,y2,F,B,boxtype);
  854.     If (BoxType in [5..9]) and (X1 > 1) then     {is there a drop shadow}
  855.     begin
  856.         For I := succ(Y1) to succ(Y2) do
  857.             WriteAt(pred(X1),I,Shadcolor,black,chr(219));
  858.         WriteAt(X1,succ(Y2),Shadcolor,black,
  859.                 replicate(X2-succ(X1),chr(219)));
  860.     end;
  861. end;
  862.  
  863. procedure GrowMKwin(x1,y1,x2,y2,F,B,boxtype:integer);
  864. {same as MKwin but window explodes}
  865. var I : integer;
  866. begin
  867.     If ActiveVscreen <> 0 then
  868.     begin
  869.         W_error := 10;
  870.         exit;
  871.     end
  872.     else
  873.         W_error := 0;
  874.     CreateWin(X1,Y1,X2,Y2,F,B,Boxtype);
  875.     If (BoxType in [5..9]) and (X1 > 1) then
  876.        GrowFBox(x1,y1,x2,y2,F,B,boxtype-shadow)
  877.     else
  878.        GrowFBox(x1,y1,x2,y2,F,B,boxtype);
  879.     If (BoxType in [5..9]) and (X1 > 1) then     {is there a drop shadow}
  880.     begin
  881.         For I := succ(Y1) to succ(Y2) do
  882.             WriteAt(pred(X1),I,Shadcolor,black,chr(219));
  883.         WriteAt(X1,succ(Y2),Shadcolor,black,
  884.                 replicate(X2-succ(X1),chr(219)));
  885.     end;
  886. end;
  887.  
  888. Procedure RmWin;
  889. begin
  890.     If ActiveVscreen <> 0 then
  891.     begin
  892.         W_error := 10;
  893.         exit;
  894.     end
  895.     else
  896.         W_error := 0;
  897.     If WindowCounter > 0 then
  898.     begin
  899.         with  Win[WindowCounter]^ do
  900.         begin
  901.             PartRestore(Coord[1],Coord[2],Coord[3],Coord[4],ScreenPtr^);
  902.             PosCursor(CursorX,CursorY);
  903.             SizeCursor(ScanTop,ScanBot);
  904.             FreeMem(ScreenPtr,succ(Coord[4]-coord[2])*succ(coord[3]-coord[1])*2);
  905.             FreeMem(Win[WindowCounter],sizeof(Win[WindowCounter]^));
  906.         end; {with}
  907.         Dec(WindowCounter);
  908.     end;
  909. end;
  910.  
  911. procedure TempMessageCh(X,Y,F,B:integer;St:strscreen;var Ch : char);
  912. var
  913.  CX,CY,CT,CB,I,locC:integer;
  914.  SavedLine : array[1..160] of byte;
  915. begin
  916.     If ActiveVscreen <> 0 then
  917.     begin
  918.         W_error := 11;
  919.         exit;
  920.     end
  921.     else
  922.         W_error := 0;
  923.     PartSave(X,Y,pred(X)+length(St),Y,SavedLine);
  924.     WriteAT(X,Y,F,B,St);
  925.     Ch := GetKey;
  926.     PartRestore(X,Y,pred(X)+length(St),Y,SavedLine);
  927. end;
  928.  
  929. Procedure TempMessage(X,Y,F,B:integer;St:strscreen);
  930. var Ch : char;
  931. begin
  932.     TempMessageCH(X,Y,F,B,ST,Ch);
  933. end;              
  934.  
  935. Procedure TempMessageBoxCh(X1,Y1,F,B,BoxType:integer;St:strscreen;var Ch : char);
  936. begin
  937.     If ActiveVscreen <> 0 then
  938.     begin
  939.         W_error := 11;
  940.         exit;
  941.     end
  942.     else
  943.         W_error := 0;
  944.     MkWin(X1,Y1,succ(X1)+length(St),Y1+2,F,B,Boxtype);
  945.     WriteAt(succ(X1),Succ(Y1),F,B,St);
  946.     Ch := getKey;
  947.     Rmwin;
  948. end;
  949.  
  950. Procedure TempMessageBox(X1,Y1,F,B,BoxType:integer;St:strscreen);
  951. var Ch : char;
  952. begin
  953.     TempMessageBoxCh(X1,Y1,F,B,Boxtype,St,Ch);
  954. end;
  955.  
  956. {++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  957.  
  958. Procedure InitWinTTT;
  959. {set Pointers to nil for validity checking}
  960. Var
  961.   I : integer;
  962.   X,Y : byte;
  963. begin
  964.     For I := 1 to Max_Screens do
  965.         Screen[I] := nil;
  966.     StartMode := LastMode;           { record the initial state of screen when program was executed}
  967.     DisplayLines := succ(Hi(WindMax));
  968.     FindCursor(X,Y,StartTop,StartBot);
  969. end;
  970.  
  971.  
  972. Procedure Reset_StartUp_Mode;
  973. {resets monitor mode and cursor settings to the state they
  974.  were in at program startup}
  975. begin
  976.     TextMode(StartMode);
  977.     SizeCursor(StartTop,StartBot);
  978. end; {proc StartUp_Mode}
  979.  
  980. begin
  981.     InitWinTTT;
  982.     W_error := 0;
  983.     W_fatal := false;   {don't terminate program if fatal error}
  984.     Shadcolor := darkgray;
  985. end.
  986.