home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / dos / files / fileman / fm / fmscreen.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1988-08-23  |  11.0 KB  |  319 lines

  1. {
  2. --------------------------------------------------------------------------
  3.                        F i l e    I n f o r m a t i o n
  4.  
  5. * DESCRIPTION
  6. File used with FM.PAS.
  7.  
  8. * ASSOCIATED FILES
  9. FM.PAS
  10. FM.DOC
  11. FM.EXE
  12. FM.TPU
  13. FMFILE.PAS
  14. FMINPUT.PAS
  15. FMSCREEN.PAS
  16. FMUTEST.EXE
  17. FMUTEST.PAS
  18. FMVIEW.PAS
  19.  
  20. ==========================================================================
  21. }
  22. {$R-}      { Range checking off }                     { Unit:    FMScreen.PAS }
  23. {$S-}      { Stack checking off }                     { Program: FM.PAS       }
  24. {$I-}      { I/O checking off }                       { Author:  Jim Zwick    }
  25. {$V+}      { Strict String type checking on }         { Version: 1.0          }
  26. {$B-}      { Boolean short-circuit evaluation on }    { Date:    03-04-88     }
  27.  
  28. UNIT FMScreen;
  29.  
  30. INTERFACE
  31.  
  32. USES
  33.   Crt,
  34.   Dos;
  35.  
  36. CONST
  37.   NormalVid  = $0700;
  38.   ReverseVid = $7000;
  39.   SpaceStr : STRING[1] = '─';         { Used By KbdStatus to Keep Screen Char }
  40.   InsKeyOn : BOOLEAN = FALSE;      { Set By KbdStatus, Used By Input Routines }
  41.  
  42. VAR
  43.   StartX, StartY : BYTE;
  44.  
  45.  
  46.   PROCEDURE DisplayLine(X, Y, Len, Attr : WORD; St : STRING);
  47.   PROCEDURE WOpen(ScrNum : BYTE);
  48.   PROCEDURE WClose;
  49.   PROCEDURE CursorOn(On : BOOLEAN);
  50.   PROCEDURE ClrLn(X, Y : BYTE);
  51.   PROCEDURE ClrArea(X1, Y1, X2, Y2 : BYTE);
  52.   PROCEDURE KbdStatus;
  53.  
  54.  
  55. IMPLEMENTATION
  56.  
  57. TYPE
  58.   Str15 = STRING[15];
  59.   WinRec = RECORD                                        { Window Coordinates }
  60.               WX1     : BYTE;
  61.               WY1     : BYTE;
  62.               WX2     : BYTE;
  63.               WY2     : BYTE;
  64.               WBorder : BOOLEAN;
  65.               WTitle  : Str15;
  66.             END;
  67.   WScreenContent = ARRAY[0..3999] OF CHAR;   { Buffer to hold window contents }
  68.   WDisplayRec = RECORD
  69.                   WStackScr : BYTE;
  70.                   WCursX    : BYTE;
  71.                   WCursY    : BYTE;
  72.                   WScreen   : ^WScreenContent;
  73.                 END;
  74.  
  75. CONST
  76.   VidAddr     : WORD = $B000;                 { Default value for monochrome. }
  77.   CursOn      : BOOLEAN = TRUE;   { Used to Store Cursor Status for KbdStatus }
  78.   WStackSize  : BYTE = 0;
  79.   MaxWindows  = 4;     { Set at max used at one time or set with SetWindCoord }
  80.  
  81. VAR
  82.   WSetWindow : ARRAY[0..MaxWindows] OF WinRec;
  83.   WDisp      : ARRAY[0..MaxWindows] OF WDisplayRec;
  84.   WScreenPtr : ^CHAR;    { Pointer to start of video display memory.  Avoids  }
  85.   WCurr      : WinRec;   {   need for addresses to both mono and color memory }
  86.   ExitSave   : Pointer;  {   locations used in most other implementations.    }
  87.   StdStart, StdStop : WORD;              { Saves cursor scan lines at startup }
  88.  
  89.   { ------------------------------------------------------------------------- }
  90.  
  91.   PROCEDURE DisplayLine(X, Y, Len, Attr : WORD; St : STRING);
  92.   BEGIN
  93.     Y := PRED(Y) * 160 + PRED(X) * 2;      { Maps St and Attr to Video memory }
  94.     X := 0;
  95.     WHILE X < Len do
  96.       BEGIN
  97.         Inc(X);
  98.         MEMW[VidAddr:Y] := ORD(St[X]) + Attr;
  99.         Y := Y + 2;
  100.       END;
  101.   END;
  102.   { ------------------------------------------------------------------------- }
  103.  
  104.   PROCEDURE InitVideo;        { Initializes Video Address and Color Variables }
  105.   BEGIN
  106.     IF MEM[$0000:$0449] = 7 THEN                                 { Monochrome }
  107.       BEGIN
  108.         VidAddr := $B000;
  109.         TextColor(LightGray);
  110.         TextBackGround(Black);
  111.       END
  112.     ELSE
  113.       BEGIN
  114.         VidAddr := $B800;                                            { Color }
  115.         TextColor(LightGray);
  116.         TextBackGround(Blue);
  117.         CheckSnow := TRUE;
  118.       END;
  119.     WScreenPtr := Ptr(VidAddr, $0000);
  120.     MEM[$0000:$0417] := (MEM[$0000:$0417] AND $7F);            { Clear Insert }
  121.   END;
  122.   { ------------------------------------------------------------------------- }
  123.  
  124.   PROCEDURE GetShape(VAR StartLine, StopLine : WORD);
  125.   VAR
  126.     CursReg : Registers;                { Determine Current Cursor Scan Lines }
  127.   BEGIN
  128.     WITH CursReg DO
  129.       BEGIN
  130.         AH := $03;
  131.         BH := $00;
  132.       END;
  133.     INTR($10, CursReg);
  134.     WITH CursReg DO
  135.       BEGIN
  136.         StartLine := CH;
  137.         StopLine := CL;
  138.       END;
  139.   END;
  140.   { ------------------------------------------------------------------------- }
  141.  
  142.   PROCEDURE SetShape(StartLine, StopLine : WORD);
  143.   VAR
  144.     CursReg : Registers;                              { Set Cursor Scan Lines }
  145.   BEGIN
  146.     WITH CursReg DO
  147.       BEGIN
  148.         AH := $01;
  149.         CH := StartLine;
  150.         CL := StopLine;
  151.       END;
  152.     INTR($10, CursReg);
  153.   END;
  154.   { ------------------------------------------------------------------------- }
  155.  
  156.   PROCEDURE SetWBorders(Screen : BYTE);
  157.   VAR
  158.     i    : BYTE;                         { Sets window coordinates and writes }
  159.     Line : STRING[78];                   { border and title when applicable   }
  160.   BEGIN
  161.     WINDOW(1, 1, 80, 25);
  162.     IF (Screen > 0) AND (WStackSize > 0) THEN
  163.       BEGIN
  164.         WCurr := WSetWindow[Screen];
  165.         WITH WCurr DO
  166.           BEGIN
  167.             IF WBorder THEN
  168.               BEGIN
  169.                 FILLCHAR(Line, SIZEOF(Line), '─');
  170.                 Line[0] := CHR(WX2 - WX1 - 1);
  171.                 GOTOXY(WX1, WY1);
  172.                 WRITE('┌', Line, '┐');
  173.                 HIGHVIDEO;
  174.                 GotoXY(((WX2 - WX1 + 1 - LENGTH(WTitle)) DIV 2) + WX1, WY1);
  175.                 WRITE(WTitle);
  176.                 LOWVIDEO;
  177.                 FOR i := SUCC(WY1) TO PRED(WY2) DO
  178.                   BEGIN
  179.                     GOTOXY(WX1, i);    WRITE('│');
  180.                     GOTOXY(WX2, i);    WRITE('│');
  181.                   END;
  182.                 DisplayLine(WX1, WY2, WX2 - WX1 + 1, NormalVid, '└'+ Line + '┘');
  183.                 WINDOW(SUCC(WX1), SUCC(WY1), PRED(WX2), PRED(WY2))
  184.               END
  185.             ELSE WINDOW(WX1, WY1, WX2, WY2);
  186.           END;
  187.       END;
  188.   END;
  189.   { ------------------------------------------------------------------------- }
  190.  
  191.   PROCEDURE SetWindCoord(WindNum, X1, Y1, X2, Y2 : BYTE; Border : BOOLEAN;
  192.                                            Title : Str15);
  193.   BEGIN
  194.     WITH WCurr DO             { Stores window information for later reference }
  195.       BEGIN                   { by WindNum.  These only need to be set once   }
  196.         WX1 := X1;            { per program but if you use a lot of windows   }
  197.         WY1 := Y1;            { in an application they can be changed within  }
  198.         WX2 := X2;            { a program to avoid the memory overhead.  In   }
  199.         WY2 := Y2;            { one application in which I use these routines }
  200.         WBorder := Border;    { for layered menus, SetWindCoord is called by  }
  201.         WTitle := Title       { each menu procedure -- overhead for three     }
  202.       END;                    { windows while using eighteen!                 }
  203.     WSetWindow[WindNum] := WCurr;
  204.   END;
  205.   { ------------------------------------------------------------------------- }
  206.  
  207.   PROCEDURE WOpen(ScrNum : BYTE);
  208.   BEGIN
  209.     Inc(WStackSize);
  210.     WITH WDisp[WStackSize] DO              { Saves contents of current screen }
  211.       BEGIN                                { and opens new window             }
  212.         WStackScr := ScrNum;
  213.         WCursX := WHEREX;
  214.         WCursY := WHEREY;
  215.         NEW(WScreen);
  216.         MOVE(WScreenPtr^, WScreen^, 4000);
  217.       END;
  218.     SetWBorders(ScrNum);
  219.   END;
  220.   { ------------------------------------------------------------------------- }
  221.  
  222.   PROCEDURE WClose;
  223.   BEGIN                                                { Restores last screen }
  224.     WITH WDisp[WStackSize] DO
  225.       BEGIN
  226.         MOVE(WScreen^, WScreenPtr^, 4000);
  227.         DISPOSE(WScreen);
  228.       END;
  229.     Dec(WStackSize);
  230.     SetWBorders(WDisp[WStackSize].WStackScr);
  231.     WITH WDisp[SUCC(WStackSize)] DO GotoXY(WCursX, WCursY);
  232.   END;
  233.   { ------------------------------------------------------------------------- }
  234.  
  235.   PROCEDURE CursorOn(On : BOOLEAN);
  236.   VAR
  237.     CReg : Registers;
  238.   BEGIN
  239.     IF On THEN
  240.       IF  VidAddr = $B000 THEN CReg.CX := $0C0D
  241.       ELSE CReg.CX := $0607
  242.     ELSE CReg.CX := $2000;
  243.     CReg.AX := $0100;
  244.     INTR($10, CReg);
  245.     CursOn := On;
  246.   END;
  247.   { ------------------------------------------------------------------------- }
  248.  
  249.   PROCEDURE ClrLn(X, Y : BYTE);                { A procedure for lazy typists }
  250.   BEGIN
  251.     GotoXY(X, Y);
  252.     CLREOL;
  253.   END;
  254.   { ------------------------------------------------------------------------- }
  255.  
  256.   PROCEDURE ClrArea(X1, Y1, X2, Y2 : BYTE);
  257.   BEGIN                                  { Another procedure for lazy typists }
  258.     WINDOW(X1, Y1, X2, Y2);
  259.     CLRSCR;
  260.     WINDOW(1, 1, 80, 25);
  261.   END;
  262.   { ------------------------------------------------------------------------- }
  263.  
  264.   PROCEDURE KbdStatus;
  265.   CONST
  266.     Caps    : BOOLEAN = FALSE;
  267.     NumLock : BOOLEAN = FALSE;
  268.   VAR
  269.     KbdReg         : Registers;
  270.     OldNum, OldCap : BOOLEAN;
  271.   BEGIN
  272.     WHILE NOT KEYPRESSED DO                       { Monitors status of shift  }
  273.       BEGIN                                       { states while waiting for  }
  274.         OldCap := Caps;                           { keyboard input.  Uses     }
  275.         OldNum := NumLock;                        { DisplayLine to report     }
  276.         FILLCHAR(KbdReg, SIZEOF(KbdReg), 0);      { status so that windows    }
  277.         KbdReg.AH := 2;                           { can be overwritten.       }
  278.         INTR($16, KbdReg);                        { SpaceStr is used to store }
  279.         InsKeyOn := (KbdReg.AL AND $80) <> 0;     { the character at the      }
  280.         Caps := (KbdReg.AL AND $40) <> 0;         { lower corner of screen.   }
  281.         NumLock := (KbdReg.AL AND $20) <> 0;      { InsKeyOn is global so it  }
  282.         IF (NumLock <> OldNum) THEN               { can be used by ReadFld.   }
  283.           BEGIN
  284.             IF NumLock THEN DisplayLine(77, 25, 1, ReverseVid, '#')
  285.             ELSE DisplayLine(77, 25, 1, NormalVid, SpaceStr);
  286.           END;
  287.         IF (Caps <> OldCap) THEN
  288.           BEGIN
  289.             IF Caps THEN DisplayLine(78, 25, 1, ReverseVid, 'C')
  290.             ELSE DisplayLine(78, 25, 1, NormalVid, SpaceStr);
  291.           END;
  292.         IF CursOn THEN
  293.           IF InsKeyOn THEN SetShape(StdStart-2, StdStop)    { Increase cursor }
  294.           ELSE SetShape(StdStart, StdStop);                 { size when on    }
  295.       END;
  296.   END;
  297.   { ------------------------------------------------------------------------- }
  298.  
  299.   {$F+}
  300.   PROCEDURE FMScreenExit;  {$F-}
  301.   BEGIN
  302.     SetShape(StdStart, StdStop);      { Restore cursor before program ends. }
  303.     ExitProc := ExitSave;
  304.   END;
  305.   { ------------------------------------------------------------------------- }
  306.  
  307. BEGIN
  308.   InitVideo;          { Initializes video memory location and color variables }
  309.   GetShape(StdStart, StdStop);         { Stores cursor scan lines at start-up }
  310.   CheckBreak := FALSE;
  311.   SetWindCoord(1, 1, 1, 80, 25, TRUE, ' Spool Control ');
  312.   SetWindCoord(2, 1, 1, 80, 25, TRUE, ' File Manager ');
  313.   SetWindCoord(3, 1, 1, 80, 25, FALSE, '');                            { View }
  314.   SetWindCoord(4, 18, 8, 63, 22, TRUE, ' Help ');
  315.   ExitSave := ExitProc;
  316.   ExitProc := @FMScreenExit;
  317. END.
  318. 
  319.