home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 15 / CD_ASCQ_15_070894.iso / vrac / sk210f.zip / SHLNGSTR.PAS < prev    next >
Pascal/Delphi Source File  |  1994-05-11  |  47KB  |  1,494 lines

  1. {$I SHDEFINE.INC}
  2.  
  3. {$I SHUNITSW.INC}
  4.  
  5. {$D-,L-}
  6.  
  7. {**********************************************************************}
  8. {**************     DO NOT MODIFY THE NEXT DIRECTIVE     **************}
  9. {**********************************************************************}
  10.  
  11. {$R-,V-}
  12.  
  13. unit ShLngStr;
  14. {
  15.                                 ShLngStr
  16.  
  17.                     A Long String Manipulation Unit
  18.  
  19.                                    by
  20.  
  21.                               Bill Madison
  22.  
  23.                    W. G. Madison and Associates, Ltd.
  24.                           13819 Shavano Downs
  25.                             P.O. Box 780956
  26.                        San Antonio, TX 78278-0956
  27.                              (512)492-2777
  28.                              CIS 73240,342
  29.                 Internet bill.madison@lchance.sat.tx.us
  30.  
  31.                 Copyright 1990, '94 Madison & Associates
  32.                           All Rights Reserved
  33.  
  34.         This file may  be used and distributed  only in accord-
  35.         ance with the provisions described on the title page of
  36.                   the accompanying documentation file
  37.                               SKYHAWK.DOC
  38. }
  39.  
  40. interface
  41.  
  42. uses
  43.   ShErrMsg,
  44.   TpInline,
  45.   TpString,
  46.   TpMemChk;
  47.  
  48. const
  49.   Copyr = 'Copyright 1990, 1994 by W.G. Madison';
  50.  
  51. const
  52.   MaxLongString = 65517;                    {Maximum length of LongString.}
  53.  
  54. type
  55.   LongStringType= record
  56.                     Length,                 {Dynamic length}
  57.                     dLength : word;         {"Declared" length}
  58.                     lsData  : array[1..1] of char;
  59.                     end;
  60.   LongString    = ^LongStringType;
  61.   lsCompType    = (Less, Equal, Greater);
  62.   lsDelimSetType= set of char;
  63.   CharSet       = set of char;
  64.  
  65. const
  66.   lsDelimSet    : lsDelimSetType = [#0..#32];
  67.   lsNotFound                     =  0;      {Returned by Pos functions if
  68.                                               substring not found}
  69.   RingSize      : byte           = 25;
  70.   lsHaltErr     : boolean        = true;    {Stop program execution on
  71.                                               non-I/O errors}
  72.  
  73. {NON-I/O ERROR CODES}
  74.   lsOK                          =   0;
  75.                                 {Last operation OK.}
  76.   lsInitError                   = 250;
  77.                                 {System initialization not performed.}
  78.   lsStringTooLong               = 251;
  79.                                 {Declared string length > MaxLongString.}
  80.   lsAllocError                  = 252;
  81.                                 {Not enough heap space for long string.}
  82.   lsRingAllocError              = 253;
  83.                                 {Not enough heap space for long string
  84.                                  allocation from ring buffer.}
  85.   lsRuntimeError      : word    = lsOK;
  86.                                 {Result of last operation.}
  87.  
  88.   {========== MEMORY MANAGEMENT =============================================}
  89.  
  90. procedure lsSysInit;
  91.   {Initializes the LngStr system.}
  92.  
  93. procedure lsSysDeinit;
  94.   {Deinitializes the LngStr system, releasing the ring buffer and the
  95.    associated heap space.}
  96.  
  97. function lsInit(var A  : LongString; L : word)  : boolean;
  98.   {"Declares" a LongString of maximum declared length L and establishes
  99.    space for it on the heap. Returns false if L is greater than
  100.    MaxLongString or not enough heap space.}
  101.  
  102. procedure lsDispose(var A : LongString);
  103.   {-Dispose of A, releasing its heap space}
  104.  
  105.   {========== GENERAL HOUSEKEEPING ==========================================}
  106.  
  107. function lsComp(A1, A2 : LongString) : lsCompType;
  108.   {-Compares A1 to A2, returning LESS, EQUAL, or GREATER}
  109.  
  110. function lsCount(A, Obj : LongString):  word;
  111. function lsCountStr(A : LongString; Obj : string) : word;
  112.   {-Returns the number of occurrences of Obj in A}
  113.  
  114. function lsCountUC(A, Obj : LongString):  word;
  115. function lsCountStrUC(A : LongString; Obj : string) : word;
  116.   {-Returns the number of occurrences of Obj in A}
  117.   { The search is not CASE SENSITIVE.}
  118.  
  119. function lsLength(A : LongString) : word;
  120.   {-Return the length of a LongString. A must have been lsInited}
  121.  
  122. function lsPos(Obj, A : LongString) : word;
  123. function lsPosStr(Obj : string; A : LongString) : word;
  124.   {-Return the position of Obj in A, returning lsNotFound if not found}
  125.  
  126. function lsPosSet(A : CharSet; S : LongString) : word;
  127.   {-Returns the earliest position of any member of A in S.}
  128.  
  129. function lsPosUC(Obj, A : LongString) : word;
  130. function lsPosStrUC(Obj : string; A : LongString) : word;
  131.   {-Return the position of Obj in A, returning lsNotFound if not found.
  132.    The search is not CASE SENSITIVE.}
  133.  
  134. function lsSizeOf(A : LongString) : word;
  135.   {-Returns the total heap space required for A. A must have been lsInited}
  136.  
  137.   {========== LONGSTRING TRANSFER (ASSIGNMENT) ==============================}
  138.  
  139. procedure lsTransfer(A, B : LongString);
  140.   {Transfers the contents of A into B}
  141.   {NOTE: B^ := A^ yields unpredictable results. DO NOT USE!
  142.  
  143.   {========== STRING <-> LONGSTRING TYPE CONVERSION =========================}
  144.  
  145. function lsLongString2Str(A : LongString) : string;
  146.   {-Convert LongString to Turbo string, truncating if longer than 255 chars}
  147.  
  148. procedure lsStr2LongString(S : string; A : LongString);
  149. function lsStr2LongStringF(S : string)  : LongString;
  150.   {-Convert a Turbo string into a LongString}
  151.  
  152.   {========== MANIPULATING LONGSTRINGS, STRINGS =============================}
  153.  
  154. procedure lsConcat(A, B, C : LongString);
  155. function lsConcatF(A, B : LongString) : LongString;
  156.   {-Concatenate two LongString strings, returning a third}
  157.  
  158. procedure lsConcatStr2Ls(A : LongString; S : string; C : LongString);
  159. function lsConcatStr2LsF(A : LongString; S : string)  : LongString;
  160.   {-Concatenate a string to a LongString, returning a new LongString}
  161.  
  162. procedure lsConcatLs2Str(S : string; A : LongString; C : LongString);
  163. function lsConcatLs2StrF(S : string; A : LongString)  : LongString;
  164.   {-Concatenate a LongString to a string, returning a new LongString}
  165.  
  166.   {========== SUBSTRINGS OF LONGSTRINGS, STRINGS ============================}
  167.  
  168. procedure lsCopy(A  : LongString; Start, Len  : word; B : LongString);
  169. function lsCopyF(A  : LongString; Start, Len  : word)  : LongString;
  170.   {-Return a long substring of A. Note Start=1 for first char in A}
  171.  
  172. procedure lsDelete(A : LongString; Start, Len : word; B : LongString);
  173. function lsDeleteF(A : LongString; Start, Len : word) : LongString;
  174.   {-Delete Len characters of A, starting at position Start}
  175.  
  176. procedure lsInsert(A, Obj : LongString; Start : word; B : LongString);
  177. function lsInsertF(A, Obj : LongString; Start : word) : LongString;
  178.   {-Insert LongString Obj into A at position Start returning a new LongString}
  179.  
  180. procedure lsInsertStr(A : LongString; Obj : string;
  181.                       Start : word; B : LongString);
  182. function lsInsertStrF(A : LongString; Obj : string;
  183.                       Start : word) : LongString;
  184.   {-Insert string Obj into A at position Start returning a new LongString}
  185.  
  186. procedure lsGetNext(LS1, LS2  : LongString);
  187. function lsGetNextF(LS1 : LongString) : LongString;
  188. procedure lsGetNextStr(LS1  : LongString; var S2  : string);
  189. function lsGetNextStrF(LS1  : LongString) : string;
  190.   {-Returns the next substring of LS1 which is delimited by a member
  191.     of lsDelimSet.)
  192.  
  193.   {========== LONGSTRING TRANSFORMATIONS ====================================}
  194.  
  195. procedure lsCenter(A : LongString; Width : word; B : LongString);
  196. function lsCenterF(A : LongString; Width : word)  : LongString;
  197.   {-Return a LongString centered in a LongString of blanks with specified
  198.     width}
  199.  
  200. procedure lsCenterCh(A : LongString; Ch : Char; Width : word; B : LongString);
  201. function lsCenterChF(A : LongString; Ch : Char; Width : word) : LongString;
  202.   {-Return a LongString centered in a LongString of Ch with specified width}
  203.  
  204. procedure lsCharStr(Ch : Char; Len : word; A : LongString);
  205. function lsCharStrF(Ch : Char; Len : word) : LongString;
  206.   {-Return a LongString of length Len filled with Ch}
  207.  
  208. procedure lsLeftPad(A : LongString; Len : word; B : LongString);
  209. function lsLeftPadF(A : LongString; Len : word) : LongString;
  210.   {-Left-pad the LongString in A to length Len with blanks, returning
  211.     a new LongString}
  212.  
  213. procedure lsLeftPadCh(A : LongString; Ch : Char; Len : word; B : LongString);
  214. function lsLeftPadChF(A : LongString; Ch : Char; Len : word)  : LongString;
  215.   {-Left-pad the LongString in A to length Len with Ch, returning a new
  216.     LongString}
  217.  
  218. procedure lsLocase(A, B : LongString);
  219. function lsLocaseF(A  : LongString) : LongString;
  220.   {-Lowercase the LongString in A, returning a new LongString}
  221.  
  222. procedure lsPad(A : LongString; Len : word; B : LongString);
  223. function lsPadF(A : LongString; Len : word) : LongString;
  224.   {-Right-pad the LongString in A to length Len with blanks, returning
  225.     a new LongString}
  226.  
  227. procedure lsPadCh(A : LongString; Ch : Char; Len : word; B : LongString);
  228. function lsPadChF(A : LongString; Ch : Char; Len : word)  : LongString;
  229.   {-Right-pad the LongString in A to length Len with Ch, returning
  230.     a new LongString}
  231.  
  232. procedure lsTrim(A, B : LongString);
  233. function lsTrimF(A  : LongString) : LongString;
  234.   {-Return a LongString with leading and trailing white space removed}
  235.  
  236. procedure lsTrimLead(A, B : LongString);
  237. function lsTrimLeadF(A  : LongString): LongString;
  238.   {-Return a LongString with leading white space removed}
  239.  
  240. procedure lsTrimTrail(A, B : LongString);
  241. function lsTrimTrailF(A : LongString) : LongString;
  242.   {-Return a LongString with trailing white space removed}
  243.  
  244. procedure lsTrimLeadSet(A : LongString; CS : CharSet; B : LongString);
  245. function lsTrimLeadSetF(A : LongString; CS : CharSet) : LongString;
  246.   {-Returns a LongString with leading characters in CS stripped.}
  247.  
  248. procedure lsTrimTrailSet(A : LongString; CS : CharSet; B : LongString);
  249. function lsTrimTrailSetF(A : LongString; CS : CharSet) : LongString;
  250.   {-Returns a LongString with trailing characters in CS stripped.}
  251.  
  252. procedure lsTrimSet(A : LongString; CS : CharSet; B : LongString);
  253. function lsTrimSetF(A  : LongString; CS : CharSet) : LongString;
  254.   {-Returns a LongString with characters in CS stripped.}
  255.  
  256. procedure lsUpcase(A, B : LongString);
  257. function lsUpcaseF(A  : LongString) : LongString;
  258.   {-Uppercase the LongString in A, returning a new LongString}
  259.  
  260.   {========== GLOBAL PROCESSING =============================================}
  261.  
  262. procedure lsDelAll(A, Obj, B : LongString);
  263. function lsDelAllF(A, Obj : LongString):  LongString;
  264. procedure lsDelAllStr(A : LongString; Obj : string; B : LongString);
  265. function lsDelAllStrF(A : LongString; Obj : string) : LongString;
  266.   {-Deletes all occurrences of Obj in A}
  267.  
  268. procedure lsDelAllUC(A, Obj, B : LongString);
  269. function lsDelAllUCF(A, Obj : LongString):  LongString;
  270. procedure lsDelAllStrUC(A : LongString; Obj : string; B : LongString);
  271. function lsDelAllStrUCF(A : LongString; Obj : string) : LongString;
  272.   {-Deletes all occurrences of Obj in A}
  273.   { The search is not CASE SENSITIVE.}
  274.  
  275. procedure lsRepAll(A, Obj, Obj1, B : LongString);
  276. function lsRepAllF(A, Obj, Obj1 : LongString):  LongString;
  277. procedure lsRepAllStr(A : LongString; Obj, Obj1 : string; B : LongString);
  278. function lsRepAllStrF(A : LongString; Obj, Obj1 : string) : LongString;
  279.   {-Replaces all occurrences of Obj in A with Obj1}
  280.  
  281. procedure lsRepAllUC(A, Obj, Obj1, B : LongString);
  282. function lsRepAllUCF(A, Obj, Obj1 : LongString):  LongString;
  283. procedure lsRepAllStrUC(A : LongString; Obj, Obj1 : string; B : LongString);
  284. function lsRepAllStrUCF(A : LongString; Obj, Obj1 : string) : LongString;
  285.   {-Replaces all occurrences of Obj in A with Obj1}
  286.   { The search is not CASE SENSITIVE.}
  287.  
  288.   {========== INPUT / OUTPUT ================================================}
  289.  
  290. procedure lsReadLn(var F : Text; A : LongString);
  291.   {-Read a LongString from text file}
  292.  
  293. procedure lsWriteLn(var F : Text; A : LongString);
  294.   {-Write a LongString to text file}
  295.  
  296. procedure lsIon;
  297.   {-Has the same effect with respect to lsReadLn, lsWriteLn as the $I+
  298.     compiler has with respect to normal I/O operations, except that
  299.     the reported error address is meaningless.}
  300.  
  301. procedure lsIoff;
  302.   {-Has the same effect with respect to lsReadLn, lsWriteLn as the $I-
  303.     compiler has with respect to normal I/O operations, except that
  304.     the reported error address is meaningless.}
  305.  
  306. function lsIoResult : word;
  307.   {-Returns the value of IoResult resulting from the last lsReadLn or
  308.     lsWriteLn. NOTE: You MUST use lsIoResult for checking lsReadLn,
  309.     lsWriteLn. If you call IoResult instead, you will always get a 0
  310.     return.}
  311.  
  312. implementation
  313.  
  314.  
  315. const
  316.   Blank               : char    = #32;
  317.   MaxRingSize                   = 100;
  318.   RingSizeM1                    = MaxRingSize - 1;
  319.  
  320.   lsSysInited         : boolean = false;
  321.   lsMinErrNum                   = 250;
  322.   lsMaxErrNum                   = 255;
  323.  
  324.   lsIoRes             : word    = 0;
  325.   lsIoCheck           : boolean = true;
  326.  
  327. type
  328.   lsErrorNum                    = lsMinErrNum..lsMaxErrNum;
  329.  
  330. const
  331.   lsError             : array[lsErrorNum] of string[50] =
  332.                        ('ShLngStr not initialized.',
  333.                         'Long String too long (65517).',
  334.                         'lsInit allocation failure.',
  335.                         'lsInit allocation failure on ring buffer.',
  336.                         '',
  337.                         '');
  338.  
  339. var
  340.   Ring       : array[0..RingSizeM1] of LongString;
  341.   RingPtr    : ShortInt;
  342.  
  343. procedure ChkInit;
  344.   begin
  345.     if not lsSysInited then
  346.       RunErrorMsg(lsInitError, lsError[lsInitError]);
  347.     end;
  348.  
  349. procedure lsSysInit;
  350.   begin {lsSysInit}
  351.     if lsSysInited then exit;
  352.     if RingSize > MaxRingSize then begin
  353.       WriteLn('RingSize (',RingSize,') > MaxRingSize (',MaxRingSize,')');
  354.       WriteLn('Resetting to ',MaxRingSize);
  355.       RingSize := MaxRingSize;
  356.       end;
  357.     for RingPtr := 0 to RingSizeM1 do
  358.       Ring[RingPtr] := nil;
  359.     RingPtr := -1;
  360.     lsSysInited := true;
  361.     end; {lsSysInit}
  362.  
  363. procedure lsSysDeInit;
  364.   begin {lsSysDeInit}
  365.     if not lsSysInited then exit;
  366.     for RingPtr := 0 to RingSizeM1 do begin
  367.       if Ring[RingPtr] <> nil then
  368.         FreeMemCheck(Ring[RingPtr],
  369.                      Ring[RingPtr]^.dLength + (2 * SizeOf(word)));
  370.       Ring[RingPtr] := nil;
  371.       end;
  372.     RingPtr := -1;
  373.     lsSysInited := false;
  374.     end; {lsSysDeInit}
  375.  
  376. function Ptr2Str(P:pointer) : string; {For debugging only!}
  377.   begin
  378.     Ptr2Str := HexPtr(Normalized(P));
  379.     end;
  380.  
  381. function max(X, Y : word) : word;
  382.   begin
  383.     if X >= Y then
  384.       max := X
  385.     else
  386.       max := Y;
  387.     end; {max}
  388.  
  389. function min(X, Y : word) : word;
  390.   begin
  391.     if X <= Y then
  392.       min := X
  393.     else
  394.       min := Y;
  395.     end; {min}
  396.  
  397. function lsInitPrim(var A  : LongString; L, Err : word)  : boolean;
  398.   {"Declares" a LongString of maximum declared length L and establishes
  399.    space for it on the heap. Returns false if L is greater than
  400.    MaxLongString or not enough heap space.}
  401.   var
  402.     B1  : boolean;
  403.   begin
  404.     if L > MaxLongString then begin
  405.       lsInitPrim := false;
  406.       if lsHaltErr then
  407.         RunErrorMsg(lsStringTooLong, lsError[lsStringTooLong])
  408.       else
  409.         lsRuntimeError := lsStringTooLong;
  410.       exit;
  411.       end {if}
  412.     else begin
  413.       B1 := GetMemCheck(A, L+(2*SizeOf(word)));
  414.       if not B1 then begin
  415.         lsInitPrim := false;
  416.         if lsHaltErr then
  417.           RunErrorMsg(Err, lsError[Err])
  418.         else
  419.           lsRuntimeError := Err;
  420.         end; {if not B1}
  421.       lsInitPrim := true;
  422.       A^.dLength := L;
  423.       A^.Length := 0;
  424.       end; {else}
  425.     end; {lsInitPrim}
  426.  
  427. procedure lsDispose(var A : LongString);
  428.   {-Dispose of A, releasing its heap space}
  429.   begin
  430.     FreeMemCheck(A, A^.dLength+(2*SizeOf(word)));
  431.     A := nil;
  432.     end; {lsDispose}
  433.  
  434. function lsInit(var A  : LongString; L : word) : boolean;
  435.   begin {lsInit}
  436.     lsInit := lsInitPrim(A, L, lsAllocError);
  437.     end; {lsInit}
  438.  
  439. function NextInRing(L  : word) : LongString;
  440.   {-lsInits the next LongString on the ring buffer, lsDisposing of its
  441.     current contents, if any.}
  442.   begin
  443.     ChkInit;
  444.     RingPtr := (RingPtr+1) mod RingSize;
  445.     if Ring[RingPtr] <> nil then
  446.       lsDispose(Ring[RingPtr]);
  447.     if not lsInitPrim(Ring[RingPtr], L, lsRingAllocError) then begin
  448.       NextInRing := nil;
  449.       end
  450.     else
  451.       NextInRing := Ring[RingPtr];
  452.     end; {NextInRing}
  453.  
  454. procedure lsTransfer(A, B : LongString);
  455.   {Transfers the contents of A to B.
  456.    Truncates if the declared length of B is less than the length of A.}
  457.   begin
  458.     if Normalized(A) = Normalized(B) then exit;
  459.     B^.Length := min(A^.Length, B^.dLength);
  460.     move(A^.lsData, B^.lsData, B^.Length);
  461.     end; {lsTransfer}
  462.  
  463. function lsLength(A : LongString) : word;
  464.   {-Return the length of a LongString string}
  465.   begin
  466.     lsLength := A^.Length;
  467.     end; {lsLength}
  468.  
  469. function lsSizeOf(A : LongString) : word;
  470.   {-Returns the **declared** length of A + the overhead words}
  471.   begin
  472.     lsSizeOf := A^.dLength + (2*SizeOf(word));
  473.     end; {lsSizeOf}
  474.  
  475. function lsLongString2Str(A : LongString) : string;
  476.   {-Convert LongString to Turbo string, truncating if longer than 255 chars}
  477.   var
  478.     S : string;
  479.   begin
  480.     S[0] := char(min(A^.Length, 255));
  481.     move(A^.lsData, S[1], byte(S[0]));
  482.     lsLongString2Str := S;
  483.     end; {lsLongString2Str}
  484.  
  485. procedure lsStr2LongString(S : string; A : LongString);
  486.   {-Convert a Turbo string into a LongString. The LongString must have
  487.    been declared.}
  488.   begin
  489.     if A = nil then exit;
  490.     A^.Length := min(A^.dLength, byte(S[0]));
  491.     move(S[1], A^.lsData, A^.Length);
  492.     end; {lsStr2LongString}
  493.  
  494. function lsStr2LongStringF(S : string)  : LongString;
  495.   {-Convert a Turbo string into a LongString}
  496.   var
  497.     ThisLs  : LongString;
  498.   begin
  499.     ThisLs := NextInRing(byte(S[0]));
  500.     lsStr2LongStringF := ThisLs;
  501.     lsStr2LongString(S, ThisLs);
  502.     end; {lsStr2LongStringF}
  503.  
  504. procedure lsCopy(A  : LongString; Start, Len  : word; B : LongString);
  505.   {-Return a long substring of A. Note Start=1 for first char in A}
  506.   begin
  507.     if B = nil then exit;
  508.     if (A = nil) or (Start > A^.Length) then begin
  509.       B^.Length := 0;
  510.       exit;
  511.       end;
  512.     if ((Start-1) + Len) > A^.Length then
  513.       Len := A^.Length - Start + 1;
  514.     B^.Length := min(Len, B^.dLength);
  515.     move(A^.lsData[Start], B^.lsData, Len);
  516.     end; {lsCopy}
  517.  
  518. function lsCopyF(A  : LongString; Start, Len  : word)  : LongString;
  519.   {-Return a long substring of A. Note Start=1 for first char in A}
  520.   var
  521.     ThisLs  : LongString;
  522.   begin
  523.     ThisLs := NextInRing(Len);
  524.     lsCopyF := ThisLs;
  525.     lsCopy(A, Start, Len, ThisLs);
  526.     end; {lsCopyF}
  527.  
  528. procedure lsDelete(A : LongString; Start, Len : word; B : LongString);
  529.   {-Delete Len characters of A, starting at position Start}
  530.   begin
  531.     lsTransfer(A, B);
  532.     if Start > B^.Length then exit;
  533.     if Len > B^.Length - (Start - 1) then
  534.       Len := B^.Length - (Start - 1);
  535.     B^.Length := B^.Length - Len;
  536.     move(B^.lsData[Start+Len], B^.lsData[Start], B^.Length - (Start - 1));
  537.     end; {lsDelete}
  538.  
  539. function lsDeleteF(A  : LongString; Start, Len  : word) : LongString;
  540.   {-Delete Len characters of A, starting at position Start}
  541.   {-The function form returns A unchanged.}
  542.   var
  543.     ThisLs  : LongString;
  544.   begin
  545.     if Start > A^.Length then begin
  546.       lsDeleteF := nil;
  547.       exit;
  548.       end;
  549.     if Len > A^.Length - (Start - 1) then
  550.       Len := A^.Length - (Start - 1);
  551.     ThisLs := NextInRing(A^.Length - Len);
  552.     ThisLs^.Length := A^.Length - Len;
  553.     move(A^.lsData[1], ThisLs^.lsData[1], Start - 1);
  554.     move(A^.lsData[Start+Len], ThisLs^.lsData[Start], A^.Length - (Start - 1));
  555.     lsDeleteF := ThisLs;
  556.     end; {lsDeleteF}
  557.  
  558. procedure lsConcat(A, B, C : LongString);
  559.   {-Concatenate two LongString strings, returning a third}
  560.   var
  561.     CpyFromA,
  562.     CpyFromB  : word;
  563.   begin
  564.     if A^.Length > C^.dLength then begin
  565.       CpyFromA := C^.dLength;
  566.       CpyFromB := 0;
  567.       end
  568.     else begin
  569.       if A^.Length + B^.Length > C^.dLength then begin
  570.         CpyFromA := A^.Length;
  571.         CpyFromB := C^.dLength - CpyFromA;
  572.         end
  573.       else begin
  574.         CpyFromA := A^.Length;
  575.         CpyFromB := B^.Length;
  576.         end;
  577.       end;
  578.     C^.Length := CpyFromA + CpyFromB;
  579.     move(A^.lsData, C^.lsData, CpyFromA);
  580.     move(B^.lsData, C^.lsData[CpyFromA + 1], CpyFromB);
  581.     end; {lsConcat}
  582.  
  583. function lsConcatF(A, B : LongString) : LongString;
  584.   {-Concatenate two LongString strings, returning a third}
  585.   var
  586.     ThisLs  : LongString;
  587.     CpyFromB: word;
  588.   begin
  589.     if A^.Length + B^.Length > MaxLongString then
  590.       CpyFromB := MaxLongString - A^.Length
  591.     else
  592.       CpyFromB := B^.Length;
  593.     ThisLs := NextInRing(A^.Length + CpyFromB);
  594.     lsConcatF := ThisLs;
  595.     lsConcat(A, B, ThisLs);
  596.     end; {lsConcatF}
  597.  
  598. procedure lsConcatStr2Ls(A : LongString; S : string; C : LongString);
  599.   {-Concatenate a string to a LongString, returning a new LongString}
  600.   var
  601.     LS  : LongString;
  602.   begin
  603.     if not lsInit(LS, A^.Length + byte(S[0])) then exit;
  604.     lsStr2LongString(S, LS);
  605.     lsConcat(A, LS, C);
  606.     lsDispose(LS);
  607.     end; {lsConcatStr2Ls}
  608.  
  609. function lsConcatStr2LsF(A : LongString; S : string)  : LongString;
  610.   {-Concatenate a string to a LongString, returning a new LongString}
  611.   var
  612.     LS  : LongString;
  613.   begin
  614.     if not lsInit(LS, A^.Length + byte(S[0])) then exit;
  615.     lsStr2LongString(S, LS);
  616.     lsConcatStr2LsF := lsConcatF(A, LS);
  617.     lsDispose(LS);
  618.     end; {lsConcatStr2LsF}
  619.  
  620. procedure lsConcatLs2Str(S : string; A : LongString; C : LongString);
  621.   {-Concatenate a LongString to a string, returning a new LongString}
  622.   var
  623.     LS  : LongString;
  624.   begin
  625.     if not lsInit(LS, A^.Length + byte(S[0])) then exit;
  626.     lsStr2LongString(S, LS);
  627.     lsConcat(LS, A, C);
  628.     lsDispose(LS);
  629.     end; {lsConcatLs2Str}
  630.  
  631. function lsConcatLs2StrF(S : string; A : LongString)  : LongString;
  632.   {-Concatenate a LongString to a string, returning a new LongString}
  633.   var
  634.     LS  : LongString;
  635.   begin
  636.     if not lsInit(LS, A^.Length + byte(S[0])) then exit;
  637.     lsStr2LongString(S, LS);
  638.     lsConcatLs2StrF := lsConcatF(LS, A);
  639.     lsDispose(LS);
  640.     end; {lsConcatLs2StrF}
  641.  
  642. procedure lsInsert(A, Obj : LongString; Start : word; B : LongString);
  643.   {-Insert LongString Obj into A at position Start returning a new LongString}
  644.   var
  645.     FrontOfA,
  646.     RestOfA,
  647.     CpyFromO  : word;
  648.   begin
  649.     FrontOfA := min(Start-1, B^.dLength);
  650.     if (B^.dLength - FrontOfA) > Obj^.Length then
  651.       CpyFromO := Obj^.Length
  652.     else
  653.       CpyFromO := B^.dLength - FrontOfA;
  654.     if (B^.dLength - (FrontOfA + CpyFromO)) > (A^.Length - FrontOfA) then
  655.       RestOfA := A^.Length - FrontOfA
  656.     else
  657.       RestOfA := B^.dLength - (FrontOfA + CpyFromO);
  658.     B^.Length := FrontOfA + CpyFromO + RestOfA;
  659.     move(A^.lsData, B^.lsData, FrontOfA);
  660.     move(A^.lsData[Start], B^.lsData[FrontOfA + CpyFromO + 1], RestOfA);
  661.     move(Obj^.lsData, B^.lsData[Start], CpyFromO);
  662.     end; {lsInsert}
  663.  
  664. function lsInsertF(A, Obj : LongString; Start : word) : LongString;
  665.   {-Insert LongString Obj into A at position Start returning a new LongString}
  666.   var
  667.     ThisLs  : LongString;
  668.   begin
  669.     ThisLs := NextInRing(A^.Length + Obj^.Length);
  670.     lsInsertF := ThisLs;
  671.     lsInsert(A, Obj, Start, ThisLs);
  672.     end; {lsInsertF}
  673.  
  674. procedure lsInsertStr(A : LongString; Obj : string;
  675.                       Start : word; B : LongString);
  676.   {-Insert string Obj into A at position Start returning a new LongString}
  677.   var
  678.     LS  : LongString;
  679.   begin
  680.     if not lsInit(LS, byte(Obj[0])) then exit;
  681.     lsStr2LongString(Obj, LS);
  682.     lsInsert(A, LS, Start, B);
  683.     lsDispose(LS);
  684.     end; {lsInsertStr}
  685.  
  686. function lsInsertStrF(A : LongString; Obj : string;
  687.                       Start : word) : LongString;
  688.   {-Insert string Obj into A at position Start returning a new LongString}
  689.   var
  690.     LS  : LongString;
  691.   begin
  692.     if not lsInit(LS, byte(Obj[0])) then exit;
  693.     lsStr2LongString(Obj, LS);
  694.     lsInsertStrF := lsInsertF(A, LS, Start);
  695.     lsDispose(LS);
  696.     end; {lsInsertStrF}
  697.  
  698. procedure lsUpcase(A, B : LongString);
  699.   {-Uppercase the LongString in A, returning B}
  700.   var
  701.     W1    : word;
  702.   begin
  703.     lsTransfer(A, B);
  704.     for W1 := 1 to B^.Length do
  705.       B^.lsData[W1] := Upcase(B^.lsData[W1]);
  706.     end; {lsUpcase}
  707.  
  708. function lsUpcaseF(A  : LongString) : LongString;
  709.   {-Uppercase the LongString in A, returning B}
  710.   var
  711.     ThisLs  : LongString;
  712.   begin
  713.     ThisLs := NextInRing(A^.Length);
  714.     lsUpcase(A, ThisLs);
  715.     lsUpcaseF := ThisLs;
  716.     end; {lsUpcaseF}
  717.  
  718. procedure lsLocase(A, B : LongString);
  719.   {-Lowercase the LongString in A, returning B}
  720.   var
  721.     W1    : word;
  722.   begin
  723.     lsTransfer(A, B);
  724.     for W1 := 1 to B^.Length do
  725.       B^.lsData[W1] := Locase(B^.lsData[W1]);
  726.     end; {lsLocase}
  727.  
  728. function lsLocaseF(A  : LongString) : LongString;
  729.   {-Lowercase the LongString in A, returning B}
  730.   var
  731.     ThisLs  : LongString;
  732.   begin
  733.     ThisLs := NextInRing(A^.Length);
  734.     lsLocase(A, ThisLs);
  735.     lsLocaseF := ThisLs;
  736.     end; {lsLocaseF}
  737.  
  738. function lsComp(A1, A2 : LongString) : lsCompType;
  739.   {-Compares A1 to A2, returning LESS, EQUAL, or GREATER}
  740.   var
  741.     W1,
  742.     Search  : word;
  743.     LgthA1A2: lsCompType;
  744.   begin
  745.     if A1^.Length = A2^.Length then
  746.       LgthA1A2 := Equal
  747.     else
  748.       if A1^.Length < A2^.Length then
  749.         LgthA1A2 := Less
  750.       else
  751.         LgthA1A2 := Greater;
  752.     Search := min(A1^.Length, A2^.Length);
  753.     W1 := 1;
  754.     while (W1 < Search) and (A1^.lsData[W1] = A2^.lsData[W1]) do
  755.       inc(W1);
  756.     if A1^.lsData[W1] = A2^.lsData[W1] then begin
  757.       lsComp := LgthA1A2;
  758.       exit;
  759.       end;
  760.     if A1^.lsData[W1] < A2^.lsData[W1] then begin
  761.       lsComp := Less;
  762.       exit;
  763.       end;
  764.     if A1^.lsData[W1] > A2^.lsData[W1] then begin
  765.       lsComp := Greater;
  766.       end;
  767.     end; {lsComp}
  768.  
  769. function lsPosStr(Obj : string; A : LongString) : word;
  770.   {-Return the position of the string Obj in A, returning lsNotFound if
  771.    not found}
  772.   begin
  773.     lsPosStr := succ(Search(A^.lsData, A^.Length, Obj[1], byte(Obj[0])));
  774.     end; {lsPosStr}
  775.  
  776. function lsPos(Obj, A : LongString) : word;
  777.   {-Return the position of Obj in A, returning lsNotFound if not found}
  778.   begin
  779.     lsPos := succ(Search(A^.lsData, A^.Length, Obj^.lsData, Obj^.Length));
  780.     end; {lsPos}
  781.  
  782. function lsPosSet(A : CharSet; S : LongString) : word;
  783.   var
  784.     W1  : word;
  785.   begin
  786.     W1 := 1;
  787.     while (not (S^.lsData[W1] in A)) and (W1 < lsLength(S)) do
  788.       inc(W1);
  789.     if S^.lsData[W1] in A then
  790.       lsPosSet := W1
  791.     else
  792.       lsPosSet := 0;
  793.     end; {lsPosSet}
  794.  
  795. function lsPosStrUC(Obj : string; A : LongString) : word;
  796.   {-Return the position of the string Obj in A, returning lsNotFound if
  797.    not found. The search is not case sensitive.}
  798.   begin
  799.     lsPosStrUC := succ(SearchUC(A^.lsData, A^.Length, Obj[1], byte(Obj[0])));
  800.     end; {lsPosStrUC}
  801.  
  802. function lsPosUC(Obj, A : LongString) : word;
  803.   {-Return the position of Obj in A, returning lsNotFound if not found.
  804.    The search is not case sensitive.}
  805.   begin
  806.     lsPosUC := succ(SearchUC(A^.lsData, A^.Length, Obj^.lsData, Obj^.Length));
  807.     end; {lsPosUC}
  808.  
  809. function CountPrim(A, Obj : LongString;
  810.                    CaseSens  {true if case sensitive} : boolean)  : word;
  811.   var
  812.     Next,
  813.     Now,
  814.     Count : word;
  815.   begin
  816.     Next := 1;
  817.     Now := 1;
  818.     Count := 0;
  819.     repeat
  820.       if CaseSens then
  821.         Now := succ(Search(A^.lsData[Next], A^.Length-Next+1,
  822.                            Obj^.lsData, Obj^.Length))
  823.       else
  824.         Now := succ(SearchUC(A^.lsData[Next], A^.Length-Next+1,
  825.                            Obj^.lsData, Obj^.Length));
  826.       if Now <> 0 then begin
  827.         Next := Next + Now + Obj^.Length - 1;
  828.         inc(Count);
  829.         end;
  830.       until Now = 0;
  831.     CountPrim := Count;
  832.     end; {CountPrim}
  833.  
  834.   {-Returns the number of occurrences of Obj in A}
  835. function lsCount(A, Obj : LongString):  word;
  836.   begin
  837.     lsCount := CountPrim(A, Obj, true);
  838.     end; {lsCount}
  839. function lsCountStr(A : LongString; Obj : string) : word;
  840.   var
  841.     LS  : LongString;
  842.   begin
  843.     if not lsInit(LS, byte(Obj[0])) then exit;
  844.     lsStr2LongString(Obj, LS);
  845.     lsCountStr := lsCount(A, LS);
  846.     lsDispose(LS);
  847.     end; {lsCountStr}
  848.  
  849.   {-Returns the number of occurrences of Obj in A}
  850.   { The search is not CASE SENSITIVE.}
  851. function lsCountUC(A, Obj : LongString):  word;
  852.   begin
  853.     lsCountUC := CountPrim(A, Obj, false);
  854.     end; {lsCountUC}
  855. function lsCountStrUC(A : LongString; Obj : string) : word;
  856.   var
  857.     LS  : LongString;
  858.   begin
  859.     if not lsInit(LS, byte(Obj[0])) then exit;
  860.     lsStr2LongString(Obj, LS);
  861.     lsCountStrUC := lsCountUC(A, LS);
  862.     lsDispose(LS);
  863.     end; {lsCountStrUC}
  864.  
  865. procedure RepDelPrim(In0, Obj, Obj1, Out : LongString;
  866.                      RepOrDel, {true if to replace}
  867.                      CaseSens  {true if case sensitive} : boolean);
  868.   var
  869.     In1,
  870.     Scr   : LongString;
  871.     W1    : word;
  872.   function GetPos : word;
  873.     begin
  874.       if CaseSens then
  875.         GetPos := lsPos(Obj, In1)
  876.       else
  877.         GetPos := lsPosUC(Obj, In1);
  878.       end; {GetPos}
  879.   begin
  880.     if not lsInit(In1, In0^.Length) then exit;
  881.     lsTransfer(In0, In1);
  882.     W1 := GetPos;
  883.     if W1 = lsNotFound then begin
  884.       lsTransfer(In1, Out);
  885.       lsDispose(In1);
  886.       exit;
  887.       end;
  888.     if not lsInit(Scr, In1^.Length) then exit;
  889.     Out^.Length := 0;
  890.     while W1 <> lsNotFound do begin
  891.       lsCopy(In1, 1, W1-1, Scr);
  892.       lsConcat(Out, Scr, Out);
  893.       if RepOrDel then
  894.         lsConcat(Out, Obj1, Out);
  895.       lsDelete(In1, 1, W1 + Obj^.Length - 1, In1);
  896.       W1 := GetPos;
  897.       end; {while}
  898.     lsConcat(Out, In1, Out);
  899.     lsDispose(In1);
  900.     lsDispose(Scr);
  901.     end; {RepDelPrim}
  902.  
  903.   {-Deletes all occurrences of Obj in A}
  904. procedure lsDelAll(A, Obj, B : LongString);
  905.   begin
  906.     RepDelPrim(A, Obj, nil, B, false, true);
  907.     end; {lsDelAll}
  908. function lsDelAllF(A, Obj : LongString):  LongString;
  909.   var
  910.     LS  : LongString;
  911.   begin
  912.     LS := NextInRing(A^.Length - (lsCount(A, Obj) * Obj^.Length));
  913.     lsDelAll(A, Obj, LS);
  914.     lsDelAllF := LS;
  915.     end; {lsDelAllF}
  916. procedure lsDelAllStr(A : LongString; Obj : string; B : LongString);
  917.   var
  918.     LS  : LongString;
  919.   begin
  920.     if not lsInit(LS, A^.Length - (lsCountStr(A, Obj) * byte(Obj[0]))) then
  921.       exit;
  922.     lsStr2LongString(Obj, LS);
  923.     lsDelAll(A, LS, B);
  924.     lsDispose(LS);
  925.     end; {lsDelAllStr}
  926. function lsDelAllStrF(A : LongString; Obj : string) : LongString;
  927.   var
  928.     LS  : LongString;
  929.   begin
  930.     if not lsInit(LS, A^.Length - (lsCountStr(A, Obj) * byte(Obj[0]))) then
  931.       exit;
  932.     lsStr2LongString(Obj, LS);
  933.     lsDelAllStrF := lsDelAllF(A, LS);
  934.     lsDispose(LS);
  935.     end; {lsDelAllStrF}
  936.  
  937.   {-Deletes all occurrences of Obj in A}
  938.   { The search is not CASE SENSITIVE.}
  939. procedure lsDelAllUC(A, Obj, B : LongString);
  940.   begin
  941.     RepDelPrim(A, Obj, nil, B, false, false);
  942.     end; {lsDelAllUC}
  943. function lsDelAllUCF(A, Obj : LongString):  LongString;
  944.   var
  945.     LS  : LongString;
  946.   begin
  947.     LS := NextInRing(A^.Length - (lsCount(A, Obj) * Obj^.Length));
  948.     lsDelAllUC(A, Obj, LS);
  949.     lsDelAllUCF := LS;
  950.     end; {lsDelAllUCF}
  951. procedure lsDelAllStrUC(A : LongString; Obj : string; B : LongString);
  952.   var
  953.     LS  : LongString;
  954.   begin
  955.     if not lsInit(LS, A^.Length - (lsCountStrUC(A, Obj) * byte(Obj[0]))) then
  956.       exit;
  957.     lsStr2LongString(Obj, LS);
  958.     lsDelAllUC(A, LS, B);
  959.     lsDispose(LS);
  960.     end; {lsDelAllStrUC}
  961. function lsDelAllStrUCF(A : LongString; Obj : string) : LongString;
  962.   var
  963.     LS  : LongString;
  964.   begin
  965.     if not lsInit(LS, A^.Length - (lsCountStr(A, Obj) * byte(Obj[0]))) then
  966.       exit;
  967.     lsStr2LongString(Obj, LS);
  968.     lsDelAllStrUCF := lsDelAllUCF(A, LS);
  969.     lsDispose(LS);
  970.     end; {lsDelAllStrUCF}
  971.  
  972.   {-Replaces all occurrences of Obj in A with Obj1}
  973. procedure lsRepAll(A, Obj, Obj1, B : LongString);
  974.   begin
  975.     RepDelPrim(A, Obj, Obj1, B, true, true);
  976.     end; {lsRepAll}
  977. function lsRepAllF(A, Obj, Obj1 : LongString):  LongString;
  978.   var
  979.     LS    : LongString;
  980.   begin
  981.     LS := NextInRing(A^.Length +
  982.                     (lsCount(A, Obj) * (Obj1^.Length - Obj^.Length)));
  983.     lsRepAll(A, Obj, Obj1, LS);
  984.     lsRepAllF := LS;
  985.     end; {lsRepAllF}
  986. procedure lsRepAllStr(A : LongString; Obj, Obj1 : string; B : LongString);
  987.   var
  988.     LS0,
  989.     LS1  : LongString;
  990.   begin
  991.     if not lsInit(LS0, byte(Obj[0])) then exit;
  992.     lsStr2LongString(Obj, LS0);
  993.     if not lsInit(LS1, byte(Obj1[0])) then exit;
  994.     lsStr2LongString(Obj1, LS1);
  995.     lsRepAll(A, LS0, LS1, B);
  996.     lsDispose(LS0);
  997.     lsDispose(LS1);
  998.     end; {lsRepAllStr}
  999. function lsRepAllStrF(A : LongString; Obj, Obj1 : string) : LongString;
  1000.   var
  1001.     LS0,
  1002.     LS1   : LongString;
  1003.   begin
  1004.     if not lsInit(LS0, byte(Obj[0])) then exit;
  1005.     lsStr2LongString(Obj, LS0);
  1006.     if not lsInit(LS1, byte(Obj1[0])) then exit;
  1007.     lsStr2LongString(Obj1, LS1);
  1008.     lsRepAllStrF := lsRepAllF(A, LS0, LS1);
  1009.     lsDispose(LS0);
  1010.     lsDispose(LS1);
  1011.     end; {lsRepAllStrF}
  1012.  
  1013.   {-Replaces all occurrences of Obj in A with Obj1}
  1014.   { The search is not CASE SENSITIVE.}
  1015. procedure lsRepAllUC(A, Obj, Obj1, B : LongString);
  1016.   begin
  1017.     RepDelPrim(A, Obj, Obj1, B, true, false);
  1018.     end; {lsRepAllUC}
  1019. function lsRepAllUCF(A, Obj, Obj1 : LongString):  LongString;
  1020.   var
  1021.     LS    : LongString;
  1022.   begin
  1023.     LS := NextInRing(A^.Length +
  1024.                     (lsCountUC(A, Obj) * (Obj1^.Length - Obj^.Length)));
  1025.     lsRepAllUC(A, Obj, Obj1, LS);
  1026.     lsRepAllUCF := LS;
  1027.     end; {lsRepAllUCF}
  1028. procedure lsRepAllStrUC(A : LongString; Obj, Obj1 : string; B : LongString);
  1029.   var
  1030.     LS0,
  1031.     LS1  : LongString;
  1032.   begin
  1033.     if not lsInit(LS0, byte(Obj[0])) then exit;
  1034.     lsStr2LongString(Obj, LS0);
  1035.     if not lsInit(LS1, byte(Obj1[0])) then exit;
  1036.     lsStr2LongString(Obj1, LS1);
  1037.     lsRepAllUC(A, LS0, LS1, B);
  1038.     lsDispose(LS0);
  1039.     lsDispose(LS1);
  1040.     end; {lsRepAllStrUC}
  1041. function lsRepAllStrUCF(A : LongString; Obj, Obj1 : string) : LongString;
  1042.   var
  1043.     LS0,
  1044.     LS1   : LongString;
  1045.   begin
  1046.     if not lsInit(LS0, byte(Obj[0])) then exit;
  1047.     lsStr2LongString(Obj, LS0);
  1048.     if not lsInit(LS1, byte(Obj1[0])) then exit;
  1049.     lsStr2LongString(Obj1, LS1);
  1050.     lsRepAllStrUCF := lsRepAllUCF(A, LS0, LS1);
  1051.     lsDispose(LS0);
  1052.     lsDispose(LS1);
  1053.     end; {lsRepAllStrUCF}
  1054.  
  1055. procedure lsGetNextPrim(LS1, LS2  : LongString; Delims  : lsDelimSetType);
  1056.   var
  1057.     W1  : word;
  1058.   begin
  1059.     if lsLength(LS1) = 0 then begin
  1060.       LS2^.Length := 0;
  1061.       exit;
  1062.       end;
  1063.     W1 := 1;
  1064.     while (LS1^.lsData[W1] in Delims) and (W1 <= lsLength(LS1)) do
  1065.       inc(W1);
  1066.     dec(W1);
  1067.     lsDelete(LS1, 1, W1, LS1);
  1068.     if lsLength(LS1) = 0 then
  1069.       LS2^.Length := 0
  1070.     else begin
  1071.       W1 := 1;
  1072.       while (not (LS1^.lsData[W1] in Delims)) and (W1 <= lsLength(LS1)) do
  1073.         inc(W1);
  1074.       dec(W1);
  1075.       if W1 <> 0 then begin
  1076.         lsCopy(LS1, 1, W1, LS2);
  1077.         lsDelete(LS1, 1, W1, LS1);
  1078.         end
  1079.       else begin
  1080.         lsTransfer(LS1, LS2);
  1081.         LS1^.Length := 0;
  1082.         end;
  1083.       end;
  1084.     end; {lsGetNextPrim}
  1085.  
  1086. procedure lsGetNext(LS1, LS2  : LongString);
  1087.   begin
  1088.     lsGetNextPrim(LS1, LS2, lsDelimSet);
  1089.     end;
  1090.  
  1091. function lsGetNextF(LS1 : LongString) : LongString;
  1092.   var
  1093.     Scr,
  1094.     ThisLs  : LongString;
  1095.   begin
  1096.     if not lsInit(Scr, LS1^.Length) then exit;
  1097.     lsGetNextPrim(LS1, Scr, lsDelimSet);
  1098.     ThisLs := NextInRing(Scr^.Length);
  1099.     lsTransfer(Scr, ThisLs);
  1100.     lsDispose(Scr);
  1101.     lsGetNextF := ThisLs;
  1102.     end; {lsGetNextF}
  1103.  
  1104. procedure lsGetNextStr(LS1  : LongString; var S2  : string);
  1105.   var
  1106.     LS2     : LongString;
  1107.   begin
  1108.     if not lsInit(LS2, LS1^.Length) then exit;
  1109.     lsGetNextPrim(LS1, LS2, lsDelimSet);
  1110.     S2 := lsLongString2Str(LS2);
  1111.     lsDispose(LS2);
  1112.     end; {lsGetNextStr}
  1113.  
  1114. function lsGetNextStrF(LS1  : LongString) : string;
  1115.   var
  1116.     LS2     : LongString;
  1117.   begin
  1118.     if not lsInit(LS2, LS1^.Length) then exit;
  1119.     lsGetNextPrim(LS1, LS2, lsDelimSet);
  1120.     lsGetNextStrF := lsLongString2Str(LS2);
  1121.     lsDispose(LS2);
  1122.     end; {lsGetNextStrF}
  1123.  
  1124. procedure lsCharStr(Ch : Char; Len : word; A : LongString);
  1125.   {-Return a LongString of length Len filled with Ch}
  1126.   begin
  1127.     A^.Length := min(Len, A^.dLength);
  1128.     FillChar(A^.lsData, A^.Length, Ch);
  1129.     end; {lsCharStr}
  1130.  
  1131. function lsCharStrF(Ch : Char; Len : word) : LongString;
  1132.   {-Return a LongString of length Len filled with Ch}
  1133.   var
  1134.     ThisLs  : LongString;
  1135.   begin
  1136.     ThisLs := NextInRing(Len);
  1137.     lsCharStr(Ch, Len, ThisLs);
  1138.     lsCharStrF := ThisLs;
  1139.     end; {lsCharStrF}
  1140.  
  1141. procedure lsPadCh(A : LongString; Ch : Char; Len : word; B : LongString);
  1142.   {-Right-pad the LongString in A to length Len with Ch, returning B}
  1143.   var
  1144.     CpyFromA,
  1145.     LenOfCh   : word;
  1146.   begin
  1147.     Len := min(B^.dLength, Len);
  1148.     CpyFromA := min(A^.Length, Len);
  1149.     if Len > CpyFromA then
  1150.       LenOfCh := Len - CpyFromA
  1151.     else
  1152.       LenOfCh := 0;
  1153.     B^.Length := Len;
  1154.     move(A^.lsData, B^.lsData, CpyFromA);
  1155.     FillChar(B^.lsData[CpyFromA+1], LenOfCh, Ch);
  1156.     end; {lsPadCh}
  1157.  
  1158. function lsPadChF(A : LongString; Ch : Char; Len : word)  : LongString;
  1159.   {-Right-pad the LongString in A to length Len with Ch, returning B}
  1160.   var
  1161.     ThisLs  : LongString;
  1162.   begin
  1163.     ThisLs := NextInRing(Len);
  1164.     lsPadCh(A, Ch, Len, ThisLs);
  1165.     lsPadChF := ThisLs;
  1166.     end; {lsPadChF}
  1167.  
  1168. procedure lsPad(A : LongString; Len : word; B : LongString);
  1169.   {-Right-pad the LongString in A to length Len with blanks, returning B}
  1170.   begin
  1171.     lsPadCh(A, Blank, Len, B);
  1172.     end; {lsPad}
  1173.  
  1174. function lsPadF(A : LongString; Len : word) : LongString;
  1175.   {-Right-pad the LongString in A to length Len with blanks, returning B}
  1176.   begin
  1177.     lsPadF := lsPadChF(A, Blank, Len);
  1178.     end; {lsPad}
  1179.  
  1180. procedure lsLeftPadCh(A : LongString; Ch : Char; Len : word; B : LongString);
  1181.   {-Left-pad the LongString in A to length Len with Ch, returning B}
  1182.   var
  1183.     CpyFromA,
  1184.     LenOfCh   : word;
  1185.     ThisLs    : LongString;
  1186.   begin
  1187.     Len := min(B^.dLength, Len);
  1188.     ThisLs := NextInRing(Len);
  1189.     CpyFromA := min(A^.Length, Len);
  1190.     if Len > CpyFromA then
  1191.       LenOfCh := Len - CpyFromA
  1192.     else
  1193.       LenOfCh := 0;
  1194.     ThisLs^.Length := Len;
  1195.     move(A^.lsData, ThisLs^.lsData[LenOfCh+1], CpyFromA);
  1196.     FillChar(ThisLs^.lsData, LenOfCh, Ch);
  1197.     lsTransfer(ThisLs, B);
  1198.     end; {lsLeftPadCh}
  1199.  
  1200. function lsLeftPadChF(A : LongString; Ch : Char; Len : word)  : LongString;
  1201.   {-Left-pad the LongString in A to length Len with Ch, returning B}
  1202.   var
  1203.     ThisLs  : LongString;
  1204.   begin
  1205.     ThisLs := NextInRing(Len);
  1206.     lsLeftPadCh(A, Ch, Len, ThisLs);
  1207.     lsLeftPadChF := ThisLs;
  1208.     end; {lsLeftPadChF}
  1209.  
  1210. procedure lsLeftPad(A : LongString; Len : word; B : LongString);
  1211.   {-Left-pad the LongString in A to length Len with blanks, returning B}
  1212.   begin
  1213.     lsLeftPadCh(A, Blank, Len, B);
  1214.     end; {lsLeftPad}
  1215.  
  1216. function lsLeftPadF(A : LongString; Len : word) : LongString;
  1217.   {-Left-pad the LongString in A to length Len with blanks, returning B}
  1218.   begin
  1219.     lsLeftPadF := lsLeftPadChF(A, Blank, Len);
  1220.     end; {lsLeftPad}
  1221.  
  1222. procedure lsTrimLeadSet(A : LongString; CS : CharSet; B : LongString);
  1223.   {-Returns a LongString with leading characters in CS stripped.}
  1224.   var
  1225.     W1    : word;
  1226.   begin
  1227.     lsTransfer(A, B);
  1228.     W1 := lsPosSet([#0..#255] - CS, B);
  1229.     if W1 <> 0 then
  1230.       lsDelete(B, 1, pred(W1), B);
  1231.     end; {lsTrimLeadSet}
  1232.  
  1233. function lsTrimLeadSetF(A : LongString; CS : CharSet) : LongString;
  1234.   {-Returns a LongString with leading characters in CS stripped.}
  1235.   var
  1236.     ThisLS  : LongString;
  1237.   begin {lsTrimLeadSetF}
  1238.     ThisLs := NextInRing(A^.Length);
  1239.     lsTrimLeadSet(A, CS, ThisLs);
  1240.     lsTrimLeadSetF := ThisLs;
  1241.     end; {lsTrimLeadSetF}
  1242.  
  1243. procedure lsTrimTrailSet(A : LongString; CS : CharSet; B : LongString);
  1244.   {-Returns a LongString with trailing characters in CS stripped.}
  1245.   var
  1246.     W1    : word;
  1247.   begin
  1248.     lsTransfer(A, B);
  1249.     W1 := B^.Length;
  1250.     while (W1 >= 1) and (B^.lsData[W1] in CS) do begin
  1251.       dec(W1);
  1252.       dec(B^.Length);
  1253.       end;
  1254.     end; {lsTrimTrailSet}
  1255.  
  1256. function lsTrimTrailSetF(A : LongString; CS : CharSet) : LongString;
  1257.   {-Returns a LongString with trailing characters in CS stripped.}
  1258.   var
  1259.     ThisLs  : LongString;
  1260.   begin {lsTrimTrailSetF}
  1261.     ThisLs := NextInRing(A^.Length);
  1262.     lsTrimTrailSet(A, CS, ThisLs);
  1263.     lsTrimTrailSetF := ThisLs;
  1264.     end; {lsTrimTrailSetF}
  1265.  
  1266. procedure lsTrimSet(A : LongString; CS : CharSet; B : LongString);
  1267.   {-Returns a LongString with characters in CS stripped.}
  1268.   var
  1269.     ThisLs  : LongString;
  1270.   begin
  1271.     if not lsInit(ThisLs, A^.Length) then exit;
  1272.     lsTransfer(A, ThisLs);
  1273.     lsTrimLeadSet(lsTrimTrailSetF(ThisLs, CS), CS, B);
  1274.     lsDispose(ThisLs);
  1275.     end; {lsTrimSet}
  1276.  
  1277. function lsTrimSetF(A  : LongString; CS : CharSet) : LongString;
  1278.   {-Returns a LongString with characters in CS stripped.}
  1279.   var
  1280.     ThisLs  : LongString;
  1281.   begin
  1282.     ThisLs := NextInRing(A^.Length);
  1283.     lsTrimSet(A, CS, ThisLs);
  1284.     lsTrimSetF := ThisLs;
  1285.     end; {lsTrimSetF}
  1286.  
  1287. procedure lsTrimLead(A, B : LongString);
  1288.   {-Return a LongString with leading white space removed}
  1289.   var
  1290.     W1    : word;
  1291.   begin
  1292.     lsTransfer(A, B);
  1293.     W1 := 1;
  1294.     while (W1 <= B^.Length) and (B^.lsData[W1] <= Blank) do
  1295.       inc(W1);
  1296.     if W1 <= B^.Length then begin
  1297.       move(B^.lsData[W1], B^.lsData[1], B^.Length - W1 + 1);
  1298.       B^.Length := B^.Length - W1 + 1;
  1299.       end;
  1300.     end; {lsTrimLead}
  1301.  
  1302. function lsTrimLeadF(A  : LongString): LongString;
  1303.   {-Return a LongString with leading white space removed}
  1304.   var
  1305.     ThisLs  : LongString;
  1306.   begin
  1307.     ThisLs := NextInRing(A^.Length);
  1308.     lsTrimLead(A, ThisLs);
  1309.     lsTrimLeadF := ThisLs;
  1310.     end; {lsTrimLeadF}
  1311.  
  1312. procedure lsTrimTrail(A, B : LongString);
  1313.   {-Return a LongString with trailing white space removed}
  1314.   var
  1315.     W1    : word;
  1316.   begin
  1317.     lsTransfer(A, B);
  1318.     W1 := B^.Length;
  1319.     while (W1 >= 1) and (B^.lsData[W1] <= Blank) do begin
  1320.       dec(W1);
  1321.       dec(B^.Length);
  1322.       end;
  1323.     end; {lsTrimTrail}
  1324.  
  1325. function lsTrimTrailF(A : LongString) : LongString;
  1326.   {-Return a LongString with trailing white space removed}
  1327.   var
  1328.     ThisLs  : LongString;
  1329.   begin
  1330.     ThisLs := NextInRing(A^.Length);
  1331.     lsTrimTrail(A, ThisLs);
  1332.     lsTrimTrailF := ThisLs;
  1333.     end; {lsTrimTrailF}
  1334.  
  1335. procedure lsTrim(A, B : LongString);
  1336.   {-Return a LongString with leading and trailing white space removed}
  1337.   var
  1338.     ThisLs  : LongString;
  1339.   begin
  1340.     if not lsInit(ThisLs, A^.Length) then exit;
  1341.     lsTransfer(A, ThisLs);
  1342.     lsTrimLead(lsTrimTrailF(ThisLs), B);
  1343.     lsDispose(ThisLs);
  1344.     end; {lsTrim}
  1345.  
  1346. function lsTrimF(A  : LongString) : LongString;
  1347.   {-Return a LongString with leading and trailing white space removed}
  1348.   var
  1349.     ThisLs  : LongString;
  1350.   begin
  1351.     ThisLs := NextInRing(A^.Length);
  1352.     lsTrim(A, ThisLs);
  1353.     lsTrimF := ThisLs;
  1354.     end; {lsTrimF}
  1355.  
  1356. procedure lsCenterCh(A : LongString; Ch : Char; Width : word; B : LongString);
  1357.   {-Return a LongString centered in a LongString of Ch with specified Width}
  1358.   var
  1359.     W1      : word;
  1360.   begin
  1361.     lsTransfer(A, B);
  1362.     if Width > B^.dLength then exit;
  1363.     if Width < B^.Length then begin
  1364.       B^.Length := Width;
  1365.       exit;
  1366.       end;
  1367.     W1 := Width - ((Width - B^.Length) shr 1);
  1368.     lsLeftPadCh(B, Ch, W1, B);
  1369.     lsPadCh(B, Ch, Width, B);
  1370.     end; {lsCenterCh}
  1371.  
  1372. function lsCenterChF(A : LongString; Ch : Char; Width : word) : LongString;
  1373.   {-Return a LongString centered in a LongString of Ch with specified width}
  1374.   var
  1375.     ThisLs  : LongString;
  1376.   begin
  1377.     ThisLs := NextInRing(Width);
  1378.     lsCenterCh(A, Ch, Width, ThisLs);
  1379.     lsCenterChF := ThisLs;
  1380.     end; {lsCenterChF}
  1381.  
  1382. procedure lsCenter(A : LongString; Width : word; B : LongString);
  1383.   {-Return a LongString centered in a LongString of blanks with specified width}
  1384.   begin
  1385.     lsCenterCh(A, Blank, Width, B);
  1386.     end; {lsCenter}
  1387.  
  1388. function lsCenterF(A : LongString; Width : word)  : LongString;
  1389.   {-Return a LongString centered in a LongString of blanks with specified width}
  1390.   var
  1391.     ThisLs  : LongString;
  1392.   begin
  1393.     ThisLs := NextInRing(Width);
  1394.     lsCenterCh(A, Blank, Width, ThisLs);
  1395.     lsCenterF := ThisLs;
  1396.     end; {lsCenterF}
  1397.  
  1398. procedure lsIon;
  1399.   {-Has the same effect with respect to lsReadLn, lsWriteLn as the $I+
  1400.     compiler has with respect to normal I/O operations, except that
  1401.     the reported error address is meaningless.}
  1402.   begin
  1403.     lsIoCheck := true;
  1404.     end; {lsIon}
  1405.  
  1406. procedure lsIoff;
  1407.   {-Has the same effect with respect to lsReadLn, lsWriteLn as the $I-
  1408.     compiler has with respect to normal I/O operations, except that
  1409.     the reported error address is meaningless.}
  1410.   begin
  1411.     lsIoCheck := false;
  1412.     end; {lsIoff}
  1413.  
  1414. procedure SetIoRes;
  1415.   begin
  1416.     lsIoRes := IoResult;
  1417.     if lsIoCheck and (lsIoRes <> 0) then
  1418.       RunError(lsIoRes);
  1419.     end; {SetIoRes}
  1420.  
  1421. procedure CheckIoRes;
  1422.   begin
  1423.     if (lsIoRes <> 0) then
  1424.       RunError(lsIoRes);
  1425.     end;
  1426.  
  1427. function lsIoResult : word;
  1428.   {-Returns the value of IoResult resulting from the last lsReadLn or
  1429.     lsWriteLn. NOTE: You MUST use lsIoResult for checking lsReadLn,
  1430.     lsWriteLn. If you call IoResult instead, you will always get a 0
  1431.     return.}
  1432.   begin
  1433.     lsIoResult := lsIoRes;
  1434.     lsIoRes := 0;
  1435.     end;
  1436.  
  1437. {$I-}
  1438. procedure lsReadLn(var F  : text; A : LongString);
  1439.   {-Reads a LongString from a text file. Returns the value of IoResult as
  1440.    the function value.}
  1441.   var
  1442.     S   : string;
  1443.     W1  : word;
  1444.   begin
  1445.     CheckIoRes;
  1446.     A^.Length := 0;
  1447.     while (not eoln(F)) and (A^.dLength > A^.Length) do begin
  1448.       Read(F, S);
  1449.       SetIoRes;
  1450.       if lsIoRes <> 0 then begin
  1451.         exit;
  1452.         end;
  1453.       lsConcatStr2Ls(A, S, A);
  1454.       end; {while}
  1455.     ReadLn(F);
  1456.     SetIoRes;
  1457.     end; {lsReadLn}
  1458.  
  1459. procedure lsWriteLn(var F  : text; A : LongString);
  1460.   {-Writes a LongString to a text file. Returns the value of IoResult as
  1461.    the function value.}
  1462.   var
  1463.     S       : string;
  1464.     W1,
  1465.     W2,
  1466.     Q,
  1467.     R       : word;
  1468.     ThisLs  : LongString;
  1469.   begin
  1470.     CheckIoRes;
  1471.     if not lsInit(ThisLs, A^.Length) then exit;
  1472.     lsTransfer(A, ThisLs);
  1473.     Q := A^.Length div $FF;
  1474.     R := A^.Length mod $FF;
  1475.     for W1 := 1 to Q do begin
  1476.       Write(F, lsLongString2Str(ThisLs));
  1477.       SetIoRes;
  1478.       Flush(F);
  1479.       SetIoRes;
  1480.       if lsIoRes <> 0 then begin
  1481.         lsDispose(ThisLs);
  1482.         exit;
  1483.         end;
  1484.       lsDelete(ThisLs, 1, $FF, ThisLs);
  1485.       end; {for W1}
  1486.     WriteLn(F, lsLongString2Str(ThisLs));
  1487.     SetIoRes;
  1488.     Flush(F);
  1489.     SetIoRes;
  1490.     lsDispose(ThisLs);
  1491.     end; {lsWriteLn}
  1492. {$I+}
  1493.   end.
  1494.