home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / utility / crossref / pxl / pxlinit.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1988-05-04  |  38.5 KB  |  1,094 lines

  1. {$R-}    {Range checking off}                                          {.CP5}
  2. {$B-}    {Boolean complete evaluation off}
  3. {$S+}    {Stack checking on}
  4. {$I+}    {I/O checking on}
  5. {$N-}    {No numeric coprocessor}
  6.  
  7. Unit PXLINIT;
  8.  
  9. Interface
  10.  
  11. Uses
  12.   Crt,
  13.   Dos;
  14.  
  15. const                                                                  {.CP9}
  16.    StdLineWidth   = 80;
  17.    ScreenSize     = 2000;
  18.    Triggers: set of char = [#27,#3];
  19.    NoIncFiles = 8;
  20.    BoxT =  5;
  21.    BoxB = 21;
  22.    BoxL = 10;
  23.    BoxR = 70;
  24.  
  25. type                                                                  {.CP25}
  26.    ColType      =  record                    {These 3 make a scrn size array}
  27.                       case boolean of        {Addressed like BASIC'S screen }
  28.                          True:  (C,A: byte); {[Row,Col].C = char            }
  29.                          False: (I: word)    {[Row,Col].A = attribute       }
  30.                    end;                      {[Row,Col].I = both, but with  }
  31.    RowType      =  array[1..80] of ColType;  {   attribute in hi byte       }
  32.    ScrType      =  array[1..25] of RowType;  {   character in lo byte       }
  33.    ScrPtrType   =  ^ScrType;
  34.    MonitorType  =  (MDA,CGA,EGA);
  35.    LineType     =  string[StdLineWidth];
  36.    CharSet      =  set of char;
  37.    TpFace   = (MrkB,MrkE,EliteB,EliteE,CondB,CondE,FF);
  38.    ByteLine = array[0..3] of byte;
  39.    Bytes    = array[MrkB..FF] of Byteline;
  40.    Fil      = file of ByteLine;
  41.    Str255   = string[255];
  42.    CMD      = string[128]; {For command line}
  43.    Str20    = string[20];
  44.    Str10    = string[10]; {Must be large enough for longest reserved word}
  45.    Str9     = string[9];
  46.    Str5     = string[5];
  47.    Str4     = string[4];
  48.    Str3     = string[3];
  49.    str2     = string[2];
  50.    ResArr   = array[1..100] of Str20;
  51.  
  52. var                                                                   {.CP20}
  53.    CRTube:    ScrPtrType;  {Set to point at real screen buffer}
  54.    CRTAddr:   array[1..2] of word absolute CRTube;
  55.    Monitor:   MonitorType;
  56.    OrigAtt:   byte;
  57.    BlnkLn:    LineType;
  58.    Scr:                ScrType;
  59.    C:                  char;
  60.    Inside,
  61.    BottomMargin,
  62.    MaxLin,
  63.    NormalColor,
  64.    FrameColor,
  65.    Background,
  66.    Bright,Dim:         byte;
  67.    F,Lst:              text;
  68.    IFil:               array[1..NoIncFiles] of text;
  69.    IFileName:          array[1..NoIncFiles] of LineType;
  70.    IFN:                1..NoIncFiles;
  71.    PathSign,
  72.    FileName:           LineType;
  73.    Opening,Closing:    Str3;                                          {.CP22}
  74.    PrintDate,
  75.    FileDate:           Str20;
  76.    PrintTime,
  77.    FileTime:           Str10;
  78.    UserID:             string[25];
  79.    Number:             string[16];
  80.    Line:               Str255;
  81.    Day,I,LineNumber,
  82.      PageLineNumber,
  83.      Page,Year,NRes:  integer;
  84.    ScrSeg:             word;
  85.    GotPrnData,Plain,
  86.      Mrk,XRef,Wide,
  87.      XRefOnly,Enough,
  88.      NumberLines,
  89.      InABatch,FFeed,
  90.      DataFiles:        boolean;
  91.    Inst:               Bytes;
  92.    T:                  TpFace;
  93.    Istring:            array[MrkB..CondE] of Str3;
  94.    Reserv:             ResArr;
  95.    OutputDevice:       string[14];
  96.    Command:            CMD;
  97.  
  98. procedure Bip;
  99. procedure Beep;
  100. procedure Bop;
  101. procedure ToScrn(var S: ScrType);
  102. procedure FromScrn(var S: ScrType);
  103. procedure FillWd(Segm,Offst,Num,Wd: word);
  104. procedure FillOdd(Segm,Offst,Num: integer; Bt: byte);
  105. procedure SkipMove(var From,Target; Num: word);
  106. procedure GetScreen;
  107. procedure WipeSlate(var S: ScrType; Clr: byte);
  108. procedure Rectangle(var S: ScrType; R1,C1,R2,C2,Att,Vert,Hor: byte);
  109. procedure WriteIt(var Scr: ScrType; Str: LineType; R,C,Color: byte);
  110. procedure WriteCRT(Str: LineType; Row,Col,Att: byte);
  111. procedure CenterCRT(S: LineType; Row,Attrib,Width: byte);
  112. procedure Center(var Scr: ScrType; Str: LineType; Line,Color,Width: byte);
  113. function CurrentAttribute: byte;
  114. procedure CursorOff; {invisible but present}
  115. procedure CursorOn;
  116. procedure RestoreScreen;
  117. procedure SetErrorLevel(Level: byte);
  118. procedure SetScrAtt(Att: byte);
  119.  
  120. function IsIntense(A: byte): boolean;
  121. function Intensified(A: byte): byte;
  122. function Dimmed(A: byte): byte;
  123. function IsBlinking(A: byte): boolean;
  124. function Blinking(A: byte): byte;
  125. function UnBlinking(A: byte): byte;
  126. function BlackBackground(A: byte): boolean;
  127. function BlackForeground(A: byte): boolean;
  128. function BackgroundOf(A: byte): byte;
  129. function ForegroundOf(A: byte): byte;
  130. function InverseOf(A: byte): byte;
  131. function CombinedAttributeOf(F,B: byte): byte;
  132.  
  133. function PadOrChop(L: LineType; Len: byte):LineType;
  134. procedure Replace(This,WithThat: LineType; var TheLine: LineType);
  135.  
  136. function StrgB(B,L: Byte): LineType;
  137. function StrgR(R: real;L1,L2: Byte): LineType;
  138. function StrgI(B,L: Integer): Str9;
  139. function Strip(L: LineType; NoNo: CharSet): LineType;
  140. function InCapitals(L: LineType): LineType;
  141.  
  142. function KbIn(var Extended: boolean): char;
  143. function EditTrm(N: byte): LineType;
  144.  
  145. function CurrentDriveAndDirectory: LineType;
  146.    {Returns full current drive:\directory}
  147.  
  148. function EnvironLine(LineStart: LineType): LineType;                   {.CP3}
  149.    {Searches DOS environment for line beginning with LineStart}
  150.    {If found, returned in EnvironLine.  If not returns "NONE"}
  151. function FindFile(var FName: LineType): boolean;                       {.CP4}
  152.    {Takes File name.  Searches for file on default drive & along DOS PATH. }
  153.    {Reports success or failure in FindFile.                                }
  154.    {If file is found, returns openable FName with successful path prefixed.}
  155. procedure CloseCarefully(var F: text);
  156.  
  157. function Escape: boolean;                                              {.CP3}
  158. {  Empties the keyboard buffer & returns False if no trigger}
  159. {  Does not wait for a keypress}
  160.  
  161. procedure Blank(Top,Bot: integer);
  162. procedure ByeBye;
  163. procedure GetOutOfHere;
  164. procedure PXLRectangle;
  165. procedure CantCont(FilNam,Comment: LineType);
  166. procedure GetPrinterData;                                              {.CP3}
  167. {If constant DataFiles is True, this procedure loads printer control }
  168. {symbols from PXL.PRN.  If it's false, they're set here.             }
  169. function DefaultDrive: char; {Returns letter of Default Drive}
  170. procedure FixUpFileName(Var FilNam: LineType);
  171. function Shortened(FileName: LineType): Str20;
  172.  
  173. {===========================================================================}
  174.  
  175. Implementation
  176.  
  177. procedure Bip;                                                         {.CP5}
  178. begin
  179.    sound(1760); delay(10); sound(440); delay(30);
  180.    sound(1760); delay(15); nosound
  181. end;
  182.  
  183. procedure Beep;                                                        {.CP4}
  184. begin
  185.    sound(456);
  186. end; {Beep}
  187.  
  188. procedure Bop;                                                         {.CP4}
  189. begin
  190.    delay(100); nosound; delay(150); sound(362); delay(400); nosound;
  191. end; {Bop}
  192.  
  193. procedure ToScrn;                                                     {.CP14}
  194. const
  195.    ScrnPort        = $3D8;           {for CGA board}
  196.    On              =  45;            {for ScrnPort}
  197.    Off             =   5;
  198. begin
  199.    if Monitor=CGA then begin
  200.       Port[ScrnPort] := Off;
  201.       CRTube^ := S;
  202.       Port[ScrnPort] := On
  203.    end {if CGA}
  204.    else
  205.       CRTube^ := S
  206. end; {ToScrn}
  207.  
  208. procedure FromScrn;                                                   {.CP14}
  209. const
  210.    ScrnPort        = $3D8;           {for CGA board}
  211.    On              =  45;            {for ScrnPort}
  212.    Off             =   5;
  213. begin
  214.    if Monitor=CGA then begin
  215.       Port[ScrnPort] := Off;
  216.       S := CRTube^;
  217.       Port[ScrnPort] := On
  218.    end {if CGA}
  219.    else
  220.       S := CRTube^
  221. end; {FromScrn}
  222.  
  223. procedure FillWd;                                                     {.CP18}
  224. { Like FillChar but fills with 2-byte integers.  Here declared:      }
  225. {      procedure FillWd(Segm,Offst,Num,Wd: integer)                  }
  226. { Can also be declared:                                              }
  227. {      procedure FillWd(var S; Num,Wd: integer)                      }
  228. begin
  229.    inline
  230.                   {FILLWD PROC NEAR                                  }
  231.                   {       INLINE                                     }
  232.    ($C4/$7E/$0A/  { <     les  di, 08H[bp] ; load di and ds at once  }
  233.                   {                                                  }
  234.    $8B/$4E/$08/   { <     MOV  CX,6[BP]    ; Num                     }
  235.    $8B/$46/$06/   { <     MOV  AX,4[BP]    ; Wd                      }
  236.                   {                                                  }
  237.    $FC/           {       cld              ;8088 ==> autoincrement   }
  238.    $F3/           {       rep              ;store CX copies of AX in }
  239.    $AB)           {       stosw            ; ES:[DI] (not DS:[DI])   }
  240. end; {FillWd}
  241.  
  242. procedure FillOdd;                                                    {.CP21}
  243.    {Turbo Pascal INLINE procedure like FillChar but skips even bytes in }
  244.    {target.  Use it To write without coloring or color without writing. }
  245.    {Here declared:                                                      }
  246.    {   procedure FillOdd(Segm,Offst,Num: integer; Bt: byte);            }
  247.    {Can also be declared:                                               }
  248.    {   procedure FillWd(var V; Num, integer; Bt: byte);                 }
  249. begin                  {       INLINE                                   }
  250.    inline(             {FILLWD PROC NEAR                                }
  251.    $1E/                {       PUSH DS          ; Save DS               }
  252.    $8E/$5E/$0C/        {       MOV  DS,0AH[BP]  ; Segm                  }
  253.    $8B/$7E/$0A/        {       MOV  DI,8H[BP]   ; Offst                 }
  254.    $8B/$4E/$08/        {       MOV  CX,6H[BP]   ; Num                   }
  255.    $29/$C0/            {       SUB  AX,AX                               }
  256.    $8A/$46/$06/        {       MOV  AL,4H[BP]   ; Bt                    }
  257.    $88/$05/            {START  MOV  [DI],AL     ; Put Bt in target      }
  258.    $47/                {       INC  DI          ; Shift target          }
  259.    $47/                {       INC  DI          ;  twice                }
  260.    $E2/$FA/            {       LOOP START       ; Loop CX (Num) times   }
  261.    $1F)                {       POP  DS          ; Restore DS            }
  262. end; {FillOdd}         {       ENDP                                     }
  263.  
  264. procedure SkipMove;                                                   {.CP27}
  265.   {Moves Num bytes from source to Target, skipping bytes in Target.     }
  266.   {Could write to screen w/o coloring. (Beware: can't handle overlap).  }
  267.   {Here declared:                                                       }
  268.   {   procedure SkipMove(var From,Target; Num: integer);                }
  269.   {Can also be declared:                                                }
  270.   {   procedure SkipMove(SegS,OffS,SegT,OffT,Num: integer);             }
  271. begin                   {                                               }
  272.    inline(              {       inline                                  }
  273.                         {FILLWD PROC NEAR                               }
  274.    $1E/                 {       push ds                                 }
  275.    $8E/$46/$0E/         {       mov  es,0ch[bp]  ;SegS                  }
  276.    $8B/$76/$0C/         {       mov  si,0ah[bp]  ;OffS                  }
  277.                         {                                               }
  278.    $8E/$5E/$0A/         {       MOV  DS,08H[BP]  ; SegT                 }
  279.    $8B/$7E/$08/         {       MOV  DI,06H[BP]  ; OffT                 }
  280.    $28/$ED/             {       sub  ch,ch                              }
  281.    $8A/$4E/$06/         {       MOV  CL,04h[BP]    ; Num in CX          }
  282.                         {                                               }
  283.    $26/$8A/$04/         {START  mov  al,es:[si]  ; Get byte from source }
  284.    $88/$05/             {       MOV  [DI],al     ; Put byte in target   }
  285.    $47/                 {       INC  DI          ; Shift target         }
  286.    $47/                 {       INC  DI          ;  twice               }
  287.    $46/                 {       inc  si          ; Shift source once    }
  288.    $E2/$F6/             {       LOOP START       ; Loop CX (Num) times  }
  289.    $1F)                 {       POP  DS          ; Restore DS           }
  290. end; {SkipMove}         {       ENDP                                    }
  291.  
  292. procedure GetScreen;                                                  {.CP13}
  293.  
  294.    function MonitorIsEGA: boolean;
  295.    var
  296.       R: Registers;
  297.    begin
  298.      with R do begin
  299.         AH := $12;
  300.         BX := $FF10;
  301.         intr($10,R);
  302.         MonitorIsEga := BH<>$FF
  303.      end {with}
  304.   end; {MonitorIsEGA}
  305.  
  306. begin                                                                 {.CP12}
  307.    if (Lo(LastMode)=7) then begin
  308.       CRTube := Ptr($B000,0000);
  309.       Monitor := MDA;
  310.    end {if mode 7}
  311.    else begin
  312.       CRTube := Ptr($B800,0000);
  313.       if MonitorIsEGA
  314.          then Monitor := EGA
  315.          else Monitor := CGA
  316.    end {else not 7}
  317. end; {GetScrn}
  318.  
  319. procedure WipeSlate;                                                   {.CP8}
  320. {Set attributes all to same color)}
  321. var
  322.    Filler:    integer;
  323. begin
  324.    Filler := (Clr shl 8) + $20;
  325.    FillWd(seg(S),ofs(S),2000,Filler);
  326. end; {WipeSlate}
  327.  
  328. procedure Rectangle;                                                  {.CP11}
  329. {R1,C1 is row & col of upper left corner, R2,C2 is lower right      }
  330. {Vert is single or double vert char, Hor is single or 2ble horizontal}
  331. const
  332.    OK: set of byte = [1..2];
  333. type
  334.    Rchars = (Hr,Vr,UL,UR,LL,LR);
  335. var
  336.    Element: array[Hr..LR] of byte;
  337.    Row:     byte;
  338.    Filler:  integer;
  339. begin                                                                 {.CP20}
  340.    if not (Hor in OK) then Hor := 1;
  341.    if not (Vert in OK) then Vert := 1;
  342.    if Vert=1 then begin
  343.       Element[Vr] := 179;
  344.       if Hor=1 then begin
  345.          Element[Hr] := 196;       {V1 H1}
  346.          Element[UL] := 218;
  347.          Element[UR] := 191;
  348.          Element[LL] := 192;
  349.          Element[LR] := 217;
  350.       end {if Hor=1}
  351.       else if Hor=2 then begin    {V1 H2}
  352.          Element[Hr] := 205;
  353.          Element[UL] := 213;
  354.          Element[UR] := 184;
  355.          Element[LL] := 212;
  356.          Element[LR] := 190;
  357.        end {if Hor=2}
  358.    end {if V1}
  359.    else begin                                                         {.CP17}
  360.       Element[Vr] := 186;
  361.       if Hor=1 then begin
  362.          Element[Hr] := 196;       {V2 H1}
  363.          Element[UL] := 214;
  364.          Element[UR] := 183;
  365.          Element[LL] := 211;
  366.          Element[LR] := 189;
  367.       end {if Hor=1}
  368.       else if Hor=2 then begin    {V2 H2}
  369.          Element[Hr] := 205;
  370.          Element[UL] := 201;
  371.          Element[UR] := 187;
  372.          Element[LL] := 200;
  373.          Element[LR] := 188;
  374.        end {if Hor=2}
  375.    end; {else Ver=2}
  376.  
  377.    Filler := Att shl 8 + Element[Hr];                                 {.CP4}
  378.    FillWd(seg(S[R1,C1].I),ofs(S[R1,C1].I),succ(C2-C1),Filler);
  379.    FillWd(seg(S[R2,C1].I),ofs(S[R2,C1].I),succ(C2-C1),Filler);
  380.    Filler := Att shl 8 + Element[Vr];
  381.  
  382.    for Row := succ(R1) to pred(R2) do begin                           {.CP4}
  383.       S[Row,C1].I  := Filler;
  384.       S[Row,C2].I  := Filler
  385.    end; {for Row}
  386.  
  387.    S[R1,C1].I  := Att shl 8 + Element[UL];                            {.CP5}
  388.    S[R2,C1].I  := Att shl 8 + Element[LL];
  389.    S[R1,C2].I  := Att shl 8 + Element[UR];
  390.    S[R2,C2].I  := Att shl 8 + Element[LR];
  391. end; {Rectangle}
  392.  
  393. procedure WriteIt;                                                    {.CP6}
  394. {R is row; C is column in which to start.}
  395. begin
  396.    FillWd(Seg(Scr[R,C]),Ofs(Scr[R,C]),ord(Str[0]),succ(Color shl 8));
  397.    SkipMove(Str[1],Scr[R,C],ord(Str[0]));
  398. end; {WriteIt}
  399.  
  400. procedure WriteCRT;                                                   {.CP4}
  401.  { Writes characters quickly to the screen starting at Row, Col, }
  402.  { using attribute Att.  Detects presence of Text or CGA board.  }
  403.  { If it finds a CGA, chars are snuck in during vertical retrace }
  404.  { to avoid snow. }
  405. begin
  406.    inline(      {         INLINE ; CHASM's famous Turbo feature  }    {.CP29}
  407.                 {WRITECRT PROC FAR                               }
  408.    $1E/         {         PUSH DS                                }
  409.    $1E/         {         PUSH DS                                }
  410.    $8A/$46/$0A/ {         MOV  AL,08H[BP]     ; Row.             }
  411.    $FE/$C8/     {         DEC  AL             ; Make top Row 1   }
  412.    $B3/$50/     {         MOV  BL,80                             }
  413.    $F6/$E3/     {         MUL  BL                                }
  414.    $29/$DB/     {         SUB  BX,BX                             }
  415.    $8A/$5E/$08/ {         MOV  BL,06H[BP]     ; Col              }
  416.    $FE/$CB/     {         DEC  BL             ; Make 1st Col 1   }
  417.    $01/$D8/     {         ADD  AX,BX                             }
  418.    $01/$C0/     {         ADD  AX,AX                             }
  419.    $8B/$F8/     {         MOV  DI,AX                             }
  420.    $8A/$7E/$06/ {         MOV  BH,04H[BP] ; Attrib into BH       }
  421.    $8E/$46/$0E/ {         MOV  ES,0CH[BP] ; Str SEG -> ES        }
  422.    $8B/$76/$0C/ {         MOV  SI,0AH[BP] ; Str OFS -> SI        }
  423.    $29/$C9/     {         SUB  CX,CX ; Addr of Str now in ES:SI  }
  424.    $26/$8A/$0C/ {         MOV  CL,ES:[SI] ; Length of Str in CX  }
  425.    $29/$C0/     {         SUB  AX,AX   ; See if graphix or mono  }
  426.    $8E/$D8/     {         MOV  DS,AX                             }
  427.    $3E/$A0/$49/$04/ {     MOV  AL,DS:[449H]                      }
  428.    $1F/         {         POP  DS                                }
  429.    $20/$C9/     {         AND  CL,CL ; If length(Str)=0 then done}
  430.    $74/$26/     {         JZ   DONE                              }
  431.    $BA/$00/$B0/ {         MOV  DX,0B000H      ; For MONO         }
  432.    $8E/$DA/     {         MOV  DS,DX                             }
  433.    $2C/$07/     {         SUB  AL,7                              }
  434.    $74/$12/     {         JZ   GETCHAR                           }
  435.  
  436.    $BA/$00/$B8/ {GRAPHICS MOV  DX,0B800H ; Load display mem      }     {.CP9}
  437.    $8E/$DA/     {         MOV  DS,DX   ;    into DS              }
  438.    $BA/$DA/$03/ {         MOV  DX,3DAH ; Status port CGA board   }
  439.    $EC/         {TESTLOW  IN   AL,DX   ; Await vert retr (Test 8)}
  440.    $A8/$08/     {         TEST AL,8    ; (This code found in     }
  441.    $75/$FB/     {         JNZ  TESTLOW ; Tech Ref Man BIOS listg)}
  442.    $EC/         {TESTHI   IN   AL,DX                             }
  443.    $A8/$08/     {         TEST AL,8                              }
  444.    $74/$FB/     {         JZ   TESTHI                            }
  445.  
  446.    $46/         {GETCHAR  INC  SI     ; Point at next char in Str}     {.CP8}
  447.    $26/$8A/$1C/ {         MOV  BL,ES:[SI] ; Get char into BL     }
  448.    $3E/$89/$1D/ {         MOV  DS:[DI],BX ; Write wd into target }
  449.    $47/         {         INC  DI         ; Shift aim            }
  450.    $47/         {         INC  DI         ;   by 2 bytes         }
  451.    $E2/$F5/     {         LOOP GETCHAR ; CX times (len of string)}
  452.  
  453.    $1F)         {DONE     POP  DS                                }
  454. end; {WriteCRT} {         ENDP                                   }
  455.  
  456. procedure CenterCRT;                                                   {.CP8}
  457. begin
  458.    if Width >0 then begin
  459.       BlnkLn[0] := char(Width);
  460.       WriteCRT(BlnkLn,Row,41-(ord(BlnkLn[0]) div 2),Attrib);
  461.    end; {if Width}
  462.    WriteCRT(S,Row,41-(ord(S[0]) div 2),Attrib)
  463. end;
  464.  
  465. procedure Center;                                                     {.CP13}
  466. var
  467.    StartCol:   byte;
  468.    Filler:     integer;
  469. begin
  470.    if Width>0 then begin
  471.       Filler := (Color shl 8) + $20;
  472.       StartCol := 41 - (Width div 2);
  473.       FillWd(seg(Scr),ofs(Scr[Line,StartCol]),Width,Filler);
  474.    end; {if Width}
  475.    StartCol := 41 - (ord(Str[0]) div 2);
  476.    WriteIt(Scr,Str,Line,StartCol,Color)
  477. end; {Center}
  478.  
  479. function CurrentAttribute;                                            {.CP12}
  480. var
  481.    R:    DOS.Registers;
  482. begin
  483.    GotoXY(1,pred(WhereY));
  484.    with R do begin
  485.       AH := $08;
  486.       BH := 0;
  487.       Intr($10,R);
  488.       CurrentAttribute := AH
  489.    end {with R}
  490. end; {CurrentAttribute}
  491.  
  492. procedure CursorOff;                                                   {.CP9}
  493. var
  494.    R:    Registers;
  495. begin
  496.    R.AH := 1;
  497.    R.CH := $20;
  498.    R.CL := 0;
  499.    intr($10,R)
  500. end; {CursorOff}
  501.  
  502. procedure CursorOn;                                                   {.CP21}
  503. var
  504.    R:    Registers;
  505. begin
  506.    with R do begin {Make standard 2-line cursor}
  507.       AH := 1;      {Make Cursor }
  508.       if Monitor=CGA then begin
  509.          CH := 6;   {top line 6}
  510.          CL := 7;   {bot line 7}
  511.       end {if CGA}
  512.       else if Monitor=EGA then begin
  513.          CH := 7;   {top line 7}
  514.          CL := 10;  {bot line 10}
  515.       end {else if EGA}
  516.       else begin
  517.          CH := 12;  {top 12}
  518.          CL := 13;  {bot 13}
  519.       end; {else MDA}
  520.    end; {with R}
  521.    Intr($10,R);    {BIOS Video service}
  522. end; {CursorOn}
  523.  
  524. procedure RestoreScreen;                                              {.CP19}
  525. { Put screen back politely (if A is the atribute found by CurrentAttribute  }
  526. { on entry).  Scrolls up one line to set color, but does not overwrite any- }
  527. { other part of the screen.  Makes standard 2-line DOS cursor, placed at    }
  528. { bottom of the screen.                                                     }
  529. var
  530.    Filler:    integer;
  531.    R:         Registers;
  532. begin
  533.    CursorOn;
  534.    GotoXY(1,24);
  535.    with R do begin {Scroll up one line at bottom of screen coloring   }
  536.       AX := $0601;    {BIOS Video Svc 6 in AH, 1 line to scroll in AL }
  537.       CX := $1700;    {Top row 23 in CH, Lft col 0 in CL }
  538.       DX := $184F;    {Bot row 24 in CH, Rt col 79 in CL }
  539.       BH := OrigAtt;        {Attribute in BH }
  540.    end; {with R}
  541.    Intr($10,R);    {BIOS Video service}
  542. end; {RestoreScreen}
  543.  
  544. procedure SetErrorLevel(Level: byte);                                 {.CP21}
  545. {Uses DOS function $4C to terminate, setting error level for DOS batch   }
  546. {file to read.  Checks for DOS 2 or higher --$4C would crash DOS 1.10-.  }
  547. {Since $4C also terminates program, handle like halt statement.  Be care-}
  548. {ful.  If run from Turbo, it will terminate Turbo.                       }
  549. var
  550.    Regs:      Registers;
  551. begin
  552.    RestoreScreen;
  553.    with Regs do begin
  554.       AH := $30;                                            {Get DOS version}
  555.       MsDos(Regs);                              {0 in AL if DOS 1.00 or 1.10}
  556.       if AL>0 then begin                {if DOS 2 or higher, set error level}
  557.          AL := Level;                                {--DOS 1 crashes on $4C}
  558.          AH := $4C;                           {Terminate setting error level}
  559.          MsDos(Regs)
  560.       end {if AL>0}
  561.       else
  562.          halt
  563.    end; {with Regs}
  564. end; {SetErrorLevel}
  565.  
  566. procedure SetScrAtt;                                                   {.CP5}
  567. {Set Turbo's internal variable}
  568. begin
  569.    TextAttr := Att;
  570. end; {SetScrAtt}
  571.  
  572. function IsIntense;                                                    {.CP4}
  573. begin
  574.    IsIntense := (A and 8)=8
  575. end; {IsDim}
  576.  
  577. function Intensified;                                                  {.CP4}
  578. begin
  579.    Intensified := A or 8;
  580. end; {Intensified}
  581.  
  582. function Dimmed;                                                       {.CP4}
  583. begin
  584.    Dimmed := A and 247
  585. end; {Dimmed}
  586.  
  587. function IsBlinking;                                                   {.CP4}
  588. begin
  589.    IsBlinking := (A and 128)=128
  590. end; {IsBlinking}
  591.  
  592. function Blinking;                                                     {.CP4}
  593. begin
  594.    Blinking := A or 128
  595. end; {Blinking}
  596.  
  597. function UnBlinking;                                                   {.CP4}
  598. begin
  599.    UnBlinking := A and 127;
  600. end; {UnBlinking}
  601.  
  602. function BlackBackground;                                              {.CP4}
  603. begin
  604.    BlackBackground := (A and 112)=0
  605. end; {BlackBackground}
  606.  
  607. function BlackForeground;                                              {.CP4}
  608. begin
  609.    BlackForeground := (A and 7)=0
  610. end; {BlackForeground}
  611.  
  612. function BackgroundOf;                                                 {.CP4}
  613. begin
  614.    BackgroundOf := (A and 112) shr 4
  615. end; {BackgroundOf}
  616.  
  617. function ForegroundOf;                                                 {.CP5}
  618. {including intensity}
  619. begin
  620.    ForegroundOf := A and 15
  621. end; {ForegroundOf}
  622.  
  623. function InverseOf;                                                    {.CP6}
  624. {Switch background & foreground, preserving intensity}
  625. begin
  626.    InverseOf := (A and 128) + ((A and 112) shr 4)
  627.                 + (A and 8) + ((A and 7) shl 4)
  628. end; {InverseOf}
  629.  
  630. function CombinedAttributeOf;                                          {.CP5}
  631. {Intensity follows F(oreground); ignores blinking.}
  632. begin
  633.    CombinedAttributeOf := ((B and 7) shl 4) or (F and 15)
  634. end; {CombinedAttributeOf}
  635.  
  636. function PadOrChop(L: LineType; Len: byte):LineType;                   {.CP6}
  637. begin
  638.    while L[0]<char(Len) do L := L + #32;
  639.    if L[0]>char(Len) then L[0] := char(Len);
  640.    PadOrChop := L;
  641. end; {PadOrChop}
  642.  
  643. procedure Replace; {(This,WithThat: LineType; var TheLine: LineType); {.CP11}
  644. var
  645.    P,K: integer;
  646. begin
  647.    P := pos(This,TheLine);
  648.    while P>0 do begin
  649.       for K := 1 to ord(This[0]) do delete(TheLine,P,1);
  650.       insert(WithThat,TheLine,P);
  651.       P := pos(This,TheLine);
  652.    end; {while P>0}
  653. end; {Replace}
  654.  
  655. function StrgB;                                                        {.CP7}
  656. var
  657.    S: LineType;
  658. begin
  659.    str(B:L,S);
  660.    StrgB := S
  661. end; {StrgB}
  662.  
  663. function StrgR;                                                        {.CP7}
  664. var
  665.    S: LineType;
  666. begin
  667.    str(R:L1:L2,S);
  668.    StrgR := S
  669. end; {StrgR}
  670.  
  671. function StrgI;                                                        {.CP7}
  672.    var
  673.    S: LineType;
  674. begin
  675.    str(B:L,S);
  676.    StrgI := S
  677. end; {StrgB}
  678.  
  679. function Strip;                                                        {.CP7}
  680. {remove leading & trailing junk (list comes in  NoNo)}
  681. begin {Strip}
  682.    while (L[0]>#0) and (L[1] in NoNo) do delete(L,1,1);
  683.    while L[ord(L[0])] in NoNo do L[0] := pred(L[0]);
  684.    Strip := L
  685. end; {Strip}
  686.  
  687. function InCapitals;                                                   {.CP7}
  688. var
  689.    K:              byte;
  690. begin {InCapitals}
  691.    for K := 1 to ord(L[0]) do L[K] := UpCase(L[K]);
  692.    InCapitals := L
  693. end; {InCapitals}
  694.  
  695. function KbIn;                                                        {.CP15}
  696. var
  697.    C:              char;
  698.    N:              integer;
  699.    R:              DOS.Registers;
  700. begin
  701.    C := ReadKey;
  702.    if C<>#0 then
  703.       Extended := False
  704.    else begin
  705.       Extended := True;
  706.       C := ReadKey
  707.    end; {else}
  708.    KbIn := C;
  709. end; {KbIn}
  710.  
  711. function EditTrm;                                                      {.CP8}
  712. const
  713.    Outs: set of char = [#3,#13,#27];
  714. var
  715.    C:         char;
  716.    S:         LineType;
  717.    Ext:       boolean;
  718.    X,Y:       byte;
  719.  
  720.    procedure DeleteOne;                                                {.CP9}
  721.    begin
  722.       if length(S)>0 then begin
  723.          delete(S,length(S),1);
  724.          write(#8,#32,#8)
  725.       end {if length>0}
  726.       else
  727.          Bip
  728.    end; {DeleteOne}
  729.  
  730. begin {EditTrm}                                                       {.CP21}
  731.    S := '';
  732.    CursorOn;
  733.    repeat
  734.       X := WhereX; Y := WhereY;
  735.       C := Kbin(Ext);
  736.       GotoXY(X,Y);
  737.       if Ext then
  738.          if C='K'                                                {back-arrow}
  739.             then DeleteOne
  740.             else bip                            {beep for improper keystroke}
  741.       else if C=#8 then
  742.          DeleteOne
  743.       else if (C=#27) or (C=#3) then
  744.          S := #27
  745.       else if C<>#13 then begin
  746.          S := S + C;
  747.          write(C)
  748.       end; {if}
  749.    until (length(S)>=N) or (C in Outs);
  750.    EditTrm := S;
  751.    CursorOff
  752. end; {EditTrm}
  753.  
  754. function CurrentDriveAndDirectory;                                      {.CP8}
  755. {Returns full current drive:\directory}
  756. {Needs types: LineType, DOS.Registers}
  757. var
  758.    Data: array[1..64] of char;
  759.    Regs: DOS.Registers;
  760.    Bt:  byte;
  761.    S:    LineType;
  762.  
  763.    function CurrentDrive: byte;                                         {.CP9}
  764.    {Returns 0 for A:, 1 for B:, etc.}
  765.    var
  766.       Regs: DOS.Registers;
  767.    begin
  768.       Regs.AH := $19;
  769.       MsDos(Regs);
  770.       CurrentDrive := Regs.AL
  771.    end; {CurrentDrive}
  772.  
  773. begin                                                                  {.CP17}
  774.    Bt := CurrentDrive;
  775.    with Regs do begin
  776.       AH := $47;
  777.       DL := succ(Bt);
  778.       DS := Seg(Data);
  779.       SI := Ofs(Data);
  780.       MsDos(Regs);
  781.    end; {with Regs}
  782.    S := char(Bt+65) + ':\';
  783.    Bt := 1;
  784.    while Data[Bt]<>#0 do begin
  785.       S := S + UpCase(Data[Bt]);
  786.       Bt := succ(Bt)
  787.    end; {while}
  788.    CurrentDriveAndDirectory := S
  789. end; {CurrentDriveAndDirectory}
  790.  
  791. function EnvironLine;                                                  {.CP30}
  792. { Searches DOS Environment for line beginning with LineStart        }
  793. { Returns line with LineStart removed it in EnvironLine if found.   }
  794. { Returns "NONE" if not found. }
  795. var
  796.    S:               LineType;
  797.    EnvAdd:          word;
  798.    B:               byte;
  799.    LineFound:       boolean;
  800. begin
  801.    EnvAdd := MemW[PrefixSeg:$2C];
  802.    B := 0;
  803.    LineFound := False;
  804.    LineStart := InCapitals(LineStart);
  805.    repeat
  806.       S := '';
  807.       while Mem[EnvAdd:B]<>0 do begin
  808.          S := S + UpCase(char(Mem[EnvAdd:B]));
  809.          B := succ(B)
  810.       end; {while}
  811.       if pos(LineStart,S)=1 then begin
  812.          delete(S,1,ord(LineStart[0]));
  813.          while S[1] in [' ','='] do delete(S,1,1);
  814.          EnvironLine := S;
  815.          LineFound := True
  816.       end; {if PATH}
  817.       B := succ(B)
  818.    until (S[0]=#0) or LineFound;
  819.    if not LineFound then EnvironLine := 'NONE'
  820. end; {EnvironLine}
  821.  
  822. function FindFile;                                                      {.CP9}
  823. {Takes File name.  Searches for file on default drive & along DOS PATH.  }
  824. {Reports success or failure in FindFile.                                 }
  825. {If file is found, returns openable FName with successful path prefixed. }
  826. var
  827.    Paths,
  828.    Try:       LineType;
  829.    F:         text;   {File type doesn't matter.  File only reset, not read.}
  830.    GotIt:     boolean;
  831.  
  832.    function Path(var P: LineType): LineType;                          {.CP15}
  833.    {Takes DOS PATH line and peels one path specifier from it.  }
  834.    {Returns specifier in Path, bobtailed DOS PATH line in P.   }
  835.    var
  836.       Chunk:     LineType;
  837.    begin
  838.       Chunk := '';
  839.       while (P[1]<>';') and (P[0]<>#0) do begin
  840.          Chunk := Chunk + P[1];
  841.          delete(P,1,1)
  842.       end; {while not ";"}
  843.       while (P[1]=';') and (P[0]<>#0) do delete(P,1,1);
  844.       if Chunk[ord(Chunk[0])]<>'\' then Chunk := Chunk + '\';
  845.       Path := Chunk
  846.    end; {Path}
  847.  
  848.    function Found(var F: text): boolean;                              {.CP14}
  849.    {Takes file variable, tries to open it.  Closes file if opened. }
  850.    {Reports success or failure in Found.                           }
  851.    begin
  852.       {$I-}
  853.       reset(F);
  854.       {$I+}
  855.       if IOresult=0 then begin
  856.          Found := True;
  857.          close(F);
  858.       end {if 0}
  859.       else
  860.          Found := False;
  861.    end; {Found}
  862.  
  863. begin {FindFile}                                                      {.CP23}
  864.    assign(F,FName);
  865.    if Found(F) then
  866.       GotIt := True
  867.    else begin                                          {Strip all path specs}
  868.       while (pos(':',FName)<>0) or (pos('\',FName)<>0) do
  869.          delete(FName,1,1);
  870.       Paths := EnvironLine('PATH');               {Get PATH from Environment}
  871.       if Paths='NONE' then begin
  872.          assign(F,FName);                     {if no PATH, try default drive}
  873.          GotIt := Found(F)
  874.       end {if NONE}
  875.       else begin                                     {else search along PATH}
  876.          repeat
  877.             Try :=  Path(Paths);
  878.             assign(F,Try + FName);
  879.             GotIt := Found(F)
  880.          until (Try='\') or GotIt;
  881.          if GotIt then FName := Try + FName
  882.       end {else found a PATH}
  883.    end; {else not on default drive}
  884.    FindFile := GotIt;
  885. end; {FindFile}
  886.  
  887. function Escape: boolean;                                             {.CP15}
  888. {  Empties the keyboard buffer & returns False if no trigger}
  889. {  Does not wait for a keypress}
  890.  
  891. var
  892.    C:              char;
  893.    Temp:           boolean;
  894. begin {Escape}
  895.    Temp := False;
  896.    while KeyPressed and not Temp do begin
  897.       C := ReadKey;
  898.       if C in Triggers then Temp := True
  899.    end; {while}
  900.    Escape := Temp;
  901. end; {Escape}
  902.  
  903. procedure CloseCarefully;                                               {.CP9}
  904. var
  905.    Err: word;
  906. begin
  907.    {$I-}
  908.    close(F);
  909.    {$I+}
  910.    Err := IOresult;
  911. end; {CloseCarefully}
  912.  
  913. procedure Blank(Top,Bot: integer);                                     {.CP6}
  914. var
  915.    Row:              integer;
  916. begin
  917.    for Row := Top to Bot do CenterCRT('',Row,Bright,Inside)
  918. end; {Blank}
  919.  
  920. procedure ByeBye;                                                     {.CP19}
  921. begin
  922.    CloseCarefully(Lst);
  923.    Blank(8,9);
  924.    Blank(18,19);
  925.    if Enough
  926.       then CenterCRT('That''s it, then.',18,Bright,0)
  927.       else CenterCRT('Done.  ' + FileName + ' sent to ' + OutputDevice
  928.                      + '.',10,Bright,Inside);
  929.    CenterCRT('Signing Off.',19,Bright,0);
  930.    if InABatch and Enough then begin
  931.       CenterCRT('Can''t find ' + FileName,11,Bright,0);
  932.       SetErrorLevel(1)      {BEWARE: RUN FROM TURBO, THIS QUITS TO DOS}
  933.    end {if InABatch}
  934.    else begin
  935.       RestoreScreen;
  936.       halt
  937.    end
  938. end; {ByeBye}
  939.  
  940. procedure GetOutOfHere;                                                {.CP5}
  941. begin
  942.    Enough := True;
  943.    ByeBye
  944. end; {GetOutOfHere}
  945.  
  946. procedure PXLRectangle;                                               {.CP11}
  947. var
  948.    I: integer;
  949. begin
  950.    WipeSlate(Scr,Bright);
  951.    Rectangle(Scr,BoxT,BoxL,BoxB,BoxR,Dim,2,2);
  952.    Center(Scr,' Pascal X-ref Lister (v. 1.42)',pred(BoxT),Dim,Inside);
  953.    WriteIt(Scr,'R. N. Wisan  fecit  7/85-4/88',succ(BoxB),41,Dim);
  954.    Center(Scr,'To stop, press <Esc>',BoxB -2,Bright,Inside);
  955.    ToScrn(Scr);
  956. end; {Rectangle}
  957.  
  958. procedure CantCont(FilNam,Comment: LineType);                         {.CP18}
  959. var
  960.    B:              byte;
  961. begin
  962.    Beep;
  963.    CloseCarefully(Lst);
  964.    Blank(10,18);
  965.    CenterCRT('Can''t continue',10,Bright,0);
  966.    if FilNam<>'' then CenterCRT('Error reading ' + FilNam,12,Bright,0);
  967.    CenterCRT(Comment,13,Bright,0);
  968.    Bop;
  969.    if InABatch then
  970.       SetErrorLevel(1)
  971.    else begin
  972.       RestoreScreen;
  973.       Halt
  974.    end
  975. end; {CantCont}
  976.  
  977. procedure GetPrinterData;                                           {.CP18}
  978. {If constant DataFiles is True, this procedure loads printer control }
  979. {symbols from PXL.PRN.  If it's false, they're set here.             }
  980.  
  981.    procedure ReadPrn;  {from PXL.PRN}
  982.    var
  983.       F:              Fil;
  984.       FilNam:         LineType;
  985.    begin
  986.       FilNam := 'PXL.PRN';
  987.       GotPrnData := FindFile(FilNam);
  988.       if GotPrnData then begin
  989.          assign(F,FilNam);
  990.          reset(F);
  991.          for T := MrkB to FF do if not Eof(F) then read(F,Inst[T]);
  992.          close(F)
  993.       end {if no error}
  994.    end; {ReadPrn}
  995.  
  996.    procedure IntPrn; {Set here for Epson FX-80}                       {.CP20}
  997.    begin
  998.       {Note: MrkB & MrkE are set for underline.  If you prefer some other}
  999.       {way of marking the key words, change them here.                   }
  1000.       Inst[MrkB,0] := 3;
  1001.          Inst[MrkB,1] := 27;   Inst[MrkB,2] := 45;   Inst[MrkB,3] := 1;
  1002.       Inst[MrkE,0] := 3;
  1003.          Inst[MrkE,1] := 27;   Inst[MrkE,2] := 45;   Inst[MrkE,3] := 0;
  1004.       Inst[EliteB,0] := 2;
  1005.          Inst[EliteB,1] := 27; Inst[EliteB,2] := 77; Inst[EliteB,3] := $FF;
  1006.       Inst[EliteE,0] := 2;
  1007.          Inst[EliteE,1] := 27; Inst[EliteE,2] := 80; Inst[EliteE,3] := $FF;
  1008.       Inst[CondB,0] := 1;
  1009.          Inst[CondB,1] := 15;  Inst[CondB,2] := $FF; Inst[CondB,3] := $FF;
  1010.       Inst[CondE,0] := 1;
  1011.          Inst[CondE,1] := 18;  Inst[CondE,2] := $FF; Inst[CondE,3] := $FF;
  1012.       Inst[FF,0] := 1;
  1013.          Inst[FF,1] := 12;     Inst[FF,2] := $FF;    Inst[FF,3] := $FF;
  1014.       GotPrnData := True;
  1015.    end; {IntPrn}
  1016.  
  1017. begin {GetPrinterData}                                                {.CP10}
  1018.    if DataFiles then
  1019.       ReadPrn
  1020.    else
  1021.       IntPrn;
  1022.    if not GotPrnData then
  1023.       Inst[FF,1] := 66;                          {Default to Vanilla printer}
  1024.    if (Inst[FF,1] in [12,255])                               {Set Lines/Page}
  1025.       then MaxLin := 66 - BottomMargin
  1026.       else MaxLin := Inst[FF,1] - (BottomMargin)
  1027. end; {GetPrinterData}
  1028.  
  1029. function DefaultDrive: char; {Returns letter of Default Drive}        {.CP10}
  1030. var
  1031.    Regs:      Registers;
  1032. begin
  1033.    with Regs do begin
  1034.       AH := $19;
  1035.       MsDos(Regs);
  1036.       DefaultDrive := char(65 + AL)
  1037.    end {with Regs}
  1038. end; {DefaultDrive}
  1039.  
  1040. procedure FixUpFileName(Var FilNam: LineType);                        {.CP31}
  1041. const
  1042.    PathSigns: set of char = [':','\'];
  1043. var
  1044.    B,Len:       byte;
  1045. begin
  1046.    while (FilNam[1]=#32) and (FilNam[0]>#0) do         {Strip leading blanks}
  1047.       delete(FilNam,1,1);
  1048.    while FilNam[ord(FilNam[0])]=#32 do                {Strip trailing blanks}
  1049.       FilNam[0] := pred(FilNam[0]);
  1050.    for B := 1 to Length(FilNam) do                               {Capitalize}
  1051.       FilNam[B] := UpCase(FilNam[B]);
  1052.    B := ord(FilNam[0]);                           {count length of bare name}
  1053.    while (B>0) and not (FilNam[B] in PathSigns) do
  1054.       B := pred(B);
  1055.    Len := ord(FilNam[0]) - B;
  1056.    if pos(':',FilNam)=0 then          {if no drive letter, add Default Drive}
  1057.       FilNam := DefaultDrive + ':' + FilNam;
  1058.    if pos('.',FilNam)<>0 then begin                  {if has a period       }
  1059.       while (FilNam[0]>#0) and (FilNam[ord(FilNam[0])]='.') do begin
  1060.          FilNam[0] := pred(FilNam[0]);                 {delete terminal dots}
  1061.          Len := pred(Len)                              {adjust length count }
  1062.       end {while terminal dot}
  1063.    end {if has "."}
  1064.    else if Len>10 then begin                    {else if long, insert period}
  1065.       B := ord(FilNam[0]) - Len + 8;
  1066.       FilNam := concat(copy(FilNam,1,B),'.',copy(FilNam,succ(B),3))
  1067.    end {else no "." & over long}
  1068.    else
  1069.       FilNam := concat(FilNam,'.PAS')            {otherwise, default to .PAS}
  1070. end; {FixUpFileName}
  1071.  
  1072. function Shortened(FileName: LineType): Str20;
  1073. begin
  1074.    while (pos(':',FileName)<>0) or (pos('\',FileName)<>0) do
  1075.       delete(FileName,1,1);
  1076.    Shortened := FileName;
  1077. end; {Shortened}
  1078.  
  1079. procedure MakeBlnkLn; {private to PXLINIT}                             {.CP9}
  1080. var
  1081.    K: integer;
  1082. begin
  1083.    BlnkLn := '';
  1084.    for K := 1 to StdLineWidth do
  1085.       BlnkLn := BlnkLn + #32;
  1086.    Inside := pred(BoxR) - succ(BoxL);
  1087. end; {MakeBlnkLn}
  1088.  
  1089. begin {initialize PXLINIT}                                             {.CP5}
  1090.    OrigAtt := CurrentAttribute;
  1091.    GetScreen;
  1092.    MakeBlnkLn;
  1093. end.
  1094.