home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / turbo55 / install / tcalc.arc / TCSCREEN.PAS < prev    next >
Pascal/Delphi Source File  |  1989-05-02  |  15KB  |  523 lines

  1.  
  2. { Copyright (c) 1989 by Borland International, Inc. }
  3.  
  4. unit TCScreen;
  5. { Turbo Pascal 5.5 object-oriented example screen routines.
  6.   This unit is used by TCALC.PAS.
  7.   See TCALC.DOC for an more information about this example.
  8. }
  9.  
  10. {$S-}
  11.  
  12. interface
  13.  
  14. uses Crt, Dos, TCUtil;
  15.  
  16. const
  17.   ScreenCols = 80;
  18.   ScreenRows = 50;
  19.   MinScreenRows = 25;
  20.   ESCPress = 'Press ESC.';    { Printed in error messages }
  21.  
  22. type
  23.   Direction = (Up, Down, Left, Right);
  24.   ScreenColRange = 1..ScreenCols;
  25.   ScreenRowRange = 1..ScreenRows;
  26.   VideoTypes = (MDA, CGA, MCGA, EGA, VGA);
  27.   ScreenChar = record
  28.     Data : Char;
  29.     Attrib : Byte;
  30.   end;
  31.   ScreenArray = array[ScreenRowRange, ScreenColRange] of ScreenChar;
  32.   ScreenRow = array[ScreenColRange] of ScreenChar;
  33.   ScreenPointer = ^ScreenArray;
  34.   ScreenPos = record
  35.     Col : ScreenColRange;
  36.     Row : ScreenRowRange;
  37.   end;
  38.   Screen = object
  39.     CurrRows : ScreenRowRange;
  40.     CurrCols : ScreenColRange;
  41.     VideoType : VideoTypes;
  42.     OldCursor : Word;
  43.     InsCursor : Word;
  44.     OldMode : Word;
  45.     constructor Init;
  46.     destructor Done;
  47.     procedure ToggleMaxLinesMode;
  48.     procedure PrintError(Error : String);
  49.     procedure PrintMessage(Message : String);
  50.     procedure ClearMessage;
  51.     procedure PrintHelpLine(CommandString : String);
  52.   end;
  53.   ScreenArea = object
  54.     UpperLeft, LowerRight : ScreenPos;
  55.     Attrib : Byte;
  56.     constructor Init(InitX1 : ScreenColRange; InitY1 : ScreenRowRange;
  57.                      InitX2 : ScreenColRange; InitY2 : ScreenRowRange;
  58.                      InitAttrib : Byte);
  59.     procedure Scroll(Dir : Direction; Amt : Word);
  60.     procedure Clear;
  61.     procedure Erase;
  62.   end;
  63.   ColorTableType = (ColorMono, ColorBW, ColorColor);
  64.   ColorTablePtr = ^ColorTable;
  65.   ColorTable = object
  66.     TableType : ColorTableType;
  67.     BlankColor : Byte;
  68.     ValueCellColor : Byte;
  69.     TextCellColor : Byte;
  70.     FormulaCellColor : Byte;
  71.     RepeatCellColor : Byte;
  72.     ColColor : Byte;
  73.     RowColor : Byte;
  74.     InfoColor : Byte;
  75.     HighlightColor : Byte;
  76.     BlockColor : Byte;
  77.     InputColor : Byte;
  78.     InputArrowColor : Byte;
  79.     ErrorColor : Byte;
  80.     CellErrorColor : Byte;
  81.     MemoryColor : Byte;
  82.     CellDataColor : Byte;
  83.     PromptColor : Byte;
  84.     FileNameColor : Byte;
  85.     ChangedColor : Byte;
  86.     TitleColor : Byte;
  87.     ContentsColor : Byte;
  88.     KeyNameColor : Byte;
  89.     KeyDescColor : Byte;
  90.     MenuHiColor : Byte;
  91.     MenuLoColor : Byte;
  92.     MessageColor : Byte;
  93.     constructor Init;
  94.     procedure FillColorTable;
  95.   end;
  96.  
  97. const
  98.   NoCursor = $2000;
  99.  
  100. var
  101.   Colors : ColorTable;
  102.   Scr : Screen;
  103.   ScreenPtr : ScreenPointer;
  104.  
  105. procedure MoveToScreen(var Source, Dest; Len : Word);
  106.  
  107. procedure MoveFromScreen(var Source, Dest; Len : Word);
  108.  
  109. procedure ClrEOLXY(Col : ScreenColRange; Row : ScreenRowRange;
  110.                    Color : Byte);
  111.  
  112. procedure WriteColor(S : String; Color : Byte);
  113.  
  114. procedure WriteXY(S : String; Col : ScreenColRange; Row : ScreenRowRange;
  115.                       Color : Byte);
  116.  
  117. procedure WriteXYClr(S : String; Col : ScreenColRange; Row : ScreenRowRange;
  118.                          Color : Byte);
  119.  
  120. procedure SetCursor(NewCursor : Word);
  121.  
  122. function GetCursor : Word;
  123.  
  124. implementation
  125.  
  126. const
  127.   TotalColors = 26;
  128.   WhiteOnRed = White + (Red shl 4);
  129.   WhiteOnBlue = White + (Blue shl 4);
  130.   WhiteOnCyan = White + (Cyan shl 4);
  131.   BlackOnGray = LightGray shl 4;
  132.   WhiteOnGray = White + (LightGray shl 4);
  133.   BlinkingLightRed = LightRed + Blink;
  134.   BlinkingWhite = White + Blink;
  135.   LightCyanOnBlue = LightCyan + (Blue shl 4);
  136.   YellowOnBlue = Yellow + (Blue shl 4);
  137.  
  138. type
  139.   ColorArray = array[1..TotalColors] of Byte;
  140.  
  141. const
  142.   ColorColors : ColorArray = (White, LightCyan, White, LightMagenta, White,
  143.                               WhiteOnRed, WhiteOnRed, WhiteOnCyan,
  144.                               WhiteOnBlue, WhiteOnCyan, White, LightCyan,
  145.                               WhiteOnRed, BlinkingLightRed, LightRed,
  146.                               LightGreen, Yellow, LightCyan, Yellow,
  147.                               LightMagenta, Yellow, LightCyanOnBlue,
  148.                               YellowOnBlue, LightCyan, White,
  149.                               BlinkingLightRed);
  150.   BWColors : ColorArray = (White, White, White, White, White, BlackOnGray,
  151.                            BlackOnGray, WhiteOnGray, WhiteOnGray, BlackOnGray,
  152.                            White, White, White, BlinkingWhite, White, White,
  153.                            White, White, White, White, White, BlackOnGray,
  154.                            White, White, LightGray, BlinkingWhite);
  155.   MonoColors : ColorArray = (White, White, White, White, White, BlackOnGray,
  156.                              BlackOnGray, BlackOnGray, BlackOnGray,
  157.                              BlackOnGray, White, White, White, BlinkingWhite,
  158.                              White, White, White, White, White, White, White,
  159.                              BlackOnGray, White, White, LightGray,
  160.                              BlinkingWhite);
  161.  
  162. const
  163.   InsCursorSmall = $0007;
  164.   InsCursorLarge = $000D;
  165.  
  166. var
  167.   SavedExitProc : Pointer;
  168.  
  169. procedure ClearScreen(X1, Y1, X2, Y2, Attrib : Word);
  170. { Clears an area of the screen }
  171. var
  172.   Reg : Registers;
  173. begin
  174.   if (X1 > X2) or (Y1 > Y2) then   { Illegal values }
  175.     Exit;
  176.   with Reg do
  177.   begin
  178.     AX := $0600;              { Clear screen through the BIOS }
  179.     BH := Attrib;
  180.     CH := Pred(Y1);
  181.     CL := Pred(X1);
  182.     DH := Pred(Y2);
  183.     DL := Pred(X2);
  184.     Intr($10, Reg);
  185.   end; { with }
  186. end; { ClearScreen }
  187.  
  188. {$L TCMVSMEM}
  189.  
  190. procedure MoveToScreen(var Source, Dest; Len : Word); external;
  191. { Moves screen memory from normal RAM to screen memory - see TCMVSMEM.ASM
  192.   for source }
  193.  
  194. procedure MoveFromScreen(var Source, Dest; Len : Word); external;
  195. { Moves screen memory to normal RAM from screen memory - see TCMVSMEM.ASM
  196.   for source }
  197.  
  198. procedure MoveText(OldX1, OldY1, OldX2, OldY2, NewX1, NewY1 : Word);
  199. { Moves an area of text to a new position on the screen }
  200. var
  201.   Counter, Len : Word;
  202. begin
  203.   if (OldX2 < OldX1) or (OldY2 < OldY1) then
  204.     Exit;
  205.   Len := Succ(OldX2 - OldX1) shl 1;
  206.   if NewY1 < OldY1 then
  207.   begin                    { Move it row by row, going forwards }
  208.     for Counter := 0 to OldY2 - OldY1 do
  209.       MoveFromScreen(ScreenPtr^[OldY1 + Counter, OldX1],
  210.                      ScreenPtr^[NewY1 + Counter, NewX1], Len)
  211.   end
  212.   else begin               { Move it row by row, going backwards }
  213.     for Counter := OldY2 - OldY1 downto 0 do
  214.       MoveFromScreen(ScreenPtr^[OldY1 + Counter, OldX1],
  215.                      ScreenPtr^[NewY1 + Counter, NewX1], Len)
  216.   end;
  217. end; { MoveText }
  218.  
  219. procedure ScrollText(Dir : Direction; X1, Y1, X2, Y2, Amt, Attrib : Word);
  220. { Scrolls the screen by an amount in a direction - it does this by moving
  221.   the text to be scrolled and then clearing the area that wasn't scrolled }
  222. begin
  223.   case Dir of
  224.     Up : begin
  225.       MoveText(X1, Y1 + Amt, X2, Y2, X1, Y1);
  226.       ClearScreen(X1, Succ(Y2 - Amt), X2, Y2, Attrib);
  227.     end;
  228.     Down : begin
  229.       MoveText(X1, Y1, X2, Y2 - Amt, X1, Succ(Y1));
  230.       ClearScreen(X1, Y1, X2, Pred(Y1 + Amt), Attrib);
  231.     end;
  232.     Left : begin
  233.       MoveText(X1 + Amt, Y1, X2, Y2, X1, Y1);
  234.       ClearScreen(Succ(X2 - Amt), Y1, X2, Y2, Attrib);
  235.     end;
  236.     Right : begin
  237.       MoveText(X1, Y1, X2 - Amt, Y2, X1 + Amt, Y1);
  238.       ClearScreen(X1, Y1, Pred(X1 + Amt), Y2, Attrib);
  239.     end;
  240.   end; { case }
  241. end; { ScrollText }
  242.  
  243. function EGAInstalled : Boolean;
  244. { Tests for the presence of an EGA }
  245. var
  246.   Reg : Registers;
  247. begin
  248.   Reg.AX := $1200;
  249.   Reg.BX := $0010;
  250.   Reg.CX := $FFFF;
  251.   Intr($10, Reg);
  252.   EGAInstalled := Reg.CX <> $FFFF;
  253. end; { EGAInstalled }
  254.  
  255. function PS2 : Boolean;
  256. { This function returns True if we are running on a PS/2 type video adapter }
  257. var
  258.   Regs : Registers;
  259. begin
  260.   Regs.AX := $1A00;
  261.   Intr($10, Regs);
  262.   PS2 := ((Regs.AL and $FF) = $1A) and
  263.          ((Regs.BL and $FF) in [$07, $08, $0B, $0C]);
  264. end; { PS2 }
  265.  
  266. procedure ClrEOLXY(Col : ScreenColRange; Row : ScreenRowRange; Color : Byte);
  267. { Clears to the end-of-line in a color at a specified position }
  268. begin
  269.   GotoXY(Col, Row);
  270.   TextAttr := Color;
  271.   ClrEOL;
  272. end; { ClrEOLXY }
  273.  
  274. procedure WriteColor(S : String; Color : Byte);
  275. { Writes a string in a color }
  276. begin
  277.   TextAttr := Color;
  278.   Write(S);
  279. end; { WriteColor }
  280.  
  281. procedure WriteXY(S : String; Col : ScreenColRange; Row : ScreenRowRange;
  282.                   Color : Byte);
  283. { Writes a string in a color at a specified position }
  284. begin
  285.   GotoXY(Col, Row);
  286.   WriteColor(S, Color);
  287. end; { WriteXY }
  288.  
  289. procedure WriteXYClr(S : String; Col : ScreenColRange; Row : ScreenRowRange;
  290.                      Color : Byte);
  291. { Clears to the end-of-line in a color at a specified position and then
  292.   writes a string }
  293. begin
  294.   ClrEOLXY(Col, Row, Color);
  295.   Write(S);
  296. end; { WriteXYClr }
  297.  
  298. procedure SetCursor(NewCursor : Word);
  299. { Sets the value of the scan lines of the cursor }
  300. var
  301.   Reg : Registers;
  302. begin
  303.   with Reg do
  304.   begin
  305.     AH := 1;
  306.     BH := 0;
  307.     CX := NewCursor;
  308.     Intr($10, Reg);
  309.   end; { with }
  310. end; { SetCursor }
  311.  
  312. function GetCursor : Word;
  313. { Returns the value of the scan lines of the cursor }
  314. var
  315.   Reg : Registers;
  316. begin
  317.   with Reg do
  318.   begin
  319.     AH := 3;
  320.     BH := 0;
  321.     Intr($10, Reg);
  322.     GetCursor := CX;
  323.   end; { Reg }
  324. end; { GetCursor }
  325.  
  326. constructor Screen.Init;
  327. { Finds what type of video adapter is being run on, and initializes various
  328.   variables based on this information }
  329. var
  330.   Reg : Registers;
  331. begin
  332.   OldMode := LastMode;
  333.   Reg.AH := $0F;
  334.   Intr($10, Reg);                    { Check for the current video mode }
  335.   if Reg.AL <> 7 then
  336.   begin
  337.     if EGAInstalled then
  338.     begin
  339.       if PS2 then
  340.         VideoType := VGA
  341.       else
  342.         VideoType := EGA;
  343.     end
  344.     else begin
  345.       if PS2 then
  346.         VideoType := MCGA
  347.       else
  348.         VideoType := CGA;
  349.     end;
  350.     ScreenPtr := Ptr($B800, 0);
  351.     if Reg.AL < 2 then
  352.       CurrCols := 40
  353.     else
  354.       CurrCols := 80;
  355.   end
  356.   else begin
  357.     VideoType := MDA;
  358.     ScreenPtr := Ptr($B000, 0);
  359.     CurrCols := 80;
  360.   end;
  361.   CurrRows := Succ(Hi(WindMax));
  362.   OldCursor := GetCursor;
  363.   if (CurrRows = MinScreenRows) and (VideoType <> CGA) then
  364.     InsCursor := InsCursorLarge
  365.   else
  366.     InsCursor := InsCursorSmall;
  367. end; { Screen.Init }
  368.  
  369. destructor Screen.Done;
  370. { Restores the screen mode and cursor that existed at the start of the 
  371.   program }
  372. begin
  373.   TextMode(OldMode);
  374.   SetCursor(OldCursor);
  375.   ExitProc := SavedExitProc;
  376. end; { Screen.Done }
  377.  
  378. procedure Screen.ToggleMaxLinesMode;
  379. { Toggles the display in and out of 43/50-line mode }
  380. begin
  381.   if CurrRows = MinScreenRows then
  382.   begin
  383.     TextMode(Lo(LastMode) + Font8x8);
  384.     InsCursor := InsCursorSmall;
  385.   end
  386.   else begin
  387.     TextMode(Lo(LastMode));
  388.     InsCursor := InsCursorLarge;
  389.   end;
  390.   CurrRows := Succ(Hi(WindMax));
  391. end; { Screen.ToggleMaxLinesMode }
  392.  
  393. procedure Screen.PrintError(Error : String);
  394. { Prints an error message at the bottom of the screen }
  395. var
  396.   Ch : Word;
  397.   Buffer : ScreenRow;
  398. begin
  399.   MoveFromScreen(ScreenPtr^[CurrRows, 1], Buffer,
  400.                  SizeOf(ScreenChar) * CurrCols);  { Save bottom line }
  401.   WriteXYClr(CenterStr(Error + '. ' + ESCPress, Pred(CurrCols)), 1, CurrRows,
  402.              Colors.ErrorColor);
  403.   Beep;
  404.   repeat
  405.     Ch := GetKey;
  406.   until Ch = ESC;
  407.   MoveToScreen(Buffer, ScreenPtr^[CurrRows, 1],  { Restore bottom line }
  408.                SizeOf(ScreenChar) * CurrCols);
  409. end; { Screen.PrintError }
  410.  
  411. procedure Screen.PrintMessage(Message : String);
  412. { Prints a message }
  413. begin
  414.   WriteXYClr(Message + '...', 1, Pred(CurrRows), Colors.MessageColor);
  415. end; { Screen.PrintMessage }
  416.  
  417. procedure Screen.ClearMessage;
  418. { Clears the last printed message }
  419. begin
  420.   ClrEOLXY(1, Pred(CurrRows), Colors.MessageColor);
  421. end; { Screen.ClearMessage }
  422.  
  423. procedure Screen.PrintHelpLine(CommandString : String);
  424. { Prints a help line at the bottom of the screen. The command string is
  425.   made up of a series of keys and descriptions separated by backslashes.
  426.   Example: 'F1\Help\F2\Save\F3\Load\Alt-X\Exit'}
  427. var
  428.   P : Integer;
  429.   S : String[ScreenCols];
  430. begin
  431.   CommandString := CommandString + '\';
  432.   ClrEOLXY(1, CurrRows, Colors.KeyDescColor);
  433.   while CommandString <> '' do
  434.   begin
  435.     Write(' ');
  436.     P := Pos('\', CommandString);
  437.     WriteColor(Copy(CommandString, 1, Pred(P)), Colors.KeyNameColor);
  438.     Delete(CommandString, 1, P);
  439.     P := Pos('\', CommandString);
  440.     if CommandString[1] = '\' then
  441.       S := '-'
  442.     else
  443.       S := '-' + Copy(CommandString, 1, Pred(P));
  444.     WriteColor(S, Colors.KeyDescColor);
  445.     Delete(CommandString, 1, P);
  446.   end;
  447. end; { Screen.PrintHelpLine }
  448.  
  449. constructor ScreenArea.Init(InitX1 : ScreenColRange; InitY1 : ScreenRowRange;
  450.                             InitX2 : ScreenColRange; InitY2 : ScreenRowRange;
  451.                             InitAttrib : Byte);
  452. { Sets up a screen area }
  453. begin
  454.   UpperLeft.Col := InitX1;
  455.   UpperLeft.Row := InitY1;
  456.   LowerRight.Col := InitX2;
  457.   LowerRight.Row := InitY2;
  458.   Attrib := InitAttrib;
  459. end; { ScreenArea.Init }
  460.  
  461. procedure ScreenArea.Scroll(Dir : Direction; Amt : Word);
  462. { Scrolls a screen area an certain amount in a direction }
  463. begin
  464.   ScrollText(Dir, UpperLeft.Col, UpperLeft.Row, LowerRight.Col,
  465.              LowerRight.Row, Amt, Attrib);
  466. end; { ScreenArea.Scroll }
  467.  
  468. procedure ScreenArea.Clear;
  469. { Clears a screen area }
  470. begin
  471.   ClearScreen(UpperLeft.Col, UpperLeft.Row, LowerRight.Col, LowerRight.Row,
  472.               Attrib);
  473. end; { ScreenArea.Clear }
  474.  
  475. procedure ScreenArea.Erase;
  476. { Erases a screen area by writing over it in black }
  477. begin
  478.   ClearScreen(UpperLeft.Col, UpperLeft.Row, LowerRight.Col, LowerRight.Row,
  479.               Black);
  480. end; { ScreenArea.Erase }
  481.  
  482. constructor ColorTable.Init;
  483. { Initializes the color table by finding the video mode that is being used }
  484. begin
  485.   case Lo(LastMode) of
  486.     BW40, BW80 : TableType := ColorBW;
  487.     CO40, CO80 : TableType := ColorColor;
  488.     Mono : TableType := ColorMono;
  489.   end; { case }
  490.   FillColorTable;
  491. end; { ColorTable.Init }
  492.  
  493. procedure ColorTable.FillColorTable;
  494. { Moves the correct built-in color table to the program's color table }
  495. var
  496.   P : Pointer;
  497. begin
  498.   case TableType of
  499.     ColorColor : P := @ColorColors;
  500.     ColorBW : P := @BWColors;
  501.     ColorMono : P := @MonoColors;
  502.   end; { case }
  503.   Move(P^, BlankColor, TotalColors);
  504. end; { ColorTable.FillColorTable }
  505.  
  506. {$F+}
  507.  
  508. procedure ScreenExit;
  509. { Clears the screen at exit }
  510. begin
  511.   Scr.Done;
  512. end; { ScreenExit }
  513.  
  514. {$F-}
  515.  
  516. begin
  517.   SavedExitProc := ExitProc;
  518.   ExitProc := @ScreenExit;
  519.   TextMode(LastMode);
  520.   Scr.Init;
  521.   Colors.Init;
  522. end.
  523.