home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 2 / ctrom_ii_b.zip / ctrom_ii_b / PROGRAM / PASCAL / EDITWIN / MINIKIT.PAS < prev    next >
Pascal/Delphi Source File  |  1992-07-01  |  19KB  |  649 lines

  1. {==============================================================}
  2. {                                                              }
  3. {             Saved as: MINIKIT.PAS                            }
  4. {               Author: Pat Anderson                           }
  5. {        Last modified: Friday, June 30, 1992                  }
  6. {              Purpose: Mini tool kit for keyboard input,      }
  7. {                       string functions, color settings,      }
  8. {                       cursor control, fast screen writes     }
  9. {                       and simple windows                     }
  10. {                                                              }
  11. {==============================================================}
  12.  
  13.  
  14. unit MiniKit;
  15.  
  16.  
  17. {==============================================================}
  18.                         INTERFACE
  19. {==============================================================}
  20.  
  21. uses
  22.   Crt,
  23.   Dos;
  24.  
  25. type
  26.   proc = procedure;
  27.   PCursorRec = ^TCursorShape;
  28.   TCursorShape = record
  29.     Start : byte;
  30.     Stop  : byte;
  31.   end;
  32.  
  33.   TWindowCoords = record
  34.     LeftX, TopY, RightX, BottomY : byte;
  35.   end;
  36.  
  37.   PSavedScreenInfo = ^TSavedScreenInfo;
  38.   TSavedScreenInfo = record
  39.     SavedScreenBuffer : pointer;
  40.     WindowCoords : TWindowCoords;
  41.     CursorX : byte;
  42.     CursorY : byte;
  43.     CursorShape : TCursorShape;
  44.     ScreenAttr : byte;
  45.   end;
  46.  
  47. {$I KEYDEFS.INC}
  48.  
  49. var
  50.   IsMono : boolean;                   { TRUE for mono, FALSE for color }
  51.  
  52.   { Some useful screen stuff }
  53.   BaseOfScreen : word;                { $B000 for mono, $B800 for color }
  54.   MonoScreen   : byte absolute $B000:$0000;
  55.   ColorScreen  : byte absolute $B800:$0000;
  56.   ScreenBuffer : pointer;             { points to MonoScreen or ColorScreen }
  57.  
  58.   LinesOnScreen : byte;
  59.  
  60.   In_DV : boolean;                    { TRUE if Desqview detected }
  61.  
  62.   { variables for text attributes for various standard categories }
  63.   TextFore,                           { See SetColors for defaults }
  64.   TextBack,
  65.   Text_Attr,
  66.   EditFore,
  67.   EditBack,
  68.   Edit_Attr,
  69.   StatusFore,
  70.   StatusBack,
  71.   Status_Attr,
  72.   PopFore,
  73.   PopBack,
  74.   Pop_Attr     : byte;
  75.  
  76.   WindowsOpen  : byte;                { How many times PopWindow called }
  77.  
  78. procedure DoNothing;
  79. { Call as argument to GetKey if no other DoWhileIdle procedure }
  80.  
  81. function GetKey (DoWhileIdle : proc) : char;
  82. { Returns a single char for normal and extended ASCII keys }
  83. { Repeatedly calls DoWhileIdle procedure while waiting for key press }
  84.  
  85. function Pad (S : string; PadLength : byte) : string;
  86. { Pad string S with spaces to length PadLength }
  87.  
  88. function Strip (S : string) : string;
  89. { Strip trailing blanks from string S }
  90.  
  91. function ToUpper (S : string) : string;
  92. { Rich Sadowsky's Public Domain UpperCase routine }
  93.  
  94. function LeftStr (S : string; NumChars : byte) : string;
  95. { Returns string containing left most NumChars part of string S }
  96.  
  97. function RightStr (S : string; NumChars : byte) : string;
  98. { Returns string containing right most NumChars part of string S }
  99.  
  100. function MakeString (StrLength : byte;  StrChar : char) : string;
  101. { Returns a string of StrChars of length StrLength }
  102.  
  103. function Merge (SubStr : string; S : string; Position : byte) : string;
  104. { merge substring into string at specified position }
  105.  
  106. function Form (number : longint) : string;
  107. { longint number returned as string formatted with commas }
  108. { format integer by casting to longint }
  109.  
  110. procedure Pause;
  111. { Waits until a key is pressed }
  112.  
  113. procedure GetCursorShape (var Shape : TCursorShape);
  114. { Sets the Start and Stop fields of Shape }
  115.  
  116. procedure CursorOff;
  117. { Turns the cursor off }
  118.  
  119. procedure NormCursorOn;
  120. { Turns underscore cursor on }
  121.  
  122. procedure BlockCursorOn;
  123. { Turns block cursor on }
  124.  
  125. procedure SetCursorShape (Shape : TCursorShape);
  126. { Set cursor shape with Start and Stop fields of Shape }
  127.  
  128. function MakeAttrByte (text_fore, text_back : byte) : byte;
  129. { Return single attribute byte for specified
  130.   foreground and background combination }
  131.  
  132. procedure DrawBox (LeftX, TopY, RightX, BottomY,
  133.                    ColorAttr : byte);
  134. { Draws a single line box }
  135.  
  136. procedure GetWindowCoords (var WindowCoords : TWindowCoords);
  137. { Save current window coordinates as reported by WinMin and WinMax }
  138.  
  139. procedure SetWindowCoords (WindowCoords : TWindowCoords);
  140. { Call the Window procedure with new coordinates }
  141.  
  142. function SaveScreen (var SavedScreen : TSavedScreenInfo) : boolean;
  143. { Save screen contents to heap - returns success = true, failure = false }
  144.  
  145. procedure RestoreScreen (var SavedScreen : TSavedScreenInfo);
  146. { Restores saved screen from heap to physical screen }
  147.  
  148. procedure PopWindow (LeftX, TopY, RightX, BottomY,
  149.                      ColorAttr : byte; var SavedScreen : TSavedScreenInfo);
  150. { Pops up a framed window at specified screen coordinates }
  151.  
  152. procedure CloseWindow (var SavedScreen : TSavedScreenInfo);
  153. { procedure to close an open window }
  154.  
  155. function DirExists (DirName : string) : boolean;
  156. { TUG PD function to determine whether a specified directory exists }
  157.  
  158. function FileExists (FileName : string) : boolean;
  159. { TUG PD function to determine if a specified file already exists }
  160.  
  161. procedure FastWrite (Strng : string; Row, Col, Attr : byte);
  162. { Brian Foley's Public Domain FastWrite routine }
  163.  
  164. procedure BlockAttr (X1, Y1, X2, Y2 : word; Attr : byte);
  165. { Change color attributes in defined screen area without
  166.   altering text characters - From IPE by Bill Swenson/Allen Drennan }
  167.  
  168. {==============================================================}
  169.                         IMPLEMENTATION
  170. {==============================================================}
  171.  
  172. var
  173.   OriginalExit : pointer;             { Original TP exit procedure }
  174.   OriginalMode : word;                { Video mode on startup }
  175.   OriginalAttr : byte;                { Text attribute on startup }
  176.   OriginalCursorShape : TCursorShape;
  177.   SaveX,
  178.   SaveY,
  179.   SaveAttr           : byte;
  180.   WindowOpen         : boolean;
  181.   F                  : file;
  182.   FileAttr           : word;
  183.  
  184. procedure DoNothing;
  185.   begin
  186.   end;
  187.  
  188. function GetKey (DoWhileIdle : proc) : char;
  189.   var
  190.     key : char;
  191.   begin
  192.     while not KeyPressed do
  193.       DoWhileIdle;
  194.     key := ReadKey;
  195.     {Handle extended ASCII codes}
  196.     if (key = #0) AND KeyPressed then
  197.       key := Chr (Ord(ReadKey) OR $80);
  198.       { $80 = 1000 0000 binary, turns on high bit }
  199.     GetKey := key;
  200.   end;
  201.  
  202. function Pad (S : string; PadLength : byte) : string;
  203.   begin
  204.     while Length (S) < PadLength do
  205.       S := S + ' ';
  206.     Pad := S;
  207.   end;
  208.  
  209. function Strip (S : string) : string;
  210.   begin
  211.     while S[Length (S)] = ' ' do
  212.       S := Copy (S, 1, (Length (S) - 1));
  213.     Strip := S;
  214.     end;
  215.  
  216. function ToUpper (S : String) : string; assembler;
  217.   asm
  218.        PUSH      DS
  219.        LDS       SI,DWORD PTR [S]
  220.        LES       DI,@Result;
  221.        CLD
  222.        LODSB
  223.        STOSB
  224.        MOV       CL,AL
  225.        XOR       CH,CH
  226.        JCXZ      @ExitCode
  227.   @LowerLoop:
  228.        LODSB
  229.        CMP       AL,'a'
  230.        JB        @CopyChar
  231.        CMP       AL,'z'
  232.        JA        @CopyChar
  233.        SUB       AL,'a'-'A'
  234.   @CopyChar:
  235.        STOSB
  236.        LOOP      @LowerLoop
  237.   @ExitCode:
  238.        POP       DS
  239. end;
  240.  
  241. function LeftStr (S : string; NumChars : byte) : string;
  242.   begin
  243.     if NumChars = 0 then
  244.       LeftStr := ''
  245.     else
  246.       LeftStr := Copy (S, 1, NumChars);
  247.   end;
  248.  
  249. function RightStr (S : string; NumChars : byte) : string;
  250.   begin
  251.     if NumChars = 0 then
  252.       RightStr := ''
  253.     else if NumChars < Ord (S[0]) then
  254.       RightStr := Copy (S, Ord (S[0]) - NumChars + 1, NumChars)
  255.     else if NumChars >= Ord (S[0]) then
  256.       RightStr := S;
  257.   end;
  258.  
  259. function MakeString (StrLength : byte;  StrChar : char) : string;
  260.   var
  261.     TempStr : string;
  262.   begin
  263.     FillChar (TempStr[1], word (StrLength), StrChar);
  264.     TempStr[0] := char (StrLength);
  265.     MakeString := TempStr;
  266.   end;
  267.  
  268. function Merge (SubStr : string; S : string; Position : byte) : string;
  269.   begin
  270.     Move (SubStr[1], S[Position], Ord (SubStr[0]));
  271.     Merge := S;
  272.   end;
  273.  
  274. function Form (number : longint) : string;
  275.   var
  276.     TempStr : string;
  277.     OrgLen : byte;
  278.   begin
  279.     Str (number, tempstr);
  280.     OrgLen := Length (tempstr);
  281.     if OrgLen > 3 then
  282.       begin
  283.         if OrgLen < 7 then
  284.           Insert (',', tempstr, Length (tempstr) - 2);
  285.         if OrgLen >= 7 then
  286.           begin
  287.             Insert (',', tempstr, length (tempstr) - 5);
  288.             Insert (',', tempstr, length (tempstr) - 2);
  289.           end;
  290.       end;
  291.     Form := tempstr;
  292.   end;
  293.  
  294. procedure Pause;
  295.   var
  296.     dummy : char;
  297.   begin
  298.     dummy := GetKey (DoNothing)
  299.   end;
  300.  
  301. procedure GetCursorShape (var Shape : TCursorShape); assembler;
  302.   asm
  303.     mov ah,$03
  304.     mov bx,$00
  305.     int $10
  306.     les di,Shape
  307.     mov TCursorShape (es:[di]).Start,ch    {es:[di] is Start field of Shape}
  308.     mov TCursorShape (es:[di]).Stop,cl  {es:[di+1] is Stop field of Shape}
  309.   end;
  310.  
  311. procedure SetCursorShape; assembler;
  312.   asm
  313.     mov ah,$01             { Service 1, set cursor size }
  314.     mov ch,Shape.Start
  315.     mov cl,Shape.Stop
  316.     int $10
  317.   end;
  318.  
  319. procedure CursorOff;  assembler;
  320.   asm
  321.     mov ah,$01
  322.     mov ch,$20
  323.     mov cl,$00
  324.     int $10
  325.   end;
  326.  
  327. procedure NormCursorOn;
  328.   var
  329.     Shape : TCursorShape;
  330.   begin
  331.     if IsMono then
  332.       begin
  333.         Shape.Start := $0A;
  334.         Shape.Stop := $0B;
  335.       end
  336.     else
  337.       begin
  338.         Shape.Start := $06;
  339.         Shape.Stop := $07;
  340.       end;
  341.     SetCursorShape (Shape);
  342.   end;
  343.  
  344. procedure BlockCursorOn;
  345.   var
  346.     Shape : TCursorShape;
  347.   begin
  348.     if IsMono then
  349.       begin
  350.         Shape.Start := $02;
  351.         Shape.Stop := $0B;
  352.       end
  353.     else
  354.       begin
  355.         Shape.Start := $02;
  356.         Shape.Stop := $08;
  357.       end;
  358.     SetCursorShape (Shape);
  359.   end;
  360.  
  361. function MakeAttrByte;
  362.   begin
  363.     MakeAttrByte := (text_back * 16) + text_fore;
  364.   end;
  365.  
  366. procedure DrawBox;
  367.   const
  368.     TopLeftChar        = #213;
  369.     TopRightChar       = #184;
  370.     BottomLeftChar     = #212;
  371.     BottomRightChar    = #190;
  372.     HorizontalLineChar = #205;
  373.     VerticalLineChar   = #179;
  374.   var
  375.     column,
  376.     row : byte;
  377.   begin
  378.     {Draw corners}
  379.     FastWrite (TopLeftChar, TopY, LeftX, ColorAttr);
  380.     FastWrite (BottomLeftChar, BottomY, LeftX, ColorAttr);
  381.     FastWrite (TopRightChar, TopY, RightX, ColorAttr);
  382.     FastWrite (BottomRightChar, BottomY, RightX, ColorAttr);
  383.     {Draw horizontal lines}
  384.     for column := LeftX + 1 TO RightX - 1 do
  385.       begin
  386.         FastWrite (HorizontalLineChar, TopY, column, ColorAttr);
  387.         FastWrite (HorizontalLineChar, BottomY, column, ColorAttr);
  388.       end;
  389.  
  390.     {Draw vertical lines}
  391.     for row := TopY + 1 TO BottomY - 1 do
  392.       begin
  393.         FastWrite (VerticalLineChar, Row, LeftX, ColorAttr);
  394.         FastWrite (VerticalLineChar, Row, RightX, ColorAttr);
  395.       end;
  396. end; {of procedure DrawBox}
  397.  
  398. procedure GetWindowCoords (var WindowCoords : TWindowCoords);
  399.   begin
  400.     with WindowCoords do begin
  401.       LeftX := Succ (Lo (WindMin));
  402.       TopY  := Succ (Hi (WindMin));
  403.       RightX := Succ (Lo (WindMax));
  404.       BottomY := Succ (Hi (WindMax));
  405.     end;
  406.   end;
  407.  
  408. procedure SetWindowCoords (WindowCoords : TWindowCoords);
  409.   begin
  410.     with WindowCoords do
  411.       Window (LeftX, TopY, RightX, BottomY);
  412.   end;
  413.  
  414. function SaveScreen (var SavedScreen : TSavedScreenInfo) : boolean;
  415.   var OK : boolean;
  416.   begin
  417.     SaveScreen := true;
  418.     OK := true;
  419.     if not MaxAvail > 4000 then begin
  420.       SaveScreen := false;
  421.       OK := false;
  422.     end;
  423.     if SavedScreen.SavedScreenBuffer <> nil then begin
  424.       SaveScreen := false;
  425.       OK := false;
  426.     end;
  427.     if OK then
  428.       with SavedScreen do begin
  429.         GetMem (SavedScreenBuffer, 4000);
  430.         Move (ScreenBuffer^, SavedScreenBuffer^, 4000);
  431.         GetWindowCoords (WindowCoords);
  432.         CursorX := WhereX;
  433.         CursorY := WhereY;
  434.         GetCursorShape (CursorShape);
  435.         ScreenAttr := TextAttr;
  436.       end;
  437.   end;
  438.  
  439. procedure RestoreScreen (var SavedScreen : TSavedScreenInfo);
  440.   begin
  441.     with SavedScreen do begin
  442.       Move (SavedScreenBuffer^, ScreenBuffer^, 4000);
  443.       FreeMem (SavedScreenBuffer, 4000);
  444.       SavedScreenBuffer := nil;
  445.       SetWindowCoords (WindowCoords);
  446.       GotoXY (CursorX, CursorY);
  447.       SetCursorShape (CursorShape);
  448.       TextAttr := ScreenAttr;
  449.     end;
  450.   end;
  451.  
  452. procedure PopWindow;
  453.   var
  454.     OK : boolean;
  455.   begin
  456.     OK := SaveScreen (SavedScreen);
  457.     DrawBox (LeftX, TopY, RightX, BottomY, ColorAttr);
  458.     TextAttr := ColorAttr;
  459.     Window (LeftX + 1, TopY + 1, RightX - 1, BottomY - 1);
  460.     ClrScr;
  461.     Inc (WindowsOpen);
  462.   end; {procedure PopWindow}
  463.  
  464. procedure CloseWindow;
  465.   begin
  466.     if not WindowOpen then
  467.       Exit;
  468.     Window (1,1,80,25);
  469.     RestoreScreen (SavedScreen);
  470.     WindowOpen := FALSE;
  471.     TextAttr := SaveAttr;
  472.     Dec (WindowsOpen);
  473.   end; {of procedure CloseWindow}
  474.  
  475. function DirExists;
  476.   begin
  477.     Assign (F,DirName);
  478.     GetFAttr (F, FileAttr);
  479.     DirExists := (FileAttr AND Directory) <> 0
  480.   end; {DirExists}
  481.  
  482. function FileExists;
  483.   begin
  484.     Assign (F, FileName);
  485.     GetFAttr (F, FileAttr);
  486.     FileExists := (FileAttr <> 0) AND ((FileAttr AND Directory) = 0)
  487.   end; { FileExists }
  488.  
  489. procedure  FastWrite(Strng : String; Row, Col, Attr : Byte); assembler;
  490.   asm
  491.       PUSH    DS                     { ;Save DS }
  492.       MOV     CH,Row                 { ;CH = Row }
  493.       MOV     BL,Col                 { ;BL = Column }
  494.  
  495.       XOR     AX,AX                  { ;AX = 0 }
  496.       MOV     CL,AL                  { ;CL = 0 }
  497.       MOV     BH,AL                  { ;BH = 0 }
  498.       DEC     CH                     { ;Row (in CH) to 0..24 range }
  499.       SHR     CX,1                   { ;CX = Row * 128 }
  500.       MOV     DI,CX                  { ;Store in DI }
  501.       SHR     DI,1                   { ;DI = Row * 64 }
  502.       SHR     DI,1                   { ;DI = Row * 32 }
  503.       ADD     DI,CX                  { ;DI = (Row * 160) }
  504.       DEC     BX                     { ;Col (in BX) to 0..79 range }
  505.       SHL     BX,1                   { ;Account for attribute bytes }
  506.       ADD     DI,BX                  { ;DI = (Row * 160) + (Col * 2) }
  507.       MOV     ES,BaseOfScreen        { ;ES:DI points to BaseOfScreen:Row,Col }
  508.  
  509.       LDS     SI,DWORD PTR [Strng]   { ;DS:SI points to St[0] }
  510.       CLD                            { ;Set direction to forward }
  511.       LODSB                          { ;AX = Length(St); DS:SI -> St[1] }
  512.       XCHG    AX,CX                  { ;CX = Length; AL = WaitForRetrace }
  513.       JCXZ    @FWExit                { ;If string empty, exit }
  514.       MOV     AH,Attr                { ;AH = Attribute }
  515.     @FWDisplay:
  516.       LODSB                          { ;Load next character into AL }
  517.                                      { ; AH already has Attr }
  518.       STOSW                          { ;Move video word into place }
  519.       LOOP    @FWDisplay             { ;Get next character }
  520.     @FWExit:
  521.       POP     DS                     { ;Restore DS }
  522.   end; {asm block}
  523.  
  524. procedure BlockAttr (X1, Y1, X2, Y2 : word; Attr : byte);
  525.   var UpperLeft, LowerRight : word;
  526.   begin
  527.     UpperLeft := Pred (X1) * 2 + 160 * Pred (Y1) + 1;
  528.     LowerRight := Pred (X2) * 2 + 160 * Pred (Y2) + 1;
  529.     asm
  530.       CLD
  531.       MOV     AX,BaseOfScreen
  532.       MOV     ES,AX
  533.       MOV     DI,UpperLeft
  534.       MOV     AL, Attr
  535.       MOV     DX,X2
  536.       SUB     DX,X1
  537.       INC     DX
  538. @X23: MOV     CX,DX
  539. @X25: STOSB
  540.       INC     DI
  541.       LOOP    @X25
  542.       SUB     DI,DX
  543.       SUB     DI,DX
  544.       ADD     DI,$00A0
  545.       CMP     DI,LowerRight
  546.       JLE     @X23
  547.     end;
  548.   end;
  549.  
  550. procedure SetColors;
  551.   begin
  552.     if IsMono then
  553.       begin
  554.         TextFore := lightgray;
  555.         TextBack := black;
  556.         EditFore := white;
  557.         EditBack := black;
  558.         PopFore  := black;
  559.         PopBack  := lightgray;
  560.         PopBack  := lightgray;
  561.         StatusFore := black;
  562.         StatusBack := lightgray;
  563.       end
  564.     else
  565.       begin
  566.         TextFore := lightgray;
  567.         TextBack := blue;
  568.         EditFore := white;
  569.         EditBack := blue;
  570.         PopFore  := blue;
  571.         PopBack  := lightgray;
  572.         StatusFore := yellow;
  573.         StatusBack := red;
  574.       end;
  575.     Text_Attr   := MakeAttrByte (TextFore, TextBack);
  576.     Edit_Attr   := MakeAttrByte (EditFore, EditBack);
  577.     Pop_Attr    := MakeAttrByte (PopFore, PopBack);
  578.     Status_Attr := MakeAttrByte (StatusFore, StatusBack);
  579.   end; {of procedure SetColors}
  580.  
  581. procedure GetAlternateBuffer; assembler;
  582.   asm
  583.     mov ah,$fe
  584.     int $10
  585.     mov BaseOfScreen,es
  586.   end;
  587.  
  588. procedure CheckForDesqview; assembler;
  589.   asm
  590.     mov In_DV,false
  591.     mov cx,'DE'
  592.     mov dx,'SQ'
  593.     mov ax,$2B01
  594.     int $21
  595.     cmp al,$ff
  596.     je @No_Desqview
  597.     mov In_DV,true
  598.   @No_Desqview:
  599.   end;
  600.  
  601. procedure GetAdaptorType;
  602.   begin
  603.     if LastMode = 7 then
  604.       IsMono := true
  605.     else
  606.       IsMono := false;
  607.   end;
  608.  
  609. procedure PoliteExit; far;
  610.   begin
  611.     ExitProc := OriginalExit;             {Put TP's ExitProc back in chain}
  612.     if LastMode <> OriginalMode then      {If the text mode has changed }
  613.       TextMode (OriginalMode);            {  restore video mode}
  614.     TextAttr := OriginalAttr;             { Restore text attribute }
  615.     SetCursorShape (OriginalCursorShape); {restore cursor shape}
  616.     NormVideo;                            {restore text attributes}
  617.   end;
  618.  
  619. procedure InstallPoliteExit;
  620.   begin
  621.     OriginalMode := LastMode;             { save startup video mode }
  622.     OriginalAttr := TextAttr;             { save startup text attribute }
  623.     GetCursorShape (OriginalCursorShape); { save startup cursor shape }
  624.  
  625.     OriginalExit := ExitProc;             {Save TP's ExitProc}
  626.     ExitProc := @PoliteExit;              {Put PoliteExit in chain}
  627.   end;
  628.  
  629. { Unit initialization }
  630. begin
  631.   InstallPoliteExit;                    { restore video mode & cursor on exit }
  632.   GetAdaptorType;                       { color or mono }
  633.   CheckForDesqview;                     { initialize In_DV variable }
  634.   LinesOnScreen := Hi (WindMax) + 1;    { WindMax is 0 based }
  635.   SetColors;                            { default text, edit, status }
  636.                                         {   & pop attributes }
  637.   if IsMono then                        { define screen location }
  638.     begin
  639.       ScreenBuffer := @MonoScreen;  { a pointer }
  640.       BaseOfScreen := $B000;          { segment address as a word value }
  641.     end
  642.   else
  643.     begin
  644.       ScreenBuffer := @ColorScreen;
  645.       BaseOfScreen := $B800;
  646.     end;
  647.   WindowsOpen := 0;
  648. end.
  649.