home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / NUTUG11.ZIP / MISC.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1987-11-21  |  13.3 KB  |  413 lines

  1. Unit Misc;
  2.  
  3.               {NORTHWESTERN UNIVERSITY TURBO USERS GROUP UTILITIES}
  4.  
  5.                          (** NUtility MISC ROUTINES **)
  6.  
  7.                             {(C) J. E. Hilliard 1986}
  8.  
  9.          {This is a set of miscellaneous utilities most of which deal
  10.          with text handling.                                         }
  11.  
  12. Interface
  13.  
  14. Uses      Dos,
  15.           Crt;
  16.  
  17. PROCEDURE Chirp;                       {A pleasantly soft audio signal.     }
  18.  
  19. PROCEDURE Honk;                        {An unpleasant audio signal.         }
  20.  
  21. FUNCTION UpCaseStr (InString  : String): String;
  22.          {Converts all characters in 'InString' to upper case.       }
  23.  
  24. PROCEDURE TrimLine (Var StrT :  String);
  25.          {Deletes leading and trailing spaces from input StrT.       }
  26.  
  27. FUNCTION FTrimLine (StrT : String) : String;
  28.           {This is similar to TrimLine except that it is coded as a
  29.            a function.                                            }
  30.  
  31. FUNCTION CtrLn (Line : String) : String;
  32.          {Centers input 'Line' in a field of a width determined by
  33.          the constant.                                           }
  34.  
  35. PROCEDURE NumberLock (ONorOFF : Boolean);
  36.          {Turns NumLck key On or Off according to input.  WARNING: Be
  37.          sure to reset to OFF before exiting program.               }
  38.  
  39. PROCEDURE BackSpace (Numb : byte);
  40.          {Backspaces cursor 'Numb' characters.                       }
  41.  
  42. FUNCTION Query : Boolean;
  43.          {This function simplifies the handling of queries to the user
  44.          that require a Y/N response.  It appends  ' (Y/N)? : ' to the
  45.          current line and waits for a valid response. Returns 'TRUE' if
  46.          it is 'y' or 'Y'.                                            }
  47.  
  48. FUNCTION LJust (Line : String; F : byte): String;
  49.          {Left justifies 'Line' in a field of length 'F'.            }
  50.  
  51. FUNCTION KeyCheck : char;
  52.          {This function checks the keyboard buffer and returns: (1) #0
  53.          if there is no entry. (2) The first character in the buffer
  54.          if it is not a Turbo ESC pair. (3) The scan code plus 128 if
  55.          it is an ESC pair. (Unfortunately, this scheme precludes the
  56.          identification of certain CTRL and ALT key combinations. If
  57.          this is important, other coding should be used.)
  58.  
  59. PROCEDURE Tab (Ind : byte);
  60.          {Tabs to location 'Ind'. Since it uses the WhereX command it
  61.          will not work on output to the printer unless the text is
  62.          being simultaneously displayed on the screen.              }
  63.  
  64. Implementation
  65.  
  66.  
  67. PROCEDURE Chirp;                       {A pleasantly soft audio signal.     }
  68.  
  69. Begin
  70.  
  71.   Sound(2000);
  72.   Delay(8);
  73.   NoSound;
  74.  
  75. End; {Chirp}
  76.  
  77.  
  78. PROCEDURE Honk;                        {An unpleasant audio signal.         }
  79.  
  80. Begin
  81.  
  82.   write (#7);                          {^G - Bell                           }
  83.  
  84. End; {Honk}
  85.  
  86.  
  87. FUNCTION UpCaseStr (InString  : String): String;
  88.  
  89.          {Converts all characters in 'InString' to upper case.       }
  90.  
  91.  
  92. VAR J : byte;
  93.  
  94. Begin
  95.  
  96.   for J := 1 to length (InString) do
  97.     InString[J] := UpCase ( InString[J] );
  98.   UpCaseStr := InString;
  99.  
  100. end; {UpCaseStr}
  101.  
  102.  
  103. PROCEDURE TrimLine (Var StrT :  String);
  104.  
  105.          {Deletes leading and trailing spaces from input StrT.       }
  106.  
  107. Begin
  108.  
  109.   if Length (StrT) = 0 then
  110.     Exit;
  111.  
  112.   while (StrT[ length (StrT) ] = #32) and (length (StrT) > 0) do
  113.     StrT[0] := pred (StrT[0]);         {Eliminate trailing blanks,          }
  114.  
  115.   while (StrT[1] = #32) and (length (StrT) > 0) do
  116.     delete (StrT, 1, 1);
  117.  
  118. End; {TrimLine}
  119.  
  120.  
  121. FUNCTION FTrimLine (StrT : String) : String;
  122.  
  123.           {This is similar to TrimLine except that it is coded as a
  124.            a function.                                            }
  125.  
  126. Begin
  127.  
  128.   FTrimLine := '';
  129.   if length (StrT) = 0 then
  130.     Exit;                              {Nothing to trim!                    }
  131.   while (StrT[ length (StrT) ] = #32) and (length (StrT) > 0) do
  132.     StrT[0] := pred (StrT[0]);         {Eliminate trailing blanks,          }
  133.  
  134.   while (StrT[1] = #32) and (length (StrT) > 0) do
  135.     delete (StrT, 1, 1);
  136.  
  137.   FTrimLine := StrT;
  138.  
  139. End; {FTrimLine (StrT : String) : String}
  140.  
  141.  
  142. FUNCTION CtrLn (Line : String) : String;
  143.  
  144.          {Centers input 'Line' in a field of a width determined by
  145.          the constant.                                           }
  146.  
  147. CONST
  148.  
  149.   Field = 80;                          {Change if desired.                  }
  150.  
  151. VAR
  152.  
  153.   K     : integer;
  154.   Blank : String;
  155.  
  156. Begin
  157.  
  158.   CtrLn := Line;
  159.   K := (Field - length (Line)) div 2;
  160.   if K < 0 then
  161.     Exit;
  162.   FillChar (Blank[1], K, ' ');         {This is faster than using a loop to }
  163.   Blank[0] := chr (K);                 {add spaces.                         }
  164.   CtrLn := Blank + Line;
  165.  
  166. End; {CtrLn (Line : String) : String}
  167.  
  168.  
  169. PROCEDURE NumberLock (ONorOFF : Boolean);
  170.  
  171.          {Turns NumLck key On or Off according to input.  WARNING: Be
  172.          sure to reset to OFF before exiting program.               }
  173.  
  174.          {Location 40:17 is byte mapped to the following bits in hex:
  175.  
  176.                       80 - Ins on,
  177.                       40 - Caps Lck.
  178.                       20 - Num Lck,
  179.                       10 - Scroll,
  180.                        8 - Alt,
  181.                        4 - Ctl,
  182.                        2 - Left shift,
  183.                        1 - Right shift.                                     }
  184.  
  185. VAR
  186.  
  187.   KeyBoardMode : byte absolute $40:$17;
  188.  
  189. Begin
  190.  
  191.   if ONorOFF = true
  192.     then
  193.       KeyBoardMode := $20              {Set NumLck ON.                      }
  194.     else
  195.       KeyBoardMode := $0;              {Set NumLck OFF.                     }
  196.  
  197. end; {NumberLock}
  198.  
  199.  
  200. PROCEDURE BackSpace (Numb : byte);
  201.  
  202.          {Backspaces cursor 'Numb' characters.                       }
  203.  
  204. Begin
  205.  
  206.   GoToXY (WhereX - Numb, WhereY);
  207.  
  208. End; {BackSpace (Numb : byte)}
  209.  
  210.  
  211. FUNCTION Query : Boolean;
  212.  
  213.          {This function simplifies the handling of queries to the user
  214.          that require a Y/N response.  It appends  ' (Y/N)? : ' to the
  215.          current line and waits for a valid response. Returns 'TRUE' if
  216.          it is 'y' or 'Y'.                                            }
  217.  
  218.          {EXAMPLE:  write ('Do you wish to continue');
  219.                     if Query
  220.                       then
  221.                         (Y response)
  222.                       else
  223.                         (N response);                                }
  224.  
  225.          {/The above illustrates one aspect of Pascal functions that
  226.          the newcomer may find a little strange. Namely, that even an
  227.          oblique reference to a function serves to execute it.      /}
  228.  
  229. VAR
  230.  
  231.   ch : char;
  232.  
  233. Begin
  234.  
  235.   Chirp; write (' (Y/N)? :  ');
  236.   BackSpace (1);
  237.   repeat
  238.     ch := readkey;
  239.     ch := UpCase (ch);
  240.     if ord (ch) in [33..90] then       {Echo input.                         }
  241.       begin
  242.         write (ch);
  243.         BackSpace (1);
  244.       end;
  245.   until ch in ['Y','N'];
  246.   Query := (ch = 'Y');
  247.  
  248. End; {Query : Boolean}
  249.  
  250.  
  251. FUNCTION LJust (Line : String; F : byte): String;
  252.  
  253.          {Left justifies 'Line' in a field of length 'F'.            }
  254. VAR
  255.  
  256.   Blank : String;
  257.   K     : byte;
  258.  
  259. Begin
  260.  
  261.   K := F - length (Line);
  262.   FillChar (Blank[1], K, ' ');         {This is faster than using a loop to }
  263.   Blank[0] := chr (K);                 {add spaces.                         }
  264.   LJust := Line + Blank;
  265.  
  266. End; {LJust (Line : String; F : byte)}
  267.  
  268.  
  269. FUNCTION KeyCheck : char;
  270.  
  271.          {This function checks the keyboard buffer and returns: (1) #0
  272.          if there is no entry. (2) The first character in the buffer
  273.          if it is not a Turbo ESC pair. (3) The scan code plus 128 if
  274.          it is an ESC pair. (Unfortunately, this scheme precludes the
  275.          identification of certain CTRL and ALT key combinations. If
  276.          this is important, other coding should be used.)
  277.  
  278.          The buffer is cleared before exiting to allow for impatient
  279.          users who pound the keys if the response is not immediate.  }
  280.  
  281.          (****************           NOTE            ****************)
  282.          (* This function will not operate satisfactorily if output is
  283.          being sent to the screen unless the compiler option {$C-} has
  284.          been set.                                                  *)
  285.  
  286.          {/In the PC DOS system each key generates a scan code in
  287.          addition to an ASCII code. The scan codes are used to distin-
  288.          guish certain keys (such as the function and arrow keys). For
  289.          these and other special keys, TURBO returns an ESC sequence
  290.          (ie. #27 followed by a character.) These sequences are listed
  291.          on pp. 341-3 of the V3 manual. The choice of an ESC to signal
  292.          a special character is a bad one since it makes it necessary
  293.          to resort to some trickery to distinguish between an ESC en-
  294.          tered at the keyboard from that generated by TURBO. This
  295.          problem could easily have been avoided by using the null
  296.          character (#0) as a signal instead.                        /}
  297.  
  298. VAR
  299.  
  300.   ch  : char;
  301.  
  302. Begin
  303.  
  304.   KeyCheck := #0;                      {Default value.                      }
  305.   if not KeyPressed then
  306.     Exit;
  307.   ch := ReadKey;
  308.   KeyCheck := ch;
  309.   if KeyPressed and (ch = #27) then    { #27 = ESC so this is a TURBO ESC   }
  310.     begin                              {sequence or else the user is dood-  }
  311.       ch := ReadKey;                   {ing on the keyboard.                }
  312.       if ord (ch) < 128
  313.         then
  314.           KeyCheck := chr ( ord (ch) + 128 )
  315.         else                           {Entry not allowed by coding system. }
  316.           KeyCheck := #0;
  317.     end; {if KeyPressed . .}
  318.   while KeyPressed do                  {Make sure that buffer is clear.     }
  319.     ch := ReadKey;
  320.  
  321. End; {KeyCheck : char}
  322.  
  323.  
  324. PROCEDURE Tab (Ind : byte);
  325.  
  326.          {Tabs to location 'Ind'. Since it uses the WhereX command it
  327.          will not work on output to the printer unless the text is
  328.          being simultaneously displayed on the screen.              }
  329.  
  330. VAR  J : byte;
  331.  
  332. Begin
  333.  
  334.   for J := WhereX to Ind do
  335.     write (#32);
  336.  
  337. end; {Tab}
  338.  
  339.  
  340. (* FUNCTION SaveCOMFile (PathFileName : String) : Boolean;
  341.  
  342.              Note: This program does not compile It may or may
  343.              not do what it claims with version 4.0 after it is altered
  344.              to compile. Use it at your own risk
  345.  
  346.           {/This function saves the code segment of a TURBO Pascal pro-
  347.           gram that is being run as a COM file. One application is to
  348.           allow the user to save an 'installed' version of the program.
  349.           NOTE: Any variables (such as video attributes) that will be
  350.           changed by the user must be defined as typed constants so
  351.           that they are stored in the code segment. The input 'Path-
  352.           FileName' can optionally include a drive and/or directory
  353.           path in addition to the file name. (Curiously, DOS does not
  354.           apparently provide any means for a program to discover its
  355.           own name.) The function returns 'FALSE' if an error is detec-
  356.           ted. Because the file size is estimated in increments of 16
  357.           bytes, the COM file saved by this routine may be up to 15
  358.           bytes larger than the original file. However, this has no
  359.           effect on the memory occupied when the file is loaded.     /}
  360.  
  361.           {             *********** WARNING ***********
  362.  
  363.           This routine must ONLY be run when the program has been load-
  364.           ed as a COM file. A file saved when in memory mode will be-
  365.           have erratically when loaded and may hang the computer. (This
  366.           is because of a difference in the location assigned to CSeg
  367.           in the two modes.)                                          }
  368.  
  369. VAR
  370.  
  371.   ComStart : byte absolute CSeg:$100;  {Addr. of the start of the program.  }
  372.   ComSize  : integer;                  {Size of loaded program in 16-byte   }
  373.   OutFile  : file;                     {paragraphs.                         }
  374.   Check    : integer;                  {Error return.                       }
  375.   Loc      : byte;                     {Loc and HoldStr used only by the    }
  376.   HoldStr  : string[80];               {back up routine.                    }
  377.  
  378. Begin
  379.  
  380.   SaveCOMFile := false;                {Default return.                     }
  381.  
  382.           { Uncomment the next eight lines if back up is required. }
  383.   (*
  384.   HoldStr := PathFileName;
  385.   Loc := Pos ('.', HoldStr);
  386.   Delete (HoldStr, Loc, 4);            {Delete .COM.                        }
  387.   HoldStr := HoldStr + '.CMB';         {Change extension if desired.        }
  388.   Assign (OutFile, PathFileName);
  389.   {$I-} ReName (OutFile, HoldStr); {$I+}
  390.   if IOResult <> 0 then                {Error - probably file not found.    }
  391.     Exit;
  392.   *)(*                    { End of Backup routine. }
  393.  
  394.   ComSize := DSeg - CSeg - 16;         {The first 16 paras. is the PSP.     }
  395.   Assign (OutFile, PathFileName);
  396.   {$I-}
  397.   ReWrite (OutFile, 16);               {Record size = 16 byte (1 para.)     }
  398.   BlockWrite (OutFile, ComStart, ComSize, Check);
  399.   {$I+}
  400.   if (IOResult <> 0) or (Check <> ComSize)
  401.     then                               {Error.                              }
  402.       Exit;
  403.   Close (OutFile);
  404.   SaveComFile := true;
  405.  
  406. End; {SaveCOMFile}*)
  407.  
  408. Begin
  409. End.
  410.  
  411.  
  412.  
  413.