strutils.pp 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676
  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 insensitive 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 sensitive 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. Function LeftBStr(const AText: AnsiString; const AByteCount: Integer): AnsiString;
  58. Function LeftStr(const AText: WideString; const ACount: Integer): WideString;
  59. Function RightStr(const AText: WideString; const ACount: Integer): WideString;
  60. Function MidStr(const AText: WideString; const AStart, ACount: Integer): WideString;
  61. { ---------------------------------------------------------------------
  62. Extended search and replace
  63. ---------------------------------------------------------------------}
  64. const
  65. { Default word delimiters are any character except the core alphanumerics. }
  66. WordDelimiters: set of Char = [#0..#255] - ['a'..'z','A'..'Z','1'..'9','0'];
  67. type
  68. TStringSearchOption = (soDown, soMatchCase, soWholeWord);
  69. TStringSearchOptions = set of TStringSearchOption;
  70. TStringSeachOption = TStringSearchOption;
  71. Function SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String; Options: TStringSearchOptions): PChar;
  72. Function SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String): PChar; // ; Options: TStringSearchOptions = [soDown]
  73. Function PosEx(const SubStr, S: string; Offset: Cardinal): Integer;
  74. Function PosEx(const SubStr, S: string): Integer; // Offset: Cardinal = 1
  75. Function PosEx(c:char; const S: string; Offset: Cardinal): Integer;
  76. { ---------------------------------------------------------------------
  77. Soundex Functions.
  78. ---------------------------------------------------------------------}
  79. type
  80. TSoundexLength = 1..MaxInt;
  81. Function Soundex(const AText: string; ALength: TSoundexLength): string;
  82. Function Soundex(const AText: string): string; // ; ALength: TSoundexLength = 4
  83. type
  84. TSoundexIntLength = 1..8;
  85. Function SoundexInt(const AText: string; ALength: TSoundexIntLength): Integer;
  86. Function SoundexInt(const AText: string): Integer; //; ALength: TSoundexIntLength = 4
  87. Function DecodeSoundexInt(AValue: Integer): string;
  88. Function SoundexWord(const AText: string): Word;
  89. Function DecodeSoundexWord(AValue: Word): string;
  90. Function SoundexSimilar(const AText, AOther: string; ALength: TSoundexLength): Boolean;
  91. Function SoundexSimilar(const AText, AOther: string): Boolean; //; ALength: TSoundexLength = 4
  92. Function SoundexCompare(const AText, AOther: string; ALength: TSoundexLength): Integer;
  93. Function SoundexCompare(const AText, AOther: string): Integer; //; ALength: TSoundexLength = 4
  94. Function SoundexProc(const AText, AOther: string): Boolean;
  95. type
  96. TCompareTextProc = Function(const AText, AOther: string): Boolean;
  97. Const
  98. AnsiResemblesProc: TCompareTextProc = @SoundexProc;
  99. { ---------------------------------------------------------------------
  100. Other functions, based on RxStrUtils.
  101. ---------------------------------------------------------------------}
  102. function IsEmptyStr(const S: string; const EmptyChars: TSysCharSet): Boolean;
  103. function DelSpace(const S: string): string;
  104. function DelChars(const S: string; Chr: Char): string;
  105. function DelSpace1(const S: string): string;
  106. function Tab2Space(const S: string; Numb: Byte): string;
  107. function NPos(const C: string; S: string; N: Integer): Integer;
  108. Function RPosEX(C:char;const S : AnsiString;offs:cardinal):Integer; overload;
  109. Function RPosex (Const Substr : AnsiString; Const Source : AnsiString;offs:cardinal) : Integer; overload;
  110. Function RPos(c:char;const S : AnsiString):Integer; overload;
  111. Function RPos (Const Substr : AnsiString; Const Source : AnsiString) : Integer; overload;
  112. function AddChar(C: Char; const S: string; N: Integer): string;
  113. function AddCharR(C: Char; const S: string; N: Integer): string;
  114. function PadLeft(const S: string; N: Integer): string;
  115. function PadRight(const S: string; N: Integer): string;
  116. function PadCenter(const S: string; Len: Integer): string;
  117. function Copy2Symb(const S: string; Symb: Char): string;
  118. function Copy2SymbDel(var S: string; Symb: Char): string;
  119. function Copy2Space(const S: string): string;
  120. function Copy2SpaceDel(var S: string): string;
  121. function AnsiProperCase(const S: string; const WordDelims: TSysCharSet): string;
  122. function WordCount(const S: string; const WordDelims: TSysCharSet): Integer;
  123. function WordPosition(const N: Integer; const S: string; const WordDelims: TSysCharSet): Integer;
  124. function ExtractWord(N: Integer; const S: string; const WordDelims: TSysCharSet): string;
  125. function ExtractWordPos(N: Integer; const S: string; const WordDelims: TSysCharSet; var Pos: Integer): string;
  126. function ExtractDelimited(N: Integer; const S: string; const Delims: TSysCharSet): string;
  127. function ExtractSubstr(const S: string; var Pos: Integer; const Delims: TSysCharSet): string;
  128. function IsWordPresent(const W, S: string; const WordDelims: TSysCharSet): Boolean;
  129. function FindPart(const HelpWilds, InputStr: string): Integer;
  130. function IsWild(InputStr, Wilds: string; IgnoreCase: Boolean): Boolean;
  131. function XorString(const Key, Src: ShortString): ShortString;
  132. function XorEncode(const Key, Source: string): string;
  133. function XorDecode(const Key, Source: string): string;
  134. function GetCmdLineArg(const Switch: string; SwitchChars: TSysCharSet): string;
  135. function Numb2USA(const S: string): string;
  136. function Hex2Dec(const S: string): Longint;
  137. function Dec2Numb(N: Longint; Len, Base: Byte): string;
  138. function Numb2Dec(S: string; Base: Byte): Longint;
  139. function IntToBin(Value: Longint; Digits, Spaces: Integer): string;
  140. function IntToRoman(Value: Longint): string;
  141. function RomanToInt(const S: string): Longint;
  142. procedure BinToHex(BinValue, HexValue: PChar; BinBufSize: Integer);
  143. function HexToBin(HexValue, BinValue: PChar; BinBufSize: Integer): Integer;
  144. const
  145. DigitChars = ['0'..'9'];
  146. Brackets = ['(',')','[',']','{','}'];
  147. StdWordDelims = [#0..' ',',','.',';','/','\',':','''','"','`'] + Brackets;
  148. StdSwitchChars = ['-','/'];
  149. implementation
  150. { ---------------------------------------------------------------------
  151. Auxiliary functions
  152. ---------------------------------------------------------------------}
  153. Procedure NotYetImplemented (FN : String);
  154. begin
  155. Raise Exception.CreateFmt('Function "%s" (strutils) is not yet implemented',[FN]);
  156. end;
  157. { ---------------------------------------------------------------------
  158. Case insensitive search/replace
  159. ---------------------------------------------------------------------}
  160. Function AnsiResemblesText(const AText, AOther: string): Boolean;
  161. begin
  162. if Assigned(AnsiResemblesProc) then
  163. Result:=AnsiResemblesProc(AText,AOther)
  164. else
  165. Result:=False;
  166. end;
  167. Function AnsiContainsText(const AText, ASubText: string): Boolean;
  168. begin
  169. AnsiContainsText:=AnsiPos(ASubText,AText)<>0;
  170. end;
  171. Function AnsiStartsText(const ASubText, AText: string): Boolean;
  172. begin
  173. Result:=AnsiCompareText(Copy(AText,1,Length(AsubText)),ASubText)=0;
  174. end;
  175. Function AnsiEndsText(const ASubText, AText: string): Boolean;
  176. begin
  177. result:=AnsiCompareText(Copy(AText,Length(AText)-Length(ASubText)+1,Length(ASubText)),asubtext)=0;
  178. end;
  179. Function AnsiReplaceText(const AText, AFromText, AToText: string): string;
  180. var iFrom, iTo: longint;
  181. begin
  182. iTo:=Pos(AFromText,AText);
  183. if iTo=0 then
  184. result:=AText
  185. else
  186. begin
  187. result:='';
  188. iFrom:=1;
  189. while (ito<>0) do
  190. begin
  191. result:=Result+Copy(AText,IFrom,Ito-IFrom+1)+AToText;
  192. ifrom:=ITo+Length(afromtext);
  193. ito:=Posex(Afromtext,atext,ifrom);
  194. end;
  195. if ifrom<=length(atext) then
  196. result:=result+copy(AText,ifrom, length(atext));
  197. end;
  198. end;
  199. Function AnsiMatchText(const AText: string; const AValues: array of string): Boolean;
  200. begin
  201. Result:=(AnsiIndexText(AText,AValues)<>-1)
  202. end;
  203. Function AnsiIndexText(const AText: string; const AValues: array of string): Integer;
  204. var i : longint;
  205. begin
  206. result:=-1;
  207. if high(AValues)=-1 Then
  208. Exit;
  209. for i:=low(AValues) to High(Avalues) do
  210. if CompareText(avalues[i],atext)=0 Then
  211. exit(i); // make sure it is the first val.
  212. end;
  213. { ---------------------------------------------------------------------
  214. Case sensitive search/replace
  215. ---------------------------------------------------------------------}
  216. Function AnsiContainsStr(const AText, ASubText: string): Boolean;
  217. begin
  218. Result := AnsiPos(ASubText,AText)<>0;
  219. end;
  220. Function AnsiStartsStr(const ASubText, AText: string): Boolean;
  221. begin
  222. Result := AnsiPos(ASubText,AText)=1;
  223. end;
  224. Function AnsiEndsStr(const ASubText, AText: string): Boolean;
  225. begin
  226. Result := AnsiPos(ASubText,AText)=(length(AText)-length(ASubText)+1);
  227. end;
  228. Function AnsiReplaceStr(const AText, AFromText, AToText: string): string;
  229. begin
  230. Result := StringReplace(AText,AFromText,AToText,[rfReplaceAll]);
  231. end;
  232. Function AnsiMatchStr(const AText: string; const AValues: array of string): Boolean;
  233. begin
  234. Result:=AnsiIndexStr(AText,Avalues)<>-1;
  235. end;
  236. Function AnsiIndexStr(const AText: string; const AValues: array of string): Integer;
  237. var i : longint;
  238. begin
  239. result:=-1;
  240. if high(AValues)=-1 Then
  241. Exit;
  242. for i:=low(AValues) to High(Avalues) do
  243. if (avalues[i]=AText) Then
  244. exit(i); // make sure it is the first val.
  245. end;
  246. { ---------------------------------------------------------------------
  247. Playthingies
  248. ---------------------------------------------------------------------}
  249. Function DupeString(const AText: string; ACount: Integer): string;
  250. var i,l : integer;
  251. begin
  252. result:='';
  253. if aCount>=0 then
  254. begin
  255. l:=length(atext);
  256. SetLength(result,aCount*l);
  257. for i:=0 to ACount-1 do
  258. move(atext[1],Result[l*i+1],l);
  259. end;
  260. end;
  261. Function ReverseString(const AText: string): string;
  262. var
  263. i,j:longint;
  264. begin
  265. setlength(result,length(atext));
  266. i:=1; j:=length(atext);
  267. while (i<=j) do
  268. begin
  269. result[i]:=atext[j-i+1];
  270. inc(i);
  271. end;
  272. end;
  273. Function AnsiReverseString(const AText: AnsiString): AnsiString;
  274. begin
  275. Result:=ReverseString(AText);
  276. end;
  277. Function StuffString(const AText: string; AStart, ALength: Cardinal; const ASubText: string): string;
  278. var i,j : longint;
  279. begin
  280. j:=length(ASubText);
  281. i:=length(AText);
  282. SetLength(Result,i-ALength+j);
  283. move (AText[1],result[1],AStart-1);
  284. move (ASubText[1],result[AStart],j);
  285. move (AText[AStart+ALength], Result[AStart+j],i-AStart-ALength+1);
  286. end;
  287. Function RandomFrom(const AValues: array of string): string; overload;
  288. begin
  289. if high(AValues)=-1 then exit('');
  290. result:=Avalues[random(High(AValues)+1)];
  291. end;
  292. Function IfThen(AValue: Boolean; const ATrue: string; AFalse: string): string;
  293. begin
  294. if avalue then
  295. result:=atrue
  296. else
  297. result:=afalse;
  298. end;
  299. Function IfThen(AValue: Boolean; const ATrue: string): string; // ; AFalse: string = ''
  300. begin
  301. if avalue then
  302. result:=atrue
  303. else
  304. result:='';
  305. end;
  306. { ---------------------------------------------------------------------
  307. VB emulations.
  308. ---------------------------------------------------------------------}
  309. Function LeftStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  310. begin
  311. Result:=Copy(AText,1,ACount);
  312. end;
  313. Function RightStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  314. var j,l:integer;
  315. begin
  316. l:=length(atext);
  317. j:=ACount;
  318. if j>l then j:=l;
  319. Result:=Copy(AText,l-j+1,j);
  320. end;
  321. Function MidStr(const AText: AnsiString; const AStart, ACount: Integer): AnsiString;
  322. begin
  323. if (ACount=0) or (AStart>length(atext)) then
  324. exit('');
  325. Result:=Copy(AText,AStart,ACount);
  326. end;
  327. Function LeftBStr(const AText: AnsiString; const AByteCount: Integer): AnsiString;
  328. begin
  329. Result:=LeftStr(AText,AByteCount);
  330. end;
  331. Function RightBStr(const AText: AnsiString; const AByteCount: Integer): AnsiString;
  332. begin
  333. Result:=RightStr(Atext,AByteCount);
  334. end;
  335. Function MidBStr(const AText: AnsiString; const AByteStart, AByteCount: Integer): AnsiString;
  336. begin
  337. Result:=MidStr(AText,AByteStart,AByteCount);
  338. end;
  339. Function AnsiLeftStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  340. begin
  341. Result := copy(AText,1,ACount);
  342. end;
  343. Function AnsiRightStr(const AText: AnsiString; const ACount: Integer): AnsiString;
  344. begin
  345. Result := copy(AText,length(AText)-ACount+1,ACount);
  346. end;
  347. Function AnsiMidStr(const AText: AnsiString; const AStart, ACount: Integer): AnsiString;
  348. begin
  349. Result:=Copy(AText,AStart,ACount);
  350. end;
  351. Function LeftStr(const AText: WideString; const ACount: Integer): WideString;
  352. begin
  353. Result:=Copy(AText,1,ACount);
  354. end;
  355. Function RightStr(const AText: WideString; const ACount: Integer): WideString;
  356. var
  357. j,l:integer;
  358. begin
  359. l:=length(atext);
  360. j:=ACount;
  361. if j>l then j:=l;
  362. Result:=Copy(AText,l-j+1,j);
  363. end;
  364. Function MidStr(const AText: WideString; const AStart, ACount: Integer): WideString;
  365. begin
  366. Result:=Copy(AText,AStart,ACount);
  367. end;
  368. { ---------------------------------------------------------------------
  369. Extended search and replace
  370. ---------------------------------------------------------------------}
  371. Function SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String; Options: TStringSearchOptions): PChar;
  372. var
  373. Len,I,SLen: Integer;
  374. C: Char;
  375. Found : Boolean;
  376. Direction: Shortint;
  377. CharMap: array[Char] of Char;
  378. Function GotoNextWord(var P : PChar): Boolean;
  379. begin
  380. if (Direction=1) then
  381. begin
  382. // Skip characters
  383. While (Len>0) and not (P^ in WordDelimiters) do
  384. begin
  385. Inc(P);
  386. Dec(Len);
  387. end;
  388. // skip delimiters
  389. While (Len>0) and (P^ in WordDelimiters) do
  390. begin
  391. Inc(P);
  392. Dec(Len);
  393. end;
  394. Result:=Len>0;
  395. end
  396. else
  397. begin
  398. // Skip Delimiters
  399. While (Len>0) and (P^ in WordDelimiters) do
  400. begin
  401. Dec(P);
  402. Dec(Len);
  403. end;
  404. // skip characters
  405. While (Len>0) and not (P^ in WordDelimiters) do
  406. begin
  407. Dec(P);
  408. Dec(Len);
  409. end;
  410. Result:=Len>0;
  411. // We're on the first delimiter. Pos back on char.
  412. Inc(P);
  413. Inc(Len);
  414. end;
  415. end;
  416. begin
  417. Result:=nil;
  418. Slen:=Length(SearchString);
  419. if (BufLen<=0) or (Slen=0) then
  420. Exit;
  421. if soDown in Options then
  422. begin
  423. Direction:=1;
  424. Inc(SelStart,SelLength);
  425. Len:=BufLen-SelStart-SLen+1;
  426. if (Len<=0) then
  427. Exit;
  428. end
  429. else
  430. begin
  431. Direction:=-1;
  432. Dec(SelStart,Length(SearchString));
  433. Len:=SelStart+1;
  434. end;
  435. if (SelStart<0) or (SelStart>BufLen) then
  436. Exit;
  437. Result:=@Buf[SelStart];
  438. for C:=Low(Char) to High(Char) do
  439. if (soMatchCase in Options) then
  440. CharMap[C]:=C
  441. else
  442. CharMap[C]:=Upcase(C);
  443. if Not (soMatchCase in Options) then
  444. SearchString:=UpCase(SearchString);
  445. Found:=False;
  446. while (Result<>Nil) and (Not Found) do
  447. begin
  448. if ((soWholeWord in Options) and
  449. (Result<>@Buf[SelStart]) and
  450. not GotoNextWord(Result)) then
  451. Result:=Nil
  452. else
  453. begin
  454. // try to match whole searchstring
  455. I:=0;
  456. while (I<Slen) and (CharMap[Result[I]]=SearchString[I+1]) do
  457. Inc(I);
  458. // Whole searchstring matched ?
  459. if (I=SLen) then
  460. Found:=(Len=0) or
  461. (not (soWholeWord in Options)) or
  462. (Result[SLen] in WordDelimiters);
  463. if not Found then
  464. begin
  465. Inc(Result,Direction);
  466. Dec(Len);
  467. If (Len=0) then
  468. Result:=Nil;
  469. end;
  470. end;
  471. end;
  472. end;
  473. Function SearchBuf(Buf: PChar; BufLen: Integer; SelStart, SelLength: Integer; SearchString: String): PChar; // ; Options: TStringSearchOptions = [soDown]
  474. begin
  475. Result:=SearchBuf(Buf,BufLen,SelStart,SelLength,SearchString,[soDown]);
  476. end;
  477. Function PosEx(const SubStr, S: string; Offset: Cardinal): Integer;
  478. var i : pchar;
  479. begin
  480. if (offset<1) or (offset>length(s)) then exit(0);
  481. i:=strpos(@s[offset],@substr[1]);
  482. if i=nil then
  483. PosEx:=0
  484. else
  485. PosEx:=succ(i-pchar(s));
  486. end;
  487. Function PosEx(const SubStr, S: string): Integer; // Offset: Cardinal = 1
  488. begin
  489. posex:=posex(substr,s,1);
  490. end;
  491. Function PosEx(c:char; const S: string; Offset: Cardinal): Integer;
  492. var l : longint;
  493. begin
  494. if (offset<1) or (offset>length(s)) then exit(0);
  495. l:=length(s);
  496. {$ifndef useindexbyte}
  497. while (offset<=l) and (s[offset]<>c) do inc(offset);
  498. if offset>l then
  499. posex:=0
  500. else
  501. posex:=offset;
  502. {$else}
  503. posex:=offset+indexbyte(s[offset],l-offset+1);
  504. if posex=(offset-1) then
  505. posex:=0;
  506. {$endif}
  507. end;
  508. { ---------------------------------------------------------------------
  509. Soundex Functions.
  510. ---------------------------------------------------------------------}
  511. Const
  512. SScore : array[1..255] of Char =
  513. ('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
  514. '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
  515. '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
  516. '0','0','0','0','0','0', // 91..95
  517. '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
  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', // 123..154
  519. '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
  520. '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
  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', // 219..250
  522. '0','0','0','0','0'); // 251..255
  523. Function Soundex(const AText: string; ALength: TSoundexLength): string;
  524. Var
  525. S,PS : Char;
  526. I,L : integer;
  527. begin
  528. Result:='';
  529. PS:=#0;
  530. If Length(AText)>0 then
  531. begin
  532. Result:=Upcase(AText[1]);
  533. I:=2;
  534. L:=Length(AText);
  535. While (I<=L) and (Length(Result)<ALength) do
  536. begin
  537. S:=SScore[Ord(AText[i])];
  538. If Not (S in ['0','i',PS]) then
  539. Result:=Result+S;
  540. If (S<>'i') then
  541. PS:=S;
  542. Inc(I);
  543. end;
  544. end;
  545. L:=Length(Result);
  546. If (L<ALength) then
  547. Result:=Result+StringOfChar('0',Alength-L);
  548. end;
  549. Function Soundex(const AText: string): string; // ; ALength: TSoundexLength = 4
  550. begin
  551. Result:=Soundex(AText,4);
  552. end;
  553. Const
  554. Ord0 = Ord('0');
  555. OrdA = Ord('A');
  556. Function SoundexInt(const AText: string; ALength: TSoundexIntLength): Integer;
  557. var
  558. SE: string;
  559. I: Integer;
  560. begin
  561. Result:=-1;
  562. SE:=Soundex(AText,ALength);
  563. If Length(SE)>0 then
  564. begin
  565. Result:=Ord(SE[1])-OrdA;
  566. if ALength > 1 then
  567. begin
  568. Result:=Result*26+(Ord(SE[2])-Ord0);
  569. for I:=3 to ALength do
  570. Result:=(Ord(SE[I])-Ord0)+Result*7;
  571. end;
  572. Result:=ALength+Result*9;
  573. end;
  574. end;
  575. Function SoundexInt(const AText: string): Integer; //; ALength: TSoundexIntLength = 4
  576. begin
  577. Result:=SoundexInt(AText,4);
  578. end;
  579. Function DecodeSoundexInt(AValue: Integer): string;
  580. var
  581. I, Len: Integer;
  582. begin
  583. Result := '';
  584. Len := AValue mod 9;
  585. AValue := AValue div 9;
  586. for I:=Len downto 3 do
  587. begin
  588. Result:=Chr(Ord0+(AValue mod 7))+Result;
  589. AValue:=AValue div 7;
  590. end;
  591. if Len>2 then
  592. Result:=IntToStr(AValue mod 26)+Result;
  593. AValue:=AValue div 26;
  594. Result:=Chr(OrdA+AValue)+Result;
  595. end;
  596. Function SoundexWord(const AText: string): Word;
  597. Var
  598. S : String;
  599. begin
  600. S:=SoundEx(Atext,4);
  601. Result:=Ord(S[1])-OrdA;
  602. Result:=Result*26+StrToInt(S[2]);
  603. Result:=Result*7+StrToInt(S[3]);
  604. Result:=Result*7+StrToInt(S[4]);
  605. end;
  606. Function DecodeSoundexWord(AValue: Word): string;
  607. begin
  608. Result := Chr(Ord0+ (AValue mod 7));
  609. AValue := AValue div 7;
  610. Result := Chr(Ord0+ (AValue mod 7)) + Result;
  611. AValue := AValue div 7;
  612. Result := IntToStr(AValue mod 26) + Result;
  613. AValue := AValue div 26;
  614. Result := Chr(OrdA+AValue) + Result;
  615. end;
  616. Function SoundexSimilar(const AText, AOther: string; ALength: TSoundexLength): Boolean;
  617. begin
  618. Result:=Soundex(AText,ALength)=Soundex(AOther,ALength);
  619. end;
  620. Function SoundexSimilar(const AText, AOther: string): Boolean; //; ALength: TSoundexLength = 4
  621. begin
  622. Result:=SoundexSimilar(AText,AOther,4);
  623. end;
  624. Function SoundexCompare(const AText, AOther: string; ALength: TSoundexLength): Integer;
  625. begin
  626. Result:=AnsiCompareStr(Soundex(AText,ALength),Soundex(AOther,ALength));
  627. end;
  628. Function SoundexCompare(const AText, AOther: string): Integer; //; ALength: TSoundexLength = 4
  629. begin
  630. Result:=SoundexCompare(AText,AOther,4);
  631. end;
  632. Function SoundexProc(const AText, AOther: string): Boolean;
  633. begin
  634. Result:=SoundexSimilar(AText,AOther);
  635. end;
  636. { ---------------------------------------------------------------------
  637. RxStrUtils-like functions.
  638. ---------------------------------------------------------------------}
  639. function IsEmptyStr(const S: string; const EmptyChars: TSysCharSet): Boolean;
  640. var
  641. i,l: Integer;
  642. begin
  643. l:=Length(S);
  644. i:=1;
  645. Result:=True;
  646. while Result and (i<=l) do
  647. begin
  648. Result:=Not (S[i] in EmptyChars);
  649. Inc(i);
  650. end;
  651. end;
  652. function DelSpace(const S: String): string;
  653. begin
  654. Result:=DelChars(S,' ');
  655. end;
  656. function DelChars(const S: string; Chr: Char): string;
  657. var
  658. I,J: Integer;
  659. begin
  660. Result:=S;
  661. I:=Length(Result);
  662. While I>0 do
  663. begin
  664. if Result[I]=Chr then
  665. begin
  666. J:=I-1;
  667. While (J>0) and (Result[J]=Chr) do
  668. Dec(j);
  669. Delete(Result,J+1,I-J);
  670. I:=J+1;
  671. end;
  672. dec(I);
  673. end;
  674. end;
  675. function DelSpace1(const S: string): string;
  676. var
  677. i: Integer;
  678. begin
  679. Result:=S;
  680. for i:=Length(Result) downto 2 do
  681. if (Result[i]=' ') and (Result[I-1]=' ') then
  682. Delete(Result,I,1);
  683. end;
  684. function Tab2Space(const S: string; Numb: Byte): string;
  685. var
  686. I: Integer;
  687. begin
  688. I:=1;
  689. Result:=S;
  690. while I <= Length(Result) do
  691. if Result[I]<>Chr(9) then
  692. inc(I)
  693. else
  694. begin
  695. Result[I]:=' ';
  696. If (Numb>1) then
  697. Insert(StringOfChar('0',Numb-1),Result,I);
  698. Inc(I,Numb);
  699. end;
  700. end;
  701. function NPos(const C: string; S: string; N: Integer): Integer;
  702. var
  703. i,p,k: Integer;
  704. begin
  705. Result:=0;
  706. if N<1 then
  707. Exit;
  708. k:=0;
  709. i:=1;
  710. Repeat
  711. p:=pos(C,S);
  712. Inc(k,p);
  713. if p>0 then
  714. delete(S,1,p);
  715. Inc(i);
  716. Until (i>n) or (p=0);
  717. If (P>0) then
  718. Result:=K;
  719. end;
  720. function AddChar(C: Char; const S: string; N: Integer): string;
  721. Var
  722. l : Integer;
  723. begin
  724. Result:=S;
  725. l:=Length(Result);
  726. if l<N then
  727. Result:=StringOfChar(C,N-l)+Result;
  728. end;
  729. function AddCharR(C: Char; const S: string; N: Integer): string;
  730. Var
  731. l : Integer;
  732. begin
  733. Result:=S;
  734. l:=Length(Result);
  735. if l<N then
  736. Result:=Result+StringOfChar(C,N-l);
  737. end;
  738. function PadRight(const S: string; N: Integer): string;
  739. begin
  740. Result:=AddCharR(' ',S,N);
  741. end;
  742. function PadLeft(const S: string; N: Integer): string;
  743. begin
  744. Result:=AddChar(' ',S,N);
  745. end;
  746. function Copy2Symb(const S: string; Symb: Char): string;
  747. var
  748. p: Integer;
  749. begin
  750. p:=Pos(Symb,S);
  751. if p=0 then
  752. p:=Length(S)+1;
  753. Result:=Copy(S,1,p-1);
  754. end;
  755. function Copy2SymbDel(var S: string; Symb: Char): string;
  756. begin
  757. Result:=Copy2Symb(S,Symb);
  758. S:=TrimRight(Copy(S,Length(Result)+1,Length(S)));
  759. end;
  760. function Copy2Space(const S: string): string;
  761. begin
  762. Result:=Copy2Symb(S,' ');
  763. end;
  764. function Copy2SpaceDel(var S: string): string;
  765. begin
  766. Result:=Copy2SymbDel(S,' ');
  767. end;
  768. function AnsiProperCase(const S: string; const WordDelims: TSysCharSet): string;
  769. var
  770. // l : Integer;
  771. P,PE : PChar;
  772. begin
  773. Result:=AnsiLowerCase(S);
  774. P:=PChar(Result);
  775. PE:=P+Length(Result);
  776. while (P<PE) do
  777. begin
  778. while (P<PE) and (P^ in WordDelims) do
  779. inc(P);
  780. if (P<PE) then
  781. P^:=UpCase(P^);
  782. while (P<PE) and not (P^ in WordDelims) do
  783. inc(P);
  784. end;
  785. end;
  786. function WordCount(const S: string; const WordDelims: TSysCharSet): Integer;
  787. var
  788. P,PE : PChar;
  789. begin
  790. Result:=0;
  791. P:=Pchar(S);
  792. PE:=P+Length(S);
  793. while (P<PE) do
  794. begin
  795. while (P<PE) and (P^ in WordDelims) do
  796. Inc(P);
  797. if (P<PE) then
  798. inc(Result);
  799. while (P<PE) and not (P^ in WordDelims) do
  800. inc(P);
  801. end;
  802. end;
  803. function WordPosition(const N: Integer; const S: string; const WordDelims: TSysCharSet): Integer;
  804. var
  805. PS,P,PE : PChar;
  806. Count: Integer;
  807. begin
  808. Result:=0;
  809. Count:=0;
  810. PS:=PChar(S);
  811. PE:=PS+Length(S);
  812. P:=PS;
  813. while (P<PE) and (Count<>N) do
  814. begin
  815. while (P<PE) and (P^ in WordDelims) do
  816. inc(P);
  817. if (P<PE) then
  818. inc(Count);
  819. if (Count<>N) then
  820. while (P<PE) and not (P^ in WordDelims) do
  821. inc(P)
  822. else
  823. Result:=(P-PS)+1;
  824. end;
  825. end;
  826. function ExtractWord(N: Integer; const S: string; const WordDelims: TSysCharSet): string;
  827. var
  828. i: Integer;
  829. begin
  830. Result:=ExtractWordPos(N,S,WordDelims,i);
  831. end;
  832. function ExtractWordPos(N: Integer; const S: string; const WordDelims: TSysCharSet; var Pos: Integer): string;
  833. var
  834. i,j,l: Integer;
  835. begin
  836. j:=0;
  837. i:=WordPosition(N, S, WordDelims);
  838. Pos:=i;
  839. if (i<>0) then
  840. begin
  841. j:=i;
  842. l:=Length(S);
  843. while (j<=L) and not (S[j] in WordDelims) do
  844. inc(j);
  845. end;
  846. SetLength(Result,j-i);
  847. If ((j-i)>0) then
  848. Move(S[i],Result[1],j-i);
  849. end;
  850. function ExtractDelimited(N: Integer; const S: string; const Delims: TSysCharSet): string;
  851. var
  852. w,i,l,len: Integer;
  853. begin
  854. w:=0;
  855. i:=1;
  856. l:=0;
  857. len:=Length(S);
  858. SetLength(Result, 0);
  859. while (i<=len) and (w<>N) do
  860. begin
  861. if s[i] in Delims then
  862. inc(w)
  863. else
  864. begin
  865. if (N-1)=w then
  866. begin
  867. inc(l);
  868. SetLength(Result,l);
  869. Result[L]:=S[i];
  870. end;
  871. end;
  872. inc(i);
  873. end;
  874. end;
  875. function ExtractSubstr(const S: string; var Pos: Integer; const Delims: TSysCharSet): string;
  876. var
  877. i,l: Integer;
  878. begin
  879. i:=Pos;
  880. l:=Length(S);
  881. while (i<=l) and not (S[i] in Delims) do
  882. inc(i);
  883. Result:=Copy(S,Pos,i-Pos);
  884. if (i<=l) and (S[i] in Delims) then
  885. inc(i);
  886. Pos:=i;
  887. end;
  888. function isWordPresent(const W, S: string; const WordDelims: TSysCharSet): Boolean;
  889. var
  890. i,Count : Integer;
  891. begin
  892. Result:=False;
  893. Count:=WordCount(S, WordDelims);
  894. I:=1;
  895. While (Not Result) and (I<=Count) do
  896. begin
  897. Result:=ExtractWord(i,S,WordDelims)=W;
  898. Inc(i);
  899. end;
  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. 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. 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. // def from delphi.about.com:
  1311. procedure BinToHex(BinValue, HexValue: PChar; BinBufSize: Integer);
  1312. Const
  1313. HexDigits='0123456789ABCDEF';
  1314. var
  1315. i : longint;
  1316. begin
  1317. for i:=0 to binbufsize-1 do
  1318. begin
  1319. HexValue[0]:=hexdigits[1+((ord(binvalue^) shr 4))];
  1320. HexValue[1]:=hexdigits[1+((ord(binvalue^) and 15))];
  1321. inc(hexvalue,2);
  1322. inc(binvalue);
  1323. end;
  1324. end;
  1325. function HexToBin(HexValue, BinValue: PChar; BinBufSize: Integer): Integer;
  1326. // more complex, have to accept more than bintohex
  1327. // A..F    1000001
  1328. // a..f    1100001
  1329. // 0..9     110000
  1330. var i,j,h,l : integer;
  1331. begin
  1332. i:=binbufsize;
  1333. while (i>0) do
  1334. begin
  1335. if hexvalue^ IN ['A'..'F','a'..'f'] then
  1336. h:=((ord(hexvalue^)+9) and 15)
  1337. else if hexvalue^ IN ['0'..'9'] then
  1338. h:=((ord(hexvalue^)) and 15)
  1339. else
  1340. break;
  1341. inc(hexvalue);
  1342. if hexvalue^ IN ['A'..'F','a'..'f'] then
  1343. l:=(ord(hexvalue^)+9) and 15
  1344. else if hexvalue^ IN ['0'..'9'] then
  1345. l:=(ord(hexvalue^)) and 15
  1346. else
  1347. break;
  1348. j := l + (h shl 4);
  1349. inc(hexvalue);
  1350. binvalue^:=chr(j);
  1351. inc(binvalue);
  1352. dec(i);
  1353. end;
  1354. result:=binbufsize-i;
  1355. end;
  1356. end.