strutils.pp 40 KB

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