2
0

strutils.pp 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617
  1. {
  2. Delphi/Kylix compatibility unit: String handling routines.
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2005 by the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$mode objfpc}
  12. {$h+}
  13. {$inline on}
  14. unit strutils;
  15. interface
  16. uses
  17. SysUtils{, Types};
  18. { ---------------------------------------------------------------------
  19. Case insensitive search/replace
  20. ---------------------------------------------------------------------}
  21. Function AnsiResemblesText(const AText, AOther: string): Boolean;
  22. Function AnsiContainsText(const AText, ASubText: string): Boolean;inline;
  23. Function AnsiStartsText(const ASubText, AText: string): Boolean;inline;
  24. Function AnsiEndsText(const ASubText, AText: string): Boolean;inline;
  25. Function AnsiReplaceText(const AText, AFromText, AToText: string): string;inline;
  26. Function AnsiMatchText(const AText: string; const AValues: array of string): Boolean;inline;
  27. Function AnsiIndexText(const AText: string; const AValues: array of string): Integer;
  28. { ---------------------------------------------------------------------
  29. Case sensitive search/replace
  30. ---------------------------------------------------------------------}
  31. Function AnsiContainsStr(const AText, ASubText: string): Boolean;inline;
  32. Function AnsiStartsStr(const ASubText, AText: string): Boolean;inline;
  33. Function AnsiEndsStr(const ASubText, AText: string): Boolean;inline;
  34. Function AnsiReplaceStr(const AText, AFromText, AToText: string): string;inline;
  35. Function AnsiMatchStr(const AText: string; const AValues: array of string): Boolean;inline;
  36. Function AnsiIndexStr(const AText: string; const AValues: array of string): Integer;
  37. { ---------------------------------------------------------------------
  38. Playthingies
  39. ---------------------------------------------------------------------}
  40. Function DupeString(const AText: string; ACount: Integer): string;
  41. Function ReverseString(const AText: string): string;
  42. Function AnsiReverseString(const AText: AnsiString): AnsiString;inline;
  43. Function StuffString(const AText: string; AStart, ALength: Cardinal; const ASubText: string): string;
  44. Function RandomFrom(const AValues: array of string): string; overload;
  45. Function IfThen(AValue: Boolean; const ATrue: string; AFalse: string): string;inline;
  46. Function IfThen(AValue: Boolean; const ATrue: string): string;inline; // ; AFalse: string = ''
  47. { ---------------------------------------------------------------------
  48. VB emulations.
  49. ---------------------------------------------------------------------}
  50. Function LeftStr(const AText: AnsiString; const ACount: Integer): AnsiString;inline;
  51. Function RightStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  52. Function MidStr(const AText: AnsiString; const AStart, ACount: Integer): AnsiString;inline;
  53. Function RightBStr(const AText: AnsiString; const AByteCount: Integer): AnsiString;inline;
  54. Function MidBStr(const AText: AnsiString; const AByteStart, AByteCount: Integer): AnsiString;inline;
  55. Function AnsiLeftStr(const AText: AnsiString; const ACount: Integer): AnsiString;inline;
  56. Function AnsiRightStr(const AText: AnsiString; const ACount: Integer): AnsiString;inline;
  57. Function AnsiMidStr(const AText: AnsiString; const AStart, ACount: Integer): AnsiString;inline;
  58. Function LeftBStr(const AText: AnsiString; const AByteCount: Integer): AnsiString;inline;
  59. Function LeftStr(const AText: WideString; const ACount: Integer): WideString;inline;
  60. Function RightStr(const AText: WideString; const ACount: Integer): WideString;
  61. Function MidStr(const AText: WideString; const AStart, ACount: Integer): WideString;inline;
  62. { ---------------------------------------------------------------------
  63. Extended search and replace
  64. ---------------------------------------------------------------------}
  65. const
  66. { Default word delimiters are any character except the core alphanumerics. }
  67. WordDelimiters: set of Char = [#0..#255] - ['a'..'z','A'..'Z','1'..'9','0'];
  68. type
  69. TStringSearchOption = (soDown, soMatchCase, soWholeWord);
  70. TStringSearchOptions = set of TStringSearchOption;
  71. TStringSeachOption = TStringSearchOption;
  72. Function SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String; Options: TStringSearchOptions): PChar;
  73. Function SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String): PChar;inline; // ; Options: TStringSearchOptions = [soDown]
  74. Function PosEx(const SubStr, S: string; Offset: Cardinal): Integer;
  75. Function PosEx(const SubStr, S: string): Integer;inline; // Offset: Cardinal = 1
  76. Function PosEx(c:char; const S: string; Offset: Cardinal): Integer;
  77. { ---------------------------------------------------------------------
  78. Soundex Functions.
  79. ---------------------------------------------------------------------}
  80. type
  81. TSoundexLength = 1..MaxInt;
  82. Function Soundex(const AText: string; ALength: TSoundexLength): string;
  83. Function Soundex(const AText: string): string;inline; // ; ALength: TSoundexLength = 4
  84. type
  85. TSoundexIntLength = 1..8;
  86. Function SoundexInt(const AText: string; ALength: TSoundexIntLength): Integer;
  87. Function SoundexInt(const AText: string): Integer;inline; //; ALength: TSoundexIntLength = 4
  88. Function DecodeSoundexInt(AValue: Integer): string;
  89. Function SoundexWord(const AText: string): Word;
  90. Function DecodeSoundexWord(AValue: Word): string;
  91. Function SoundexSimilar(const AText, AOther: string; ALength: TSoundexLength): Boolean;inline;
  92. Function SoundexSimilar(const AText, AOther: string): Boolean;inline; //; ALength: TSoundexLength = 4
  93. Function SoundexCompare(const AText, AOther: string; ALength: TSoundexLength): Integer;inline;
  94. Function SoundexCompare(const AText, AOther: string): Integer;inline; //; ALength: TSoundexLength = 4
  95. Function SoundexProc(const AText, AOther: string): Boolean;
  96. type
  97. TCompareTextProc = Function(const AText, AOther: string): Boolean;
  98. Const
  99. AnsiResemblesProc: TCompareTextProc = @SoundexProc;
  100. { ---------------------------------------------------------------------
  101. Other functions, based on RxStrUtils.
  102. ---------------------------------------------------------------------}
  103. function IsEmptyStr(const S: string; const EmptyChars: TSysCharSet): Boolean;
  104. function DelSpace(const S: string): string;
  105. function DelChars(const S: string; Chr: Char): string;
  106. function DelSpace1(const S: string): string;
  107. function Tab2Space(const S: string; Numb: Byte): string;
  108. function NPos(const C: string; S: string; N: Integer): Integer;
  109. Function RPosEX(C:char;const S : AnsiString;offs:cardinal):Integer; overload;
  110. Function RPosex (Const Substr : AnsiString; Const Source : AnsiString;offs:cardinal) : Integer; overload;
  111. Function RPos(c:char;const S : AnsiString):Integer; overload;
  112. Function RPos (Const Substr : AnsiString; Const Source : AnsiString) : Integer; overload;
  113. function AddChar(C: Char; const S: string; N: Integer): string;
  114. function AddCharR(C: Char; const S: string; N: Integer): string;
  115. function PadLeft(const S: string; N: Integer): string;inline;
  116. function PadRight(const S: string; N: Integer): string;inline;
  117. function PadCenter(const S: string; Len: Integer): string;
  118. function Copy2Symb(const S: string; Symb: Char): string;
  119. function Copy2SymbDel(var S: string; Symb: Char): string;
  120. function Copy2Space(const S: string): string;inline;
  121. function Copy2SpaceDel(var S: string): string;inline;
  122. function AnsiProperCase(const S: string; const WordDelims: TSysCharSet): string;
  123. function WordCount(const S: string; const WordDelims: TSysCharSet): Integer;
  124. function WordPosition(const N: Integer; const S: string; const WordDelims: TSysCharSet): Integer;
  125. function ExtractWord(N: Integer; const S: string; const WordDelims: TSysCharSet): string;inline;
  126. function ExtractWordPos(N: Integer; const S: string; const WordDelims: TSysCharSet; var Pos: Integer): string;
  127. function ExtractDelimited(N: Integer; const S: string; const Delims: TSysCharSet): string;
  128. function ExtractSubstr(const S: string; var Pos: Integer; const Delims: TSysCharSet): string;
  129. function IsWordPresent(const W, S: string; const WordDelims: TSysCharSet): Boolean;
  130. function FindPart(const HelpWilds, InputStr: string): Integer;
  131. function IsWild(InputStr, Wilds: string; IgnoreCase: Boolean): Boolean;
  132. function XorString(const Key, Src: ShortString): ShortString;
  133. function XorEncode(const Key, Source: string): string;
  134. function XorDecode(const Key, Source: string): string;
  135. function GetCmdLineArg(const Switch: string; SwitchChars: TSysCharSet): string;
  136. function Numb2USA(const S: string): string;
  137. function Hex2Dec(const S: string): Longint;
  138. function Dec2Numb(N: Longint; Len, Base: Byte): string;
  139. function Numb2Dec(S: string; Base: Byte): Longint;
  140. function IntToBin(Value: Longint; Digits, Spaces: Integer): string;
  141. function IntToRoman(Value: Longint): string;
  142. function RomanToInt(const S: string): Longint;
  143. procedure BinToHex(BinValue, HexValue: PChar; BinBufSize: Integer);
  144. function HexToBin(HexValue, BinValue: PChar; BinBufSize: Integer): Integer;
  145. const
  146. DigitChars = ['0'..'9'];
  147. Brackets = ['(',')','[',']','{','}'];
  148. StdWordDelims = [#0..' ',',','.',';','/','\',':','''','"','`'] + Brackets;
  149. StdSwitchChars = ['-','/'];
  150. implementation
  151. { ---------------------------------------------------------------------
  152. Auxiliary functions
  153. ---------------------------------------------------------------------}
  154. Procedure NotYetImplemented (FN : String);
  155. begin
  156. Raise Exception.CreateFmt('Function "%s" (strutils) is not yet implemented',[FN]);
  157. end;
  158. { ---------------------------------------------------------------------
  159. Case insensitive search/replace
  160. ---------------------------------------------------------------------}
  161. Function AnsiResemblesText(const AText, AOther: string): Boolean;
  162. begin
  163. if Assigned(AnsiResemblesProc) then
  164. Result:=AnsiResemblesProc(AText,AOther)
  165. else
  166. Result:=False;
  167. end;
  168. Function AnsiContainsText(const AText, ASubText: string): Boolean;inline;
  169. begin
  170. AnsiContainsText:=AnsiPos(ASubText,AText)<>0;
  171. end;
  172. Function AnsiStartsText(const ASubText, AText: string): Boolean;inline;
  173. begin
  174. Result:=AnsiCompareText(Copy(AText,1,Length(AsubText)),ASubText)=0;
  175. end;
  176. Function AnsiEndsText(const ASubText, AText: string): Boolean;inline;
  177. begin
  178. result:=AnsiCompareText(Copy(AText,Length(AText)-Length(ASubText)+1,Length(ASubText)),asubtext)=0;
  179. end;
  180. Function AnsiReplaceText(const AText, AFromText, AToText: string): string;inline;
  181. begin
  182. Result := StringReplace(AText,AFromText,AToText,[rfReplaceAll,rfIgnoreCase]);
  183. end;
  184. Function AnsiMatchText(const AText: string; const AValues: array of string): Boolean;inline;
  185. begin
  186. Result:=(AnsiIndexText(AText,AValues)<>-1)
  187. end;
  188. Function AnsiIndexText(const AText: string; const AValues: array of string): Integer;
  189. var i : longint;
  190. begin
  191. result:=-1;
  192. if high(AValues)=-1 Then
  193. Exit;
  194. for i:=low(AValues) to High(Avalues) do
  195. if CompareText(avalues[i],atext)=0 Then
  196. exit(i); // make sure it is the first val.
  197. end;
  198. { ---------------------------------------------------------------------
  199. Case sensitive search/replace
  200. ---------------------------------------------------------------------}
  201. Function AnsiContainsStr(const AText, ASubText: string): Boolean;inline;
  202. begin
  203. Result := AnsiPos(ASubText,AText)<>0;
  204. end;
  205. Function AnsiStartsStr(const ASubText, AText: string): Boolean;inline;
  206. begin
  207. Result := AnsiPos(ASubText,AText)=1;
  208. end;
  209. Function AnsiEndsStr(const ASubText, AText: string): Boolean;inline;
  210. begin
  211. Result := AnsiPos(ASubText,AText)=(length(AText)-length(ASubText)+1);
  212. end;
  213. Function AnsiReplaceStr(const AText, AFromText, AToText: string): string;inline;
  214. begin
  215. Result := StringReplace(AText,AFromText,AToText,[rfReplaceAll]);
  216. end;
  217. Function AnsiMatchStr(const AText: string; const AValues: array of string): Boolean;inline;
  218. begin
  219. Result:=AnsiIndexStr(AText,Avalues)<>-1;
  220. end;
  221. Function AnsiIndexStr(const AText: string; const AValues: array of string): Integer;
  222. var
  223. i : longint;
  224. begin
  225. result:=-1;
  226. if high(AValues)=-1 Then
  227. Exit;
  228. for i:=low(AValues) to High(Avalues) do
  229. if (avalues[i]=AText) Then
  230. exit(i); // make sure it is the first val.
  231. end;
  232. { ---------------------------------------------------------------------
  233. Playthingies
  234. ---------------------------------------------------------------------}
  235. Function DupeString(const AText: string; ACount: Integer): string;
  236. var i,l : integer;
  237. begin
  238. result:='';
  239. if aCount>=0 then
  240. begin
  241. l:=length(atext);
  242. SetLength(result,aCount*l);
  243. for i:=0 to ACount-1 do
  244. move(atext[1],Result[l*i+1],l);
  245. end;
  246. end;
  247. Function ReverseString(const AText: string): string;
  248. var
  249. i,j:longint;
  250. begin
  251. setlength(result,length(atext));
  252. i:=1; j:=length(atext);
  253. while (i<=j) do
  254. begin
  255. result[i]:=atext[j-i+1];
  256. inc(i);
  257. end;
  258. end;
  259. Function AnsiReverseString(const AText: AnsiString): AnsiString;inline;
  260. begin
  261. Result:=ReverseString(AText);
  262. end;
  263. Function StuffString(const AText: string; AStart, ALength: Cardinal; const ASubText: string): string;
  264. var i,j : SizeUInt;
  265. begin
  266. j:=length(ASubText);
  267. i:=length(AText);
  268. SetLength(Result,i+j-ALength);
  269. move (AText[1],result[1],AStart-1);
  270. move (ASubText[1],result[AStart],j);
  271. move (AText[AStart+ALength], Result[AStart+j],i+1-AStart-ALength);
  272. end;
  273. Function RandomFrom(const AValues: array of string): string; overload;
  274. begin
  275. if high(AValues)=-1 then exit('');
  276. result:=Avalues[random(High(AValues)+1)];
  277. end;
  278. Function IfThen(AValue: Boolean; const ATrue: string; AFalse: string): string;inline;
  279. begin
  280. if avalue then
  281. result:=atrue
  282. else
  283. result:=afalse;
  284. end;
  285. Function IfThen(AValue: Boolean; const ATrue: string): string;inline; // ; AFalse: string = ''
  286. begin
  287. if avalue then
  288. result:=atrue
  289. else
  290. result:='';
  291. end;
  292. { ---------------------------------------------------------------------
  293. VB emulations.
  294. ---------------------------------------------------------------------}
  295. Function LeftStr(const AText: AnsiString; const ACount: Integer): AnsiString;inline;
  296. begin
  297. Result:=Copy(AText,1,ACount);
  298. end;
  299. Function RightStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  300. var j,l:integer;
  301. begin
  302. l:=length(atext);
  303. j:=ACount;
  304. if j>l then j:=l;
  305. Result:=Copy(AText,l-j+1,j);
  306. end;
  307. Function MidStr(const AText: AnsiString; const AStart, ACount: Integer): AnsiString;inline;
  308. begin
  309. if (ACount=0) or (AStart>length(atext)) then
  310. exit('');
  311. Result:=Copy(AText,AStart,ACount);
  312. end;
  313. Function LeftBStr(const AText: AnsiString; const AByteCount: Integer): AnsiString;inline;
  314. begin
  315. Result:=LeftStr(AText,AByteCount);
  316. end;
  317. Function RightBStr(const AText: AnsiString; const AByteCount: Integer): AnsiString;inline;
  318. begin
  319. Result:=RightStr(Atext,AByteCount);
  320. end;
  321. Function MidBStr(const AText: AnsiString; const AByteStart, AByteCount: Integer): AnsiString;inline;
  322. begin
  323. Result:=MidStr(AText,AByteStart,AByteCount);
  324. end;
  325. Function AnsiLeftStr(const AText: AnsiString; const ACount: Integer): AnsiString;inline;
  326. begin
  327. Result := copy(AText,1,ACount);
  328. end;
  329. Function AnsiRightStr(const AText: AnsiString; const ACount: Integer): AnsiString;inline;
  330. begin
  331. Result := copy(AText,length(AText)-ACount+1,ACount);
  332. end;
  333. Function AnsiMidStr(const AText: AnsiString; const AStart, ACount: Integer): AnsiString;inline;
  334. begin
  335. Result:=Copy(AText,AStart,ACount);
  336. end;
  337. Function LeftStr(const AText: WideString; const ACount: Integer): WideString;inline;
  338. begin
  339. Result:=Copy(AText,1,ACount);
  340. end;
  341. Function RightStr(const AText: WideString; const ACount: Integer): WideString;
  342. var
  343. j,l:integer;
  344. begin
  345. l:=length(atext);
  346. j:=ACount;
  347. if j>l then j:=l;
  348. Result:=Copy(AText,l-j+1,j);
  349. end;
  350. Function MidStr(const AText: WideString; const AStart, ACount: Integer): WideString;inline;
  351. begin
  352. Result:=Copy(AText,AStart,ACount);
  353. end;
  354. { ---------------------------------------------------------------------
  355. Extended search and replace
  356. ---------------------------------------------------------------------}
  357. Function SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String; Options: TStringSearchOptions): PChar;
  358. var
  359. Len,I,SLen: Integer;
  360. C: Char;
  361. Found : Boolean;
  362. Direction: Shortint;
  363. CharMap: array[Char] of Char;
  364. Function GotoNextWord(var P : PChar): Boolean;
  365. begin
  366. if (Direction=1) then
  367. begin
  368. // Skip characters
  369. While (Len>0) and not (P^ in WordDelimiters) do
  370. begin
  371. Inc(P);
  372. Dec(Len);
  373. end;
  374. // skip delimiters
  375. While (Len>0) and (P^ in WordDelimiters) do
  376. begin
  377. Inc(P);
  378. Dec(Len);
  379. end;
  380. Result:=Len>0;
  381. end
  382. else
  383. begin
  384. // Skip Delimiters
  385. While (Len>0) and (P^ in WordDelimiters) do
  386. begin
  387. Dec(P);
  388. Dec(Len);
  389. end;
  390. // skip characters
  391. While (Len>0) and not (P^ in WordDelimiters) do
  392. begin
  393. Dec(P);
  394. Dec(Len);
  395. end;
  396. Result:=Len>0;
  397. // We're on the first delimiter. Pos back on char.
  398. Inc(P);
  399. Inc(Len);
  400. end;
  401. end;
  402. begin
  403. Result:=nil;
  404. Slen:=Length(SearchString);
  405. if (BufLen<=0) or (Slen=0) then
  406. Exit;
  407. if soDown in Options then
  408. begin
  409. Direction:=1;
  410. Inc(SelStart,SelLength);
  411. Len:=BufLen-SelStart-SLen+1;
  412. if (Len<=0) then
  413. Exit;
  414. end
  415. else
  416. begin
  417. Direction:=-1;
  418. Dec(SelStart,Length(SearchString));
  419. Len:=SelStart+1;
  420. end;
  421. if (SelStart<0) or (SelStart>BufLen) then
  422. Exit;
  423. Result:=@Buf[SelStart];
  424. for C:=Low(Char) to High(Char) do
  425. if (soMatchCase in Options) then
  426. CharMap[C]:=C
  427. else
  428. CharMap[C]:=Upcase(C);
  429. if Not (soMatchCase in Options) then
  430. SearchString:=UpCase(SearchString);
  431. Found:=False;
  432. while (Result<>Nil) and (Not Found) do
  433. begin
  434. if ((soWholeWord in Options) and
  435. (Result<>@Buf[SelStart]) and
  436. not GotoNextWord(Result)) then
  437. Result:=Nil
  438. else
  439. begin
  440. // try to match whole searchstring
  441. I:=0;
  442. while (I<Slen) and (CharMap[Result[I]]=SearchString[I+1]) do
  443. Inc(I);
  444. // Whole searchstring matched ?
  445. if (I=SLen) then
  446. Found:=(Len=0) or
  447. (not (soWholeWord in Options)) or
  448. (Result[SLen] in WordDelimiters);
  449. if not Found then
  450. begin
  451. Inc(Result,Direction);
  452. Dec(Len);
  453. If (Len=0) then
  454. Result:=Nil;
  455. end;
  456. end;
  457. end;
  458. end;
  459. Function SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String): PChar;inline; // ; Options: TStringSearchOptions = [soDown]
  460. begin
  461. Result:=SearchBuf(Buf,BufLen,SelStart,SelLength,SearchString,[soDown]);
  462. end;
  463. Function PosEx(const SubStr, S: string; Offset: Cardinal): Integer;
  464. var i : pchar;
  465. begin
  466. if (offset<1) or (offset>SizeUInt(length(s))) then exit(0);
  467. i:=strpos(@s[offset],@substr[1]);
  468. if i=nil then
  469. PosEx:=0
  470. else
  471. PosEx:=succ(i-pchar(s));
  472. end;
  473. Function PosEx(const SubStr, S: string): Integer;inline; // Offset: Cardinal = 1
  474. begin
  475. posex:=posex(substr,s,1);
  476. end;
  477. Function PosEx(c:char; const S: string; Offset: Cardinal): Integer;
  478. var l : longint;
  479. begin
  480. if (offset<1) or (offset>SizeUInt(length(s))) then exit(0);
  481. l:=length(s);
  482. {$ifndef useindexbyte}
  483. while (SizeInt(offset)<=l) and (s[offset]<>c) do inc(offset);
  484. if SizeInt(offset)>l then
  485. posex:=0
  486. else
  487. posex:=offset;
  488. {$else}
  489. posex:=offset+indexbyte(s[offset],l-offset+1);
  490. if posex=(offset-1) then
  491. posex:=0;
  492. {$endif}
  493. end;
  494. { ---------------------------------------------------------------------
  495. Soundex Functions.
  496. ---------------------------------------------------------------------}
  497. Const
  498. SScore : array[1..255] of Char =
  499. ('0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0', // 1..32
  500. '0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0', // 33..64
  501. '0','1','2','3','0','1','2','i','0','2','2','4','5','5','0','1','2','6','2','3','0','1','i','2','i','2', // 64..90
  502. '0','0','0','0','0','0', // 91..95
  503. '0','1','2','3','0','1','2','i','0','2','2','4','5','5','0','1','2','6','2','3','0','1','i','2','i','2', // 96..122
  504. '0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0', // 123..154
  505. '0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0', // 155..186
  506. '0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0', // 187..218
  507. '0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0', // 219..250
  508. '0','0','0','0','0'); // 251..255
  509. Function Soundex(const AText: string; ALength: TSoundexLength): string;
  510. Var
  511. S,PS : Char;
  512. I,L : integer;
  513. begin
  514. Result:='';
  515. PS:=#0;
  516. If Length(AText)>0 then
  517. begin
  518. Result:=Upcase(AText[1]);
  519. I:=2;
  520. L:=Length(AText);
  521. While (I<=L) and (Length(Result)<ALength) do
  522. begin
  523. S:=SScore[Ord(AText[i])];
  524. If Not (S in ['0','i',PS]) then
  525. Result:=Result+S;
  526. If (S<>'i') then
  527. PS:=S;
  528. Inc(I);
  529. end;
  530. end;
  531. L:=Length(Result);
  532. If (L<ALength) then
  533. Result:=Result+StringOfChar('0',Alength-L);
  534. end;
  535. Function Soundex(const AText: string): string;inline; // ; ALength: TSoundexLength = 4
  536. begin
  537. Result:=Soundex(AText,4);
  538. end;
  539. Const
  540. Ord0 = Ord('0');
  541. OrdA = Ord('A');
  542. Function SoundexInt(const AText: string; ALength: TSoundexIntLength): Integer;
  543. var
  544. SE: string;
  545. I: Integer;
  546. begin
  547. Result:=-1;
  548. SE:=Soundex(AText,ALength);
  549. If Length(SE)>0 then
  550. begin
  551. Result:=Ord(SE[1])-OrdA;
  552. if ALength > 1 then
  553. begin
  554. Result:=Result*26+(Ord(SE[2])-Ord0);
  555. for I:=3 to ALength do
  556. Result:=(Ord(SE[I])-Ord0)+Result*7;
  557. end;
  558. Result:=ALength+Result*9;
  559. end;
  560. end;
  561. Function SoundexInt(const AText: string): Integer;inline; //; ALength: TSoundexIntLength = 4
  562. begin
  563. Result:=SoundexInt(AText,4);
  564. end;
  565. Function DecodeSoundexInt(AValue: Integer): string;
  566. var
  567. I, Len: Integer;
  568. begin
  569. Result := '';
  570. Len := AValue mod 9;
  571. AValue := AValue div 9;
  572. for I:=Len downto 3 do
  573. begin
  574. Result:=Chr(Ord0+(AValue mod 7))+Result;
  575. AValue:=AValue div 7;
  576. end;
  577. if Len>2 then
  578. Result:=IntToStr(AValue mod 26)+Result;
  579. AValue:=AValue div 26;
  580. Result:=Chr(OrdA+AValue)+Result;
  581. end;
  582. Function SoundexWord(const AText: string): Word;
  583. Var
  584. S : String;
  585. begin
  586. S:=SoundEx(Atext,4);
  587. Result:=Ord(S[1])-OrdA;
  588. Result:=Result*26+StrToInt(S[2]);
  589. Result:=Result*7+StrToInt(S[3]);
  590. Result:=Result*7+StrToInt(S[4]);
  591. end;
  592. Function DecodeSoundexWord(AValue: Word): string;
  593. begin
  594. Result := Chr(Ord0+ (AValue mod 7));
  595. AValue := AValue div 7;
  596. Result := Chr(Ord0+ (AValue mod 7)) + Result;
  597. AValue := AValue div 7;
  598. Result := IntToStr(AValue mod 26) + Result;
  599. AValue := AValue div 26;
  600. Result := Chr(OrdA+AValue) + Result;
  601. end;
  602. Function SoundexSimilar(const AText, AOther: string; ALength: TSoundexLength): Boolean;inline;
  603. begin
  604. Result:=Soundex(AText,ALength)=Soundex(AOther,ALength);
  605. end;
  606. Function SoundexSimilar(const AText, AOther: string): Boolean;inline; //; ALength: TSoundexLength = 4
  607. begin
  608. Result:=SoundexSimilar(AText,AOther,4);
  609. end;
  610. Function SoundexCompare(const AText, AOther: string; ALength: TSoundexLength): Integer;inline;
  611. begin
  612. Result:=AnsiCompareStr(Soundex(AText,ALength),Soundex(AOther,ALength));
  613. end;
  614. Function SoundexCompare(const AText, AOther: string): Integer;inline; //; ALength: TSoundexLength = 4
  615. begin
  616. Result:=SoundexCompare(AText,AOther,4);
  617. end;
  618. Function SoundexProc(const AText, AOther: string): Boolean;
  619. begin
  620. Result:=SoundexSimilar(AText,AOther);
  621. end;
  622. { ---------------------------------------------------------------------
  623. RxStrUtils-like functions.
  624. ---------------------------------------------------------------------}
  625. function IsEmptyStr(const S: string; const EmptyChars: TSysCharSet): Boolean;
  626. var
  627. i,l: Integer;
  628. begin
  629. l:=Length(S);
  630. i:=1;
  631. Result:=True;
  632. while Result and (i<=l) do
  633. begin
  634. Result:=Not (S[i] in EmptyChars);
  635. Inc(i);
  636. end;
  637. end;
  638. function DelSpace(const S: String): string;
  639. begin
  640. Result:=DelChars(S,' ');
  641. end;
  642. function DelChars(const S: string; Chr: Char): string;
  643. var
  644. I,J: Integer;
  645. begin
  646. Result:=S;
  647. I:=Length(Result);
  648. While I>0 do
  649. begin
  650. if Result[I]=Chr then
  651. begin
  652. J:=I-1;
  653. While (J>0) and (Result[J]=Chr) do
  654. Dec(j);
  655. Delete(Result,J+1,I-J);
  656. I:=J+1;
  657. end;
  658. dec(I);
  659. end;
  660. end;
  661. function DelSpace1(const S: string): string;
  662. var
  663. i: Integer;
  664. begin
  665. Result:=S;
  666. for i:=Length(Result) downto 2 do
  667. if (Result[i]=' ') and (Result[I-1]=' ') then
  668. Delete(Result,I,1);
  669. end;
  670. function Tab2Space(const S: string; Numb: Byte): string;
  671. var
  672. I: Integer;
  673. begin
  674. I:=1;
  675. Result:=S;
  676. while I <= Length(Result) do
  677. if Result[I]<>Chr(9) then
  678. inc(I)
  679. else
  680. begin
  681. Result[I]:=' ';
  682. If (Numb>1) then
  683. Insert(StringOfChar('0',Numb-1),Result,I);
  684. Inc(I,Numb);
  685. end;
  686. end;
  687. function NPos(const C: string; S: string; N: Integer): Integer;
  688. var
  689. i,p,k: Integer;
  690. begin
  691. Result:=0;
  692. if N<1 then
  693. Exit;
  694. k:=0;
  695. i:=1;
  696. Repeat
  697. p:=pos(C,S);
  698. Inc(k,p);
  699. if p>0 then
  700. delete(S,1,p);
  701. Inc(i);
  702. Until (i>n) or (p=0);
  703. If (P>0) then
  704. Result:=K;
  705. end;
  706. function AddChar(C: Char; const S: string; N: Integer): string;
  707. Var
  708. l : Integer;
  709. begin
  710. Result:=S;
  711. l:=Length(Result);
  712. if l<N then
  713. Result:=StringOfChar(C,N-l)+Result;
  714. end;
  715. function AddCharR(C: Char; const S: string; N: Integer): string;
  716. Var
  717. l : Integer;
  718. begin
  719. Result:=S;
  720. l:=Length(Result);
  721. if l<N then
  722. Result:=Result+StringOfChar(C,N-l);
  723. end;
  724. function PadRight(const S: string; N: Integer): string;inline;
  725. begin
  726. Result:=AddCharR(' ',S,N);
  727. end;
  728. function PadLeft(const S: string; N: Integer): string;inline;
  729. begin
  730. Result:=AddChar(' ',S,N);
  731. end;
  732. function Copy2Symb(const S: string; Symb: Char): string;
  733. var
  734. p: Integer;
  735. begin
  736. p:=Pos(Symb,S);
  737. if p=0 then
  738. p:=Length(S)+1;
  739. Result:=Copy(S,1,p-1);
  740. end;
  741. function Copy2SymbDel(var S: string; Symb: Char): string;
  742. begin
  743. Result:=Copy2Symb(S,Symb);
  744. S:=TrimRight(Copy(S,Length(Result)+1,Length(S)));
  745. end;
  746. function Copy2Space(const S: string): string;inline;
  747. begin
  748. Result:=Copy2Symb(S,' ');
  749. end;
  750. function Copy2SpaceDel(var S: string): string;inline;
  751. begin
  752. Result:=Copy2SymbDel(S,' ');
  753. end;
  754. function AnsiProperCase(const S: string; const WordDelims: TSysCharSet): string;
  755. var
  756. // l : Integer;
  757. P,PE : PChar;
  758. begin
  759. Result:=AnsiLowerCase(S);
  760. P:=PChar(Result);
  761. PE:=P+Length(Result);
  762. while (P<PE) do
  763. begin
  764. while (P<PE) and (P^ in WordDelims) do
  765. inc(P);
  766. if (P<PE) then
  767. P^:=UpCase(P^);
  768. while (P<PE) and not (P^ in WordDelims) do
  769. inc(P);
  770. end;
  771. end;
  772. function WordCount(const S: string; const WordDelims: TSysCharSet): Integer;
  773. var
  774. P,PE : PChar;
  775. begin
  776. Result:=0;
  777. P:=Pchar(S);
  778. PE:=P+Length(S);
  779. while (P<PE) do
  780. begin
  781. while (P<PE) and (P^ in WordDelims) do
  782. Inc(P);
  783. if (P<PE) then
  784. inc(Result);
  785. while (P<PE) and not (P^ in WordDelims) do
  786. inc(P);
  787. end;
  788. end;
  789. function WordPosition(const N: Integer; const S: string; const WordDelims: TSysCharSet): Integer;
  790. var
  791. PS,P,PE : PChar;
  792. Count: Integer;
  793. begin
  794. Result:=0;
  795. Count:=0;
  796. PS:=PChar(S);
  797. PE:=PS+Length(S);
  798. P:=PS;
  799. while (P<PE) and (Count<>N) do
  800. begin
  801. while (P<PE) and (P^ in WordDelims) do
  802. inc(P);
  803. if (P<PE) then
  804. inc(Count);
  805. if (Count<>N) then
  806. while (P<PE) and not (P^ in WordDelims) do
  807. inc(P)
  808. else
  809. Result:=(P-PS)+1;
  810. end;
  811. end;
  812. function ExtractWord(N: Integer; const S: string; const WordDelims: TSysCharSet): string;inline;
  813. var
  814. i: Integer;
  815. begin
  816. Result:=ExtractWordPos(N,S,WordDelims,i);
  817. end;
  818. function ExtractWordPos(N: Integer; const S: string; const WordDelims: TSysCharSet; var Pos: Integer): string;
  819. var
  820. i,j,l: Integer;
  821. begin
  822. j:=0;
  823. i:=WordPosition(N, S, WordDelims);
  824. Pos:=i;
  825. if (i<>0) then
  826. begin
  827. j:=i;
  828. l:=Length(S);
  829. while (j<=L) and not (S[j] in WordDelims) do
  830. inc(j);
  831. end;
  832. SetLength(Result,j-i);
  833. If ((j-i)>0) then
  834. Move(S[i],Result[1],j-i);
  835. end;
  836. function ExtractDelimited(N: Integer; const S: string; const Delims: TSysCharSet): string;
  837. var
  838. w,i,l,len: Integer;
  839. begin
  840. w:=0;
  841. i:=1;
  842. l:=0;
  843. len:=Length(S);
  844. SetLength(Result, 0);
  845. while (i<=len) and (w<>N) do
  846. begin
  847. if s[i] in Delims then
  848. inc(w)
  849. else
  850. begin
  851. if (N-1)=w then
  852. begin
  853. inc(l);
  854. SetLength(Result,l);
  855. Result[L]:=S[i];
  856. end;
  857. end;
  858. inc(i);
  859. end;
  860. end;
  861. function ExtractSubstr(const S: string; var Pos: Integer; const Delims: TSysCharSet): string;
  862. var
  863. i,l: Integer;
  864. begin
  865. i:=Pos;
  866. l:=Length(S);
  867. while (i<=l) and not (S[i] in Delims) do
  868. inc(i);
  869. Result:=Copy(S,Pos,i-Pos);
  870. if (i<=l) and (S[i] in Delims) then
  871. inc(i);
  872. Pos:=i;
  873. end;
  874. function isWordPresent(const W, S: string; const WordDelims: TSysCharSet): Boolean;
  875. var
  876. i,Count : Integer;
  877. begin
  878. Result:=False;
  879. Count:=WordCount(S, WordDelims);
  880. I:=1;
  881. While (Not Result) and (I<=Count) do
  882. begin
  883. Result:=ExtractWord(i,S,WordDelims)=W;
  884. Inc(i);
  885. end;
  886. end;
  887. function Numb2USA(const S: string): string;
  888. var
  889. i, NA: Integer;
  890. begin
  891. i:=Length(S);
  892. Result:=S;
  893. NA:=0;
  894. while (i > 0) do begin
  895. if ((Length(Result) - i + 1 - NA) mod 3 = 0) and (i <> 1) then
  896. begin
  897. insert(',', Result, i);
  898. inc(NA);
  899. end;
  900. Dec(i);
  901. end;
  902. end;
  903. function PadCenter(const S: string; Len: Integer): string;
  904. begin
  905. if Length(S)<Len then
  906. begin
  907. Result:=StringOfChar(' ',(Len div 2) -(Length(S) div 2))+S;
  908. Result:=Result+StringOfChar(' ',Len-Length(Result));
  909. end
  910. else
  911. Result:=S;
  912. end;
  913. function Hex2Dec(const S: string): Longint;
  914. var
  915. HexStr: string;
  916. begin
  917. if Pos('$',S)=0 then
  918. HexStr:='$'+ S
  919. else
  920. HexStr:=S;
  921. Result:=StrTointDef(HexStr,0);
  922. end;
  923. function Dec2Numb(N: Longint; Len, Base: Byte): string;
  924. var
  925. C: Integer;
  926. Number: Longint;
  927. begin
  928. if N=0 then
  929. Result:='0'
  930. else
  931. begin
  932. Number:=N;
  933. Result:='';
  934. while Number>0 do
  935. begin
  936. C:=Number mod Base;
  937. if C>9 then
  938. C:=C+55
  939. else
  940. C:=C+48;
  941. Result:=Chr(C)+Result;
  942. Number:=Number div Base;
  943. end;
  944. end;
  945. if (Result<>'') then
  946. Result:=AddChar('0',Result,Len);
  947. end;
  948. function Numb2Dec(S: string; Base: Byte): Longint;
  949. var
  950. i, P: Longint;
  951. begin
  952. i:=Length(S);
  953. Result:=0;
  954. S:=UpperCase(S);
  955. P:=1;
  956. while (i>=1) do
  957. begin
  958. if (S[i]>'@') then
  959. Result:=Result+(Ord(S[i])-55)*P
  960. else
  961. Result:=Result+(Ord(S[i])-48)*P;
  962. Dec(i);
  963. P:=P*Base;
  964. end;
  965. end;
  966. function RomanToint(const S: string): Longint;
  967. const
  968. RomanChars = ['C','D','i','L','M','V','X'];
  969. RomanValues : array['C'..'X'] of Word
  970. = (100,500,0,0,0,0,1,0,0,50,1000,0,0,0,0,0,0,0,0,5,0,10);
  971. var
  972. index, Next: Char;
  973. i,l: Integer;
  974. Negative: Boolean;
  975. begin
  976. Result:=0;
  977. i:=0;
  978. Negative:=(Length(S)>0) and (S[1]='-');
  979. if Negative then
  980. inc(i);
  981. l:=Length(S);
  982. while (i<l) do
  983. begin
  984. inc(i);
  985. index:=UpCase(S[i]);
  986. if index in RomanChars then
  987. begin
  988. if Succ(i)<=l then
  989. Next:=UpCase(S[i+1])
  990. else
  991. Next:=#0;
  992. if (Next in RomanChars) and (RomanValues[index]<RomanValues[Next]) then
  993. begin
  994. inc(Result, RomanValues[Next]);
  995. Dec(Result, RomanValues[index]);
  996. inc(i);
  997. end
  998. else
  999. inc(Result, RomanValues[index]);
  1000. end
  1001. else
  1002. begin
  1003. Result:=0;
  1004. Exit;
  1005. end;
  1006. end;
  1007. if Negative then
  1008. Result:=-Result;
  1009. end;
  1010. function intToRoman(Value: Longint): string;
  1011. const
  1012. Arabics : Array[1..13] of Integer
  1013. = (1,4,5,9,10,40,50,90,100,400,500,900,1000);
  1014. Romans : Array[1..13] of String
  1015. = ('I','IV','V','IX','X','XL','L','XC','C','CD','D','CM','M');
  1016. var
  1017. i: Integer;
  1018. begin
  1019. Result:='';
  1020. for i:=13 downto 1 do
  1021. while (Value >= Arabics[i]) do
  1022. begin
  1023. Value:=Value-Arabics[i];
  1024. Result:=Result+Romans[i];
  1025. end;
  1026. end;
  1027. function intToBin(Value: Longint; Digits, Spaces: Integer): string;
  1028. begin
  1029. Result:='';
  1030. if (Digits>32) then
  1031. Digits:=32;
  1032. while (Digits>0) do
  1033. begin
  1034. if (Digits mod Spaces)=0 then
  1035. Result:=Result+' ';
  1036. Dec(Digits);
  1037. Result:=Result+intToStr((Value shr Digits) and 1);
  1038. end;
  1039. end;
  1040. function FindPart(const HelpWilds, inputStr: string): Integer;
  1041. var
  1042. i, J: Integer;
  1043. Diff: Integer;
  1044. begin
  1045. Result:=0;
  1046. i:=Pos('?',HelpWilds);
  1047. if (i=0) then
  1048. Result:=Pos(HelpWilds, inputStr)
  1049. else
  1050. begin
  1051. Diff:=Length(inputStr) - Length(HelpWilds);
  1052. for i:=0 to Diff do
  1053. begin
  1054. for J:=1 to Length(HelpWilds) do
  1055. if (inputStr[i + J] = HelpWilds[J]) or (HelpWilds[J] = '?') then
  1056. begin
  1057. if (J=Length(HelpWilds)) then
  1058. begin
  1059. Result:=i+1;
  1060. Exit;
  1061. end;
  1062. end
  1063. else
  1064. Break;
  1065. end;
  1066. end;
  1067. end;
  1068. function isWild(inputStr, Wilds: string; ignoreCase: Boolean): Boolean;
  1069. function SearchNext(var Wilds: string): Integer;
  1070. begin
  1071. Result:=Pos('*', Wilds);
  1072. if Result>0 then
  1073. Wilds:=Copy(Wilds,1,Result - 1);
  1074. end;
  1075. var
  1076. CWild, CinputWord: Integer; { counter for positions }
  1077. i, LenHelpWilds: Integer;
  1078. MaxinputWord, MaxWilds: Integer; { Length of inputStr and Wilds }
  1079. HelpWilds: string;
  1080. begin
  1081. if Wilds = inputStr then begin
  1082. Result:=True;
  1083. Exit;
  1084. end;
  1085. repeat { delete '**', because '**' = '*' }
  1086. i:=Pos('**', Wilds);
  1087. if i > 0 then
  1088. Wilds:=Copy(Wilds, 1, i - 1) + '*' + Copy(Wilds, i + 2, Maxint);
  1089. until i = 0;
  1090. if Wilds = '*' then begin { for fast end, if Wilds only '*' }
  1091. Result:=True;
  1092. Exit;
  1093. end;
  1094. MaxinputWord:=Length(inputStr);
  1095. MaxWilds:=Length(Wilds);
  1096. if ignoreCase then begin { upcase all letters }
  1097. inputStr:=AnsiUpperCase(inputStr);
  1098. Wilds:=AnsiUpperCase(Wilds);
  1099. end;
  1100. if (MaxWilds = 0) or (MaxinputWord = 0) then begin
  1101. Result:=False;
  1102. Exit;
  1103. end;
  1104. CinputWord:=1;
  1105. CWild:=1;
  1106. Result:=True;
  1107. repeat
  1108. if inputStr[CinputWord] = Wilds[CWild] then begin { equal letters }
  1109. { goto next letter }
  1110. inc(CWild);
  1111. inc(CinputWord);
  1112. Continue;
  1113. end;
  1114. if Wilds[CWild] = '?' then begin { equal to '?' }
  1115. { goto next letter }
  1116. inc(CWild);
  1117. inc(CinputWord);
  1118. Continue;
  1119. end;
  1120. if Wilds[CWild] = '*' then begin { handling of '*' }
  1121. HelpWilds:=Copy(Wilds, CWild + 1, MaxWilds);
  1122. i:=SearchNext(HelpWilds);
  1123. LenHelpWilds:=Length(HelpWilds);
  1124. if i = 0 then begin
  1125. { no '*' in the rest, compare the ends }
  1126. if HelpWilds = '' then Exit; { '*' is the last letter }
  1127. { check the rest for equal Length and no '?' }
  1128. for i:=0 to LenHelpWilds - 1 do begin
  1129. if (HelpWilds[LenHelpWilds - i] <> inputStr[MaxinputWord - i]) and
  1130. (HelpWilds[LenHelpWilds - i]<> '?') then
  1131. begin
  1132. Result:=False;
  1133. Exit;
  1134. end;
  1135. end;
  1136. Exit;
  1137. end;
  1138. { handle all to the next '*' }
  1139. inc(CWild, 1 + LenHelpWilds);
  1140. i:=FindPart(HelpWilds, Copy(inputStr, CinputWord, Maxint));
  1141. if i= 0 then begin
  1142. Result:=False;
  1143. Exit;
  1144. end;
  1145. CinputWord:=i + LenHelpWilds;
  1146. Continue;
  1147. end;
  1148. Result:=False;
  1149. Exit;
  1150. until (CinputWord > MaxinputWord) or (CWild > MaxWilds);
  1151. { no completed evaluation }
  1152. if CinputWord <= MaxinputWord then Result:=False;
  1153. if (CWild <= MaxWilds) and (Wilds[MaxWilds] <> '*') then Result:=False;
  1154. end;
  1155. function XorString(const Key, Src: ShortString): ShortString;
  1156. var
  1157. i: Integer;
  1158. begin
  1159. Result:=Src;
  1160. if Length(Key) > 0 then
  1161. for i:=1 to Length(Src) do
  1162. Result[i]:=Chr(Byte(Key[1 + ((i - 1) mod Length(Key))]) xor Ord(Src[i]));
  1163. end;
  1164. function XorEncode(const Key, Source: string): string;
  1165. var
  1166. i: Integer;
  1167. C: Byte;
  1168. begin
  1169. Result:='';
  1170. for i:=1 to Length(Source) do
  1171. begin
  1172. if Length(Key) > 0 then
  1173. C:=Byte(Key[1 + ((i - 1) mod Length(Key))]) xor Byte(Source[i])
  1174. else
  1175. C:=Byte(Source[i]);
  1176. Result:=Result+AnsiLowerCase(intToHex(C, 2));
  1177. end;
  1178. end;
  1179. function XorDecode(const Key, Source: string): string;
  1180. var
  1181. i: Integer;
  1182. C: Char;
  1183. begin
  1184. Result:='';
  1185. for i:=0 to Length(Source) div 2 - 1 do
  1186. begin
  1187. C:=Chr(StrTointDef('$' + Copy(Source, (i * 2) + 1, 2), Ord(' ')));
  1188. if Length(Key) > 0 then
  1189. C:=Chr(Byte(Key[1 + (i mod Length(Key))]) xor Byte(C));
  1190. Result:=Result + C;
  1191. end;
  1192. end;
  1193. function GetCmdLineArg(const Switch: string; SwitchChars: TSysCharSet): string;
  1194. var
  1195. i: Integer;
  1196. S: string;
  1197. begin
  1198. i:=1;
  1199. Result:='';
  1200. while (Result='') and (i<=ParamCount) do
  1201. begin
  1202. S:=ParamStr(i);
  1203. if (SwitchChars=[]) or ((S[1] in SwitchChars) and (Length(S) > 1)) and
  1204. (AnsiCompareText(Copy(S,2,Length(S)-1),Switch)=0) then
  1205. begin
  1206. inc(i);
  1207. if i<=ParamCount then
  1208. Result:=ParamStr(i);
  1209. end;
  1210. inc(i);
  1211. end;
  1212. end;
  1213. Function RPosEX(C:char;const S : AnsiString;offs:cardinal):Integer; overload;
  1214. var I : SizeUInt;
  1215. p,p2: pChar;
  1216. Begin
  1217. I:=Length(S);
  1218. If (I<>0) and (offs<=i) Then
  1219. begin
  1220. p:=@s[offs];
  1221. p2:=@s[1];
  1222. while (p2<=p) and (p^<>c) do dec(p);
  1223. RPosEx:=(p-p2)+1;
  1224. end
  1225. else
  1226. RPosEX:=0;
  1227. End;
  1228. Function RPos(c:char;const S : AnsiString):Integer; overload;
  1229. var I : Integer;
  1230. p,p2: pChar;
  1231. Begin
  1232. I:=Length(S);
  1233. If I<>0 Then
  1234. begin
  1235. p:=@s[i];
  1236. p2:=@s[1];
  1237. while (p2<=p) and (p^<>c) do dec(p);
  1238. i:=p-p2+1;
  1239. end;
  1240. RPos:=i;
  1241. End;
  1242. Function RPos (Const Substr : AnsiString; Const Source : AnsiString) : Integer; overload;
  1243. var
  1244. MaxLen,llen : Integer;
  1245. c : char;
  1246. pc,pc2 : pchar;
  1247. begin
  1248. rPos:=0;
  1249. llen:=Length(SubStr);
  1250. maxlen:=length(source);
  1251. if (llen>0) and (maxlen>0) and ( llen<=maxlen) then
  1252. begin
  1253. // i:=maxlen;
  1254. pc:=@source[maxlen];
  1255. pc2:=@source[llen-1];
  1256. c:=substr[llen];
  1257. while pc>=pc2 do
  1258. begin
  1259. if (c=pc^) and
  1260. (CompareChar(Substr[1],pchar(pc-llen+1)^,Length(SubStr))=0) then
  1261. begin
  1262. rPos:=pchar(pc-llen+1)-pchar(@source[1])+1;
  1263. exit;
  1264. end;
  1265. dec(pc);
  1266. end;
  1267. end;
  1268. end;
  1269. Function RPosex (Const Substr : AnsiString; Const Source : AnsiString;offs:cardinal) : Integer; overload;
  1270. var
  1271. MaxLen,llen : Integer;
  1272. c : char;
  1273. pc,pc2 : pchar;
  1274. begin
  1275. rPosex:=0;
  1276. llen:=Length(SubStr);
  1277. maxlen:=length(source);
  1278. if SizeInt(offs)<maxlen then maxlen:=offs;
  1279. if (llen>0) and (maxlen>0) and ( llen<=maxlen) then
  1280. begin
  1281. // i:=maxlen;
  1282. pc:=@source[maxlen];
  1283. pc2:=@source[llen-1];
  1284. c:=substr[llen];
  1285. while pc>=pc2 do
  1286. begin
  1287. if (c=pc^) and
  1288. (CompareChar(Substr[1],pchar(pc-llen+1)^,Length(SubStr))=0) then
  1289. begin
  1290. rPosex:=pchar(pc-llen+1)-pchar(@source[1])+1;
  1291. exit;
  1292. end;
  1293. dec(pc);
  1294. end;
  1295. end;
  1296. end;
  1297. // def from delphi.about.com:
  1298. procedure BinToHex(BinValue, HexValue: PChar; BinBufSize: Integer);
  1299. Const
  1300. HexDigits='0123456789ABCDEF';
  1301. var
  1302. i : longint;
  1303. begin
  1304. for i:=0 to binbufsize-1 do
  1305. begin
  1306. HexValue[0]:=hexdigits[1+((ord(binvalue^) shr 4))];
  1307. HexValue[1]:=hexdigits[1+((ord(binvalue^) and 15))];
  1308. inc(hexvalue,2);
  1309. inc(binvalue);
  1310. end;
  1311. end;
  1312. function HexToBin(HexValue, BinValue: PChar; BinBufSize: Integer): Integer;
  1313. // more complex, have to accept more than bintohex
  1314. // A..F    1000001
  1315. // a..f    1100001
  1316. // 0..9     110000
  1317. var i,j,h,l : integer;
  1318. begin
  1319. i:=binbufsize;
  1320. while (i>0) do
  1321. begin
  1322. if hexvalue^ IN ['A'..'F','a'..'f'] then
  1323. h:=((ord(hexvalue^)+9) and 15)
  1324. else if hexvalue^ IN ['0'..'9'] then
  1325. h:=((ord(hexvalue^)) and 15)
  1326. else
  1327. break;
  1328. inc(hexvalue);
  1329. if hexvalue^ IN ['A'..'F','a'..'f'] then
  1330. l:=(ord(hexvalue^)+9) and 15
  1331. else if hexvalue^ IN ['0'..'9'] then
  1332. l:=(ord(hexvalue^)) and 15
  1333. else
  1334. break;
  1335. j := l + (h shl 4);
  1336. inc(hexvalue);
  1337. binvalue^:=chr(j);
  1338. inc(binvalue);
  1339. dec(i);
  1340. end;
  1341. result:=binbufsize-i;
  1342. end;
  1343. end.