home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / TP_ADV.ZIP / LIST0907.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1989-11-17  |  8.8 KB  |  287 lines

  1. Unit WindTool;
  2.  
  3. Interface
  4.  
  5. Uses
  6.   CRT,
  7.   DOS;
  8.  
  9. Type
  10.   BorderType = Byte;
  11.  
  12. Var
  13.   { The width of the screen in the current video mode }
  14.   VidWidth : Word;
  15.  
  16.   { The base offset of display memory of the current display }
  17.   BaseAddr : Word;
  18.  
  19.   { To control the sound on or off based on TRUE or FALSE }
  20.   SoundOn  : Boolean;
  21.  
  22. Procedure OpenWindow ( X1, Y1, X2, Y2 : Byte; Border : BorderType;
  23.                        BorderColor : Word; Title : String );
  24.  
  25. Procedure CloseWindow;
  26.  
  27. Procedure MoveNoSnow (  Count : Word; FromAddr, ToAddr : Pointer );
  28.  
  29. Procedure MoveFast ( Count : Word; FromAddr, ToAddr : Pointer );
  30.  
  31. Procedure MovWindow ( ToScreen : Boolean; X1, Y1, X2, Y2 : Word;
  32.                       Buff : Pointer );
  33.  
  34. Procedure DoBorder ( X1, Y1, X2, Y2 : Byte; Border : BorderType;
  35.                      BorderColor : Word; Title : String );
  36.  
  37. Procedure DefineBorder ( Num : Byte; UpLeft, UpRight, BtmLeft, BtmRight,
  38.                          HorizLine, VertLine, BegTitle, EndTitle : Char );
  39.  
  40. Procedure WindowSound ( Open : Boolean );
  41.  
  42. Procedure GetVideoAddress;
  43.  
  44. Function GetWindowSize ( X1, Y1, X2, Y2 : Word ) : Word;
  45.  
  46. Implementation
  47.  
  48. Const
  49.   MaxStack = 1000;  { Largest size for window stack }
  50.   MaxBorders = 4;
  51.  
  52. Type
  53.   BorderRec    = Record
  54.                    UL, UR, BL, BR,
  55.                    HL, VL,
  56.                    BT, ET : Char;
  57.                  End;
  58.   BorderArray  = Array [ 1..MaxBorders ] of BorderRec;
  59.   StackElement = Record
  60.                    sX1, sY1,
  61.                    sX2, sY2 : Byte;
  62.                    sBuff : Pointer;
  63.                  End;
  64.   StackType    = Array [0..MaxStack] of StackElement;
  65.  
  66. Var
  67.   BArr      : BorderArray;
  68.   Stack     : StackType;
  69.   StackPtr  : Word;
  70.  
  71. {$L WindTool.obj}
  72.  
  73. {$F+}
  74. Procedure MoveNoSnow; External;
  75.  
  76. Procedure MoveFast; External;
  77.  
  78. Procedure MovWindow; External;
  79. {$F-}
  80.  
  81. Procedure ReportError ( s : String );
  82. { Brut force error checking. If an error occurs, clear the screen and  }
  83. { report problem, then terminate program. This is more for development }
  84. { error reporting then a shipping error generater.                     }
  85. Begin
  86.   ClrScr;
  87.   WriteLn ( s );
  88.   Halt ( 1 );
  89. End;
  90.  
  91. Function GetWindowSize;
  92. { Calculate the total amount of memory needed to store the window, }
  93. { character and attribute.                                         }
  94. Begin
  95.   GetWindowSize := ( X2 - X1 + 1 ) * ( Y2 - Y1 + 1 ) * 2;
  96. End;
  97.  
  98. Procedure PushWindow ( pX1,pY1,pX2,pY2 : Byte );
  99. { Allocate memory on the internal window stack for the window, then }
  100. { save the memory in that area.                                     }
  101. Begin
  102.   If ( StackPtr = 0 ) Then      { Special case. If it is the first window   }
  103.   Begin                         { opened, get the current windowcoordinates.}
  104.     With Stack [ StackPtr ] Do
  105.     Begin
  106.       sX1 := Lo ( WindMin ) + 1;
  107.       sY1 := Hi ( WindMin ) + 1;
  108.       sX2 := Lo ( WindMax ) + 1;
  109.       sY2 := Hi ( WindMax ) + 1;
  110.     End;
  111.   End;
  112.   Inc ( StackPtr );             { Increment the stack pointer }
  113.   With Stack [ StackPtr ] Do    { Store the X,Y coordinates }
  114.   Begin
  115.     sX1 := pX1;
  116.     sY1 := pY1;
  117.     sX2 := pX2;
  118.     sY2 := pY2;
  119.                                { Allocate storage for window }
  120.     GetMem ( sBuff, GetWindowSize ( sX1, sY1, sX2, sY2 ) );
  121.     If ( sBuff = NIL ) Then
  122.       ReportError ( 'No heap left for window allocation.' );
  123.                                { Move window into storage area }
  124.     MovWindow ( FALSE, sX1, sY1, sX2, sY2, sBuff );
  125.   End;
  126. End;
  127.  
  128. Procedure PopWindow;
  129. Begin
  130.   With WindTool.Stack [ WindTool.StackPtr ] Do
  131.   Begin
  132.                                { Resore the window information }
  133.     MovWindow ( TRUE, sX1, sY1, sX2, sY2, sBuff );
  134.                                { Release heap storage }
  135.     FreeMem ( sBuff, GetWindowSize ( sX1, sY1, sX2, sY2 ) );
  136.   End;
  137.   Dec ( StackPtr );            { Decrement the stack pointer }
  138. End;
  139.  
  140. Procedure DoBorder;
  141. Var
  142.   i : Integer;
  143.   s : String;
  144.   tmp : Word;
  145. Begin
  146.   tmp := TextAttr;                          { Save the current screencolors }
  147.   TextColor ( Lo ( BorderColor ) );         { Set color for border }
  148.   TextBackground ( Hi ( BorderColor ) );    { " }
  149.   Window ( 1, 1, 80, 25 );                  { Set window to entire screen }
  150.   If ( Border > MaxBorders ) OR ( Border < 0 ) Then
  151.     Border := 1;
  152.   s := BArr [ Border ].UL;              { Build top line of window border }
  153.   For i := 1 to ( X2 - X1 - 1 ) Do      { " }
  154.     s := s + BArr [ Border ].HL;        { " }
  155.   s := s + BArr [ Border ].UR;          { " }
  156.   GotoXY ( X1, Y1 );                    { Print top line of window border }
  157.   Write ( s );
  158.   i := Length ( s );
  159.   s [ 1 ] := BArr [ Border ].BL;        { Build bottom line of windowborder }
  160.   s [ i ] := BArr [ Border ].BR;        { " }
  161.   GotoXY ( X1, Y2 );                    { Print bottom line of border }
  162.   Write ( s );
  163.   FillChar ( s, i, ' ' );               { Build center of window }
  164.   s [ 0 ] := Chr ( i );                 { " }
  165.   s [ 1 ] := BArr [ Border ].VL;        { " }
  166.   s [ Length ( s ) ] := BArr [ Border ].VL; { " }
  167.   For i := ( Y1 + 1 ) to ( Y2 - 1 ) Do
  168.   Begin
  169.     GotoXY ( X1, i );                   { Loop and print center of window }
  170.     Write ( s );
  171.   End;
  172.  
  173.   { Build Title string }
  174.   If ( Length ( Title ) > 0 ) Then      { If title string is not zero, }
  175.   Begin                                 { dont draw a title string.    }
  176.     If ( Length ( Title ) > ( X2 - X1 - 3 ) ) Then  { If string larger than}
  177.       Title [0] := Chr ( X2 - X1 - 3 );             { window, shorten it.  }
  178.     Insert ( BArr [ Border ].BT, Title, 1 ); { Add start Title character }
  179.     Title := Title + BArr [ Border ].ET;     { Add end Title character   }
  180.     i := X1 + ((X2 - X1 + 1) div 2 ) - ( Length (Title) Div 2);
  181.     GotoXY ( X1 + ( ( X2 - X1 + 1 ) Div 2 ) - ( Length ( Title ) Div 2 ),Y1 );
  182.     Write ( Title );                         { Write the title to thewindow }
  183.   End;
  184.  
  185.   Window ( X1 + 1, Y1 + 1, X2 - 1, Y2 - 1 );  { Make Turbo aware of window }
  186.   TextAttr := tmp;                            { Restore orig. screen colors}
  187.   ClrScr;
  188. End;
  189.  
  190. Procedure DefineBorder;
  191. { Define a border for the DoBorder procedure }
  192. Begin
  193.   With BArr [ Num ] Do
  194.   Begin
  195.     UL := UpLeft;
  196.     UR := UpRight;
  197.     BL := BtmLeft;
  198.     BR := BtmRight;
  199.     HL := HorizLine;
  200.     VL := VertLine;
  201.     BT := BegTitle;
  202.     ET := EndTitle;
  203.   End;
  204. End;
  205.  
  206. Procedure WindowSound;
  207. { Based on value of the SoundOn boolean variable, make a sound for }
  208. { opening or closing a window.                                     }
  209. Begin
  210.   If ( SoundOn ) Then
  211.   Begin
  212.     If Open Then
  213.     Begin
  214.       Sound ( 100 );  { Open a window sound }
  215.       Delay ( 50 );
  216.       Sound ( 200 );
  217.       Delay ( 50 );
  218.       Sound ( 300 );
  219.       Delay ( 50 );
  220.       NoSound;
  221.     End
  222.     Else
  223.     Begin
  224.       Sound ( 300 );  { Close a window sound }
  225.       Delay ( 50 );
  226.       Sound ( 200 );
  227.       Delay ( 50 );
  228.       Sound ( 100 );
  229.       Delay ( 50 );
  230.       NoSound;
  231.     End;
  232.   End;
  233. End;
  234.  
  235. Procedure GetVideoAddress;
  236. { Based on the current video mode, set the width of the screen and }
  237. { the base address of the video screen.                            }
  238. Var
  239.   reg : Registers;
  240. Begin
  241.   reg.AH := $0F;
  242.   Intr ( $10, reg );  { BIOS interrupt to get current video mode }
  243.   VidWidth := reg.AH;
  244.   Case ( reg.AL ) Of
  245.        0..3 : BaseAddr := $B800;  { Color display }
  246.        7    : BaseAddr := $B000;  { Monochrome display }
  247.        Else
  248.        Begin          { Must be in a graphics mode, halt program }
  249.          ReportError ( 'Not in a text mode!' );
  250.        End;
  251.   End;
  252. End;
  253.  
  254. Procedure OpenWindow;
  255. { Perform all the work required to open a window on the screen, draw the }
  256. { border, make the sound, ...                                            }
  257. Begin
  258.   WindowSound ( TRUE );
  259.   PushWindow ( X1, Y1, X2, Y2 );
  260.   DoBorder ( X1, Y1, X2, Y2, Border, BorderColor, Title );
  261. End;
  262.  
  263. Procedure CloseWindow;
  264. { Perform all the work required to close a window and make the sound. }
  265. Begin
  266.   WindowSound ( FALSE );
  267.   PopWindow;
  268.   With Stack [ StackPtr ] Do
  269.   Begin
  270.     If ( StackPtr = 0 ) Then
  271.       Window ( sX1, sY1, sX2, sY2 )    { Main window }
  272.     Else
  273.       Window ( sX1 + 1, sY1 + 1, sX2 - 1, sY2 - 1 );
  274.   End;
  275. End;
  276.  
  277. Begin
  278.   GetVideoAddress;                        { Get current video information  }
  279.   FillChar ( Stack, SizeOf (Stack), 0 );  { Initialize window stack        }
  280.   StackPtr := 0;                          { Initialize window stack pointer}
  281.   SoundOn := TRUE;                        { Default sound to be on         }
  282.   DefineBorder ( 1, ' ',' ',' ',' ',' ',' ',' ',' ' ); { Set predefined }
  283.   DefineBorder ( 2, '┌','┐','└','┘','─','│','┤','├' ); { border types.  }
  284.   DefineBorder ( 3, '╔','╗','╚','╝','═','║','╡','╞' );
  285.   DefineBorder ( 4, ' ',' ',' ',' ',' ',' ',' ',' ' );
  286. End.
  287.