/[projects]/dao/DelphiScanner/Components/tpsystools_4.04/source/StStrZ.pas
ViewVC logotype

Contents of /dao/DelphiScanner/Components/tpsystools_4.04/source/StStrZ.pas

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2671 - (show annotations) (download)
Tue Aug 25 18:15:15 2015 UTC (8 years, 9 months ago) by torben
File size: 122842 byte(s)
Added tpsystools component
1 (* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1
3 *
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
8 *
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
13 *
14 * The Original Code is TurboPower SysTools
15 *
16 * The Initial Developer of the Original Code is
17 * TurboPower Software
18 *
19 * Portions created by the Initial Developer are Copyright (C) 1996-2002
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 * ***** END LICENSE BLOCK ***** *)
25
26 {*********************************************************}
27 {* SysTools: StStrZ.pas 4.04 *}
28 {*********************************************************}
29 {* SysTools: Null terminated string routines *}
30 {*********************************************************}
31
32 {$I StDefine.inc}
33
34 unit StStrZ;
35
36 interface
37
38 uses
39 Windows,
40 Classes, SysUtils, StConst, StBase;
41
42 {-------- Numeric conversion -----------}
43
44 function HexBZ(Dest : PAnsiChar; B : Byte) : PAnsiChar; overload;
45 function HexBZ(Dest : PWideChar; B : Byte) : PWideChar; overload;
46 {-Return the hex string for a byte.}
47
48 function HexWZ(Dest : PAnsiChar; W : Word) : PAnsiChar;
49 {-Return the hex string for a word.}
50
51 function HexLZ(Dest : PAnsiChar; L : LongInt) : PAnsiChar;
52 {-Return the hex string for a long integer.}
53
54 function HexPtrZ(Dest : PAnsiChar; P : Pointer) : PAnsiChar;
55 {-Return the hex string for a pointer.}
56
57 function BinaryBZ(Dest : PAnsiChar; B : Byte) : PAnsiChar;
58 {-Return a binary string for a byte.}
59
60 function BinaryWZ(Dest : PAnsiChar; W : Word) : PAnsiChar;
61 {-Return the binary string for a word.}
62
63 function BinaryLZ(Dest : PAnsiChar; L : LongInt) : PAnsiChar;
64 {-Return the binary string for a long integer.}
65
66 function OctalBZ(Dest : PAnsiChar; B : Byte) : PAnsiChar;
67 {-Return an octal string for a byte.}
68
69 function OctalWZ(Dest : PAnsiChar; W : Word) : PAnsiChar;
70 {-Return an octal string for a word.}
71
72 function OctalLZ(Dest : PAnsiChar; L : LongInt) : PAnsiChar;
73 {-Return an octal string for a long integer.}
74
75 function Str2Int16Z(S : PAnsiChar; var I : SmallInt) : Boolean;
76 {-Convert a string to an SmallInt.}
77
78 function Str2WordZ(S : PAnsiChar; var I : Word) : Boolean;
79 {-Convert a string to a word.}
80
81 function Str2LongZ(S : PAnsiChar; var I : LongInt) : Boolean;
82 {-Convert a string to a long integer.}
83
84 {$IFDEF VER93}
85 function Str2RealZ(S : PAnsiChar; var R : Double) : Boolean;
86 {$ELSE}
87 function Str2RealZ(S : PChar; var R : Real) : Boolean;
88 {$ENDIF}
89 {-Convert a string to a real.}
90
91 function Str2ExtZ(S : PAnsiChar; var R : Extended) : Boolean;
92 {-Convert a string to an extended.}
93
94 function Long2StrZ(Dest : PAnsiChar; L : LongInt) : PAnsiChar;
95 {-Convert an integer type to a string.}
96
97 function Real2StrZ(Dest : PAnsiChar; R : Double; Width : Byte;
98 Places : ShortInt) : PAnsiChar;
99 {-Convert a real to a string.}
100
101 function Ext2StrZ(Dest : PAnsiChar; R : Extended; Width : Byte;
102 Places : ShortInt) : PAnsiChar;
103 {-Convert an extended to a string.}
104
105 function ValPrepZ(S : PAnsiChar) : PAnsiChar; overload;
106 {$IFDEF UNICODE}
107 function ValPrepZ(S : PWideChar) : PWideChar; overload;
108 {$ENDIF}
109 {-Prepares a string for calling Val.}
110
111
112 {-------- General purpose string manipulation --------}
113
114 function CharStrZ(Dest : PAnsiChar; C : AnsiChar; Len : Cardinal) : PAnsiChar;
115 {-Return a string filled with the specified character.}
116
117 function PadChZ(Dest, S : PAnsiChar; C : AnsiChar; Len : Cardinal) : PAnsiChar;
118 {-Pad a string on the right with a specified character.}
119
120 function PadZ(Dest, S : PAnsiChar; Len : Cardinal) : PAnsiChar;
121 {-Pad a string on the right with spaces.}
122
123 function LeftPadChZ(Dest, S : PAnsiChar; C : AnsiChar; Len : Cardinal) : PAnsiChar;
124 {-Pad a string on the left with a specified character.}
125
126 function LeftPadZ(Dest, S : PAnsiChar; Len : Cardinal) : PAnsiChar;
127 {-Pad a string on the left with spaces.}
128
129 function PadChPrimZ(S : PAnsiChar; C : AnsiChar; Len : Cardinal) : PAnsiChar;
130 {-Pad a string on the right with a specified character.
131 This primitive version modifies the source string directly.}
132
133 function PadPrimZ(S : PAnsiChar; Len : Cardinal) : PAnsiChar;
134 {-Pad a string on the right with spaces. This primitive version modifies the
135 source string directly.}
136
137 function LeftPadChPrimZ(S : PAnsiChar; C : AnsiChar; Len : Cardinal) : PAnsiChar;
138 {-Pad a string on the left with a specified character. This primitive
139 version modifies the source string directly.}
140
141 function LeftPadPrimZ(S : PAnsiChar; Len : Cardinal) : PAnsiChar;
142 {-Pad a string on the left with spaces. This primitive version modifies the
143 source string directly.}
144
145 function TrimLeadZ(Dest, S : PAnsiChar) : PAnsiChar;
146 {-Return a string with leading white space removed.}
147
148 function TrimTrailZ(Dest, S : PAnsiChar) : PAnsiChar;
149 {-Return a string with trailing white space removed.}
150
151 function TrimZ(Dest, S : PAnsiChar) : PAnsiChar;
152 {-Return a string with leading and trailing white space removed.}
153
154 function TrimSpacesZ(Dest, S : PAnsiChar) : PAnsiChar;
155 {-Return a string with leading and trailing spaces removed.}
156
157 function TrimLeadPrimZ(S : PAnsiChar) : PAnsiChar;
158 {-Return a string with leading white space removed. This primitive version
159 modifies the source string directly.}
160
161 function TrimTrailPrimZ(S : PAnsiChar) : PAnsiChar; overload;
162 function TrimTrailPrimZ(S : PWideChar) : PWideChar; overload;
163 {-Return a string with trailing white space removed. This primitive version
164 modifies the source string directly.}
165
166 function TrimPrimZ(S : PAnsiChar) : PAnsiChar;
167 {-Return a string with leading and trailing white space removed. This
168 primitive version modifies the source string directly.}
169
170 function TrimSpacesPrimZ(S : PAnsiChar) : PAnsiChar; overload;
171 {$IFDEF UNICODE}
172 function TrimSpacesPrimZ(S : PWideChar) : PWideChar; overload;
173 {$ENDIF}
174 {-Return a string with leading and trailing spaces removed. This primitive
175 version modifies the source string directly.}
176
177 function CenterChPrimZ(S : PAnsiChar; C : AnsiChar; Len : Cardinal) : PAnsiChar;
178 {-Pad a string on the left and right with a specified character. This
179 primitive version modifies the source string directly.}
180
181 function CenterPrimZ(S : PAnsiChar; Len : Cardinal) : PAnsiChar;
182 {-Pad a string on the left and right with spaces. This primitive version
183 modifies the source string directly.}
184
185 function CenterChZ(Dest, S : PAnsiChar; C : AnsiChar; Len : Cardinal) : PAnsiChar;
186 {-Pad a string on the left and right with a specified character.}
187
188 function CenterZ(Dest, S : PAnsiChar; Len : Cardinal) : PAnsiChar;
189 {-Pad a string on the left and right with spaces.}
190
191 function EntabZ(Dest, Src : PAnsiChar; TabSize : Byte) : PAnsiChar;
192 {-Convert blanks in a string to tabs.}
193
194 function DetabZ(Dest, Src : PAnsiChar; TabSize : Byte) : PAnsiChar;
195 {-Expand tabs in a string to blanks.}
196
197 function ScramblePrimZ(S, Key : PAnsiChar) : PAnsiChar;
198 {-Encrypt / Decrypt string with enhanced XOR encryption. This
199 primitive version modifies the source string directly.}
200
201 function ScrambleZ(Dest, S, Key : PAnsiChar) : PAnsiChar;
202 {-Encrypt / Decrypt string with enhanced XOR encryption.}
203
204 function SubstituteZ(Dest, Src, FromStr, ToStr : PAnsiChar) : PAnsiChar;
205 {-Map the characters found in FromStr to the corresponding ones in ToStr.}
206
207 function FilterZ(Dest, Src, Filters : PAnsiChar) : PAnsiChar;
208 {-Remove characters from a string. The characters to remove are specified in
209 ChSet.}
210
211 {--------------- Word / Char manipulation -------------------------}
212
213 function CharExistsZ(S : PAnsiChar; C : AnsiChar) : Boolean; overload;
214 function CharExistsZ(S : PWideChar; C : Char) : Boolean; overload;
215 {-Determine whether the given character exists in a string. }
216
217 function CharCountZ(S : PAnsiChar; C : AnsiChar) : Cardinal;
218 {-Count the number of a given character in a string. }
219
220 function WordCountZ(S : PAnsiChar; WordDelims : PAnsiChar) : Cardinal;
221 {-Given an array of word delimiters, return the number of words in a string.}
222
223 function WordPositionZ(N : Cardinal; S : PAnsiChar; WordDelims : PAnsiChar;
224 var Pos : Cardinal) : Boolean;
225 {-Given an array of word delimiters, set Pos to the start position of the
226 N'th word in a string. Result indicates success/failure.}
227
228 function ExtractWordZ(Dest : PAnsiChar; N : Cardinal; Src : PAnsiChar;
229 WordDelims : PAnsiChar) : PAnsiChar;
230 {-Given an array of word delimiters, return the N'th word in a string.}
231
232 function AsciiCountZ(S : PAnsiChar; WordDelims : PAnsiChar; Quote : AnsiChar) : Cardinal;
233 {-Return the number of words in a string.}
234
235 function AsciiPositionZ(N : Cardinal; S : PAnsiChar; WordDelims : PAnsiChar;
236 Quote : AnsiChar; var Pos : Cardinal) : Boolean;
237 {-Return the position of the N'th word in a string.}
238
239 function ExtractAsciiZ(Dest : PAnsiChar; N : Cardinal; Src : PAnsiChar;
240 WordDelims : PAnsiChar; Quote : AnsiChar) : PAnsiChar;
241 {-Given an array of word delimiters, return the N'th word in a string. Any
242 text within Quote characters is counted as one word.}
243
244 procedure WordWrapZ(Dest : PAnsiChar; InSt, Overlap : PAnsiChar;
245 Margin : Cardinal;
246 PadToMargin : Boolean);
247 {-Wrap a text string at a specified margin.}
248
249 {--------------- String comparison and searching -----------------}
250 function CompStringZ(S1, S2 : PAnsiChar) : Integer;
251 {-Compare two strings.}
252
253 function CompUCStringZ(S1, S2 : PAnsiChar) : Integer;
254 {-Compare two strings. This compare is not case sensitive.}
255
256 function SoundexZ(Dest : PAnsiChar; S : PAnsiChar) : PAnsiChar;
257 {-Return 4 character soundex of an input string}
258
259 function MakeLetterSetZ(S : PAnsiChar) : Longint;
260 {-Return a bit-mapped long storing the individual letters contained in S.}
261
262 procedure BMMakeTableZ(MatchString : PAnsiChar; var BT : BTable);
263 {-Build a Boyer-Moore link table}
264
265 function BMSearchZ(var Buffer; BufLength : Cardinal; var BT : BTable;
266 MatchString : PAnsiChar ; var Pos : Cardinal) : Boolean;
267 {-Use the Boyer-Moore search method to search a buffer for a string.}
268
269 function BMSearchUCZ(var Buffer; BufLength : Cardinal; var BT : BTable;
270 MatchString : PAnsiChar ; var Pos : Cardinal) : Boolean;
271 {-Use the Boyer-Moore search method to search a buffer for a string. This
272 search is not case sensitive.}
273
274 {--------------- DOS pathname parsing -----------------}
275
276 function DefaultExtensionZ(Dest : PAnsiChar; Name, Ext : PAnsiChar) : PAnsiChar;
277 {-Return a file name with a default extension attached.}
278
279 function ForceExtensionZ(Dest : PAnsiChar; Name, Ext : PAnsiChar) : PAnsiChar;
280 {-Force the specified extension onto the file name.}
281
282 function JustFilenameZ(Dest : PAnsiChar; PathName : PAnsiChar) : PAnsiChar; overload;
283 {$IFDEF UNICODE}
284 function JustFilenameZ(Dest : PWideChar; PathName : PWideChar) : PWideChar; overload;
285 {$ENDIF}
286 {-Return just the filename and extension of a pathname.}
287
288 function JustNameZ(Dest : PAnsiChar; PathName : PAnsiChar) : PAnsiChar;
289 {-Return just the filename (no extension, path, or drive) of a pathname.}
290
291 function JustExtensionZ(Dest : PAnsiChar; Name : PAnsiChar) : PAnsiChar;
292 {-Return just the extension of a pathname.}
293
294 function JustPathnameZ(Dest : PAnsiChar; PathName : PAnsiChar) : PAnsiChar;
295 {-Return just the drive and directory portion of a pathname.}
296
297 function AddBackSlashZ(Dest : PAnsiChar; DirName : PAnsiChar) : PAnsiChar;
298 {-Add a default backslash to a directory name.}
299
300 function CleanPathNameZ(Dest : PAnsiChar; PathName : PAnsiChar) : PAnsiChar;
301 {-Return a pathname cleaned up as DOS does it.}
302
303 function HasExtensionZ(Name : PAnsiChar; var DotPos : Cardinal) : Boolean; overload;
304 {$IFDEF UNICODE}
305 function HasExtensionZ(Name : PWideChar; var DotPos : Cardinal) : Boolean; overload;
306 {$ENDIF}
307 {-Determine if a pathname contains an extension and, if so, return the
308 position of the dot in front of the extension.}
309
310 {------------------ Formatting routines --------------------}
311
312 function CommaizeZ(Dest : PAnsiChar; L : LongInt) : PAnsiChar;
313 {-Convert a long integer to a string with commas.}
314
315 function CommaizeChZ(Dest : PAnsiChar; L : Longint; Ch : AnsiChar) : PAnsiChar;
316 {-Convert a long integer to a string with Ch in comma positions.}
317
318 function FloatFormZ(Dest, Mask : PAnsiChar ; R : TstFloat ; LtCurr,
319 RtCurr : PAnsiChar ; Sep, DecPt : AnsiChar) : PAnsiChar;
320 {-Return a formatted string with digits from R merged into mask.}
321
322 function LongIntFormZ(Dest, Mask : PAnsiChar ; L : LongInt ; LtCurr,
323 RtCurr : PAnsiChar ; Sep : AnsiChar) : PAnsiChar;
324 {-Return a formatted string with digits from L merged into mask.}
325
326 function StrChPosZ(P : PAnsiChar; C : AnsiChar; var Pos : Cardinal) : Boolean; overload;
327 {$IFDEF UNICODE}
328 function StrChPosZ(P : PWideChar; C : Char; var Pos : Cardinal) : Boolean; overload;
329 {$ENDIF}
330 {-Return the position of a specified character within a string.}
331
332 function StrStPosZ(P, S : PAnsiChar; var Pos : Cardinal) : Boolean;
333 {-Return the position of a specified substring within a string.}
334
335 function StrStCopyZ(Dest, S : PAnsiChar; Pos, Count : Cardinal) : PAnsiChar; overload;
336 {$IFDEF UNICODE}
337 function StrStCopyZ(Dest, S : PWideChar; Pos, Count : Cardinal) : PWideChar; overload;
338 {$ENDIF}
339 {-Copy characters at a specified position in a string.}
340
341 function StrChInsertZ(Dest, S : PAnsiChar; C : AnsiChar; Pos : Cardinal) : PAnsiChar;
342 {-Insert a character into a string at a specified position.}
343
344 function StrStInsertZ(Dest, S1, S2 : PAnsiChar; Pos : Cardinal) : PAnsiChar;
345 {-Insert a string into another string at a specified position.}
346
347 function StrChDeleteZ(Dest, S : PAnsiChar; Pos : Cardinal) : PAnsiChar;
348 {-Delete the character at a specified position in a string.}
349
350 function StrStDeleteZ(Dest, S : PAnsiChar; Pos, Count : Cardinal) : PAnsiChar;
351 {-Delete characters at a specified position in a string.}
352
353 function StrChInsertPrimZ(Dest : PAnsiChar; C : AnsiChar; Pos : Cardinal) : PAnsiChar;
354 {-Insert a character into a string at a specified position. This primitive
355 version modifies the source string directly.}
356
357 function StrStInsertPrimZ(Dest, S : PAnsiChar; Pos : Cardinal) : PAnsiChar;
358 {-Insert a string into another string at a specified position. This
359 primitive version modifies the source string directly.}
360
361 function StrChDeletePrimZ(P : PAnsiChar; Pos : Cardinal) : PAnsiChar;
362 {-Delete the character at a specified position in a string. This primitive
363 version modifies the source string directly.}
364
365 function StrStDeletePrimZ(P : PAnsiChar; Pos, Count : Cardinal) : PAnsiChar; overload;
366 function StrStDeletePrimZ(P : PWideChar; Pos, Count : Cardinal) : PWideChar; overload;
367 {-Delete characters at a specified position in a string. This primitive
368 version modifies the source string directly.}
369
370
371 {-------------------------- New Functions -----------------------------------}
372
373 function ContainsOnlyZ(const S, Chars : PAnsiChar;
374 var BadPos : Cardinal) : Boolean;
375
376 function ContainsOtherThanZ(const S, Chars : PAnsiChar;
377 var BadPos : Cardinal) : Boolean;
378
379 function CopyFromNthWordZ(Dest, S, WordDelims, AWord : PAnsiChar;
380 N : Cardinal) : Boolean;
381
382 function CopyFromToWordZ(Dest, S, WordDelims, Word1, Word2 : PAnsiChar;
383 N1, N2 : Cardinal) : Boolean;
384
385 function CopyLeftZ(Dest, S : PAnsiChar; Len : Cardinal) : PAnsiChar;
386 {-Return the left Len characters of a string}
387
388 function CopyMidZ(Dest, S : PAnsiChar; First, Len : Cardinal) : PAnsiChar;
389 {-Return the mid part of a string}
390
391 function CopyRightZ(Dest, S : PAnsiChar; First : Cardinal) : PAnsiChar;
392 {-Return the right Len characters of a string}
393
394 function CopyRightAbsZ(Dest, S : PAnsiChar; NumChars : Cardinal) : PAnsiChar;
395 {-Return the right Len characters of a string}
396
397
398 function CopyWithinZ(Dest, S, Delimiter : PAnsiChar;
399 Strip : Boolean) : PAnsiChar;
400
401 function DeleteFromNthWordZ(Dest, S, WordDelims, AWord : PAnsiChar;
402 N : Cardinal) : Boolean;
403
404 function DeleteFromToWordZ(Dest, S, WordDelims, Word1, Word2 : PAnsiChar;
405 N1, N2 : Cardinal) : Boolean;
406
407 function DeleteWithinZ(Dest, S, Delimiter : PAnsiChar) : PAnsiChar;
408
409 function ExtractTokensZ(S, Delims : PAnsiChar;
410 QuoteChar : AnsiChar;
411 AllowNulls : Boolean;
412 Tokens : TStrings) : Cardinal;
413
414 function IsChAlphaZ(C : Char) : Boolean;
415 {-Returns true if Ch is an alpha}
416
417 function IsChNumericZ(C : AnsiChar; Numbers : PAnsiChar) : Boolean;
418 {-Returns true if Ch in numeric set}
419
420 function IsChAlphaNumericZ(C : Char; Numbers : PChar) : Boolean;
421 {-Returns true if Ch is an alpha or numeric}
422
423 function IsStrAlphaZ(S : PChar) : Boolean;
424 {-Returns true if all characters in string are an alpha}
425
426 function IsStrNumericZ(S, Numbers : PAnsiChar) : Boolean;
427 {-Returns true if all characters in string are in numeric set}
428
429 function IsStrAlphaNumericZ(S, Numbers : PChar) : Boolean;
430 {-Returns true if all characters in string are alpha or numeric}
431
432 function KeepCharsZ(Dest, S, Chars : PAnsiChar) : PAnsiChar;
433
434 function LastStringZ(S, AString : PAnsiChar;
435 var Position : Cardinal) : Boolean;
436
437 function LastWordZ(S, WordDelims, AWord : PAnsiChar;
438 var Position : Cardinal) : Boolean;
439
440
441 function LastWordAbsZ(S, WordDelims : PAnsiChar;
442 var Position : Cardinal) : Boolean;
443
444 function LeftTrimCharsZ(Dest, S, Chars : PAnsiChar) : PAnsiChar;
445
446 function RepeatStringZ(Dest, RepeatString : PAnsiChar;
447 var Repetitions : Cardinal;
448 MaxLen : Cardinal) : PAnsiChar;
449
450 function ReplaceWordZ(Dest, S, WordDelims, OldWord, NewWord : PAnsiChar;
451 N : Cardinal;
452 var Replacements : Cardinal) : PAnsiChar;
453
454 function ReplaceWordAllZ(Dest, S, WordDelims, OldWord, NewWord : PAnsiChar;
455 var Replacements : Cardinal) : PAnsiChar;
456
457 function ReplaceStringZ(Dest, S, OldString, NewString : PAnsiChar;
458 N : Cardinal;
459 var Replacements : Cardinal) : PAnsiChar;
460
461 function ReplaceStringAllZ(Dest, S, OldString, NewString : PAnsiChar;
462 var Replacements : Cardinal) : PAnsiChar;
463
464 function RightTrimCharsZ(Dest, S, Chars : PAnsiChar) : PAnsiChar;
465
466 function StrWithinZ(S, SearchStr : PAnsiChar;
467 Start : Cardinal;
468 var Position : Cardinal) : Boolean;
469
470 function TrimCharsZ(Dest, S, Chars : PAnsiChar) : PAnsiChar;
471
472
473 function WordPosZ(S, WordDelims, AWord : PAnsiChar;
474 N : Cardinal; var Position : Cardinal) : Boolean;
475 {-returns the Occurrence instance of a word within a string}
476
477
478
479 implementation
480
481
482 function HexBZ(Dest : PAnsiChar; B : Byte) : PAnsiChar;
483 {-Return hex string for byte}
484 begin
485 Result := Dest;
486 Dest^ := StHexDigits[B shr 4];
487 Inc(Dest);
488 Dest^ := StHexDigits[B and $F];
489 Inc(Dest);
490 Dest^ := #0;
491 end;
492
493 function HexBZ(Dest : PWideChar; B : Byte) : PWideChar;
494 {-Return hex string for byte}
495 begin
496 Result := Dest;
497 Dest^ := WideChar(StHexDigits[B shr 4]);
498 Inc(Dest);
499 Dest^ := WideChar(StHexDigits[B and $F]);
500 Inc(Dest);
501 Dest^ := #0;
502 end;
503
504 function HexWZ(Dest : PAnsiChar; W : Word) : PAnsiChar;
505 {-Return hex string for word}
506 begin
507 Result := Dest;
508 Dest^ := StHexDigits[hi(W) shr 4];
509 Inc(Dest);
510 Dest^ := StHexDigits[hi(W) and $F];
511 Inc(Dest);
512 Dest^ := StHexDigits[lo(W) shr 4];
513 Inc(Dest);
514 Dest^ := StHexDigits[lo(W) and $F];
515 Inc(Dest);
516 Dest^ := #0;
517 end;
518
519 function HexLZ(Dest : PAnsiChar; L : LongInt) : PAnsiChar;
520 {-Return hex string for LongInt}
521 //type {!!.02}
522 // LH = record L, H : word; end; {!!.02}
523 var
524 T2 : Array[0..4] of AnsiChar;
525 begin
526 // Result := StrCat(HexWZ(Dest, LH(L).H), HexWZ(T2, LH(L).L)); {!!.02}
527 Result := StrCat(HexWZ(Dest, HiWord(DWORD(L))), {!!.02}
528 HexWZ(T2, LoWord(DWORD(L)))); {!!.02}
529 end;
530
531 function HexPtrZ(Dest : PAnsiChar; P : Pointer) : PAnsiChar;
532 {-Return hex string for pointer}
533 var
534 T2 : array[0..8] of AnsiChar;
535 begin
536 StrCopy(Dest, ':');
537 Result := StrCat(Dest, HexLZ(T2, LongInt(P)));
538 end;
539
540 function BinaryBZ(Dest : PAnsiChar; B : Byte) : PAnsiChar;
541 {-Return binary string for byte}
542 var
543 I : Word;
544 begin
545 Result := Dest;
546 for I := 7 downto 0 do begin
547 Dest^ := StHexDigits[Ord(B and (1 shl I) <> 0)]; {0 or 1}
548 Inc(Dest);
549 end;
550 Dest^ := #0;
551 end;
552
553 function BinaryWZ(Dest : PAnsiChar; W : Word) : PAnsiChar;
554 {-Return binary string for word}
555 var
556 I : Word;
557 begin
558 Result := Dest;
559 for I := 15 downto 0 do begin
560 Dest^ := StHexDigits[Ord(W and (1 shl I) <> 0)]; {0 or 1}
561 Inc(Dest);
562 end;
563 Dest^ := #0;
564 end;
565
566 function BinaryLZ(Dest : PAnsiChar; L : LongInt) : PAnsiChar;
567 {-Return binary string for LongInt}
568 var
569 I : Longint;
570 begin
571 Result := Dest;
572 for I := 31 downto 0 do begin
573 Dest^ := StHexDigits[Ord(L and LongInt(1 shl I) <> 0)]; {0 or 1}
574 Inc(Dest);
575 end;
576 Dest^ := #0;
577 end;
578
579 function OctalBZ(Dest : PAnsiChar; B : Byte) : PAnsiChar;
580 {-Return octal string for byte}
581 var
582 I : Word;
583 begin
584 Result := Dest;
585 for I := 0 to 2 do begin
586 Dest[2-I] := StHexDigits[B and 7];
587 B := B shr 3;
588 end;
589 Dest[3] := #0;
590 end;
591
592 function OctalWZ(Dest : PAnsiChar; W : Word) : PAnsiChar;
593 {-Return octal string for word}
594 var
595 I : Word;
596 begin
597 Result := Dest;
598 for I := 0 to 5 do begin
599 Dest[5-I] := StHexDigits[W and 7];
600 W := W shr 3;
601 end;
602 Dest[6] := #0;
603 end;
604
605 function OctalLZ(Dest : PAnsiChar; L : LongInt) : PAnsiChar;
606 {-Return octal string for word}
607 var
608 I : Word;
609 begin
610 Result := Dest;
611 for I := 0 to 11 do begin
612 Dest[11-I] := StHexDigits[L and 7];
613 L := L shr 3;
614 end;
615 Dest[12] := #0;
616 end;
617
618 function CharStrZ(Dest : PAnsiChar; C : AnsiChar; Len : Cardinal) : PAnsiChar;
619 register;
620 asm
621 push edi { Save EDI-about to change it }
622 push eax { Save Dest pointer for return }
623 mov edi, eax { Point EDI to Dest }
624
625 mov dh, dl { Dup character 4 times }
626 mov eax, edx
627 shl eax, $10
628 mov ax, dx
629
630 mov edx, ecx { Save Len }
631
632 shr ecx, 2 { Store dword char chunks first }
633 rep stosd
634 mov ecx, edx { Store remaining characters }
635 and ecx, 3
636 rep stosb
637
638 xor al,al { Add null terminator }
639 mov [edi], al
640
641 pop eax { Return Dest pointer }
642 pop edi { Restore orig value of EDI }
643 end;
644
645 function PadChPrimZ(S : PAnsiChar; C : AnsiChar; Len : Cardinal) : PAnsiChar;
646 register;
647 asm
648 push eax
649 push ebx
650 push edi
651
652 mov edi, eax
653 mov ebx, ecx
654 xor eax, eax
655 or ecx, -1
656 repne scasb
657 not ecx
658 dec ecx
659 dec edi
660 mov eax, ebx
661 sub eax, ecx
662 jbe @@ExitPoint
663
664 mov ecx, eax
665 mov eax, edx
666 rep stosb
667
668 @@ExitPoint:
669 xor eax, eax
670 mov [edi], al
671
672 pop edi
673 pop ebx
674 pop eax
675 end;
676
677 function PadPrimZ(S : PAnsiChar; Len : Cardinal) : PAnsiChar;
678 {-Return a string right-padded to length len with blanks}
679 begin
680 Result := PadChPrimZ(S, ' ', Len);
681 end;
682
683 function LeftPadChPrimZ(S : PAnsiChar; C : AnsiChar; Len : Cardinal) : PAnsiChar;
684 {-Return a string left-padded to length len with C}
685 register;
686 asm
687 push ebx
688 push edi
689 push esi
690
691 mov edi, eax
692 mov esi, edi
693 mov ebx, ecx
694
695 xor eax, eax
696 or ecx, -1
697 repne scasb
698 not ecx
699 dec ecx
700 mov eax, ebx
701 mov edi, esi
702 add edi, ebx
703 mov ebx, esi
704 sub eax, ecx
705 jbe @@ExitPoint
706
707 add esi, ecx
708 inc ecx
709 std
710 rep movsb
711 mov ecx, eax
712 mov eax, edx
713 rep stosb
714
715 @@ExitPoint:
716 cld
717 mov eax, ebx
718 pop esi
719 pop edi
720 pop ebx
721 end;
722
723 function LeftPadPrimZ(S : PAnsiChar; Len : Cardinal) : PAnsiChar;
724 {-Return a string left-padded to length len with blanks}
725 begin
726 Result := LeftPadChPrimZ(S, ' ', Len);
727 end;
728
729 function PadChZ(Dest, S : PAnsiChar; C : AnsiChar; Len : Cardinal) : PAnsiChar;
730 {-Return a PChar right-padded to length Len with C}
731 begin
732 StrCopy(Dest, S);
733 Result := PadChPrimZ(Dest, C, Len);
734 end;
735
736 function PadZ(Dest, S : PAnsiChar; Len : Cardinal) : PAnsiChar;
737 {-Return a string right-padded to length len with blanks}
738 begin
739 StrCopy(Dest, S);
740 Result := PadPrimZ(Dest, Len);
741 end;
742
743 function LeftPadChZ(Dest, S : PAnsiChar; C : AnsiChar; Len : Cardinal) : PAnsiChar;
744 {-Return a string left-padded to length len with C}
745 begin
746 StrCopy(Dest, S);
747 Result := LeftPadChPrimZ(Dest, C, Len);
748 end;
749
750 function LeftPadZ(Dest, S : PAnsiChar; Len : Cardinal) : PAnsiChar;
751 {-Return a string left-padded to length len with blanks}
752 begin
753 StrCopy(Dest, S);
754 Result := LeftPadPrimZ(Dest, Len);
755 end;
756
757 function TrimLeadPrimZ(S : PAnsiChar) : PAnsiChar;
758 {-Return a string with leading white space removed}
759 register;
760 asm
761 push edi
762 push esi
763
764 mov edi, eax
765 mov esi, eax
766 mov edx, eax
767 xor eax, eax
768 or ecx, -1
769 repne scasb
770 not ecx
771 dec ecx
772 mov edi, edx
773 jz @@CopyRest
774
775 @@Lo:
776 cmp byte ptr [esi], ' '
777 ja @@CopyRest
778 inc esi
779 dec ecx
780 jnz @@Lo
781
782 @@CopyRest:
783 inc ecx
784 rep movsb
785 mov eax, edx
786
787 pop esi
788 pop edi
789 end;
790
791 function TrimLeadZ(Dest, S : PAnsiChar) : PAnsiChar;
792 {-Return a string with leading white space removed}
793 begin
794 StrCopy(Dest, S);
795 Result := TrimLeadPrimZ(Dest);
796 end;
797
798 function TrimTrailPrimZ(S : PAnsiChar) : PAnsiChar;
799 {-Return a string with trailing white space removed}
800 register;
801 asm
802 push edi
803
804 mov edi, eax
805 mov edx, eax
806 xor eax, eax
807 or ecx, -1
808 repne scasb
809 not ecx
810 dec ecx
811 jz @@ExitPoint
812 dec edi
813 dec edi
814
815 @@Lo:
816 cmp BYTE PTR [edi], ' '
817 ja @@AllDone
818 dec edi
819 dec ecx
820 jnz @@Lo
821
822 @@AllDone:
823 inc edi
824 mov byte ptr [edi], 0h
825
826 @@ExitPoint:
827 mov eax, edx
828 pop edi
829 end;
830
831 function TrimTrailPrimZ(S : PWideChar) : PWideChar; //SZ
832 {-Return a string with trailing white space removed}
833 register;
834 asm
835 push edi
836
837 mov edi, eax
838 mov edx, eax
839 xor eax, eax
840 or ecx, -1
841 repne scasw
842 not ecx
843 dec ecx
844 dec ecx
845 jz @@ExitPoint
846 dec edi
847 dec edi
848 dec edi
849 dec edi
850
851 @@Lo:
852 cmp WORD PTR [edi], ' '
853 ja @@AllDone
854 dec edi
855 dec edi
856 dec ecx
857 dec ecx
858 jnz @@Lo
859
860 @@AllDone:
861 inc edi
862 inc edi
863 mov word ptr [edi], 0h
864
865 @@ExitPoint:
866 mov eax, edx
867 pop edi
868 end;
869
870
871 function TrimTrailZ(Dest, S : PAnsiChar) : PAnsiChar;
872 {-Return a string with trailing white space removed}
873 begin
874 StrCopy(Dest, S);
875 Result := TrimTrailPrimZ(Dest);
876 end;
877
878 function TrimPrimZ(S : PAnsiChar) : PAnsiChar;
879 {-Return a string with leading and trailing white space removed}
880 begin
881 Result := TrimTrailPrimZ(TrimLeadPrimZ(S));
882 end;
883
884 function TrimZ(Dest, S : PAnsiChar) : PAnsiChar;
885 {-Return a string with leading and trailing white space removed}
886 begin
887 StrCopy(Dest, S);
888 Result := TrimPrimZ(Dest);
889 end;
890
891 function TrimSpacesPrimZ(S : PAnsiChar) : PAnsiChar;
892 {-Return a string with leading and trailing spaces removed}
893 var
894 I, SLen : Cardinal;
895 begin
896 Result := S;
897 SLen := StrLen(S);
898 while (SLen > 0) and (S[SLen-1] = ' ') do
899 Dec(SLen);
900 S[SLen] := #0;
901 I := 0;
902 while (I < SLen) and (S[I] = ' ') do
903 Inc(I);
904 if I > 0 then
905 StrStDeletePrimZ(S, 0, I);
906 end;
907
908 {$IFDEF UNICODE}
909 function TrimSpacesPrimZ(S : PWideChar) : PWideChar;
910 {-Return a string with leading and trailing spaces removed}
911 var
912 I, SLen : Cardinal;
913 begin
914 Result := S;
915 SLen := StrLen(S);
916 while (SLen > 0) and (S[SLen-1] = ' ') do
917 Dec(SLen);
918 S[SLen] := #0;
919 I := 0;
920 while (I < SLen) and (S[I] = ' ') do
921 Inc(I);
922 if I > 0 then
923 StrStDeletePrimZ(S, 0, I);
924 end;
925 {$ENDIF}
926
927 function TrimSpacesZ(Dest, S : PAnsiChar) : PAnsiChar;
928 {-Return a string with leading and trailing spaces removed}
929 begin
930 StrCopy(Dest, S);
931 Result := TrimSpacesPrimZ(Dest);
932 end;
933
934 function CenterChPrimZ(S : PAnsiChar; C : AnsiChar; Len : Cardinal) : PAnsiChar;
935 {-Return a string centered in a string of C with specified width}
936 register;
937 asm
938 push eax { save registers }
939 push ebx
940 push edi
941 push esi
942
943 mov edi, eax { set EDI and ESI to S }
944 mov esi, eax
945 mov ebx, ecx { store Len in EBX }
946 xor eax, eax
947 or ecx, -1
948 repne scasb { Find null terminator in S }
949 not ecx
950 dec ecx { ECX has length of S }
951 jz @@SpecialCase { if zero, jump to special case }
952
953 cmp ecx, ebx
954 jae @@ExitPoint { if Len >= Length(S), we're done }
955
956 mov eax, ebx { copy Len to EAX }
957 sub ebx, ecx { EBX = number of pad characters }
958 inc ebx
959 shr ebx, 1 { EBX = number of pad characters on one side }
960 sub eax, ebx
961 sub eax, ecx
962 push eax
963 add esi, ecx { set ESI to end of text in S }
964 mov edi, esi
965 add edi, ebx { set EDI to end of destination }
966 dec esi
967 push edi
968 dec edi
969 std { Backward string ops }
970 rep movsb { move string }
971 mov eax, edx { copy pad character to EAX }
972 mov ecx, ebx
973 rep stosb { pad to left of text }
974 pop edi
975 pop ecx
976 cld { forward string ops }
977 rep stosb { pad to right of text }
978 jmp @@AddNull { add null terminator }
979
980 @@SpecialCase:
981 mov ecx, ebx { fill string with C }
982 mov eax, edx
983 mov edi, esi
984 rep stosb
985
986 @@AddNull:
987 mov byte ptr [edi], 0h { add null at end of string }
988
989 @@ExitPoint:
990 pop esi { restore registers }
991 pop edi
992 pop ebx
993 pop eax
994 end;
995
996 function CenterChZ(Dest, S : PAnsiChar; C : AnsiChar; Len : Cardinal) : PAnsiChar;
997 {-Return a string centered in a string of C with specified width}
998 begin
999 StrCopy(Dest, S);
1000 Result := CenterChPrimZ(Dest, C, Len);
1001 end;
1002
1003 function CenterPrimZ(S : PAnsiChar; Len : Cardinal) : PAnsiChar;
1004 {-Return a string centered in a blank string of specified width}
1005 begin
1006 Result := CenterChPrimZ(S, ' ', Len);
1007 end;
1008
1009 function CenterZ(Dest, S : PAnsiChar; Len : Cardinal) : PAnsiChar;
1010 {-Return a string centered in a blank string of specified width}
1011 begin
1012 StrCopy(Dest, S);
1013 Result := CenterPrimZ(Dest, Len);
1014 end;
1015
1016 function ScramblePrimZ(S, Key : PAnsiChar) : PAnsiChar;
1017 {-Encrypt / Decrypt string with enhanced XOR encryption. This
1018 primitive version modifies the source string directly.}
1019 var
1020 SPtr, KPtr, EndPtr : PAnsiChar;
1021 begin
1022 Result := S;
1023 if Key^ = #0 then Exit;
1024 if S^ = #0 then Exit;
1025 SPtr := S;
1026 EndPtr := StrEnd(Key);
1027 Dec(EndPtr);
1028 KPtr := EndPtr;
1029 while SPtr^ <> #0 do begin
1030 if KPtr < Key then
1031 KPtr := EndPtr;
1032 if (SPtr^ <> KPtr^) then
1033 SPtr^ := AnsiChar(Byte(SPtr^) xor Byte(KPtr^));
1034 Inc(SPtr);
1035 Dec(KPtr);
1036 end;
1037 end;
1038
1039 function ScrambleZ(Dest, S, Key : PAnsiChar) : PAnsiChar;
1040 {-Encrypt / Decrypt string with enhanced XOR encryption.}
1041 begin
1042 StrCopy(Dest, S);
1043 Result := ScramblePrimZ(Dest, Key);
1044 end;
1045
1046 function SubstituteZ(Dest, Src, FromStr, ToStr : PAnsiChar) : PAnsiChar;
1047 {-Return string S after mapping characters found in FromStr to the
1048 corresponding ones in ToStr}
1049 var
1050 I : Cardinal;
1051 P : Cardinal;
1052 L : Cardinal;
1053 begin
1054 StrCopy(Dest, Src);
1055 if StrLen(FromStr) = StrLen(ToStr) then begin
1056 L := StrLen(Dest);
1057 if L > 0 then
1058 for I := 0 to L-1 do begin
1059 if StrChPosZ(FromStr, Dest[I], P) then
1060 Dest[I] := ToStr[P];
1061 end;
1062 end;
1063 Result := Dest;
1064 end;
1065
1066 function FilterZ(Dest, Src, Filters : PAnsiChar) : PAnsiChar;
1067 {-Return string S after removing all characters in Filters from it}
1068 var
1069 I : Cardinal;
1070 Len : Cardinal;
1071 L : Cardinal;
1072 begin
1073 Result := Dest;
1074 StrCopy(Dest, Src);
1075 Len := 0;
1076 L := StrLen(Dest);
1077 if L > 0 then
1078 for I := 0 to L-1 do
1079 if not CharExistsZ(Filters, Dest[I]) then begin
1080 Result[Len] := Dest[I];
1081 inc(Len);
1082 end;
1083 Result[Len] := #0;
1084 end;
1085
1086 function EntabZ(Dest, Src : PAnsiChar; TabSize : Byte) : PAnsiChar;
1087 {-Convert blanks in a string to tabs on spacing TabSize}
1088 register;
1089 asm
1090 push eax { Save registers }
1091 push ebx
1092 push edi
1093 push esi
1094
1095 mov edi, eax
1096 and ecx, 0FFh { zero all but low byte of ECX }
1097 jz @@Done
1098 mov esi, edx
1099 xor ebx, ebx { Zero EBX and EDX }
1100 xor edx, edx
1101 inc edx { Set EDX to 1 }
1102
1103 @@Next:
1104 or ebx, ebx
1105 je @@NoTab { Jump to NoTab if spacecount is zero }
1106 mov eax, edx { IPos to EAX }
1107 push edx
1108 xor edx, edx
1109 div ecx
1110 cmp edx, 1 { Is mod = 1? }
1111 pop edx
1112 jne @@NoTab { If not, no tab }
1113
1114 sub edi, ebx
1115 mov byte ptr [edi], 9h { Store a tab }
1116 inc edi
1117 xor ebx, ebx { Reset spacecount }
1118
1119 @@NoTab:
1120 mov al, [esi] { Get next input character }
1121 inc esi
1122 or al, al { End of string? }
1123 jz @@Done { Yes, done }
1124 inc ebx { Increment SpaceCount }
1125 cmp al, 20h { Is character a space? }
1126 jz @@Store { Yes, store it for now }
1127 xor ebx, ebx { Reset SpaceCount }
1128 cmp al, 27h { Is it a quote? }
1129 jz @@Quotes { Yep, enter quote loop }
1130 cmp al, 22h { Is it a doublequote? }
1131 jnz @@Store { Nope, store it }
1132
1133 @@Quotes:
1134 mov ah, al { Save quote start }
1135
1136 @@NextQ:
1137 mov [edi], al { Store quoted character }
1138 inc edi
1139 mov al, [esi] { Get next character }
1140 inc esi
1141 inc edx { Increment Ipos }
1142 cmp edx, ecx { At end of line? }
1143 jae @@Store { If so, exit quote loop }
1144
1145 cmp al, ah { Matching end quote? }
1146 jnz @@NextQ { Nope, stay in quote loop }
1147 cmp al, 27h { Single quote? }
1148 jz @@Store { Exit quote loop }
1149 cmp byte ptr [esi-2],'\' { Previous character an escape? }
1150 jz @@NextQ { Stay in if so }
1151
1152 @@Store:
1153 mov [edi], al { Store last character }
1154 inc edi
1155 inc edx { Increment input position }
1156 jmp @@Next { Repeat while characters left }
1157
1158 @@Done:
1159 mov byte ptr [edi], 0h
1160 pop esi
1161 pop edi
1162 pop ebx
1163 pop eax
1164 end;
1165
1166 function DetabZ(Dest, Src : PAnsiChar; TabSize : Byte) : PAnsiChar;
1167 { -Expand tabs in a string to blanks on spacing TabSize- }
1168 register;
1169 asm
1170 push eax { Save Dest for return value }
1171 push edi { Save EDI, ESI and EBX, we'll be changing them }
1172 push esi
1173 push ebx
1174
1175 mov esi, edx { ESI -> Src }
1176 mov edi, eax { EDI -> Dest }
1177 xor ebx, ebx { Get TabSize in EBX }
1178 add bl, cl
1179 jz @@Done { Exit if TabSize is zero }
1180
1181 xor edx, edx { Set output length to zero }
1182
1183 @@Next:
1184 mov al, [esi]
1185 inc esi { Get next input character }
1186 or al, al { Is it a null? }
1187 jz @@Done { Yes-all done }
1188 cmp al, 09 { Is it a tab? }
1189 je @@Tab { Yes, compute next tab stop }
1190 mov [edi], al { No, store to output }
1191 inc edi
1192 inc edx { Increment output length }
1193 jmp @@Next { Next character }
1194
1195 @@Tab:
1196 push edx { Save output length }
1197 mov eax, edx { Get current output length in EDX:EAX }
1198 xor edx, edx
1199 div ebx { Output length MOD TabSize in DX }
1200 mov ecx, ebx { Calc number of spaces to insert... }
1201 sub ecx, edx { = TabSize - Mod value }
1202 pop edx
1203 add edx, ecx { Add count of spaces into current output length }
1204
1205 mov eax,$2020 { Blank in AH, Blank in AL }
1206 shr ecx, 1 { Store blanks }
1207 rep stosw
1208 adc ecx, ecx
1209 rep stosb
1210 jmp @@Next { Back for next input }
1211
1212 @@Done:
1213 mov byte ptr [edi], 0h { Store final null terminator }
1214
1215 pop ebx { Restore caller's EBX, ESI and EDI }
1216 pop esi
1217 pop edi
1218 pop eax { Return Dest }
1219 end;
1220
1221 function HasExtensionZ(Name : PAnsiChar; var DotPos : Cardinal) : Boolean;
1222 {-Return whether and position of extension separator dot in a pathname}
1223 var
1224 I, L : Integer;
1225 Pos : Cardinal;
1226 P : TSmallArrayA;
1227 begin
1228 I := -1;
1229 DotPos := Cardinal(I);
1230 Result := False;
1231 L := StrLen(Name);
1232 if L = 0 then
1233 Exit;
1234 for I := L-1 downto 0 do
1235 if (Name[I] = '.') and (DotPos = Cardinal(-1)) then
1236 DotPos := I;
1237 Result := (DotPos <> Cardinal(-1)) and not
1238 StrChPosZ(StrStCopyZ(P, Name, Succ(DotPos), StMaxFileLen), '\', Pos);
1239 end;
1240
1241 {$IFDEF UNICODE}
1242 function HasExtensionZ(Name : PWideChar; var DotPos : Cardinal) : Boolean;
1243 {-Return whether and position of extension separator dot in a pathname}
1244 var
1245 I, L : Integer;
1246 Pos : Cardinal;
1247 P : TSmallArray;
1248 begin
1249 I := -1;
1250 DotPos := Cardinal(I);
1251 Result := False;
1252 L := StrLen(Name);
1253 if L = 0 then
1254 Exit;
1255 for I := L-1 downto 0 do
1256 if (Name[I] = '.') and (DotPos = Cardinal(-1)) then
1257 DotPos := I;
1258 Result := (DotPos <> Cardinal(-1)) and not
1259 StrChPosZ(StrStCopyZ(P, Name, Succ(DotPos), StMaxFileLen), '\', Pos);
1260 end;
1261 {$ENDIF}
1262
1263
1264 function DefaultExtensionZ(Dest : PAnsiChar; Name, Ext : PAnsiChar) : PAnsiChar;
1265 {-Return a pathname with the specified extension attached}
1266 var
1267 DotPos : Cardinal;
1268 begin
1269 if HasExtensionZ(Name, DotPos) then
1270 StrCopy(Dest, Name)
1271 else if StrLen(Name) = 0 then
1272 Dest[0] := #0
1273 else begin
1274 StrCopy(Dest, Name);
1275 StrCat(Dest, '.');
1276 StrCat(Dest, Ext);
1277 end;
1278 Result := Dest;
1279 end;
1280
1281 function ForceExtensionZ(Dest : PAnsiChar; Name, Ext : PAnsiChar) : PAnsiChar;
1282 {-Return a pathname with the specified extension attached}
1283 var
1284 DotPos : Cardinal;
1285 begin
1286 if HasExtensionZ(Name, DotPos) then
1287 Dest := StrCat(StrStCopyZ(Dest, Name, 0, Succ(DotPos)), Ext)
1288 else if StrLen(Name) = 0 then
1289 Dest[0] := #0
1290 else begin
1291 Dest := StrCopy(Dest, Name);
1292 Dest := StrCat(Dest, '.');
1293 Dest := StrCat(Dest, Ext);
1294 end;
1295 Result := Dest;
1296 end;
1297
1298 function JustExtensionZ(Dest : PAnsiChar; Name : PAnsiChar) : PAnsiChar;
1299 {-Return just the extension of a pathname}
1300 var
1301 DotPos : Cardinal;
1302 begin
1303 if HasExtensionZ(Name, DotPos) then
1304 Dest := StrStCopyZ(Dest, Name, Succ(DotPos), StMaxFileLen)
1305 else
1306 Dest[0] := #0;
1307 Result := Dest;
1308 end;
1309
1310 function JustFilenameZ(Dest : PAnsiChar; PathName : PAnsiChar) : PAnsiChar;
1311 {-Return just the filename of a pathname}
1312 var
1313 I : Integer;
1314 begin
1315 I := StrLen(PathName);
1316 while (I > 0) and (not (PathName[I-1] in DosDelimSet)) do
1317 Dec(I);
1318 Dest := StrStCopyZ(Dest, PathName, I, StMaxFileLen);
1319 Result := Dest;
1320 end;
1321
1322 {$IFDEF UNICODE}
1323 function JustFilenameZ(Dest : PWideChar; PathName : PWideChar) : PWideChar;
1324 {-Return just the filename of a pathname}
1325 var
1326 I : Integer;
1327 begin
1328 I := StrLen(PathName);
1329 while (I > 0) and (not (PathName[I-1] in DosDelimSet)) do
1330 Dec(I);
1331 Dest := StrStCopyZ(Dest, PathName, I, StMaxFileLen);
1332 Result := Dest;
1333 end;
1334 {$ENDIF}
1335
1336
1337 function JustNameZ(Dest : PAnsiChar; PathName : PAnsiChar) : PAnsiChar;
1338 {-Return just the name (no extension, no path) of a pathname}
1339 var
1340 DotPos : Cardinal;
1341 T : TSmallArrayA;
1342 begin
1343 JustFileNameZ(T, PathName);
1344 if HasExtensionZ(T, DotPos) then
1345 Dest := StrStCopyZ(Dest, T, 0, DotPos)
1346 else
1347 StrCopy(Dest, T);
1348 Result := Dest;
1349 end;
1350
1351 function JustPathnameZ(Dest : PAnsiChar; PathName : PAnsiChar) : PAnsiChar;
1352 {-Return just the drive:directory portion of a pathname}
1353 var
1354 I : Longint;
1355 begin
1356 I := StrLen(PathName);
1357 repeat
1358 Dec(I);
1359 until (I = -1) or (PathName[I] in DosDelimSet);
1360
1361 if I = -1 then
1362 {Had no drive or directory name}
1363 Dest[0] := #0
1364 else if I = 0 then begin
1365 {Either the root directory of default drive or invalid pathname}
1366 Dest[0] := PathName[0];
1367 Dest[1] := #0;
1368 end
1369 else if (PathName[I] = '\') then begin
1370 if PathName[Pred(I)] = ':' then
1371 {Root directory of a drive, leave trailing backslash}
1372 Dest := StrStCopyZ(Dest, PathName, 0, Succ(I))
1373 else
1374 {Subdirectory, remove the trailing backslash}
1375 Dest := StrStCopyZ(Dest, PathName, 0, I);
1376 end else
1377 {Either the default directory of a drive or invalid pathname}
1378 Dest:= StrStCopyZ(Dest, PathName, 0, Succ(I));
1379 Result := Dest;
1380 end;
1381
1382 function AddBackSlashZ(Dest : PAnsiChar; DirName : PAnsiChar) : PAnsiChar;
1383 {-Add a default backslash to a directory name}
1384 var
1385 L : Integer;
1386 begin
1387 Result := Dest;
1388 StrCopy(Dest, DirName);
1389 L := StrLen(DirName);
1390 if (L > 0) then begin
1391 if ((L = 2) and (Dest[1] = ':')) or
1392 ((L > 2) and (Dest[L-1] <> '\')) then begin
1393 Dest[L] := '\';
1394 Dest[L+1] := #0;
1395 end;
1396 end;
1397 end;
1398
1399 function CleanFileNameZ(Dest, FileName : PAnsiChar) : PAnsiChar;
1400 {-Return filename with at most 8 chars of name and 3 of extension}
1401 var
1402 DotPos : Cardinal;
1403 NameLen : Integer;
1404 P2 : TSmallArrayA;
1405 begin
1406 if HasExtensionZ(FileName, DotPos) then begin
1407 {Take the first 8 chars of name and first 3 chars of extension}
1408 NameLen := DotPos;
1409 if NameLen > 8 then
1410 NameLen := 8;
1411 StrStCopyZ(Dest, FileName, 0, NameLen);
1412 StrCat(Dest, StrStCopyZ(P2, FileName, DotPos, 4));
1413 end else
1414 {Take the first 8 chars of name}
1415 StrStCopyZ(Dest, FileName, 0, 8);
1416 Result := Dest;
1417 end;
1418
1419 function CleanPathNameZ(Dest : PAnsiChar; PathName : PAnsiChar) : PAnsiChar;
1420 {-Return a pathname cleaned up as DOS will do it}
1421 var
1422 I : Word;
1423 S1, S, OName : TSmallArrayA;
1424 begin
1425 Result := Dest;
1426 StrCopy(Dest, PathName);
1427 I := StrLen(PathName);
1428 OName[0] := #0;
1429 while I > 0 do begin
1430 Dec(I);
1431 if I > 1 then
1432 if (Dest[I] = '\') and (Dest[I-1] = '\') then
1433 if (Dest[I-2] <> ':') then
1434 StrChDeletePrimZ(Dest, I);
1435 end;
1436 I := StrLen(Dest);
1437 while I > 0 do begin
1438 Dec(I);
1439 {Get the next directory or drive portion of pathname}
1440 while ((I > 0) and not (Dest[I] in DosDelimSet)) do {!!.02}
1441 Dec(I);
1442 {Clean it up and prepend it to output string}
1443 StrStCopyZ(S1, Dest, I + 1, StMaxFileLen);
1444 StrCopy(S, OName);
1445 CleanFileNameZ(OName, S1);
1446 StrCat(OName, S);
1447 {if I >= 0 then begin}
1448 StrCopy(S, OName);
1449 StrStCopyZ(OName, Dest, I, 1);
1450 StrCat(OName, S);
1451 StrStDeletePrimZ(Dest, I, 255);
1452 {end;}
1453 end;
1454 StrCopy(Dest, OName);
1455 end;
1456
1457 function ConvertToShortString(S : PAnsiChar; var SS : ShortString) : integer;
1458
1459 var
1460 LenS : integer;
1461 begin
1462 {returns 0 if the string was converted successfully
1463 1 if the string is nil
1464 2 if the string length is greater than 255}
1465 if (S = nil) then begin
1466 Result := 1;
1467 end
1468 else begin
1469 LenS := StrLen(S);
1470 if (LenS > 255) then begin
1471 Result := 2;
1472 end
1473 else begin
1474 {we can't use StrPas in 32-bit since it assumes a long string
1475 and that would incur too much overhead, so convert to a short
1476 string from first principles}
1477 Move(S^, SS[1], LenS);
1478 SetLength(SS, LenS);
1479 Result := 0;
1480 end;
1481 end;
1482 end;
1483
1484 function Str2Int16Z(S : PAnsiChar; var I : SmallInt) : Boolean;
1485 {-Convert a string to an integer, returning true if successful}
1486
1487 var
1488 ec : integer;
1489 SS : ShortString;
1490 begin
1491 case ConvertToShortString(S, SS) of
1492 0 : begin {success}
1493 ValSmallint(SS, I, ec);
1494 if (ec = 0) then
1495 Result := true
1496 else begin
1497 Result := false;
1498 if (ec < 0) then
1499 I := StrLen(S)
1500 else
1501 I := pred(ec); {null terminated strings are zero-based}
1502 end;
1503 end;
1504 1 : begin {S is nil}
1505 Result := false;
1506 I := 0;
1507 end;
1508 2 : begin {S is more than 255 characters long}
1509 Result := false;
1510 I := 256;
1511 end;
1512 else
1513 Result := false;
1514 end;
1515 end;
1516
1517 function Str2WordZ(S : PAnsiChar; var I : Word) : Boolean;
1518 {-Convert a string to a word, returning true if successful}
1519
1520 var
1521 ec : integer;
1522 SS : ShortString;
1523 begin
1524 case ConvertToShortString(S, SS) of
1525 0 : begin {success}
1526 ValWord(SS, I, ec);
1527 if (ec = 0) then
1528 Result := true
1529 else begin
1530 Result := false;
1531 if (ec < 0) then
1532 I := StrLen(S)
1533 else
1534 I := pred(ec); {null terminated strings are zero-based}
1535 end;
1536 end;
1537 1 : begin {S is nil}
1538 Result := false;
1539 I := 0;
1540 end;
1541 2 : begin {S is more than 255 characters long}
1542 Result := false;
1543 I := 256;
1544 end;
1545 else
1546 Result := false;
1547 end;
1548 end;
1549
1550 function Str2LongZ(S : PAnsiChar; var I : LongInt) : Boolean;
1551 {-Convert a string to a longint, returning true if successful}
1552
1553 var
1554 ec : integer;
1555 SS : ShortString;
1556 begin
1557 case ConvertToShortString(S, SS) of
1558 0 : begin {success}
1559 ValLongint(SS, I, ec);
1560 if (ec = 0) then
1561 Result := true
1562 else begin
1563 Result := false;
1564 if (ec < 0) then
1565 I := StrLen(S)
1566 else
1567 I := pred(ec); {null terminated strings are zero-based}
1568 end;
1569 end;
1570 1 : begin {S is nil}
1571 Result := false;
1572 I := 0;
1573 end;
1574 2 : begin {S is more than 255 characters long}
1575 Result := false;
1576 I := 256;
1577 end;
1578 else
1579 Result := false;
1580 end;
1581 end;
1582
1583 {$IFDEF VER93}
1584 function Str2RealZ(S : PAnsiChar; var R : Double) : Boolean;
1585 {$ELSE}
1586 function Str2RealZ(S : PChar; var R : Real) : Boolean;
1587 {$ENDIF}
1588 {-Convert a string to a real, returning true if successful}
1589 var
1590 Code : Integer;
1591 P : TSmallArray;
1592 begin
1593 if StrLen(S)+1 > SizeOf(P) then begin
1594 Result := False;
1595 R := -1;
1596 Exit;
1597 end;
1598 StrCopy(P, S);
1599 TrimTrailPrimZ(P);
1600 Val(ValPrepZ(P), R, Code);
1601 if Code <> 0 then begin
1602 R := Code - 1;
1603 Result := False;
1604 end else
1605 Result := True;
1606 end;
1607
1608 function Str2ExtZ(S : PAnsiChar; var R : Extended) : Boolean;
1609 {-Convert a string to an extended, returning true if successful}
1610 var
1611 Code : Integer;
1612 P : TSmallArrayA;
1613 begin
1614 if StrLen(S)+1 > SizeOf(P) then begin
1615 Result := False;
1616 R := -1;
1617 Exit;
1618 end;
1619 StrCopy(P, S);
1620 TrimTrailPrimZ(P);
1621 Val(ValPrepZ(P), R, Code);
1622 if Code <> 0 then begin
1623 R := Code - 1;
1624 Result := False;
1625 end else
1626 Result := True;
1627 end;
1628
1629 function Long2StrZ(Dest : PAnsiChar; L : LongInt) : PAnsiChar;
1630 {-Convert a long/word/integer/byte/shortint to a string}
1631 type
1632 PCharArray = ^TCharArray;
1633 TCharArray = array[0..99] of AnsiChar;
1634 begin
1635 Str(L, PCharArray(Dest)^);
1636 Result := Dest;
1637 end;
1638
1639 function Real2StrZ(Dest : PAnsiChar; R : Double; Width : Byte;
1640 Places : ShortInt) : PAnsiChar;
1641 {-Convert a real to a string}
1642 type
1643 PCharArray = ^TCharArray;
1644 TCharArray = array[0..99] of AnsiChar;
1645 begin
1646 Str(R:Width:Places, PCharArray(Dest)^);
1647 Result := Dest;
1648 end;
1649
1650 function Ext2StrZ(Dest : PAnsiChar; R : Extended; Width : Byte;
1651 Places : ShortInt) : PAnsiChar;
1652 {-Convert an extended to a string}
1653 type
1654 PCharArray = ^TCharArray;
1655 TCharArray = array[0..99] of AnsiChar;
1656 begin
1657 Str(R:Width:Places, PCharArray(Dest)^);
1658 Result := Dest;
1659 end;
1660
1661 function ValPrepZ(S : PAnsiChar) : PAnsiChar;
1662 {-Prepares a string for calling Val.}
1663 var
1664 P : Cardinal;
1665 begin
1666 Result := TrimSpacesPrimZ(S);
1667 if StrLen(Result) <> 0 then begin
1668 if StrChPosZ(Result, AnsiChar({$IFDEF DELPHIXE2}FormatSettings.{$ENDIF}DecimalSeparator), P) then begin
1669 Result[P] := '.';
1670 if Succ(P) = StrLen(Result) then
1671 Result[P] := #0;
1672 end;
1673 end else begin
1674 Result := '0';
1675 end;
1676 end;
1677
1678 {$IFDEF UNICODE}
1679 function ValPrepZ(S : PWideChar) : PWideChar;
1680 {-Prepares a string for calling Val.}
1681 var
1682 P : Cardinal;
1683 begin
1684 Result := TrimSpacesPrimZ(S);
1685 if StrLen(Result) <> 0 then begin
1686 if StrChPosZ(Result, {$IFDEF DELPHIXE2}FormatSettings.{$ENDIF}DecimalSeparator, P) then begin
1687 Result[P] := '.';
1688 if Succ(P) = StrLen(Result) then
1689 Result[P] := #0;
1690 end;
1691 end else begin
1692 Result := '0';
1693 end;
1694 end;
1695 {$ENDIF}
1696
1697 function CharExistsZ(S : PAnsiChar; C : AnsiChar) : Boolean;
1698 {-Determine whether the given character exists in a string. }
1699 register;
1700 asm
1701 xor dh, dh
1702 xor ecx, ecx
1703 @@Loop:
1704 cmp dh, [eax+0]
1705 je @@Done
1706 cmp dl, [eax+0]
1707 jne @@1
1708 inc ecx
1709 jmp @@Done
1710 @@1:
1711 cmp dh, [eax+1]
1712 je @@Done
1713 cmp dl, [eax+1]
1714 jne @@2
1715 inc ecx
1716 jmp @@Done
1717 @@2:
1718 cmp dh, [eax+2]
1719 je @@Done
1720 cmp dl, [eax+2]
1721 jne @@3
1722 inc ecx
1723 jmp @@Done
1724 @@3:
1725 cmp dh, [eax+3]
1726 je @@Done
1727 cmp dl, [eax+3]
1728 jne @@4
1729 inc ecx
1730 jmp @@Done
1731 @@4:
1732 add eax, 4
1733 jmp @@Loop
1734 @@Done:
1735 mov eax, ecx
1736 end;
1737
1738 function CharExistsZ(S : PWideChar; C : Char) : Boolean; //SZ
1739 {-Determine whether the given character exists in a string. }
1740 register;
1741 asm
1742 xor dx, dx
1743 xor ecx, ecx
1744 @@Loop:
1745 cmp dx, [eax+0]
1746 je @@Done
1747 cmp dx, [eax+0]
1748 jne @@1
1749 inc ecx
1750 inc ecx
1751 jmp @@Done
1752 @@1:
1753 cmp dx, [eax+2]
1754 je @@Done
1755 cmp dx, [eax+2]
1756 jne @@2
1757 inc ecx
1758 inc ecx
1759 jmp @@Done
1760 @@2:
1761 cmp dx, [eax+4]
1762 je @@Done
1763 cmp dx, [eax+4]
1764 jne @@3
1765 inc ecx
1766 inc ecx
1767 jmp @@Done
1768 @@3:
1769 cmp dx, [eax+6]
1770 je @@Done
1771 cmp dx, [eax+6]
1772 jne @@4
1773 inc ecx
1774 inc ecx
1775 jmp @@Done
1776 @@4:
1777 add eax, 8
1778 jmp @@Loop
1779 @@Done:
1780 mov eax, ecx
1781 end;
1782
1783
1784 function CharCountZ(S : PAnsiChar; C : AnsiChar) : Cardinal;
1785 {-Count the number of a given character in a string. }
1786 register;
1787 asm
1788 xor dh, dh
1789 xor ecx, ecx
1790 @@Loop:
1791 cmp dh, [eax+0]
1792 je @@Done
1793 cmp dl, [eax+0]
1794 jne @@1
1795 inc ecx
1796 @@1:
1797 cmp dh, [eax+1]
1798 je @@Done
1799 cmp dl, [eax+1]
1800 jne @@2
1801 inc ecx
1802 @@2:
1803 cmp dh, [eax+2]
1804 je @@Done
1805 cmp dl, [eax+2]
1806 jne @@3
1807 inc ecx
1808 @@3:
1809 cmp dh, [eax+3]
1810 je @@Done
1811 cmp dl, [eax+3]
1812 jne @@4
1813 inc ecx
1814 @@4:
1815 add eax, 4
1816 jmp @@Loop
1817 @@Done:
1818 mov eax, ecx
1819 end;
1820
1821 function WordCountZ(S : PAnsiChar; WordDelims : PAnsiChar) : Cardinal;
1822 {-Given a set of word delimiters, return number of words in S}
1823 var
1824 Count : Cardinal;
1825 I : Cardinal;
1826 SLen : Cardinal;
1827
1828 begin
1829 Count := 0;
1830 I := 0;
1831 SLen := StrLen(S);
1832 while I < SLen do begin
1833 {skip over delimiters}
1834 while (I < SLen) and (CharExistsZ(WordDelims, S^)) do begin
1835 Inc(I);
1836 Inc(S);
1837 end;
1838 {if we're not beyond end of S, we're at the start of a word}
1839 if I < SLen then
1840 Inc(Count);
1841
1842 {find the end of the current word}
1843 while (I < SLen) and (not CharExistsZ(WordDelims, S^)) do begin
1844 Inc(I);
1845 Inc(S);
1846 end;
1847 end;
1848
1849 Result := Count;
1850 end;
1851
1852 function WordPositionZ(N : Cardinal; S : PAnsiChar; WordDelims : PAnsiChar;
1853 var Pos : Cardinal) : Boolean;
1854 {-Given a set of word delimiters, return start position of N'th word in S}
1855 var
1856 Count : Cardinal;
1857 SLen : Cardinal;
1858 begin
1859 Count := 0;
1860 Pos := 0;
1861 Result := False;
1862 SLen := StrLen(S);
1863
1864 while (Pos < SLen) and (Count <> N) do begin
1865 {skip over delimiters}
1866 while (Pos < SLen) and (CharExistsZ(WordDelims, S^)) do begin
1867 Inc(Pos);
1868 Inc(S);
1869 end;
1870 {if we're not beyond end of S, we're at the start of a word}
1871 if Pos < SLen then
1872 Inc(Count);
1873
1874 {if not finished, find the end of the current word}
1875 if Count <> N then begin
1876 while (Pos < SLen) and (not CharExistsZ(WordDelims, S^)) do begin
1877 Inc(Pos);
1878 Inc(S);
1879 end;
1880 end
1881 else
1882 Result := True;
1883 end;
1884 end;
1885
1886 function ExtractWordZ(Dest : PAnsiChar; N : Cardinal; Src : PAnsiChar;
1887 WordDelims : PAnsiChar) : PAnsiChar;
1888 {-Given a set of word delimiters, return in Dest the N'th word in Src}
1889 var
1890 I : Cardinal;
1891 SLen : Cardinal;
1892 begin
1893 Result := Dest;
1894 SLen := StrLen(Src);
1895 if WordPositionZ(N, Src, WordDelims, I) then begin
1896 Inc(Src, I);
1897 {find the end of the current word}
1898 while (I <= SLen) and (not CharExistsZ(WordDelims, Src^)) do begin
1899 {add the I'th character to result}
1900 Dest^ := Src^;
1901 Inc(Dest);
1902 Inc(Src);
1903 Inc(I);
1904 end;
1905 end;
1906 Dest^ := #0;
1907 end;
1908
1909 function AsciiCountZ(S : PAnsiChar; WordDelims : PAnsiChar; Quote : AnsiChar) : Cardinal;
1910 {-Given a set of word delimiters, return number of words in S}
1911 var
1912 Count : Cardinal;
1913 I : Cardinal;
1914 SLen : Cardinal;
1915 InQuote : Boolean;
1916 begin
1917 Count := 0;
1918 I := 1;
1919 InQuote := False;
1920 SLen := StrLen(S);
1921 while I <= SLen do begin
1922 {skip over delimiters}
1923 while (I <= SLen) and (S^ <> Quote) and CharExistsZ(WordDelims, S^) do begin
1924 Inc(I);
1925 Inc(S);
1926 end;
1927 {if we're not beyond end of S, we're at the start of a word}
1928 if I <= SLen then
1929 Inc(Count);
1930 {find the end of the current word}
1931 while (I <= SLen) and ((InQuote) or (not CharExistsZ(WordDelims, S^))) do begin
1932 if S^ = Quote then
1933 InQuote := not(InQuote);
1934 Inc(I);
1935 Inc(S);
1936 end;
1937 end;
1938
1939 Result := Count;
1940 end;
1941
1942 function AsciiPositionZ(N : Cardinal; S : PAnsiChar; WordDelims : PAnsiChar;
1943 Quote : AnsiChar; var Pos : Cardinal) : Boolean;
1944 {-Given a set of word delimiters, return start position of N'th word in S}
1945 var
1946 Count : Cardinal;
1947 SLen : Cardinal;
1948 InQuote : Boolean;
1949 begin
1950 Count := 0;
1951 Pos := 0;
1952 InQuote := False;
1953 Result := False;
1954 SLen := StrLen(S);
1955 while (Pos < SLen) and (Count <= N) do begin
1956 {skip over delimiters}
1957 while (Pos < SLen) and (S^ <> Quote) and CharExistsZ(WordDelims, S^) do begin
1958 Inc(Pos);
1959 Inc(S);
1960 end;
1961
1962 {if we're not beyond end of S, we're at the start of a word}
1963 if Pos < SLen then
1964 Inc(Count);
1965
1966 {if not finished, find the end of the current word}
1967 if Count <> N then
1968 while (Pos < SLen) and ((InQuote) or (not CharExistsZ(WordDelims, S^))) do begin
1969 if S^ = Quote then
1970 InQuote := not(InQuote);
1971 Inc(Pos);
1972 Inc(S);
1973 end
1974 else begin
1975 Result := True;
1976 Exit;
1977 end;
1978 end;
1979 end;
1980
1981 function ExtractAsciiZ(Dest : PAnsiChar; N : Cardinal; Src : PAnsiChar;
1982 WordDelims : PAnsiChar; Quote : AnsiChar) : PAnsiChar;
1983 {-Given a set of word delimiters, return in Dest the N'th word in Src}
1984 var
1985 I : Cardinal;
1986 Len : Cardinal;
1987 SLen : Cardinal;
1988 InQuote : Boolean;
1989 begin
1990 Len := 0;
1991 InQuote := False;
1992 Dest[0] := #0;
1993 Result := Dest;
1994 SLen := StrLen(Src);
1995 if AsciiPositionZ(N, Src, WordDelims, Quote, I) then
1996 {find the end of the current word}
1997 while (I < SLen) and ((InQuote) or (not CharExistsZ(WordDelims, Src[I]))) do begin
1998 {add the I'th character to result}
1999 if Src[I] = Quote then
2000 InQuote := Not(InQuote);
2001 Dest[Len] := Src[I];
2002 Inc(Len);
2003 Inc(I);
2004 end;
2005 Dest[Len] := #0;
2006 end;
2007
2008 procedure WordWrapZ(Dest : PAnsiChar; InSt, Overlap : PAnsiChar;
2009 Margin : Cardinal;
2010 PadToMargin : Boolean);
2011 {-Wrap InSt at Margin, storing the result in Dest and the remainder
2012 in Overlap}
2013 var
2014 InStLen : Cardinal;
2015 OutStLen : Cardinal;
2016 OvrLen : Cardinal;
2017 EOS, BOS : Cardinal;
2018 begin
2019 OutStLen := 0;
2020 InStLen := StrLen(InSt);
2021
2022 {!!.02 - Added }
2023 { handle empty string on input }
2024 if InStLen = 0 then begin
2025 if Assigned(Dest) then
2026 Dest[0] := #0;
2027 if Assigned(Overlap) then
2028 Overlap[0] := #0;
2029 Exit;
2030 end;
2031 {!!.02 - End Added }
2032
2033 {find the end of the new output string}
2034 if InStLen > Margin then begin
2035 {assume this is a good break point}
2036 EOS := Margin-1;
2037
2038 {is this the position of the last character of a word}
2039 if InSt[EOS+1] <> ' ' then begin {check next char}
2040 {look for the space before the current word}
2041 while (EOS > 0) and (InSt[EOS] <> ' ') do
2042 Dec(EOS);
2043 {when done, EOS points to a space char or is zero}
2044
2045 {if EOS = 0 then - can't wrap it properly}
2046 if EOS = 0 then
2047 EOS := Margin-1 {set up to break line at margin}
2048 else
2049 while (InSt[EOS] = ' ') and (EOS > 0) do {trim trailing blanks}
2050 Dec(EOS);
2051 end else
2052 while (EOS > 0) and (InSt[EOS] = ' ') do {trim trailing blanks}
2053 Dec(EOS);
2054 end
2055 else
2056 EOS := InStLen-1;
2057
2058 {at this point EOS points to the break point, the end of the line,
2059 or is zero}
2060
2061 {copy the unwrapped portion of the line}
2062 if (EOS = 0) and (InSt[EOS] = ' ') then
2063 Dest[0] := #0
2064 else begin
2065 OutStLen := EOS+1;
2066 Move(InSt^, Dest^, OutStLen);
2067 Dest[OutStLen] := #0;
2068 end;
2069
2070 {find the start of the next word in the line}
2071 BOS := EOS+1;
2072 while (BOS < InStLen) and (InSt[BOS] = ' ') do
2073 Inc(BOS);
2074
2075 if BOS >= InStLen then begin
2076 OverLap[0] := #0;
2077 end else begin
2078 {copy from the start of the next word to the end of the line}
2079 OvrLen := InStLen-BOS;
2080 Move(InSt[BOS], Overlap^, OvrLen);
2081 Overlap[OvrLen] := #0;
2082 end;
2083
2084 {pad the end of the output string if requested}
2085 if PadToMargin and (OutStLen < Margin) then begin
2086 FillChar(Dest[OutStLen], Margin-OutStLen, ' ');
2087 Dest[Margin] := #0;
2088 end;
2089 end;
2090
2091 function CompStringZ(S1, S2 : PAnsiChar) : Integer;
2092 {-Return -1, 0, 1 if S1<S2, S1=S2, or S1>S2}
2093 register;
2094 asm
2095 push ebx
2096 push edi
2097 push esi
2098
2099 mov edi, eax
2100 mov esi, eax
2101 xor eax, eax
2102 or ecx, -1
2103 repne scasb
2104 not ecx
2105 dec ecx
2106
2107 mov edi, edx
2108 mov ebx, edx
2109 mov edx, ecx
2110 or ecx, -1
2111 repne scasb
2112 not ecx
2113 dec ecx
2114 mov edi, ebx
2115 or ebx, -1
2116 cmp edx, ecx
2117 je @@EqLen
2118 jb @@Comp
2119
2120 inc ebx
2121 mov ecx, edx
2122
2123 @@EqLen:
2124 inc ebx
2125
2126 @@Comp:
2127 or ecx, ecx
2128 jz @@Done
2129
2130 repe cmpsb
2131 je @@Done
2132
2133 mov ebx, 1
2134 ja @@Done
2135 or ebx, -1
2136
2137 @@Done:
2138 mov eax, ebx
2139 pop esi
2140 pop edi
2141 pop ebx
2142 end;
2143
2144
2145 function CompUCStringZ(S1, S2 : PAnsiChar) : Integer;
2146 {-Return -1, 0, 1 if s1<s2, s1=s2, or s1>s2. Comparison is done in
2147 uppercase}
2148 register;
2149 asm
2150 push ebx
2151 push edi
2152 push esi
2153
2154 mov edi, eax
2155 mov esi, eax
2156 xor eax, eax
2157 or ecx, -1
2158 repne scasb
2159 not ecx
2160 dec ecx
2161
2162 mov edi, edx
2163 mov ebx, edx
2164 mov edx, ecx
2165 or ecx, -1
2166 repne scasb
2167 not ecx
2168 dec ecx
2169 mov edi, ebx
2170 or ebx, -1
2171 cmp edx, ecx
2172 je @@EqLen
2173 jb @@Comp
2174
2175 inc ebx
2176 mov ecx, edx
2177
2178 @@EqLen:
2179 inc ebx
2180
2181 @@Comp:
2182 or ecx, ecx
2183 jz @@Done { Done if either is empty }
2184
2185 @@Start:
2186 mov al, [esi]
2187 inc esi
2188 push ebx { Save registers }
2189 push ecx
2190 push edx
2191 push eax { Push Char onto stack for CharUpper }
2192 call CharUpper
2193 pop edx { Restore registers }
2194 pop ecx
2195 pop ebx
2196
2197 mov edx, eax
2198 mov al, [edi]
2199 inc edi
2200
2201 push ebx { Save registers }
2202 push ecx
2203 push edx
2204 push eax { Push Char onto stack for CharUpper }
2205 call CharUpper
2206 pop edx { Restore registers }
2207 pop ecx
2208 pop ebx
2209
2210 cmp edx, eax
2211 jne @@Output
2212 dec ecx
2213 jnz @@Start
2214 je @@Done
2215
2216 @@Output:
2217 mov ebx, 1
2218 ja @@Done
2219 or ebx, -1
2220
2221 @@Done:
2222 mov eax, ebx
2223 pop esi
2224 pop edi
2225 pop ebx
2226 end;
2227
2228 function SoundexZ(Dest : PAnsiChar; S : PAnsiChar) : PAnsiChar; assembler;
2229 {-Return 4 character soundex of input string}
2230 register;
2231 const
2232 SoundexTable : array[0..255] of AnsiChar =
2233 (#0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
2234 #0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
2235 #0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
2236 #0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
2237 #0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
2238 #0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
2239 #0, #0, #0, #0, #0,
2240 { A B C D E F G H I J K L M }
2241 #0, '1', '2', '3', #0, '1', '2', #0, #0, '2', '2', '4', '5',
2242 { N O P Q R S T U V W X Y X }
2243 '5', #0, '1', '2', '6', '2', '3', #0, '1', #0, '2', #0, '2',
2244 #0, #0, #0, #0, #0, #0,
2245 { a b c d e f g h i j k l m }
2246 #0, '1', '2', '3', #0, '1', '2', #0, #0, '2', '2', '4', '5',
2247 { n o p q r s t u v w x y x }
2248 '5', #0, '1', '2', '6', '2', '3', #0, '1', #0, '2', #0, '2',
2249 #0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
2250 #0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
2251 #0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
2252 #0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
2253 #0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
2254 #0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
2255 #0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
2256 #0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
2257 #0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
2258 #0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
2259 #0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
2260 #0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
2261 #0, #0, #0, #0, #0, #0, #0, #0, #0, #0,
2262 #0, #0, #0);
2263 asm
2264 push eax { Save registers }
2265 push ebx
2266 push edi
2267 push esi
2268 mov edi, edx
2269 mov ebx, eax
2270 mov esi, edx
2271
2272 mov dword ptr [ebx], '0000' { Initialize output string to '0000'. }
2273 xor eax, eax
2274 mov [ebx+4], al { Set null at end of string. }
2275
2276 or ecx, -1 { Set ECX to $FFFFFFFF }
2277 repne scasb
2278 not ecx
2279 dec ecx { ECX has length of S }
2280 jz @@Done { Exit if null string. }
2281
2282 mov edi, ebx
2283 mov al, [esi] { Get first character of input string. }
2284 inc esi
2285
2286 push ecx { Save ECX across call to CharUpper. }
2287 push eax { Push Char onto stack for CharUpper. }
2288 call CharUpper { Uppercase AL. }
2289 pop ecx { Restore saved register. }
2290
2291 mov [edi], al { Store first output character. }
2292 inc edi
2293
2294 dec ecx { One input character used. }
2295 jz @@Done { Was input string one char long?. }
2296
2297 mov bh, 03h { Output max 3 chars beyond first. }
2298 mov edx, offset SoundexTable { EDX => Soundex table. }
2299 xor eax, eax { Prepare for address calc. }
2300 xor bl, bl { BL will be used to store 'previous char'. }
2301
2302 @@Next:
2303 mov al, [esi] { Get next char in AL. }
2304 inc esi
2305 mov al, [edx+eax] { Get soundex code into AL. }
2306 or al, al { Is AL zero? }
2307 jz @@NoStore { If yes, skip this char. }
2308 cmp bl, al { Is it the same as the previous stored char? }
2309 je @@NoStore { If yes, skip this char. }
2310 mov [edi], al { Store char to Dest. }
2311 inc edi
2312 dec bh { Decrement output counter. }
2313 jz @@Done { If zero, we're done. }
2314 mov bl, al { New previous character. }
2315
2316 @@NoStore:
2317 dec ecx { Decrement input counter. }
2318 jnz @@Next
2319
2320 @@Done: { Restore registers }
2321 pop esi
2322 pop edi
2323 pop ebx
2324 pop eax
2325 end;
2326
2327 function MakeLetterSetZ(S : PAnsiChar) : Longint;
2328 {-Return a bit-mapped long storing the individual letters contained in S.}
2329 register;
2330 asm
2331 push ebx { Save registers }
2332 push edi
2333 push esi
2334 mov esi, eax
2335 mov edi, eax
2336 xor edx, edx
2337 xor eax, eax { Measure S }
2338 or ecx, -1
2339 repne scasb
2340 not ecx
2341 dec ecx { ECX has length of S }
2342 jz @@Exit
2343
2344 @@Next:
2345 mov al, [esi] { EAX has next char in S }
2346 inc esi
2347
2348 push ecx { Save registers }
2349 push edx
2350 push eax { Push Char onto stack for CharUpper }
2351 call CharUpper
2352 pop edx { Restore registers }
2353 pop ecx
2354
2355 sub eax, 'A' { Convert to bit number }
2356 cmp eax, 'Z'-'A' { Was char in range 'A'..'Z'? }
2357 ja @@Skip { Skip it if not }
2358
2359 mov ebx, eax { Exchange EAX and ECX }
2360 mov eax, ecx
2361 mov ecx, ebx
2362 ror edx, cl
2363 or edx, 01h { Set appropriate bit }
2364 rol edx, cl
2365 mov ebx, eax { Exchange EAX and ECX }
2366 mov eax, ecx
2367 mov ecx, ebx
2368
2369 @@Skip:
2370 dec ecx
2371 jnz @@Next { Get next character }
2372
2373 @@Exit:
2374 mov eax, edx { Move EDX to result }
2375 pop esi
2376 pop edi { Restore registers }
2377 pop ebx
2378 end;
2379
2380 procedure BMMakeTableZ(MatchString : PAnsiChar; var BT : BTable);
2381 {Build Boyer-Moore link table}
2382 register;
2383 asm
2384 push esi { Save registers because they will be changed }
2385 push edi
2386 push ebx
2387
2388 mov edi, eax { Move EAX to ESI & EDI }
2389 mov esi, eax
2390 xor eax, eax { Zero EAX }
2391 or ecx, -1
2392 repne scasb { Search for null terminator }
2393 not ecx
2394 dec ecx { ECX is length of search string }
2395 cmp ecx, 0FFh { If ECX > 255, force to 255 }
2396 jbe @@1
2397 mov ecx, 0FFh
2398
2399 @@1:
2400 mov ch, cl { Duplicate CL in CH }
2401 mov eax, ecx { Fill each byte in EAX with length }
2402 shl eax, 16
2403 mov ax, cx
2404 mov edi, edx { Point to the table }
2405 mov ecx, 64 { Fill table bytes with length }
2406 rep stosd
2407 cmp al, 1 { If length <= 1, we're done }
2408 jbe @@MTDone
2409 mov edi, edx { Reset EDI to beginning of table }
2410 xor ebx, ebx { Zero EBX }
2411 mov cl, al { Restore CL to length of string }
2412 dec ecx
2413
2414 @@MTNext:
2415 mov bl, [esi] { Load table with positions of letters }
2416 inc esi { That exist in the search string }
2417 mov [edi+ebx], cl
2418 dec ecx
2419 jnz @@MTNext
2420
2421 @@MTDone:
2422 pop ebx { Restore registers }
2423 pop edi
2424 pop esi
2425 end;
2426
2427 function BMSearchZ(var Buffer; BufLength : Cardinal; var BT : BTable;
2428 MatchString : PAnsiChar; var Pos : Cardinal) : Boolean; assembler;
2429 register;
2430 var
2431 BufPtr : Pointer;
2432 asm
2433 push edi { Save registers since we will be changing }
2434 push esi
2435 push ebx
2436 push edx
2437
2438 mov BufPtr, eax { Copy Buffer to local variable and ESI }
2439 mov esi, eax
2440 mov ebx, ecx { Copy BT ptr to EBX }
2441
2442 xor eax, eax { Zero out EAX so we can search for null }
2443 mov edi, MatchString { Set EDI to beginning of MatchString }
2444 or ecx, -1 { We will be counting down }
2445 repne scasb { Find null }
2446 not ecx { ECX = length of MatchString + null }
2447 dec ecx { ECX = length of MatchString }
2448 mov edx, ecx { Copy length of MatchString to EDX }
2449
2450 pop ecx { Pop length of buffer into ECX }
2451 mov edi, esi { Set EDI to beginning of search buffer }
2452 mov esi, MatchString { Set ESI to beginning of MatchString }
2453
2454 cmp dl, 1 { Check to see if we have a trivial case }
2455 ja @@BMSInit { If Length(MatchString) > 1 do BM search }
2456 jb @@BMSNotFound { If Length(MatchString) = 0 we're done }
2457
2458 mov al,[esi] { If Length(MatchString) = 1 do a REPNE SCASB }
2459 mov ebx, edi
2460 repne scasb
2461 jne @@BMSNotFound { No match during REP SCASB }
2462 dec edi { Found, calculate position }
2463 sub edi, ebx
2464 mov esi, Pos { Set position in Pos }
2465 mov [esi], edi
2466 mov eax, 1 { Set result to True }
2467 jmp @@BMSDone { We're done }
2468
2469 @@BMSInit:
2470 dec edx { Set up for BM Search }
2471 add esi, edx { Set ESI to end of MatchString }
2472 add ecx, edi { Set ECX to end of buffer }
2473 add edi, edx { Set EDI to first check point }
2474 mov dh, [esi] { Set DH to character we'll be looking for }
2475 dec esi { Dec ESI in prep for BMSFound loop }
2476 std { Backward string ops }
2477 jmp @@BMSComp { Jump to first comparison }
2478
2479 @@BMSNext:
2480 mov al, [ebx+eax] { Look up skip distance from table }
2481 add edi, eax { Skip EDI ahead to next check point }
2482
2483 @@BMSComp:
2484 cmp edi, ecx { Have we reached end of buffer? }
2485 jae @@BMSNotFound { If so, we're done }
2486 mov al, [edi] { Move character from buffer into AL for comparison }
2487 cmp dh, al { Compare }
2488 jne @@BMSNext { If not equal, go to next checkpoint }
2489
2490 push ecx { Save ECX }
2491 dec edi
2492 xor ecx, ecx { Zero ECX }
2493 mov cl, dl { Move Length(MatchString) to ECX }
2494 repe cmpsb { Compare MatchString to buffer }
2495 je @@BMSFound { If equal, string is found }
2496
2497 mov al, dl { Move Length(MatchString) to AL }
2498 sub al, cl { Calculate offset that string didn't match }
2499 add esi, eax { Move ESI back to end of MatchString }
2500 add edi, eax { Move EDI to pre-string compare location }
2501 inc edi
2502 mov al, dh { Move character back to AL }
2503 pop ecx { Restore ECX }
2504 jmp @@BMSNext { Do another compare }
2505
2506 @@BMSFound: { EDI points to start of match }
2507 mov edx, BufPtr { Move pointer to buffer into EDX }
2508 sub edi, edx { Calculate position of match }
2509 mov eax, edi
2510 inc eax
2511 mov esi, Pos
2512 mov [esi], eax { Set Pos to position of match }
2513 mov eax, 1 { Set result to True }
2514 pop ecx { Restore ESP }
2515 jmp @@BMSDone
2516
2517 @@BMSNotFound:
2518 xor eax, eax { Set result to False }
2519
2520 @@BMSDone:
2521 cld { Restore direction flag }
2522 pop ebx { Restore registers }
2523 pop esi
2524 pop edi
2525 end;
2526
2527 function BMSearchUCZ(var Buffer; BufLength : Cardinal; var BT : BTable;
2528 MatchString : PAnsiChar; var Pos : Cardinal) : Boolean; assembler;
2529 {- Case-insensitive search of Buffer for MatchString. Return indicates
2530 success or failure. Assumes MatchString is already raised to
2531 uppercase (PRIOR to creating the table) -}
2532 register;
2533 var
2534 BufPtr : Pointer;
2535 asm
2536 push edi { Save registers since we will be changing }
2537 push esi
2538 push ebx
2539 push edx
2540
2541 mov BufPtr, eax { Copy Buffer to local variable and ESI }
2542 mov esi, eax
2543 mov ebx, ecx { Copy BufLength to EBX }
2544
2545 xor eax, eax { Zero out EAX so we can search for null }
2546 mov edi, MatchString { Set EDI to beginning of MatchString }
2547 or ecx, -1 { We will be counting down }
2548 repne scasb { Find null }
2549 not ecx { ECX = length of MatchString + null }
2550 dec ecx { ECX = length of MatchString }
2551 mov edx, ecx { Copy length of MatchString to EDX }
2552
2553 pop ecx { Pop length of buffer into ECX }
2554 mov edi, esi { Set EDI to beginning of search buffer }
2555 mov esi, MatchString { Set ESI to beginning of MatchString }
2556
2557 or dl, dl { Check to see if we have a trivial case }
2558 jz @@BMSNotFound { If Length(MatchString) = 0 we're done }
2559
2560 @@BMSInit:
2561 dec edx { Set up for BM Search }
2562 add esi, edx { Set ESI to end of MatchString }
2563 add ecx, edi { Set ECX to end of buffer }
2564 add edi, edx { Set EDI to first check point }
2565 mov dh, [esi] { Set DH to character we'll be looking for }
2566 dec esi { Dec ESI in prep for BMSFound loop }
2567 std { Backward string ops }
2568 jmp @@BMSComp { Jump to first comparison }
2569
2570 @@BMSNext:
2571 mov al, [ebx+eax] { Look up skip distance from table }
2572 add edi, eax { Skip EDI ahead to next check point }
2573
2574 @@BMSComp:
2575 cmp edi, ecx { Have we reached end of buffer? }
2576 jae @@BMSNotFound { If so, we're done }
2577 mov al, [edi] { Move character from buffer into AL for comparison }
2578
2579 push ebx { Save registers }
2580 push ecx
2581 push edx
2582 push eax { Push Char onto stack for CharUpper }
2583 cld
2584 call CharUpper
2585 std
2586 pop edx { Restore registers }
2587 pop ecx
2588 pop ebx
2589
2590 cmp dh, al { Compare }
2591 jne @@BMSNext { If not equal, go to next checkpoint }
2592
2593 push ecx { Save ECX }
2594 dec edi
2595 xor ecx, ecx { Zero ECX }
2596 mov cl, dl { Move Length(MatchString) to ECX }
2597 jecxz @@BMSFound { If ECX is zero, string is found }
2598
2599 @@StringComp:
2600 mov al, [edi] { Get char from buffer }
2601 dec edi { Dec buffer index }
2602
2603 push ebx { Save registers }
2604 push ecx
2605 push edx
2606 push eax { Push Char onto stack for CharUpper }
2607 cld
2608 call CharUpper
2609 std
2610 pop edx { Restore registers }
2611 pop ecx
2612 pop ebx
2613
2614 mov ah, al { Move buffer char to AH }
2615 lodsb { Get MatchString char }
2616 cmp ah, al { Compare }
2617 loope @@StringComp { OK? Get next character }
2618 je @@BMSFound { Matched! }
2619
2620 xor ah, ah { Zero AH }
2621 mov al, dl { Move Length(MatchString) to AL }
2622 sub al, cl { Calculate offset that string didn't match }
2623 add esi, eax { Move ESI back to end of MatchString }
2624 add edi, eax { Move EDI to pre-string compare location }
2625 inc edi
2626 mov al, dh { Move character back to AL }
2627 pop ecx { Restore ECX }
2628 jmp @@BMSNext { Do another compare }
2629
2630 @@BMSFound: { EDI points to start of match }
2631 mov edx, BufPtr { Move pointer to buffer into EDX }
2632 sub edi, edx { Calculate position of match }
2633 mov eax, edi
2634 inc eax
2635 mov esi, Pos
2636 mov [esi], eax { Set Pos to position of match }
2637 mov eax, 1 { Set result to True }
2638 pop ecx { Restore ESP }
2639 jmp @@BMSDone
2640
2641 @@BMSNotFound:
2642 xor eax, eax { Set result to False }
2643
2644 @@BMSDone:
2645 cld { Restore direction flag }
2646 pop ebx { Restore registers }
2647 pop esi
2648 pop edi
2649 end;
2650
2651 {------------------ Formatting routines --------------------}
2652
2653 function CommaizeChZ(Dest : PAnsiChar; L : Longint; Ch : AnsiChar) : PAnsiChar;
2654 var
2655 NumCommas, Len, I : Cardinal;
2656 begin
2657 Result := Dest;
2658 Long2StrZ(Dest, L);
2659 Len := StrLen(Dest);
2660 NumCommas := (Len - 1) div 3;
2661 for I := 1 to NumCommas do
2662 StrChInsertPrimZ(Dest, Ch, Len - (I * 3));
2663 end;
2664
2665 function CommaizeZ(Dest : PAnsiChar; L : LongInt) : PAnsiChar;
2666 begin
2667 Result := CommaizeChZ(Dest, L, ',');
2668 end;
2669
2670 function FormPrimZ(Dest, Mask : PAnsiChar; R : TstFloat; LtCurr,
2671 RtCurr : PAnsiChar; Sep, DecPt : AnsiChar;
2672 AssumeDP : Boolean) : PAnsiChar;
2673 {-Returns a formatted string with digits from R merged into the Mask}
2674 const
2675 Blank = 0;
2676 Asterisk = 1;
2677 Zero = 2;
2678 const
2679 {$IFOPT N+}
2680 MaxPlaces = 18;
2681 {$ELSE}
2682 MaxPlaces = 11;
2683 {$ENDIF}
2684 FormChars : array[0..8] of AnsiChar = '#@*$-+,.';
2685 PlusArray : array[Boolean] of AnsiChar = ('+', '-');
2686 MinusArray : array[Boolean] of AnsiChar = (' ', '-');
2687 FillArray : array[Blank..Zero] of AnsiChar = (' ', '*', '0');
2688 var
2689 Temp : PAnsiChar;
2690 S : array[0..20] of AnsiChar; {temporary string}
2691 Filler : integer;{char for unused digit slots: ' ', '*', '0'}
2692 WontFit, {true if number won't fit in the mask}
2693 AddMinus, {true if minus sign needs to be added}
2694 Dollar, {true if floating dollar sign is desired}
2695 Negative : Boolean; {true if B is negative}
2696 StartF, {starting point of the numeric field}
2697 EndF : Cardinal; {end of numeric field}
2698 RtChars, {# of chars to add to right}
2699 LtChars, {# of chars to add to left}
2700 DotPos, {position of '.' in Mask}
2701 Digits, {total # of digits}
2702 Places, {# of digits after the '.'}
2703 Blanks, {# of blanks returned by Str}
2704 FirstDigit, {pos. of first digit returned by Str}
2705 Extras, {# of extra digits needed for special cases}
2706 I : Cardinal;
2707 label
2708 EndFound,
2709 RedoCase,
2710 Done;
2711 begin
2712 {assume decimal point at end?}
2713 Result := Dest;
2714 StrCopy(Result, Mask);
2715 if (not AssumeDP) and (not CharExistsZ(Result, '.')) then
2716 AssumeDP := true;
2717 if AssumeDP and (Result^ <> #0) then
2718 StrCat(Result, '.');
2719
2720 RtChars := 0;
2721 LtChars := 0;
2722
2723 {check for empty string}
2724 if Result^ = #0 then
2725 goto Done;
2726
2727 {initialize variables}
2728 Filler := Blank;
2729 DotPos := 0;
2730 Places := 0;
2731 Digits := 0;
2732 Dollar := False;
2733 AddMinus := True;
2734 StartF := 0;
2735
2736 {store the sign of the real and make it positive}
2737 Negative := (R < 0);
2738 R := Abs(R);
2739
2740 {strip and count c's}
2741 Temp := StrEnd(Result);
2742 Dec(Temp);
2743 while Temp >= Result do begin
2744 if Temp^ = 'C' then begin
2745 Inc(RtChars);
2746 StrChDeletePrimZ(Result, Temp - Result);
2747 end else if Temp^ = 'c' then begin
2748 Inc(LtChars);
2749 StrChDeletePrimZ(Result, Temp - Result);
2750 end;
2751 Dec(Temp);
2752 end;
2753
2754 {find the starting point for the field}
2755 Temp := Result;
2756 while (Temp^ <> #0) and not CharExistsZ(FormChars, Temp^) do begin
2757 Inc(StartF);
2758 Inc(Temp);
2759 end;
2760 if Succ(StartF) > StrLen(Result) then
2761 goto Done;
2762
2763 {find the end point for the field}
2764 EndF := StartF;
2765 while (Temp^ <> #0) do begin
2766 case Temp^ of
2767 '*' : Filler := Asterisk;
2768 '@' : Filler := Zero;
2769 '$' : Dollar := True;
2770 '-',
2771 '+' : AddMinus := False;
2772 '#' : {ignore} ;
2773 ',',
2774 '.' : DotPos := EndF;
2775 else
2776 goto EndFound;
2777 end;
2778 Inc(Temp);
2779 Inc(EndF);
2780 end;
2781
2782 EndFound:
2783 {correct the off-by-one nature of the loop}
2784 Dec(EndF);
2785
2786 {disallow Dollar if Filler is Zero}
2787 if Filler = Zero then
2788 Dollar := False;
2789
2790 {we need an extra slot if Dollar is True}
2791 Extras := Ord(Dollar);
2792
2793 {get total # of digits and # after the decimal point}
2794 for I := StartF to EndF do
2795 case Result[I] of
2796 '#', '@',
2797 '*', '$' :
2798 begin
2799 Inc(Digits);
2800 if (I > DotPos) and (DotPos <> 0) then
2801 Inc(Places);
2802 end;
2803 end;
2804
2805 {need one more 'digit' if Places > 0}
2806 Inc(Digits, Ord(Places > 0));
2807
2808 {also need an extra blank if (1) Negative is true, and (2) Filler is Blank,
2809 and (3) AddMinus is true}
2810 if Negative and AddMinus and (Filler = Blank) then
2811 Inc(Extras)
2812 else
2813 AddMinus := False;
2814
2815 {translate the real to a string}
2816 Real2StrZ(S, R, Digits, Places);
2817
2818 {add zeros that Str may have left out}
2819 if Places > MaxPlaces then begin
2820 Temp := StrEnd(S);
2821 CharStrZ(Temp, '0', Places-MaxPlaces);
2822 while (StrLen(S) > Digits) and (S[0] = ' ') do
2823 StrChDeletePrimZ(S, 0);
2824 end;
2825
2826 {count number of initial blanks}
2827 Blanks := 0;
2828 while S[Blanks] = ' ' do
2829 Inc(Blanks);
2830 FirstDigit := Blanks;
2831
2832 {the number won't fit if (a) S is longer than Digits or (b) the number of
2833 initial blanks is less than Extras}
2834 WontFit := (StrLen(S) > Digits) or (Blanks < Extras);
2835
2836 {if it won't fit, fill decimal slots with '*'}
2837 if WontFit then begin
2838 for I := StartF to EndF do
2839 case Result[I] of
2840 '#', '@', '*', '$' : Result[I] := '*';
2841 '+' : Result[I] := PlusArray[Negative];
2842 '-' : Result[I] := MinusArray[Negative];
2843 end;
2844 goto Done;
2845 end;
2846
2847 {fill initial blanks in S with Filler; insert floating dollar sign}
2848 if Blanks > 0 then begin
2849 FillChar(S[0], Blanks, FillArray[Filler]);
2850
2851 {put floating dollar sign in last blank slot if necessary}
2852 if Dollar then begin
2853 S[Pred(Blanks)] := LtCurr[0];
2854 Dec(Blanks);
2855 end;
2856
2857 {insert a minus sign if necessary}
2858 if AddMinus then
2859 S[Pred(Blanks)] := '-';
2860 end;
2861
2862 {put in the digits / signs}
2863 Temp := StrEnd(S);
2864 Dec(Temp);
2865 for I := EndF downto StartF do begin
2866 RedoCase:
2867 case Result[I] of
2868 '#', '@', '*', '$' :
2869 if Temp >= S then begin
2870 Result[I] := Temp^;
2871 Dec(Temp);
2872 if (Temp^ = '.') and (Temp >= S) then
2873 Dec(Temp);
2874 end
2875 else
2876 Result[I] := FillArray[Filler];
2877 ',' :
2878 begin
2879 Result[I] := Sep;
2880 if (I < DotPos) and (Temp < (S + FirstDigit)) then begin
2881 Result[I] := '#';
2882 goto RedoCase;
2883 end;
2884 end;
2885 '.' :
2886 begin
2887 Result[I] := DecPt;
2888 if (I < DotPos) and (Temp < (S + FirstDigit)) then begin
2889 Result[I] := '#';
2890 goto RedoCase;
2891 end;
2892 end;
2893 '+' : Result[I] := PlusArray[Negative];
2894 '-' : Result[I] := MinusArray[Negative];
2895 end;
2896 end;
2897
2898 Done:
2899 if AssumeDP then
2900 Result[Pred(StrLen(Result))] := #0;
2901 if RtChars > 0 then begin
2902 StrLCopy(S, RtCurr, RtChars);
2903 LeftPadPrimZ(S, RtChars);
2904 StrCat(Result, S);
2905 end;
2906 if LtChars > 0 then begin
2907 StrLCopy(S, LtCurr, LtChars);
2908 PadPrimZ(S, LtChars);
2909 StrStInsertPrimZ(Result, S, 0);
2910 end;
2911 end;
2912
2913 function FloatFormZ(Dest, Mask : PAnsiChar; R : TstFloat; LtCurr,
2914 RtCurr : PAnsiChar; Sep, DecPt : AnsiChar) : PAnsiChar;
2915 {-Return a formatted string with digits from R merged into mask.}
2916 begin
2917 Result := FormPrimZ(Dest, Mask, R, LtCurr, RtCurr, Sep, DecPt, False);
2918 end;
2919
2920 function LongIntFormZ(Dest, Mask : PAnsiChar; L : Longint; LtCurr,
2921 RtCurr : PAnsiChar; Sep : AnsiChar) : PAnsiChar;
2922 {-Return a formatted string with digits from L merged into mask.}
2923 begin
2924 Result := FormPrimZ(Dest, Mask, L, LtCurr, RtCurr, Sep, '.', True);
2925 end;
2926
2927 function StrChPosZ(P : PAnsiChar; C : AnsiChar; var Pos : Cardinal): Boolean;
2928 {-Sets Pos to position of character C within string P returns True if found}
2929 var
2930 Temp : PAnsiChar;
2931 begin
2932 Result := False;
2933 Temp := StrScan(P, C);
2934 if Temp <> nil then begin
2935 Pos := Temp - P;
2936 Result := True;
2937 end;
2938 end;
2939
2940 {$IFDEF UNICODE}
2941 function StrChPosZ(P : PWideChar; C : Char; var Pos : Cardinal): Boolean;
2942 {-Sets Pos to position of character C within string P returns True if found}
2943 var
2944 Temp : PChar;
2945 begin
2946 Result := False;
2947 Temp := StrScan(P, C);
2948 if Temp <> nil then begin
2949 Pos := Temp - P;
2950 Result := True;
2951 end;
2952 end;
2953 {$ENDIF}
2954
2955 function StrStPosZ(P, S : PAnsiChar; var Pos : Cardinal) : boolean;
2956 {-Sets Pos to position of string S within string P returns True if found}
2957 var
2958 Temp : PAnsiChar;
2959 begin
2960 Result := False;
2961 Temp := StrPos(P, S);
2962 if Temp <> nil then begin
2963 Pos := Temp - P;
2964 Result := True;
2965 end;
2966 end;
2967
2968 function StrChInsertPrimZ(Dest : PAnsiChar; C : AnsiChar;
2969 Pos : Cardinal) : PAnsiChar;
2970 register;
2971 asm
2972 push eax {save because we will be changing them}
2973 push edi
2974 push esi
2975
2976 mov esi, eax {copy Dest to ESI and EDI}
2977 mov edi, eax
2978 mov ah, dl
2979 mov edx, ecx {move POS to edx}
2980
2981 xor al, al {zero}
2982 or ecx, -1 {set ECX to $FFFFFFFF}
2983 repne scasb {find null terminator}
2984
2985 not ecx {calc length (including null)}
2986 std {backwards string ops}
2987 add esi, ecx
2988 dec esi {point to end of source string}
2989 sub ecx, edx {calculate number to do}
2990 jae @@1 {set ECX to 1 if Pos greater than strlen + 1}
2991 mov ecx, 1
2992
2993 @@1:
2994 rep movsb {adjust tail of string}
2995 mov [edi], ah {insert the new character}
2996
2997 @@ExitPoint:
2998 cld {be a good neighbor}
2999
3000 pop esi {restore registers}
3001 pop edi
3002 pop eax
3003 end;
3004
3005 function StrStInsertPrimZ(Dest : PAnsiChar; S : PAnsiChar;
3006 Pos : Cardinal) : PAnsiChar;
3007 register;
3008 asm
3009 push eax {save because we will be changing them}
3010 push edi
3011 push esi
3012 push ebx
3013
3014 mov ebx, ecx {move POS to ebx}
3015 mov esi, eax {copy Dest to ESI, S to EDI}
3016 mov edi, edx
3017
3018 xor al, al {zero}
3019 or ecx, -1 {set ECX to $FFFFFFFF}
3020 repne scasb {find null terminator}
3021 not ecx {calc length of source string (including null)}
3022 dec ecx {length without null}
3023 jz @@ExitPoint {if source length = 0, exit}
3024 push ecx {save length for later}
3025
3026 mov edi, esi {reset EDI to Dest}
3027 or ecx, -1
3028 repne scasb {find null}
3029 not ecx {length of dest string (including null)}
3030
3031 cmp ebx, ecx
3032 jb @@1
3033 mov ebx, ecx
3034 dec ebx
3035
3036 @@1:
3037 std {backwards string ops}
3038 pop eax {restore length of S from stack}
3039 add edi, eax {set EDI S beyond end of Dest}
3040 dec edi {back up one for null}
3041
3042 add esi, ecx {set ESI to end of Dest}
3043 dec esi {back up one for null}
3044 sub ecx, ebx {# of chars in Dest that are past Pos}
3045 rep movsb {adjust tail of string}
3046
3047 mov esi, edx {set ESI to S}
3048 add esi, eax {set ESI to end of S}
3049 dec esi {back up one for null}
3050 mov ecx, eax {# of chars in S}
3051 rep movsb {copy S into Dest}
3052
3053 cld {be a good neighbor}
3054
3055 @@ExitPoint:
3056
3057 pop ebx {restore registers}
3058 pop esi
3059 pop edi
3060 pop eax
3061 end;
3062
3063 function StrStCopyZ(Dest : PAnsiChar; S : PAnsiChar; Pos, Count : Cardinal) : PAnsiChar;
3064 var
3065 Len : Cardinal;
3066 begin
3067 Len := StrLen(S);
3068 if Pos < Len then begin
3069 if (Len-Pos) < Count then
3070 Count := Len-Pos;
3071 Move(S[Pos], Dest^, Count);
3072 Dest[Count] := #0;
3073 end else
3074 Dest[0] := #0;
3075 Result := Dest;
3076 end;
3077
3078 {$IFDEF UNICODE}
3079 function StrStCopyZ(Dest : PWideChar; S : PWideChar; Pos, Count : Cardinal) : PWideChar;
3080 var
3081 Len : Cardinal;
3082 begin
3083 Len := StrLen(S);
3084 if Pos < Len then begin
3085 if (Len-Pos) < Count then
3086 Count := Len-Pos;
3087 Move(S[Pos], Dest^, Count * SizeOf(WideChar));
3088 Dest[Count] := #0;
3089 end else
3090 Dest[0] := #0;
3091 Result := Dest;
3092 end;
3093 {$ENDIF}
3094
3095 function StrChDeletePrimZ(P : PAnsiChar; Pos : Cardinal) : PAnsiChar;
3096 register;
3097 asm
3098 push edi { Save because we will be changing them }
3099 push esi
3100 push ebx
3101
3102 mov ebx, eax { Save P to EDI & EBX }
3103 mov edi, eax
3104
3105 xor al, al { Zero }
3106 or ecx, -1 { Set ECX to $FFFFFFFF }
3107 repne scasb { Find null terminator }
3108 not ecx
3109 dec ecx
3110 or ecx, ecx
3111 jz @@ExitPoint
3112 sub ecx, edx { Calc number to move }
3113 jb @@ExitPoint { Exit if Pos > StrLen }
3114
3115 mov edi, ebx
3116 add edi, edx { Point to position to adjust }
3117 mov esi, edi
3118 inc esi { Offset for source string }
3119 inc ecx { One more to include null terminator }
3120 rep movsb { Adjust the string }
3121
3122 @@ExitPoint:
3123 mov eax, ebx
3124 pop ebx { restore registers }
3125 pop esi
3126 pop edi
3127 end;
3128
3129 function StrStDeletePrimZ(P : PAnsiChar; Pos, Count : Cardinal) : PAnsiChar;
3130 register;
3131 asm
3132 push eax {save because we will be changing them}
3133 push edi
3134 push esi
3135 push ebx
3136
3137 mov ebx, ecx {move Count to BX}
3138 mov esi, eax {move P to ESI and EDI}
3139 mov edi, eax
3140
3141 xor eax, eax {null}
3142 or ecx, -1
3143 repne scasb {find null terminator}
3144 not ecx {calc length}
3145 or ecx, ecx
3146 jz @@ExitPoint
3147
3148 sub ecx, ebx {subtract Count}
3149 sub ecx, edx {subtract Pos}
3150 jns @@L1
3151
3152 mov edi,esi {delete everything after Pos}
3153 add edi,edx
3154 mov [edi], al
3155 jmp @@ExitPoint
3156
3157 @@L1:
3158 mov edi,esi
3159 add edi,edx {point to position to adjust}
3160 mov esi,edi
3161 add esi,ebx {point past string to delete in src}
3162 inc ecx {one more to include null terminator}
3163 rep movsb {adjust the string}
3164
3165 @@ExitPoint:
3166
3167 pop ebx {restore registers}
3168 pop esi
3169 pop edi
3170 pop eax
3171 end;
3172
3173 function StrStDeletePrimZ(P : PWideChar; Pos, Count : Cardinal) : PWideChar; //SZ
3174 register;
3175 asm
3176 push eax {save because we will be changing them}
3177 push edi
3178 push esi
3179 push ebx
3180
3181 mov ebx, ecx {move Count to BX}
3182 mov esi, eax {move P to ESI and EDI}
3183 mov edi, eax
3184
3185 xor eax, eax {null}
3186 or ecx, -1
3187 repne scasw {find null terminator}
3188 not ecx {calc length}
3189 or ecx, ecx
3190 jz @@ExitPoint
3191
3192 sub ecx, ebx {subtract Count}
3193 sub ecx, ebx {subtract Count}
3194 sub ecx, edx {subtract Pos}
3195 sub ecx, edx {subtract Pos}
3196 jns @@L1
3197
3198 mov edi,esi {delete everything after Pos}
3199 add edi,edx
3200 mov [edi], ax
3201 jmp @@ExitPoint
3202
3203 @@L1:
3204 mov edi,esi
3205 add edi,edx {point to position to adjust}
3206 add edi,edx {point to position to adjust}
3207 mov esi,edi
3208 add esi,ebx {point past string to delete in src}
3209 add esi,ebx {point past string to delete in src}
3210 inc ecx {one more to include null terminator}
3211 inc ecx
3212 rep movsw {adjust the string}
3213
3214 @@ExitPoint:
3215
3216 pop ebx {restore registers}
3217 pop esi
3218 pop edi
3219 pop eax
3220 end;
3221
3222 function StrChDeleteZ(Dest, S : PAnsiChar; Pos : Cardinal) : PAnsiChar;
3223 begin
3224 StrCopy(Dest, S);
3225 Result := StrChDeletePrimZ(Dest, Pos);
3226 end;
3227
3228 function StrStDeleteZ(Dest, S : PAnsiChar; Pos, Count : Cardinal) : PAnsiChar;
3229 begin
3230 StrCopy(Dest, S);
3231 Result := StrStDeletePrimZ(Dest, Pos, Count);
3232 end;
3233
3234 function StrChInsertZ(Dest, S : PAnsiChar; C : AnsiChar; Pos : Cardinal) : PAnsiChar;
3235 begin
3236 StrCopy(Dest, S);
3237 Result := StrChInsertPrimZ(Dest, C, Pos);
3238 end;
3239
3240 function StrStInsertZ(Dest : PAnsiChar; S1, S2 : PAnsiChar; Pos : Cardinal) : PAnsiChar;
3241 begin
3242 StrCopy(Dest, S1);
3243 Result := StrStInsertPrimZ(Dest, S2, Pos);
3244 end;
3245
3246
3247 {----------------------------------------------------------------------------}
3248
3249 function CopyLeftZ(Dest, S : PAnsiChar; Len : Cardinal) : PAnsiChar;
3250 {-Return the left Len characters of a string}
3251 begin
3252 if (Len < 1) or (S[0] = #0) then
3253 Dest[0] := #0
3254 else
3255 Dest := StrStCopyZ(Dest, S, 0, Len);
3256 Result := Dest;
3257 end;
3258
3259 {----------------------------------------------------------------------------}
3260
3261 function CopyMidZ(Dest, S : PAnsiChar; First, Len : Cardinal) : PAnsiChar;
3262 {-Return the mid part of a string}
3263 begin
3264 if (First >= StrLen(S)) or (LongInt(Len) < 1) or (S[0] = #0) then
3265 Dest[0] := #0
3266 else
3267 Dest := StrStCopyZ(Dest, S, First, Len);
3268 Result := Dest;
3269 end;
3270
3271 {----------------------------------------------------------------------------}
3272
3273 function CopyRightZ(Dest, S : PAnsiChar; First : Cardinal) : PAnsiChar;
3274 {-Return the right characters of a string}
3275 begin
3276 if (First >= StrLen(Dest)) or (S[0] = #0) then
3277 Dest[0] := #0
3278 else
3279 Dest := StrStCopyZ(Dest, S, First, StrLen(S)-First+1);
3280 Result := Dest;
3281 end;
3282
3283 {----------------------------------------------------------------------------}
3284 function CopyRightAbsZ(Dest, S : PAnsiChar; NumChars : Cardinal) : PAnsiChar;
3285 {-Return the right Len characters of a string}
3286 var
3287 I : Cardinal;
3288 begin
3289 if (StrLen(S) > NumChars) then begin
3290 I := StrLen(S) - NumChars;
3291 Dest := StrStCopyZ(Dest, S, I, NumChars)
3292 end else
3293 Dest := S;
3294 Result := Dest;
3295 end;
3296
3297 {----------------------------------------------------------------------------}
3298
3299 function WordPosZ(S, WordDelims, AWord : PAnsiChar;
3300 N : Cardinal; var Position : Cardinal) : Boolean;
3301 {-returns the Occurrence instance of a given word within a string}
3302 var
3303 P,
3304 TmpStr : PAnsiChar;
3305 Len,
3306 I,
3307 P1,
3308 P2 : Cardinal;
3309 begin
3310 if (S[0] = #0) or (AWord[0] = #0) or
3311 (StrPos(S, AWord) = nil) or (N < 1) then begin
3312 Result := False;
3313 Position := 0;
3314 Exit;
3315 end;
3316
3317 Result := False;
3318 Position := 0;
3319
3320 GetMem(TmpStr, StrLen(S)+1);
3321 try
3322 StrCopy(TmpStr, S);
3323 I := 0;
3324 Len := StrLen(AWord);
3325 P := StrPos(TmpStr, AWord);
3326 P1 := P - TmpStr;
3327
3328 while (StrLen(TmpStr) > 0) do begin
3329 P2 := P1 + pred(Len);
3330 if (P1 = 0) then begin
3331 if (CharExistsZ(WordDelims, TmpStr[P2+1])) then begin
3332 Inc(I);
3333 end else
3334 StrStDeleteZ(TmpStr, TmpStr, 0, P2);
3335 end else if (CharExistsZ(WordDelims, TmpStr[P1-1])) and
3336 ((CharExistsZ(WordDelims, TmpStr[P2+1])) or (P2+1 = StrLen(TmpStr))) then begin
3337 Inc(I);
3338 end else if ((P1 + pred(Len)) = StrLen(TmpStr)) then begin
3339 if (CharExistsZ(WordDelims, TmpStr[P1-1])) then
3340 Inc(I);
3341 end;
3342
3343 if (I = N) then begin
3344 Result := True;
3345 Position := Position + P1;
3346 Exit;
3347 end;
3348 StrStDeletePrimZ(TmpStr, 0, P2+1);
3349 Position := Position + P2+1;
3350 P := StrPos(TmpStr, AWord);
3351 if (P <> nil) then
3352 P1 := P - TmpStr
3353 else
3354 break;
3355 end;
3356 finally
3357 FreeMem(TmpStr, StrLen(S)+1);
3358 end;
3359 end;
3360
3361
3362 {----------------------------------------------------------------------------}
3363
3364 function CopyFromNthWordZ(Dest, S, WordDelims, AWord : PAnsiChar;
3365 N : Cardinal) : Boolean;
3366 var
3367 P : Cardinal;
3368 begin
3369 if (WordPosZ(S, WordDelims, AWord, N, P)) then begin
3370 StrStCopyZ(Dest, S, P, StrLen(S)-P+1);
3371 Result := True;
3372 end else begin
3373 Dest[0] := #0;
3374 Result := False;
3375 end;
3376 end;
3377
3378 {----------------------------------------------------------------------------}
3379
3380
3381 function DeleteFromNthWordZ(Dest, S, WordDelims, AWord : PAnsiChar;
3382 N : Cardinal) : Boolean;
3383 var
3384 P : Cardinal;
3385 begin
3386 if (WordPosZ(S, WordDelims, AWord, N, P)) then begin
3387 StrStDeleteZ(Dest, S, P, StrLen(S)-P+1);
3388 Result := False;
3389 end else begin
3390 Dest[0] := #0;
3391 Result := False;
3392 end;
3393 end;
3394
3395 {----------------------------------------------------------------------------}
3396
3397 function CopyFromToWordZ(Dest, S, WordDelims, Word1, Word2 : PAnsiChar;
3398 N1, N2 : Cardinal) : Boolean;
3399 var
3400 P1,
3401 P2 : Cardinal;
3402 begin
3403 if (WordPosZ(S, WordDelims, Word1, N1, P1)) then begin
3404 if (WordPosZ(S, WordDelims, Word2, N2, P2)) then begin
3405 Dec(P2);
3406 if (P2 > P1) then begin
3407 Result := True;
3408 StrStCopyZ(Dest, S, P1, P2-P1);
3409 end else begin
3410 Result := False;
3411 Dest[0] := #0;
3412 end;
3413 end else begin
3414 Result := False;
3415 Dest[0] := #0;
3416 end;
3417 end else begin
3418 Result := False;
3419 Dest[0] := #0;
3420 end;
3421 end;
3422
3423 {----------------------------------------------------------------------------}
3424
3425 function DeleteFromToWordZ(Dest, S, WordDelims, Word1, Word2 : PAnsiChar;
3426 N1, N2 : Cardinal) : Boolean;
3427 var
3428 P1,
3429 P2 : Cardinal;
3430 begin
3431 if (WordPosZ(S, WordDelims, Word1, N1, P1)) then begin
3432 if (WordPosZ(S, WordDelims, Word2, N2, P2)) then begin
3433 Dec(P2);
3434 if (P2 > P1) then begin
3435 Result := True;
3436 StrStDeleteZ(Dest, S, P1, P2-P1+1);
3437 end else begin
3438 Result := False;
3439 Dest[0] := #0;
3440 end;
3441 end else begin
3442 Result := False;
3443 Dest[0] := #0;
3444 end;
3445 end else begin
3446 Result := False;
3447 Dest[0] := #0;
3448 end;
3449 end;
3450
3451 {----------------------------------------------------------------------------}
3452
3453 function CopyWithinZ(Dest, S, Delimiter : PAnsiChar; Strip : Boolean) : PAnsiChar;
3454 var
3455 P1,
3456 P2 : Cardinal;
3457 L : Cardinal;
3458 TmpStr : PAnsiChar;
3459 begin
3460 if (S[0] = #0) or (Delimiter[0] = #0) or
3461 (StrPos(S, Delimiter) = nil) then begin
3462 Dest[0] := #0;
3463 Result := Dest;
3464 end else begin
3465 if (StrStPosZ(S, Delimiter, P1)) then begin
3466 L := StrLen(S) - (P1 + StrLen(Delimiter)) + 1;
3467 GetMem(TmpStr, L);
3468 try
3469 StrStCopyZ(TmpStr, S, P1 + StrLen(Delimiter), StrLen(S));
3470 if (StrStPosZ(TmpStr, Delimiter, P2)) then begin
3471 StrStCopyZ(Dest, TmpStr, 0, P2);
3472 if (not Strip) then
3473 StrCat(StrStInsertZ(Dest, Dest, Delimiter, 0), Delimiter)
3474 end else begin
3475 StrCopy(Dest, TmpStr);
3476 if (not Strip) then
3477 StrStInsertZ(Dest, Dest, Delimiter, 0);
3478 end;
3479 finally
3480 FreeMem(TmpStr, L);
3481 end;
3482 end;
3483 Result := Dest;
3484 end;
3485 end;
3486
3487 {----------------------------------------------------------------------------}
3488
3489 function DeleteWithinZ(Dest, S, Delimiter : PAnsiChar) : PAnsiChar;
3490 var
3491 P1,
3492 P2 : Cardinal;
3493 L : Cardinal;
3494 TmpStr : PAnsiChar;
3495 begin
3496 if (S[0] = #0) or (Delimiter[0] = #0) or
3497 (StrPos(S, Delimiter) = nil) then begin
3498 Dest[0] := #0;
3499 Result := Dest;
3500 end else begin
3501 if (StrStPosZ(S, Delimiter, P1)) then begin
3502 L := StrLen(S) - (P1 + StrLen(Delimiter)) + 1;
3503 GetMem(TmpStr, L);
3504 try
3505 StrStCopyZ(TmpStr, S, P1 + StrLen(Delimiter), StrLen(S));
3506 if not (StrStPosZ(TmpStr, Delimiter, P2)) then
3507 StrStCopyZ(Dest, S, 0, P1)
3508 else begin
3509 P2 := P2 + (2*StrLen(Delimiter));
3510 StrStDeleteZ(Dest, S, P1, P2);
3511 end;
3512 finally
3513 FreeMem(TmpStr, L);
3514 end;
3515 end;
3516 Result := Dest;
3517 end;
3518 end;
3519
3520 {----------------------------------------------------------------------------}
3521
3522 function ReplaceWordZ(Dest, S, WordDelims, OldWord, NewWord : PAnsiChar;
3523 N : Cardinal;
3524 var Replacements : Cardinal) : PAnsiChar;
3525 var
3526 I,
3527 C,
3528 P1 : Cardinal;
3529 begin
3530 if (S[0] = #0) or (WordDelims[0] = #0) or (OldWord[0] = #0) or
3531 (StrPos(S, OldWord) = nil) then begin
3532 StrCopy(Dest, S);
3533 Replacements := 0;
3534 Result := Dest;
3535 end else begin
3536 if (WordPosZ(S, WordDelims, OldWord, N, P1)) then begin
3537 StrCopy(Dest, S);
3538 StrStDeleteZ(Dest, Dest, P1, StrLen(OldWord));
3539
3540 C := 0;
3541 for I := 1 to Replacements do begin
3542 if (StrLen(NewWord) + 1 + StrLen(Dest)) < High(Cardinal) then begin
3543 Inc(C);
3544 StrStInsertZ(Dest, Dest, NewWord, P1);
3545 Inc(P1, StrLen(NewWord) + 1);
3546 end else begin
3547 Replacements := C;
3548 Result := Dest;
3549 Exit;
3550 end;
3551 end;
3552 Result := Dest;
3553 end else begin
3554 Replacements := 0;
3555 Result := Dest;
3556 end;
3557 end;
3558 end;
3559
3560
3561 function ReplaceWordAllZ(Dest, S, WordDelims, OldWord, NewWord : PAnsiChar;
3562 var Replacements : Cardinal) : PAnsiChar;
3563 var
3564 I,
3565 C,
3566 P1 : Cardinal;
3567 begin
3568 if (S[0] = #0) or (WordDelims[0] = #0) or (OldWord[0] = #0) or
3569 (StrPos(S, OldWord) = nil) then begin
3570 Replacements := 0;
3571 StrCopy(Dest, S);
3572 Result := Dest;
3573 end else begin
3574 StrCopy(Dest, S);
3575 C := 0;
3576 while (WordPosZ(Dest, WordDelims, OldWord, 1, P1)) do begin
3577 StrStDeleteZ(Dest, Dest, P1, StrLen(OldWord));
3578 for I := 1 to Replacements do begin
3579 if ((StrLen(NewWord) + 1 + StrLen(Dest)) < High(Cardinal)) then begin
3580 Inc(C);
3581 StrStInsertZ(Dest, Dest, NewWord, P1);
3582 end else begin
3583 Result := Dest;
3584 Replacements := C;
3585 Exit;
3586 end;
3587 end;
3588 end;
3589 Replacements := C;
3590 Result := Dest;
3591 end;
3592 end;
3593
3594
3595 function ReplaceStringZ(Dest, S, OldString, NewString : PAnsiChar;
3596 N : Cardinal;
3597 var Replacements : Cardinal) : PAnsiChar;
3598 var
3599 I,
3600 L,
3601 C,
3602 P1 : Cardinal;
3603 TmpStr : PAnsiChar;
3604 begin
3605 if (S[0] = #0) or (OldString[0] = #0) or
3606 (StrPos(S, OldString) = nil) then begin
3607 StrCopy(Dest, S);
3608 Replacements := 0;
3609 Result := Dest;
3610 Exit;
3611 end;
3612
3613 L := StrLen(S) + 1;
3614 GetMem(TmpStr, L);
3615 try
3616 StrCopy(TmpStr, S);
3617
3618 I := 1;
3619 StrStPosZ(TmpStr, OldString, P1);
3620 C := P1;
3621 while (I < N) and (C < StrLen(TmpStr)) do begin
3622 Inc(I);
3623 StrStDeleteZ(TmpStr, TmpStr, P1, P1 + StrLen(OldString));
3624 Inc(C, P1 + StrLen(OldString));
3625 end;
3626 finally
3627 FreeMem(TmpStr, L);
3628 end;
3629 StrCopy(Dest, S);
3630 StrStDeleteZ(Dest, Dest, C, StrLen(OldString));
3631
3632 C := 0;
3633 for I := 1 to Replacements do begin
3634 if ((StrLen(NewString) + 1 + StrLen(Dest)) < High(Cardinal)) then begin
3635 Inc(C);
3636 StrStInsertZ(Dest, Dest, NewString, P1);
3637 Inc(P1, StrLen(NewString) + 1);
3638 end else begin
3639 Replacements := C;
3640 Result := Dest;
3641 Exit;
3642 end;
3643 end;
3644 Result := Dest;
3645 end;
3646
3647
3648 function ReplaceStringAllZ(Dest, S, OldString, NewString : PAnsiChar;
3649 var Replacements : Cardinal) : PAnsiChar;
3650 var
3651 I,
3652 C,
3653 P1 : Cardinal;
3654 begin
3655 if (S[0] = #0) or (OldString[0] = #0) or (StrPos(S, OldString) = nil) then begin
3656 StrCopy(Dest, S);
3657 Result := Dest;
3658 Replacements := 0;
3659 end else begin
3660 StrCopy(Dest, S);
3661 C := 0;
3662 while StrStPosZ(Dest, OldString, P1) do begin
3663 StrStDeleteZ(Dest, Dest, P1, StrLen(OldString));
3664 for I := 1 to Replacements do begin
3665 if (LongInt((StrLen(NewString) + 1 + StrLen(Dest))) < MaxLongInt) then begin
3666 Inc(C);
3667 StrStInsertZ(Dest, Dest, NewString, P1);
3668 end else begin
3669 Replacements := C;
3670 Result := Dest;
3671 Exit;
3672 end;
3673 end;
3674 end;
3675 Replacements := C;
3676 Result := Dest;
3677 end;
3678 end;
3679
3680
3681
3682 function LastWordZ(S, WordDelims, AWord : PAnsiChar;
3683 var Position : Cardinal) : Boolean;
3684 var
3685 TmpStr1,
3686 TmpStr2 : PAnsiChar;
3687 begin
3688 if (S[0] = #0) or (WordDelims[0] = #0) or
3689 (AWord[0] = #0) or (StrPos(S, AWord) = nil) then begin
3690 Result := False;
3691 Position := 0;
3692 Exit;
3693 end;
3694
3695 GetMem(TmpStr1, StrLen(S) + 1);
3696 GetMem(TmpStr2, StrLen(AWord) + 1);
3697 try
3698 StrCopy(TmpStr1, S);
3699 Position := StrLen(TmpStr1)-1;
3700 while (CharExistsZ(WordDelims, TmpStr1[Position])) do
3701 Dec(Position);
3702
3703 Position := StrLen(TmpStr1)-1;
3704 repeat
3705 while (not CharExistsZ(WordDelims, TmpStr1[Position])) and (Position > 0) do
3706 Dec(Position);
3707 if (CompStringZ(
3708 StrStCopyZ(TmpStr2, TmpStr1, Position+1, StrLen(AWord)),
3709 AWord) = 0) then begin
3710 Inc(Position);
3711 Result := True;
3712 Exit;
3713 end;
3714 StrStDeleteZ(TmpStr1, TmpStr1, Position, StrLen(TmpStr1));
3715 Position := StrLen(TmpStr1)-1;
3716 until (Position = 0);
3717 Result := False;
3718 Position := 0;
3719 finally
3720 FreeMem(TmpStr1, StrLen(S)+1);
3721 FreeMem(TmpStr2, StrLen(AWord)+1);
3722 end;
3723 end;
3724
3725 {----------------------------------------------------------------------------}
3726
3727 function LastWordAbsZ(S, WordDelims : PAnsiChar;
3728 var Position : Cardinal) : Boolean;
3729 begin
3730 if (S[0] = #0) or (WordDelims[0] = #0) then begin
3731 Result := False;
3732 Position := 0;
3733 Exit;
3734 end;
3735
3736 {find first non-delimiter character, if any. If not, it's a "one word wonder"}
3737 Position := StrLen(S)-1;
3738 while (Position > 0) and (CharExistsZ(WordDelims, S[Position])) do
3739 Dec(Position);
3740
3741 if (Position = 0) then begin
3742 if (CharExistsZ(WordDelims, S[Position])) then begin
3743 Result := True;
3744 Position := 1;
3745 Exit;
3746 end else begin
3747 Result := True;
3748 Exit;
3749 end;
3750 end;
3751
3752 {find next non-delimiter character}
3753 Result := True;
3754 while (Position > 0) and (not CharExistsZ(WordDelims, S[Position])) do
3755 Dec(Position);
3756 if (Position = 0) then begin
3757 if (CharExistsZ(WordDelims, S[Position])) then begin
3758 Position := 1;
3759 end else begin
3760 Position := 0;
3761 end;
3762 end else begin
3763 Inc(Position);
3764 end;
3765 end;
3766
3767 {----------------------------------------------------------------------------}
3768
3769 function LastStringZ(S, AString : PAnsiChar;
3770 var Position : Cardinal) : Boolean;
3771 var
3772 TmpStr : PAnsiChar;
3773 I, C : Cardinal;
3774 begin
3775 if (S[0] = #0) or (StrPos(S, AString) = nil) then begin
3776 Result := False;
3777 Position := 0;
3778 Exit;
3779 end;
3780
3781 GetMem(TmpStr, StrLen(S)+1);
3782 try
3783 StrCopy(TmpStr, S);
3784 C := 0;
3785 while (StrStPosZ(TmpStr, AString, I)) do begin
3786 Inc(C, I + StrLen(AString));
3787 StrStDeleteZ(TmpStr, TmpStr, 0, I + StrLen(AString));
3788 end;
3789
3790 {Go back the length of AString since the while loop deletes the last instance}
3791 Dec(C, StrLen(AString));
3792 Position := C;
3793 Result := True;
3794 finally
3795 FreeMem(TmpStr, StrLen(S)+1);
3796 end;
3797 end;
3798
3799
3800 {----------------------------------------------------------------------------}
3801
3802 function KeepCharsZ(Dest, S, Chars : PAnsiChar) : PAnsiChar;
3803
3804 begin
3805 Result := Dest;
3806 while (S^ <> #0) do begin
3807 if CharExistsZ(Chars, S^) then begin
3808 Dest^ := S^;
3809 inc(Dest);
3810 end;
3811 inc(S);
3812 end;
3813 Dest^ := #0;
3814 end;
3815
3816 {----------------------------------------------------------------------------}
3817
3818 function RepeatStringZ(Dest, RepeatString : PAnsiChar;
3819 var Repetitions : Cardinal;
3820 MaxLen : Cardinal) : PAnsiChar;
3821
3822 var
3823 i : Cardinal;
3824 Len : Cardinal;
3825 ActualReps : Cardinal;
3826 begin
3827 Result := Dest;
3828 Result^ := #0;
3829 Len := StrLen(RepeatString);
3830 if (MaxLen <> 0) and
3831 (Repetitions <> 0) and
3832 (Len <> 0) then begin
3833 ActualReps := MaxLen div Len;
3834 if (ActualReps > Repetitions) then
3835 ActualReps := Repetitions
3836 else
3837 Repetitions := ActualReps;
3838 if (ActualReps > 0) then begin
3839 for i := 0 to pred(ActualReps) do begin
3840 Move(RepeatString[0], Dest[0], Len);
3841 inc(Dest, Len);
3842 end;
3843 Dest^ := #0;
3844 end;
3845 end;
3846 end;
3847
3848 {----------------------------------------------------------------------------}
3849
3850 function TrimCharsZ(Dest, S, Chars : PAnsiChar) : PAnsiChar;
3851
3852 begin
3853 Result := LeftTrimCharsZ(Dest, RightTrimCharsZ(Dest, S, Chars), Chars);
3854 end;
3855
3856 {----------------------------------------------------------------------------}
3857
3858 function RightTrimCharsZ(Dest, S, Chars : PAnsiChar) : PAnsiChar;
3859
3860 var
3861 EndS : PAnsiChar;
3862 begin
3863 Result := Dest;
3864 EndS := StrEnd(S);
3865 while (EndS <> S) do begin
3866 dec(EndS);
3867 if not CharExistsZ(Chars, EndS^) then begin
3868 if (Dest <> S) then
3869 StrLCopy(Dest, S, succ(EndS - S))
3870 else begin
3871 inc(EndS);
3872 EndS^ := #0;
3873 end;
3874 Exit;
3875 end;
3876 end;
3877 Result^ := #0;
3878 end;
3879
3880 {----------------------------------------------------------------------------}
3881
3882 function LeftTrimCharsZ(Dest, S, Chars : PAnsiChar) : PAnsiChar;
3883
3884 begin
3885 Result := Dest;
3886 while (S^ <> #0) and CharExistsZ(Chars, S^) do
3887 inc(S);
3888 if (S^ <> #0) then
3889 StrCopy(Result, S)
3890 else
3891 Result^ := #0;
3892 end;
3893
3894 {----------------------------------------------------------------------------}
3895
3896 function ExtractTokensZ(S, Delims : PAnsiChar;
3897 QuoteChar : AnsiChar;
3898 AllowNulls : Boolean;
3899 Tokens : TStrings) : Cardinal;
3900
3901 var
3902 State : (ScanStart,
3903 ScanQuotedToken,
3904 ScanQuotedTokenEnd,
3905 ScanNormalToken,
3906 ScanNormalTokenWithQuote);
3907 CurChar : PAnsiChar;
3908 TokenStart : PAnsiChar;
3909 TempStr : PAnsiChar;
3910 SLen : integer;
3911 begin
3912 {Notes: this routine implements the following state machine
3913 start ----> ScanStart
3914 ScanStart-----quote----->ScanQuotedToken (4)
3915 ScanStart-----delim----->ScanStart (1)
3916 ScanStart-----other----->ScanNormalToken
3917 ScanQuotedToken-----quote----->ScanQuotedTokenEnd
3918 ScanQuotedToken-----other----->ScanQuotedToken
3919 ScanQuotedTokenEnd-----quote----->ScanNormalTokenWithQuote
3920 ScanQuotedTokenEnd-----delim----->ScanStart (2)
3921 ScanQuotedTokenEnd-----other----->ScanNormalToken
3922 ScanNormalToken-----quote----->ScanNormalTokenWithQuote (4)
3923 ScanNormalToken-----delim----->ScanStart (3)
3924 ScanNormalToken-----other----->ScanNormalToken
3925 ScanNormalTokenWithQuote-----quote----->ScanNormalTokenWithQuote
3926 ScanNormalTokenWithQuote-----other----->ScanNormalToken
3927
3928 (1) output a null token if allowed
3929 (2) output a token, stripping quotes (if the dequoted token is
3930 empty, output a null token if allowed)
3931 (3) output a token; no quote stripping
3932 (4) if the quote character is #0, it's taken to mean that the
3933 routine should not check for quoted substrings. These marked
3934 transitions are the only places this is checked.}
3935
3936 {clear the tokens string list, set the return value to zero}
3937 Tokens.Clear;
3938 Result := 0;
3939
3940 {if the input string is empty or the delimiter list is empty or
3941 the quote character is found in the delimiter list, return zero
3942 tokens found}
3943 if (S[0] = #0) or
3944 (Delims[0] = #0) or
3945 CharExistsZ(Delims, QuoteChar) then
3946 Exit;
3947
3948 {allocate ourselves some scratch space for temporary tokens}
3949 SLen := StrLen(S);
3950 GetMem(TempStr, SLen+1);
3951 try
3952
3953 {start off in the normal scanning state}
3954 State := ScanStart;
3955
3956 {the first token starts at the beginning of the string}
3957 TokenStart := S;
3958
3959 {read through the entire string}
3960 CurChar := S;
3961 while (CurChar^ <> #0) do begin
3962
3963 {process the character according to the current state}
3964 case State of
3965 ScanStart :
3966 begin
3967 {if the current char is the quote character, switch
3968 states}
3969 if (QuoteChar <> #0) and (CurChar^ = QuoteChar) then
3970 State := ScanQuotedToken
3971
3972 {if the current char is a delimiter, output a null token}
3973 else if CharExistsZ(Delims, CurChar^) then begin
3974
3975 {if allowed to, output a null token}
3976 if AllowNulls then begin
3977 Tokens.Add('');
3978 inc(Result);
3979 end;
3980
3981 {set the start of the next token to be one character
3982 after this delimiter}
3983 TokenStart := CurChar + 1;
3984 end
3985
3986 {otherwise, the current char is starting a normal token,
3987 so switch states}
3988 else
3989 State := ScanNormalToken
3990 end;
3991
3992 ScanQuotedToken :
3993 begin
3994 {if the current char is the quote character, switch
3995 states}
3996 if (CurChar^ = QuoteChar) then
3997 State := ScanQuotedTokenEnd
3998 end;
3999
4000 ScanQuotedTokenEnd :
4001 begin
4002 {if the current char is the quote character, we have a
4003 token consisting of two (or more) quoted substrings, so
4004 switch states}
4005 if (CurChar^ = QuoteChar) then
4006 State := ScanNormalTokenWithQuote
4007
4008 {if the current char is a delimiter, output the token
4009 without the quotes}
4010 else if CharExistsZ(Delims, CurChar^) then begin
4011
4012 {if the token is empty without the quotes, output a null
4013 token only if allowed to}
4014 if ((CurChar - TokenStart) = 2) then begin
4015 if AllowNulls then begin
4016 Tokens.Add('');
4017 inc(Result);
4018 end
4019 end
4020
4021 {else output the token without the quotes}
4022 else begin
4023 inc(TokenStart);
4024 StrLCopy(TempStr, TokenStart, CurChar - TokenStart - 1);
4025 Tokens.Add(StrPas(TempStr));
4026 inc(Result);
4027 end;
4028
4029 {set the start of the next token to be one character
4030 after this delimiter}
4031 TokenStart := CurChar + 1;
4032
4033 {switch states back to the start state}
4034 State := ScanStart;
4035 end
4036
4037 {otherwise it's a (complex) normal token, so switch
4038 states}
4039 else
4040 State := ScanNormalToken
4041 end;
4042
4043 ScanNormalToken :
4044 begin
4045 {if the current char is the quote character, we have a
4046 complex token with at least one quoted substring, so
4047 switch states}
4048 if (QuoteChar <> #0) and (CurChar^ = QuoteChar) then
4049 State := ScanNormalTokenWithQuote
4050
4051 {if the current char is a delimiter, output the token}
4052 else if CharExistsZ(Delims, CurChar^) then begin
4053 StrLCopy(TempStr, TokenStart, CurChar - TokenStart);
4054 Tokens.Add(StrPas(TempStr));
4055 inc(Result);
4056
4057 {set the start of the next token to be one character
4058 after this delimiter}
4059 TokenStart := CurChar + 1;
4060
4061 {switch states back to the start state}
4062 State := ScanStart;
4063 end;
4064 end;
4065
4066 ScanNormalTokenWithQuote :
4067 begin
4068 {if the current char is the quote character, switch states
4069 back to scanning a normal token}
4070 if (CurChar^ = QuoteChar) then
4071 State := ScanNormalToken;
4072 end;
4073
4074 end;
4075
4076 inc(CurChar);
4077 end;
4078
4079 {we need to process the (possible) final token}
4080
4081 {if we are in the scanning quoted token state, we've read an
4082 opening quote, but no closing one; increment the token start
4083 value}
4084 if (State = ScanQuotedToken) then
4085 inc(TokenStart)
4086
4087 {if we've finished scanning a quoted token, we've read both
4088 quotes; increment the token start value, and decrement the
4089 current index}
4090 else if (State = ScanQuotedTokenEnd) then begin
4091 inc(TokenStart);
4092 dec(CurChar);
4093 end;
4094
4095 {if the final token is not empty, output the token}
4096 if (TokenStart < CurChar) then begin
4097 StrLCopy(TempStr, TokenStart, CurChar - TokenStart);
4098 Tokens.Add(StrPas(TempStr));
4099 inc(Result);
4100 end
4101 {otherwise the final token is empty, so output a null token if
4102 allowed to}
4103 else if AllowNulls then begin
4104 Tokens.Add('');
4105 inc(Result);
4106 end;
4107
4108 finally
4109 FreeMem(TempStr, SLen+1);
4110 end;
4111 end;
4112
4113 {----------------------------------------------------------------------------}
4114
4115 function ContainsOnlyZ(const S, Chars : PAnsiChar;
4116 var BadPos : Cardinal) : Boolean;
4117 var
4118 Walker : PAnsiChar;
4119 begin
4120 {if the input string is empty, exit}
4121 if (S^ = #0) then begin
4122 Result := false;
4123 BadPos := 0;
4124 Exit;
4125 end;
4126 {otherwise walk through the string until we reach the end or we find
4127 the first char not in our list}
4128 Walker := S;
4129 while (Walker^ <> #0) do begin
4130 if not CharExistsZ(Chars, Walker^) then begin
4131 BadPos := Walker - S;
4132 Result := false;
4133 Exit;
4134 end;
4135 inc(Walker);
4136 end;
4137 {if we reach here, all chars are in the list}
4138 Result := true;
4139 BadPos := 0;
4140 end;
4141
4142 {----------------------------------------------------------------------------}
4143
4144 function ContainsOtherThanZ(const S, Chars : PAnsiChar;
4145 var BadPos : Cardinal) : Boolean;
4146 var
4147 Walker : PAnsiChar;
4148 begin
4149 {if the input string is empty, exit}
4150 if (S^ = #0) then begin
4151 Result := false;
4152 BadPos := 0;
4153 Exit;
4154 end;
4155 {otherwise walk through the string until we reach the end or we find
4156 the first char not in our list}
4157 Walker := S;
4158 while (Walker^ <> #0) do begin
4159 if not CharExistsZ(Chars, Walker^) then begin
4160 BadPos := Walker - S;
4161 Result := true;
4162 Exit;
4163 end;
4164 inc(Walker);
4165 end;
4166 {if we reach here, all chars are in the list}
4167 Result := false;
4168 BadPos := 0;
4169 end;
4170
4171 {----------------------------------------------------------------------------}
4172
4173 function IsChAlphaZ(C : Char) : Boolean;
4174 {-Returns true if Ch is an alpha}
4175 begin
4176 Result := Windows.IsCharAlpha(C);
4177 end;
4178
4179 {----------------------------------------------------------------------------}
4180
4181 function IsChNumericZ(C : AnsiChar; Numbers : PAnsiChar) : Boolean;
4182 {-Returns true if Ch in numeric set}
4183 begin
4184 Result := CharExistsZ(Numbers, C);
4185 end;
4186
4187 {----------------------------------------------------------------------------}
4188
4189 function IsChAlphaNumericZ(C : Char; Numbers : PChar) : Boolean;
4190 {-Returns true if Ch is an alpha or numeric}
4191 begin
4192 Result := Windows.IsCharAlpha(C) or CharExistsZ(Numbers, C);
4193 end;
4194
4195 {----------------------------------------------------------------------------}
4196
4197 function IsStrAlphaZ(S : PChar) : Boolean;
4198 {-Returns true if all characters in string are an alpha}
4199 begin
4200 Result := false;
4201 if (S^ <> #0) then begin
4202 while (S^ <> #0) do begin
4203 if not Windows.IsCharAlpha(S^) then
4204 Exit;
4205 inc(S);
4206 end;
4207 Result := true;
4208 end;
4209 end;
4210
4211 {----------------------------------------------------------------------------}
4212
4213 function IsStrNumericZ(S, Numbers : PAnsiChar) : Boolean;
4214 {-Returns true if all characters in string are in numeric set}
4215 begin
4216 Result := false;
4217 if (S^ <> #0) then begin
4218 while (S^ <> #0) do begin
4219 if not CharExistsZ(Numbers, S^) then
4220 Exit;
4221 inc(S);
4222 end;
4223 Result := true;
4224 end;
4225 end;
4226
4227 {----------------------------------------------------------------------------}
4228
4229 function IsStrAlphaNumericZ(S, Numbers : PChar) : Boolean;
4230 {-Returns true if all characters in string are alpha or numeric}
4231 begin
4232 Result := false;
4233 if (S^ <> #0) then begin
4234 while (S^ <> #0) do begin
4235 if (not Windows.IsCharAlpha(S^)) and
4236 (not CharExistsZ(Numbers, S^)) then
4237 Exit;
4238 inc(S);
4239 end;
4240 Result := true;
4241 end;
4242 end;
4243
4244
4245 function StrWithinZ(S, SearchStr : PAnsiChar;
4246 Start : Cardinal;
4247 var Position : Cardinal) : Boolean;
4248 var
4249 TmpStr : PAnsiChar;
4250 begin
4251 GetMem(TmpStr, StrLen(S) + 1);
4252 try
4253 StrCopy(TmpStr, S);
4254 if (Start > 0) then
4255 StrStDeleteZ(TmpStr, TmpStr, 0, Start);
4256 Result := StrStPosZ(TmpStr, SearchStr, Position);
4257 if (Result) then
4258 Position := Position + Start;
4259 finally
4260 FreeMem(TmpStr, StrLen(S) + 1);
4261 end;
4262 end;
4263
4264
4265 end.

  ViewVC Help
Powered by ViewVC 1.1.20