home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / pascal / shdk_1.zip / SHLNGSTR.PAS < prev    next >
Pascal/Delphi Source File  |  1992-03-24  |  44KB  |  1,391 lines

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