home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / TTT405.ZIP / WINTTT.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1988-07-17  |  14.7 KB  |  506 lines

  1. { $S-,R-,V-,D-,T-}
  2. {\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\}
  3. {         TechnoJocks Turbo Toolkit v4.05           Released: Jul 18, 1988    }
  4. {                                                                             }
  5. {         Module: WinTTT   --   screen saving, cursor and windowing procs     }
  6. {                                                                             }
  7. {                  Copyright R. D. Ainsbury (c) 1986-88                       }
  8. {\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\}
  9.  
  10. unit WinTTT;
  11.  
  12. interface
  13.  
  14. uses CRT,FastTTT,DOS;
  15.  
  16. Type
  17.  Direction = (Up, Down, Left, Right);
  18. Const
  19.  Shadow = 5;
  20. Var
  21.  Shadcolor : byte;
  22.  
  23. Procedure MoveFromScreen(var Source,Dest;Length:Word);
  24. Procedure MoveToScreen(var Source,Dest; Length:Word);
  25. Procedure Attrib(X1,Y1,X2,Y2,F,B:byte);
  26. Procedure SizeCursor(ScanTop,ScanBot:byte);
  27. Procedure FindCursor(var X,Y,ScanTop,ScanBot:byte);
  28. Procedure PosCursor(X,Y: integer);
  29. Procedure Fullcursor;
  30. Procedure HalfCursor;
  31. Procedure OnCursor;
  32. Procedure OffCursor;
  33. Procedure SaveScreen(Page:byte);
  34. Procedure RestoreScreen(Page:byte);
  35. Procedure PartRestoreScreen(Page,X1,Y1,X2,Y2,X,Y:byte);
  36. Procedure SlideRestoreScreen(Page:byte;Way:Direction);
  37. Procedure DisposeScreen(Page:byte);
  38. Procedure CopyScreenBlock(X1,Y1,X2,Y2,X,Y:byte);
  39. Procedure MoveScreenBlock(X1,Y1,X2,Y2,X,Y:byte);
  40. Procedure ScrollUp(X1,Y1,X2,Y2:byte);
  41. Procedure PartSave (X1,Y1,X2,Y2:byte; VAR Dest);
  42. Procedure PartRestore (X1,Y1,X2,Y2:byte; VAR Source);
  43. Procedure Mkwin(x1,y1,x2,y2,F,B,boxtype:integer);
  44. Procedure GrowMkwin(x1,y1,x2,y2,F,B,boxtype:integer);
  45. Procedure Rmwin;
  46. Procedure FillScreen(X1,Y1,X2,Y2:byte; F,B:byte; C:char);
  47. Procedure TempMessage(X,Y,F,B:integer;St:string);
  48.  
  49. implementation
  50.  
  51. Const
  52.     Max_Windows = 10;          {Change this constant as necessary}
  53.     Max_Screens = 10;          {Change this constant as necessary}
  54.     WindowCounter : byte = 0;
  55.     ScreenCounter : byte = 0;
  56.     DisplayLines = 25;         {Change this constant as necessary}
  57.     Screen_Size = 4000;        {Change this to 8000 for VGA 50 line Mode}
  58.     MonoAdr =$b000;
  59. Type
  60.     Image = array[1..DisplayLines,1..80] of word;
  61.     ScreenImage = record
  62.                        ScreenSnap: Image;
  63.                        CursorX : byte;
  64.                        CursorY : byte;
  65.                        ScanTop : byte;
  66.                        ScanBot : byte;
  67.                   end;
  68.     ScreenPtr = ^ScreenImage;
  69.     WindowImage = record
  70.                        ScreenPtr: Pointer;             {pointer to screen data}
  71.                        Coord    : array[1..4] of byte; {window coords}
  72.                        CursorX  : byte;                {cursor location}
  73.                        CursorY  : byte;
  74.                        ScanTop  : byte;                {cursor shape}
  75.                        ScanBot  : byte;
  76.                   end;
  77.     WindowPtr = ^WindowImage;
  78.  
  79. Var
  80.     Screen : array[1..Max_Screens] of ScreenPtr;
  81.     Win    : array[1..Max_Windows] of WindowPtr;
  82.  
  83.  
  84. {$L WINTTT}
  85.  
  86. {$F+}
  87.   Procedure Attribute(Col,Row,Attr:byte; Number:Word); external;
  88.   Procedure MoveFromScreen(var Source,Dest;Length:Word); external;
  89.   Procedure MoveToScreen(var Source,Dest; Length:Word); external;
  90. {$F-}
  91.  
  92. Procedure WinTTT_Error(No : byte);
  93. {Display error message and halts program}
  94. var Msg : String;
  95. begin
  96.     Case No of
  97.     1 : Msg := '1) -- Max_Screens exceeded.';
  98.     2 : Msg := '2) -- Screen not previously saved, cannot Restore.';
  99.     3 : Msg := '3) -- Screen not previously saved, cannot Dispose.';
  100.     4 : Msg := '4) -- Max_Windows exceeded.';
  101.     5 : Msg := '5) -- Insufficient memory to create window.';
  102.     else Msg := '?) -- Utterly confused';
  103.     end; {Case}
  104.     Msg := 'Fatal Error (WinTTT No. '+Msg;
  105.     Writeln(Msg);
  106.     Delay(5000);    {display long enough to read if child process}
  107.     Halt;
  108. end;
  109.  
  110. Procedure Attrib(X1,Y1,X2,Y2,F,B:byte);
  111. {changes color attrib at specified coords}
  112. var
  113.   I,X,A : byte;
  114. begin
  115.     A := Attr(F,B);
  116.     X := Succ(X2-X1);
  117.     For I := Y1 to Y2 do
  118.         Attribute(X1,I,A,X);
  119. end; {Proc Attrib}
  120.  
  121. Procedure FindCursor(var X,Y,ScanTop,ScanBot:byte);
  122. var
  123.    Reg : registers;
  124. begin
  125.   Reg.Ax := $0F00;              {get page in Bx}
  126.   Intr($10,Reg);
  127.   Reg.Ax := $0300;
  128.   Intr($10,Reg);
  129.   With Reg do
  130.   begin
  131.     X := lo(Dx) + 1;
  132.     Y := hi(Dx) + 1;
  133.     ScanTop := Hi(Cx) and $0F;
  134.     ScanBot := Lo(Cx) and $0F;
  135.   end;
  136. end;
  137.  
  138. Procedure PosCursor(X,Y: integer);
  139. var Reg : registers;
  140. begin
  141.   Reg.Ax := $0F00;              {get page in Bx}
  142.   Intr($10,Reg);
  143.   with Reg do
  144.   begin
  145.     Ax := $0200;
  146.     Dx := ((Y-1) shl 8) or ((X-1) and $00FF);
  147.   end;
  148.   Intr($10,Reg);
  149. end;
  150.  
  151. Procedure SizeCursor(ScanTop,ScanBot:byte);
  152. var Reg : registers;
  153. begin
  154.     with Reg do
  155.     begin
  156.       ax := 1 shl 8;
  157.       cx := Scantop shl 8 + Scanbot;
  158.       INTR($10,Reg);
  159.     end;
  160. end;
  161.  
  162. Procedure HalfCursor;
  163. begin
  164.     If BaseOfScreen = MonoAdr then
  165.        SizeCursor(8,13)
  166.     else
  167.        SizeCursor(5,7);
  168. end; {Proc HalfCursor}
  169.  
  170. Procedure Fullcursor;
  171. begin
  172.     If BaseOfScreen = MonoAdr then
  173.        SizeCursor(0,13)
  174.     else
  175.        SizeCursor(0,7);
  176. end;
  177.  
  178. Procedure OnCursor;
  179. begin
  180.     If BaseOfScreen = MonoAdr then
  181.        SizeCursor(12,13)
  182.     else
  183.        SizeCursor(6,7);
  184. end;
  185.  
  186. Procedure OffCursor;
  187. begin
  188.     Sizecursor(14,0);
  189. end;
  190.  
  191.  
  192. Procedure FillScreen(X1,Y1,X2,Y2:byte; F,B:byte; C:char);
  193. var
  194.    I : integer;
  195.    S : string;
  196. begin
  197.     Attrib(X1,Y1,X2,Y2,F,B);
  198.     S := Replicate(Succ(X2-x1),C);
  199.     For I := Y1 to Y2 do
  200.         PlainWrite(X1,I,S);
  201. end;
  202.  
  203. {
  204. ****************************
  205. * Screen Saving Procedures *
  206. ****************************
  207. }
  208. Procedure Initialize_Screens;
  209. {set Pointers to nil for validity check in RestoreScreen}
  210. Var I : integer;
  211. begin
  212.  For I := 1 to Max_Screens do
  213.   Screen[I] := nil;
  214. end;
  215.  
  216. Procedure PartSave (X1,Y1,X2,Y2:byte; VAR Dest);
  217. {transfers data from video display to Dest}
  218. var
  219.    I,width : byte;
  220.    ScreenAdr: integer;
  221. begin
  222.     width := succ(X2- X1);
  223.     For I :=  Y1 to Y2 do
  224.     begin
  225.      SCreenAdr := Pred(I)*160 + Pred(X1)*2;
  226.      MoveFromScreen(Mem[BaseOfScreen:ScreenAdr],
  227.                     Mem[seg(Dest):ofs(dest)+(I-Y1)*width*2],
  228.                     width);
  229.     end;
  230. end;
  231.  
  232. Procedure PartRestore (X1,Y1,X2,Y2:byte; VAR Source);
  233. {restores data from Source and transfers to video display}
  234. var
  235.    I,width : byte;
  236.    ScreenAdr: integer;
  237. begin
  238.     width := succ(X2- X1);
  239.     For I :=  Y1 to Y2 do
  240.     begin
  241.      ScreenAdr := Pred(I)*160 + Pred(X1)*2;
  242.      MoveToScreen(Mem[Seg(Source):ofs(Source)+(I-Y1)*width*2],
  243.                   Mem[BaseOfScreen:ScreenAdr],
  244.                   width);
  245.     end;
  246. end;
  247.  
  248. Procedure SaveScreen(Page:byte);
  249. {Save screen display and cursor details}
  250. begin
  251.     If (Page > Max_Screens) then
  252.       WinTTT_Error(1);
  253.     If MaxAvail < Screen_Size then
  254.        WinTTT_Error(5);
  255.     GetMem(Screen[Page],Screen_Size);
  256.     MoveFromScreen(Mem[BaseOfScreen:0],Screen[Page]^.ScreenSnap, Screen_Size div 2);
  257.     FindCursor(Screen[Page]^.CursorX,         {Save Cursor posn. and shape}
  258.                Screen[Page]^.CursorY,
  259.                Screen[Page]^.ScanTop,
  260.                Screen[Page]^.ScanBot);
  261. end;
  262.  
  263. Procedure RestoreScreen(Page:byte);
  264. {Display a screen that was previously saved}
  265. begin
  266.     If Screen[Page] = nil then
  267.        WinTTT_Error(2);
  268.         MoveToScreen(Screen[Page]^.ScreenSnap,mem[BaseOfScreen:0], Screen_Size div 2);
  269.     PosCursor(Screen[Page]^.CursorX,Screen[Page]^.CursorY);
  270.     SizeCursor(Screen[Page]^.ScanTop,Screen[Page]^.ScanBot);
  271. end;  {Proc RestoreScreen}
  272.  
  273.  
  274. Procedure PartRestoreScreen(Page,X1,Y1,X2,Y2,X,Y:byte);
  275. {Move from heap to screen, part of saved screen}
  276. Var
  277.    I,width     : byte;
  278.    ScreenAdr,
  279.    PageAdr     : integer;
  280. begin
  281.     If Screen[Page] = nil then
  282.        WinTTT_Error(2);
  283.     Width := succ(X2- X1);
  284.     For I :=  Y1 to Y2 do
  285.     begin
  286.         ScreenAdr := pred(Y+I-Y1)*160 + Pred(X)*2;
  287.         PageAdr   := Pred(I)*160 + Pred(X1)*2;
  288.         MoveToScreen(Mem[Seg(Screen[Page]^):ofs(Screen[Page]^)+PageAdr],
  289.                      Mem[BaseOfScreen:ScreenAdr],
  290.                      width);
  291.     end;
  292. end;
  293.  
  294. Procedure SlideRestoreScreen(Page:byte;Way:Direction);
  295. {Display a screen that was previously saved, with fancy slide}
  296. Var I : byte;
  297. begin
  298.     If Screen[Page] = nil then
  299.        WinTTT_Error(2);
  300.     Case Way of
  301.     Up    : begin
  302.                 For I := DisplayLines downto 1 do
  303.                 begin
  304.                     PartRestoreScreen(Page,
  305.                                       1,1,80,succ(DisplayLines -I),
  306.                                       1,I);
  307.                     Delay(50);
  308.                 end;
  309.             end;
  310.     Down  : begin
  311.                 For I := 1 to DisplayLines do
  312.                 begin
  313.                     PartRestoreScreen(Page,
  314.                                       1,succ(DisplayLines -I),80,DisplayLines,
  315.                                       1,1);
  316.                     Delay(50);  {savor the moment!}
  317.                 end;
  318.             end;
  319.     Left  : begin
  320.                 For I := 1 to 80 do
  321.                 begin
  322.                     PartRestoreScreen(Page,
  323.                                       1,1,I,DisplayLines,
  324.                                       succ(80-I),1);
  325.                 end;
  326.             end;
  327.     Right : begin
  328.                 For I := 80 downto 1 do
  329.                 begin
  330.                     PartRestoreScreen(Page,
  331.                                       I,1,80,DisplayLines,
  332.                                       1,1);
  333.                 end;
  334.             end;
  335.     end; {case}
  336.     PosCursor(Screen[Page]^.CursorX,Screen[Page]^.CursorY);
  337.     SizeCursor(Screen[Page]^.ScanTop,Screen[Page]^.ScanBot);
  338. end;   {Proc SlideRestoreScreen}
  339.  
  340. Procedure DisposeScreen(Page:byte);
  341. {Free memory that was allocated by SvaeScreen}
  342. begin
  343.     If Screen[Page] = nil then
  344.        WinTTT_Error(3);
  345.     FreeMem(Screen[Page],Screen_Size);
  346. end;
  347.  
  348. Procedure CopyScreenBlock(X1,Y1,X2,Y2,X,Y:byte);
  349. {copies text and attributes from one part of screen to another}
  350. Var
  351.    I,width     : byte;
  352.    SourceAdr,
  353.    TargetAdr   : integer;
  354.    TempLine    : array[1..160] of byte;
  355. begin
  356.     Width := succ(X2- X1);
  357.     For I :=  Y1 to Y2 do
  358.     begin
  359.         SourceAdr := Pred(I)*160 + Pred(X1)*2;
  360.         TargetAdr := Pred(Y+I-Y1)*160 + Pred(X)*2;
  361.         MoveFromScreen(Mem[BaseOfScreen:SourceAdr],
  362.                        TempLine,
  363.                        width);
  364.         MoveToScreen(TempLine,
  365.                      Mem[BaseOfScreen:TargetAdr],
  366.                      width);
  367.     end;
  368. end; {CopyScreenBlock}
  369.  
  370. Procedure MoveScreenBlock(X1,Y1,X2,Y2,X,Y:byte);
  371. {Moves text and attributes from one part of screen to another,
  372.  replacing with Replace_Char}
  373. const
  374.   Replace_Char = ' ';
  375. Var
  376.    I,width     : byte;
  377.    SourceAdr,
  378.    TargetAdr   : integer;
  379.    TempLine    : array[1..160] of byte;
  380. begin
  381.     Width := succ(X2- X1);
  382.     For I :=  Y1 to Y2 do
  383.     begin
  384.         SourceAdr := Pred(I)*160 + Pred(X1)*2;
  385.         TargetAdr := Pred(Y+I-Y1)*160 + Pred(X)*2;
  386.         MoveFromScreen(Mem[BaseOfScreen:SourceAdr],
  387.                        TempLine,
  388.                        width);
  389.         PlainWrite(X1,I,replicate(succ(X2-X1),Replace_Char));
  390.         MoveToScreen(TempLine,
  391.                      Mem[BaseOfScreen:TargetAdr],
  392.                      width);
  393.     end;
  394. end; {Proc MoveScreenBlock}
  395.  
  396. Procedure ScrollUp(X1,Y1,X2,Y2:byte);
  397. {used for screen scrolling, uses Copy & Plainwrite rather than Move for speed}
  398. const
  399.   Replace_Char = ' ';
  400. begin
  401.   CopyScreenBlock(X1,succ(Y1),X2,Y2,X1,Y1);
  402.   PlainWrite(X1,Y2,replicate(succ(X2-X1),Replace_Char));
  403. end;
  404.  
  405. {
  406. ****************************
  407. *   Windowing Procedures   *
  408. ****************************
  409. }
  410.  
  411. procedure CreateWin(x1,y1,x2,y2,F,B,boxtype:integer);
  412. {called by MkWin and GrowMkWin}
  413. begin
  414.     If WindowCounter >= Max_Windows then
  415.        WinTTT_Error(4);
  416.     WindowCounter :=  WindowCounter + 1;
  417.     If MaxAvail < sizeOf(Win[WindowCounter]^) then
  418.        WinTTT_Error(5);
  419.     GetMem(Win[WindowCounter],sizeof(Win[WindowCounter]^));    {allocate space}
  420.     If (BoxType in [5..9]) and (X1 > 1) then     {is there a drop shadow}
  421.     begin
  422.         X1 := pred(X1);    {increase dimensions for the box}
  423.         Y2 := succ(Y2);
  424.     end;
  425.     If MaxAvail < succ(Y2-Y1)*succ(X2-X1)*2 then
  426.        WinTTT_Error(5);
  427.     GetMem(Win[WindowCounter]^.ScreenPtr,succ(Y2-Y1)*succ(X2-X1)*2);
  428.     PartSave(X1,Y1,X2,Y2,Win[WindowCounter]^.ScreenPtr^);
  429.     with Win[WindowCounter]^ do
  430.     begin
  431.       Coord[1] := X1;
  432.       Coord[2] := Y1;
  433.       Coord[3] := X2;
  434.       Coord[4] := Y2;
  435.       FindCursor(CursorX,CursorY,ScanTop,ScanBot);
  436.     end;  {with}
  437. end; {Proc CreateWin}
  438.  
  439. procedure mkwin(x1,y1,x2,y2,F,B,boxtype:integer);
  440. {Main procedure for creating window}
  441. var I : integer;
  442. begin
  443.     CreateWin(X1,Y1,X2,Y2,F,B,Boxtype);
  444.     If (BoxType in [5..9]) and (X1 > 1) then
  445.        FBox(x1,y1,x2,y2,F,B,boxtype-shadow)
  446.     else
  447.        FBox(x1,y1,x2,y2,F,B,boxtype);
  448.     If (BoxType in [5..9]) and (X1 > 1) then     {is there a drop shadow}
  449.     begin
  450.         For I := succ(Y1) to succ(Y2) do
  451.             WriteAt(pred(X1),I,Shadcolor,black,' ');
  452.         WriteAt(X1,succ(Y2),Shadcolor,black,
  453.                 replicate(X2-succ(X1),' '));
  454.     end;
  455. end;
  456.  
  457. procedure GrowMKwin(x1,y1,x2,y2,F,B,boxtype:integer);
  458. {same as MKwin but window explodes}
  459. var I : integer;
  460. begin
  461.     CreateWin(X1,Y1,X2,Y2,F,B,Boxtype);
  462.     If (BoxType in [5..9]) and (X1 > 1) then
  463.        GrowFBox(x1,y1,x2,y2,F,B,boxtype-shadow)
  464.     else
  465.        GrowFBox(x1,y1,x2,y2,F,B,boxtype);
  466.     If (BoxType in [5..9]) and (X1 > 1) then     {is there a drop shadow}
  467.     begin
  468.         For I := succ(Y1) to succ(Y2) do
  469.             WriteAt(pred(X1),I,Shadcolor,black,' ');
  470.         WriteAt(X1,succ(Y2),Shadcolor,black,
  471.                 replicate(X2-succ(X1),' '));
  472.     end;
  473. end;
  474.  
  475. Procedure RmWin;
  476. begin
  477.     If WindowCounter > 0 then
  478.     begin
  479.         with  Win[WindowCounter]^ do
  480.         begin
  481.             PartRestore(Coord[1],Coord[2],Coord[3],Coord[4],ScreenPtr^);
  482.             PosCursor(CursorX,CursorY);
  483.             SizeCursor(ScanTop,ScanBot);
  484.             FreeMem(ScreenPtr,succ(Coord[4]-coord[2])*succ(coord[3]-coord[1])*2);
  485.             FreeMem(Win[WindowCounter],sizeof(Win[WindowCounter]^));
  486.         end; {with}
  487.         WindowCounter := WindowCounter - 1;
  488.     end;
  489. end;
  490.  
  491. procedure TempMessage(X,Y,F,B:integer;St:string);
  492. var
  493.  CX,CY,CT,CB,I,locC:integer;
  494.  SavedLine : array[1..160] of byte;
  495.  Ch :char;
  496. begin
  497.     PartSave(X,Y,pred(X)+length(St),Y,SavedLine);
  498.     WriteAT(X,Y,F,B,St);
  499.     Ch := ReadKey;
  500.     PartRestore(X,Y,pred(X)+length(St),Y,SavedLine);
  501. end;
  502.  
  503. begin
  504.     Initialize_Screens;
  505.     Shadcolor := darkgray;
  506. end.