strutils.pp 39 KB

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