sysstr.inc 59 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363
  1. {
  2. *********************************************************************
  3. $Id$
  4. Copyright (C) 1997, 1998 Gertjan Schouten
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  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. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. *********************************************************************
  17. System Utilities For Free Pascal
  18. }
  19. { NewStr creates a new PString and assigns S to it
  20. if length(s) = 0 NewStr returns Nil }
  21. function NewStr(const S: string): PString;
  22. begin
  23. if (S='') then
  24. Result:=nil
  25. else
  26. begin
  27. getmem(Result,length(s)+1);
  28. if (Result<>nil) then
  29. Result^:=s;
  30. end;
  31. end;
  32. { DisposeStr frees the memory occupied by S }
  33. procedure DisposeStr(S: PString);
  34. begin
  35. if S <> Nil then
  36. begin
  37. Freemem(S,Length(S^)+1);
  38. S:=nil;
  39. end;
  40. end;
  41. { AssignStr assigns S to P^ }
  42. procedure AssignStr(var P: PString; const S: string);
  43. begin
  44. P^ := s;
  45. end ;
  46. { AppendStr appends S to Dest }
  47. procedure AppendStr(var Dest: String; const S: string);
  48. begin
  49. Dest := Dest + S;
  50. end ;
  51. { UpperCase returns a copy of S where all lowercase characters ( from a to z )
  52. have been converted to uppercase }
  53. function UpperCase(const S: string): string;
  54. var i: integer;
  55. begin
  56. result := S;
  57. i := Length(S);
  58. while i <> 0 do begin
  59. if (result[i] in ['a'..'z']) then result[i] := char(byte(result[i]) - 32);
  60. Dec(i);
  61. end;
  62. end;
  63. { LowerCase returns a copy of S where all uppercase characters ( from A to Z )
  64. have been converted to lowercase }
  65. function LowerCase(const S: string): string;
  66. var i: integer;
  67. begin
  68. result := S;
  69. i := Length(result);
  70. while i <> 0 do begin
  71. if (result[i] in ['A'..'Z']) then result[i] := char(byte(result[i]) + 32);
  72. dec(i);
  73. end;
  74. end;
  75. { CompareStr compares S1 and S2, the result is the based on
  76. substraction of the ascii values of the characters in S1 and S2
  77. case result
  78. S1 < S2 < 0
  79. S1 > S2 > 0
  80. S1 = S2 = 0 }
  81. function CompareStr(const S1, S2: string): Integer;
  82. var count, count1, count2: integer;
  83. begin
  84. result := 0;
  85. Count1 := Length(S1);
  86. Count2 := Length(S2);
  87. if Count1>Count2 then
  88. Count:=Count2
  89. else
  90. Count:=Count1;
  91. result := CompareMemRange(Pointer(S1),Pointer(S2), Count);
  92. if result=0 then
  93. result:=Count1-Count2;
  94. end;
  95. { CompareMemRange returns the result of comparison of Length bytes at P1 and P2
  96. case result
  97. P1 < P2 < 0
  98. P1 > P2 > 0
  99. P1 = P2 = 0 }
  100. function CompareMemRange(P1, P2: Pointer; Length: cardinal): integer;
  101. var
  102. i: cardinal;
  103. begin
  104. i := 0;
  105. result := 0;
  106. while (result=0) and (I<length) do
  107. begin
  108. result:=byte(P1^)-byte(P2^);
  109. P1:=pchar(P1)+1; // VP compat.
  110. P2:=pchar(P2)+1;
  111. i := i + 1;
  112. end ;
  113. end ;
  114. function CompareMem(P1, P2: Pointer; Length: cardinal): Boolean;
  115. var
  116. i: cardinal;
  117. begin
  118. Result:=True;
  119. I:=0;
  120. If (P1)<>(P2) then
  121. While Result and (i<Length) do
  122. begin
  123. Result:=PByte(P1)^=PByte(P2)^;
  124. Inc(I);
  125. Inc(pchar(P1));
  126. Inc(pchar(P2));
  127. end;
  128. end;
  129. { CompareText compares S1 and S2, the result is the based on
  130. substraction of the ascii values of characters in S1 and S2
  131. comparison is case-insensitive
  132. case result
  133. S1 < S2 < 0
  134. S1 > S2 > 0
  135. S1 = S2 = 0 }
  136. function CompareText(const S1, S2: string): integer;
  137. var
  138. i, count, count1, count2: integer; Chr1, Chr2: byte;
  139. begin
  140. result := 0;
  141. Count1 := Length(S1);
  142. Count2 := Length(S2);
  143. if (Count1>Count2) then
  144. Count := Count2
  145. else
  146. Count := Count1;
  147. i := 0;
  148. while (result=0) and (i<count) do
  149. begin
  150. inc (i);
  151. Chr1 := byte(s1[i]);
  152. Chr2 := byte(s2[i]);
  153. if Chr1 in [97..122] then
  154. dec(Chr1,32);
  155. if Chr2 in [97..122] then
  156. dec(Chr2,32);
  157. result := Chr1 - Chr2;
  158. end ;
  159. if (result = 0) then
  160. result:=(count1-count2);
  161. end;
  162. function SameText(const s1,s2:String):Boolean;
  163. begin
  164. Result:=CompareText(S1,S2)=0;
  165. end;
  166. {==============================================================================}
  167. { Ansi string functions }
  168. { these functions rely on the character set loaded by the OS }
  169. {==============================================================================}
  170. function AnsiUpperCase(const s: string): string;
  171. var len, i: integer;
  172. begin
  173. len := length(s);
  174. SetLength(result, len);
  175. for i := 1 to len do
  176. result[i] := UpperCaseTable[ord(s[i])];
  177. end ;
  178. function AnsiLowerCase(const s: string): string;
  179. var len, i: integer;
  180. begin
  181. len := length(s);
  182. SetLength(result, len);
  183. for i := 1 to len do
  184. result[i] := LowerCaseTable[ord(s[i])];
  185. end ;
  186. function AnsiCompareStr(const S1, S2: string): integer;
  187. Var I,L1,L2 : Longint;
  188. begin
  189. Result:=0;
  190. L1:=Length(S1);
  191. L2:=Length(S2);
  192. I:=1;
  193. While (Result=0) and ((I<=L1) and (I<=L2)) do
  194. begin
  195. Result:=Ord(S1[I])-Ord(S2[I]); //!! Must be replaced by ansi characters !!
  196. Inc(I);
  197. end;
  198. If Result=0 Then
  199. Result:=L1-L2;
  200. end;
  201. function AnsiCompareText(const S1, S2: string): integer;
  202. Var I,L1,L2 : Longint;
  203. begin
  204. Result:=0;
  205. L1:=Length(S1);
  206. L2:=Length(S2);
  207. I:=1;
  208. While (Result=0) and ((I<=L1) and (I<=L2)) do
  209. begin
  210. Result:=Ord(LowerCaseTable[Ord(S1[I])])-Ord(LowerCaseTable[Ord(S2[I])]); //!! Must be replaced by ansi characters !!
  211. Inc(I);
  212. end;
  213. If Result=0 Then
  214. Result:=L1-L2;
  215. end;
  216. function AnsiSameText(const s1,s2:String):Boolean;
  217. begin
  218. AnsiSameText:=AnsiCompareText(S1,S2)=0;
  219. end;
  220. function AnsiSameStr(const s1,s2:String):Boolean;
  221. begin
  222. AnsiSameStr:=AnsiCompareStr(S1,S2)=0;
  223. end;
  224. function AnsiStrComp(S1, S2: PChar): integer;
  225. begin
  226. Result:=0;
  227. If S1=Nil then
  228. begin
  229. If S2=Nil Then Exit;
  230. result:=-1;
  231. exit;
  232. end;
  233. If S2=Nil then
  234. begin
  235. Result:=1;
  236. exit;
  237. end;
  238. Repeat
  239. Result:=Ord(S1[0])-Ord(S2[0]); //!! Must be replaced by ansi characters !!
  240. Inc(S1);
  241. Inc(S2);
  242. Until (Result<>0) or ((S1[0]=#0) or (S2[0]=#0))
  243. end;
  244. function AnsiStrIComp(S1, S2: PChar): integer;
  245. begin
  246. Result:=0;
  247. If S1=Nil then
  248. begin
  249. If S2=Nil Then Exit;
  250. result:=-1;
  251. exit;
  252. end;
  253. If S2=Nil then
  254. begin
  255. Result:=1;
  256. exit;
  257. end;
  258. Repeat
  259. Result:=Ord(LowerCaseTable[Ord(S1[0])])-Ord(LowerCaseTable[Ord(S2[0])]); //!! Must be replaced by ansi characters !!
  260. Inc(S1);
  261. Inc(S2);
  262. Until (Result<>0) or ((S1[0]=#0) or (S2[0]=#0))
  263. end;
  264. function AnsiStrLComp(S1, S2: PChar; MaxLen: cardinal): integer;
  265. Var I : cardinal;
  266. begin
  267. Result:=0;
  268. If MaxLen=0 then exit;
  269. If S1=Nil then
  270. begin
  271. If S2=Nil Then Exit;
  272. result:=-1;
  273. exit;
  274. end;
  275. If S2=Nil then
  276. begin
  277. Result:=1;
  278. exit;
  279. end;
  280. I:=0;
  281. Repeat
  282. Result:=Ord(S1[0])-Ord(S2[0]); //!! Must be replaced by ansi characters !!
  283. Inc(S1);
  284. Inc(S2);
  285. Inc(I);
  286. Until (Result<>0) or ((S1[0]=#0) or (S2[0]=#0)) or (I=MaxLen)
  287. end ;
  288. function AnsiStrLIComp(S1, S2: PChar; MaxLen: cardinal): integer;
  289. Var I : cardinal;
  290. begin
  291. Result:=0;
  292. If MaxLen=0 then exit;
  293. If S1=Nil then
  294. begin
  295. If S2=Nil Then Exit;
  296. result:=-1;
  297. exit;
  298. end;
  299. If S2=Nil then
  300. begin
  301. Result:=1;
  302. exit;
  303. end;
  304. I:=0;
  305. Repeat
  306. Result:=Ord(LowerCaseTable[Ord(S1[0])])-Ord(LowerCaseTable[Ord(S2[0])]); //!! Must be replaced by ansi characters !!
  307. Inc(S1);
  308. Inc(S2);
  309. Inc(I);
  310. Until (Result<>0) or ((S1[0]=#0) or (S2[0]=#0)) or (I=MaxLen)
  311. end ;
  312. function AnsiStrLower(Str: PChar): PChar;
  313. begin
  314. result := Str;
  315. if Str <> Nil then begin
  316. while Str^ <> #0 do begin
  317. Str^ := LowerCaseTable[byte(Str^)];
  318. Str := Str + 1;
  319. end ;
  320. end ;
  321. end ;
  322. function AnsiStrUpper(Str: PChar): PChar;
  323. begin
  324. result := Str;
  325. if Str <> Nil then begin
  326. while Str^ <> #0 do begin
  327. Str^ := UpperCaseTable[byte(Str^)];
  328. Str := Str + 1;
  329. end ;
  330. end ;
  331. end ;
  332. function AnsiLastChar(const S: string): PChar;
  333. begin
  334. //!! No multibyte yet, so we return the last one.
  335. result:=StrEnd(Pchar(S));
  336. Dec(Result);
  337. end ;
  338. function AnsiStrLastChar(Str: PChar): PChar;
  339. begin
  340. //!! No multibyte yet, so we return the last one.
  341. result:=StrEnd(Str);
  342. Dec(Result);
  343. end ;
  344. {==============================================================================}
  345. { End of Ansi functions }
  346. {==============================================================================}
  347. { Trim returns a copy of S with blanks characters on the left and right stripped off }
  348. Const WhiteSpace = [' ',#10,#13,#9];
  349. function Trim(const S: string): string;
  350. var Ofs, Len: integer;
  351. begin
  352. len := Length(S);
  353. while (Len>0) and (S[Len] in WhiteSpace) do
  354. dec(Len);
  355. Ofs := 1;
  356. while (Ofs<=Len) and (S[Ofs] in WhiteSpace) do
  357. Inc(Ofs);
  358. result := Copy(S, Ofs, 1 + Len - Ofs);
  359. end ;
  360. { TrimLeft returns a copy of S with all blank characters on the left stripped off }
  361. function TrimLeft(const S: string): string;
  362. var i,l:integer;
  363. begin
  364. l := length(s);
  365. i := 1;
  366. while (i<=l) and (s[i] in whitespace) do
  367. inc(i);
  368. Result := copy(s, i, l);
  369. end ;
  370. { TrimRight returns a copy of S with all blank characters on the right stripped off }
  371. function TrimRight(const S: string): string;
  372. var l:integer;
  373. begin
  374. l := length(s);
  375. while (l>0) and (s[l] in whitespace) do
  376. dec(l);
  377. result := copy(s,1,l);
  378. end ;
  379. { QuotedStr returns S quoted left and right and every single quote in S
  380. replaced by two quotes }
  381. function QuotedStr(const S: string): string;
  382. begin
  383. result := AnsiQuotedStr(s, '''');
  384. end ;
  385. { AnsiQuotedStr returns S quoted left and right by Quote,
  386. and every single occurance of Quote replaced by two }
  387. function AnsiQuotedStr(const S: string; Quote: char): string;
  388. var i, j, count: integer;
  389. begin
  390. result := '' + Quote;
  391. count := length(s);
  392. i := 0;
  393. j := 0;
  394. while i < count do begin
  395. i := i + 1;
  396. if S[i] = Quote then begin
  397. result := result + copy(S, 1 + j, i - j) + Quote;
  398. j := i;
  399. end ;
  400. end ;
  401. if i <> j then
  402. result := result + copy(S, 1 + j, i - j);
  403. result := result + Quote;
  404. end ;
  405. { AnsiExtractQuotedStr returns a copy of Src with quote characters
  406. deleted to the left and right and double occurances
  407. of Quote replaced by a single Quote }
  408. function AnsiExtractQuotedStr(var Src: PChar; Quote: Char): string;
  409. var i: integer; P, Q,R: PChar;
  410. begin
  411. P := Src;
  412. Q := StrEnd(P);
  413. result:='';
  414. if P=Q then exit;
  415. if P^<>quote then exit;
  416. inc(p);
  417. setlength(result,(Q-P)+1);
  418. R:=@Result[1];
  419. i := 0;
  420. while P <> Q do
  421. begin
  422. R^:=P^;
  423. inc(R);
  424. if (P^ = Quote) then
  425. begin
  426. P := P + 1;
  427. if (p^ <> Quote) then
  428. begin
  429. dec(R);
  430. break;
  431. end;
  432. end;
  433. P := P + 1;
  434. end ;
  435. src:=p;
  436. SetLength(result, (R-pchar(@Result[1])));
  437. end ;
  438. { AdjustLineBreaks returns S with all CR characters not followed by LF
  439. replaced with CR/LF }
  440. // under Linux all CR characters or CR/LF combinations should be replaced with LF
  441. function AdjustLineBreaks(const S: string): string;
  442. begin
  443. Result:=AdjustLineBreaks(S,DefaultTextLineBreakStyle);
  444. end;
  445. function AdjustLineBreaks(const S: string; Style: TTextLineBreakStyle): string;
  446. var
  447. Source,Dest: PChar;
  448. DestLen: Integer;
  449. I,J,L: Longint;
  450. begin
  451. Source:=Pointer(S);
  452. L:=Length(S);
  453. DestLen:=L;
  454. I:=1;
  455. while (I<=L) do
  456. begin
  457. case S[i] of
  458. #10: if (Style=tlbsCRLF) then
  459. Inc(DestLen);
  460. #13: if (Style=tlbsCRLF) then
  461. if (I<L) and (S[i+1]=#10) then
  462. Inc(I)
  463. else
  464. Inc(DestLen)
  465. else if (I<L) and (S[I+1]=#10) then
  466. Dec(DestLen);
  467. end;
  468. Inc(I);
  469. end;
  470. if (DestLen=L) then
  471. Result:=S
  472. else
  473. begin
  474. SetLength(Result, DestLen);
  475. FillChar(Result[1],DestLen,0);
  476. Dest := Pointer(Result);
  477. J:=0;
  478. I:=0;
  479. While I<L do
  480. case Source[I] of
  481. #10: begin
  482. if Style=tlbsCRLF then
  483. begin
  484. Dest[j]:=#13;
  485. Inc(J);
  486. end;
  487. Dest[J] := #10;
  488. Inc(J);
  489. Inc(I);
  490. end;
  491. #13: begin
  492. if Style=tlbsCRLF then
  493. begin
  494. Dest[j] := #13;
  495. Inc(J);
  496. end;
  497. Dest[j]:=#10;
  498. Inc(J);
  499. Inc(I);
  500. if Source[I]=#10 then
  501. Inc(I);
  502. end;
  503. else
  504. Dest[j]:=Source[i];
  505. Inc(J);
  506. Inc(I);
  507. end;
  508. end;
  509. end;
  510. { IsValidIdent returns true if the first character of Ident is in:
  511. 'A' to 'Z', 'a' to 'z' or '_' and the following characters are
  512. on of: 'A' to 'Z', 'a' to 'z', '0'..'9' or '_' }
  513. function IsValidIdent(const Ident: string): boolean;
  514. var i, len: integer;
  515. begin
  516. result := false;
  517. len := length(Ident);
  518. if len <> 0 then begin
  519. result := Ident[1] in ['A'..'Z', 'a'..'z', '_'];
  520. i := 1;
  521. while (result) and (i < len) do begin
  522. i := i + 1;
  523. result := result and (Ident[i] in ['A'..'Z', 'a'..'z', '0'..'9', '_']);
  524. end ;
  525. end ;
  526. end ;
  527. { IntToStr returns a string representing the value of Value }
  528. function IntToStr(Value: integer): string;
  529. begin
  530. System.Str(Value, result);
  531. end ;
  532. {$IFNDEF VIRTUALPASCAL}
  533. function IntToStr(Value: int64): string;
  534. begin
  535. System.Str(Value, result);
  536. end ;
  537. {$ENDIF}
  538. function IntToStr(Value: QWord): string;
  539. begin
  540. System.Str(Value, result);
  541. end ;
  542. { IntToHex returns a string representing the hexadecimal value of Value }
  543. const
  544. HexDigits: array[0..15] of char = '0123456789ABCDEF';
  545. function IntToHex(Value: integer; Digits: integer): string;
  546. var i: integer;
  547. begin
  548. SetLength(result, digits);
  549. for i := 0 to digits - 1 do
  550. begin
  551. result[digits - i] := HexDigits[value and 15];
  552. value := value shr 4;
  553. end ;
  554. while value <> 0 do begin
  555. result := HexDigits[value and 15] + result;
  556. value := value shr 4;
  557. end;
  558. end ;
  559. {$IFNDEF VIRTUALPASCAL} // overloading
  560. function IntToHex(Value: int64; Digits: integer): string;
  561. var i: integer;
  562. begin
  563. SetLength(result, digits);
  564. for i := 0 to digits - 1 do
  565. begin
  566. result[digits - i] := HexDigits[value and 15];
  567. value := value shr 4;
  568. end ;
  569. while value <> 0 do begin
  570. result := HexDigits[value and 15] + result;
  571. value := value shr 4;
  572. end;
  573. end ;
  574. {$ENDIF}
  575. function TryStrToInt(const s: string; var i : integer) : boolean;
  576. var Error : word;
  577. begin
  578. Val(s, i, Error);
  579. TryStrToInt:=Error=0
  580. end;
  581. { StrToInt converts the string S to an integer value,
  582. if S does not represent a valid integer value EConvertError is raised }
  583. function StrToInt(const S: string): integer;
  584. {$IFDEF VIRTUALPASCAL}
  585. var Error: longint;
  586. {$ELSE}
  587. var Error: word;
  588. {$ENDIF}
  589. begin
  590. Val(S, result, Error);
  591. if Error <> 0 then raise EConvertError.createfmt(SInValidInteger,[S]);
  592. end ;
  593. function StrToInt64(const S: string): int64;
  594. {$IFDEF VIRTUALPASCAL}
  595. var Error: longint;
  596. {$ELSE}
  597. var Error: word;
  598. {$ENDIF}
  599. begin
  600. Val(S, result, Error);
  601. if Error <> 0 then raise EConvertError.createfmt(SInValidInteger,[S]);
  602. end;
  603. function TryStrToInt64(const s: string; var i : int64) : boolean;
  604. var Error : word;
  605. begin
  606. Val(s, i, Error);
  607. TryStrToInt64:=Error=0
  608. end;
  609. { StrToIntDef converts the string S to an integer value,
  610. Default is returned in case S does not represent a valid integer value }
  611. function StrToIntDef(const S: string; Default: integer): integer;
  612. {$IFDEF VIRTUALPASCAL}
  613. var Error: longint;
  614. {$ELSE}
  615. var Error: word;
  616. {$ENDIF}
  617. begin
  618. Val(S, result, Error);
  619. if Error <> 0 then result := Default;
  620. end ;
  621. { StrToIntDef converts the string S to an integer value,
  622. Default is returned in case S does not represent a valid integer value }
  623. function StrToInt64Def(const S: string; Default: int64): int64;
  624. {$IFDEF VIRTUALPASCAL}
  625. var Error: longint;
  626. {$ELSE}
  627. var Error: word;
  628. {$ENDIF}
  629. begin
  630. Val(S, result, Error);
  631. if Error <> 0 then result := Default;
  632. end ;
  633. { LoadStr returns the string resource Ident. }
  634. function LoadStr(Ident: integer): string;
  635. begin
  636. result:='';
  637. end ;
  638. { FmtLoadStr returns the string resource Ident and formats it accordingly }
  639. function FmtLoadStr(Ident: integer; const Args: array of const): string;
  640. begin
  641. result:='';
  642. end;
  643. Const
  644. feInvalidFormat = 1;
  645. feMissingArgument = 2;
  646. feInvalidArgIndex = 3;
  647. {$ifdef fmtdebug}
  648. Procedure Log (Const S: String);
  649. begin
  650. Writeln (S);
  651. end;
  652. {$endif}
  653. Procedure DoFormatError (ErrCode : Longint);
  654. Var
  655. S : String;
  656. begin
  657. //!! must be changed to contain format string...
  658. S:='';
  659. Case ErrCode of
  660. feInvalidFormat : raise EConvertError.Createfmt(SInvalidFormat,[s]);
  661. feMissingArgument : raise EConvertError.Createfmt(SArgumentMissing,[s]);
  662. feInvalidArgIndex : raise EConvertError.Createfmt(SInvalidArgIndex,[s]);
  663. end;
  664. end;
  665. Function Format (Const Fmt : String; const Args : Array of const) : String;
  666. Var ChPos,OldPos,ArgPos,DoArg,Len : Longint;
  667. Hs,ToAdd : String;
  668. Index,Width,Prec : Longint;
  669. Left : Boolean;
  670. Fchar : char;
  671. vl : int64;
  672. {
  673. ReadFormat reads the format string. It returns the type character in
  674. uppercase, and sets index, Width, Prec to their correct values,
  675. or -1 if not set. It sets Left to true if left alignment was requested.
  676. In case of an error, DoFormatError is called.
  677. }
  678. Function ReadFormat : Char;
  679. Var Value : longint;
  680. Procedure ReadInteger;
  681. {$IFDEF VIRTUALPASCAL}
  682. var Code: longint;
  683. {$ELSE}
  684. var Code: word;
  685. {$ENDIF}
  686. begin
  687. If Value<>-1 then exit; // Was already read.
  688. OldPos:=chPos;
  689. While (Chpos<=Len) and
  690. (Pos(Fmt[chpos],'1234567890')<>0) do inc(chpos);
  691. If Chpos>len then
  692. DoFormatError(feInvalidFormat);
  693. If Fmt[Chpos]='*' then
  694. begin
  695. If (Chpos>OldPos) or (ArgPos>High(Args))
  696. or (Args[ArgPos].Vtype<>vtInteger) then
  697. DoFormatError(feInvalidFormat);
  698. Value:=Args[ArgPos].VInteger;
  699. Inc(ArgPos);
  700. Inc(chPos);
  701. end
  702. else
  703. begin
  704. If (OldPos<chPos) Then
  705. begin
  706. Val (Copy(Fmt,OldPos,ChPos-OldPos),value,code);
  707. // This should never happen !!
  708. If Code>0 then DoFormatError (feInvalidFormat);
  709. end
  710. else
  711. Value:=-1;
  712. end;
  713. end;
  714. Procedure ReadIndex;
  715. begin
  716. ReadInteger;
  717. If Fmt[ChPos]=':' then
  718. begin
  719. If Value=-1 then DoFormatError(feMissingArgument);
  720. Index:=Value;
  721. Value:=-1;
  722. Inc(Chpos);
  723. end;
  724. {$ifdef fmtdebug}
  725. Log ('Read index');
  726. {$endif}
  727. end;
  728. Procedure ReadLeft;
  729. begin
  730. If Fmt[chpos]='-' then
  731. begin
  732. left:=True;
  733. Inc(chpos);
  734. end
  735. else
  736. Left:=False;
  737. {$ifdef fmtdebug}
  738. Log ('Read Left');
  739. {$endif}
  740. end;
  741. Procedure ReadWidth;
  742. begin
  743. ReadInteger;
  744. If Value<>-1 then
  745. begin
  746. Width:=Value;
  747. Value:=-1;
  748. end;
  749. {$ifdef fmtdebug}
  750. Log ('Read width');
  751. {$endif}
  752. end;
  753. Procedure ReadPrec;
  754. begin
  755. If Fmt[chpos]='.' then
  756. begin
  757. inc(chpos);
  758. ReadInteger;
  759. If Value=-1 then
  760. Value:=0;
  761. prec:=Value;
  762. end;
  763. {$ifdef fmtdebug}
  764. Log ('Read precision');
  765. {$endif}
  766. end;
  767. begin
  768. {$ifdef fmtdebug}
  769. Log ('Start format');
  770. {$endif}
  771. Index:=-1;
  772. Width:=-1;
  773. Prec:=-1;
  774. Value:=-1;
  775. inc(chpos);
  776. If Fmt[Chpos]='%' then
  777. begin
  778. Result:='%';
  779. exit; // VP fix
  780. end;
  781. ReadIndex;
  782. ReadLeft;
  783. ReadWidth;
  784. ReadPrec;
  785. ReadFormat:=Upcase(Fmt[ChPos]);
  786. {$ifdef fmtdebug}
  787. Log ('End format');
  788. {$endif}
  789. end;
  790. {$ifdef fmtdebug}
  791. Procedure DumpFormat (C : char);
  792. begin
  793. Write ('Fmt : ',fmt:10);
  794. Write (' Index : ',Index:3);
  795. Write (' Left : ',left:5);
  796. Write (' Width : ',Width:3);
  797. Write (' Prec : ',prec:3);
  798. Writeln (' Type : ',C);
  799. end;
  800. {$endif}
  801. function Checkarg (AT : Longint;err:boolean):boolean;
  802. {
  803. Check if argument INDEX is of correct type (AT)
  804. If Index=-1, ArgPos is used, and argpos is augmented with 1
  805. DoArg is set to the argument that must be used.
  806. }
  807. begin
  808. result:=false;
  809. if Index=-1 then
  810. DoArg:=Argpos
  811. else
  812. DoArg:=Index;
  813. ArgPos:=DoArg+1;
  814. If (Doarg>High(Args)) or (Args[Doarg].Vtype<>AT) then
  815. begin
  816. if err then
  817. DoFormatError(feInvalidArgindex);
  818. dec(ArgPos);
  819. exit;
  820. end;
  821. result:=true;
  822. end;
  823. Const Zero = '000000000000000000000000000000000000000000000000000000000000000';
  824. begin
  825. Result:='';
  826. Len:=Length(Fmt);
  827. Chpos:=1;
  828. OldPos:=1;
  829. ArgPos:=0;
  830. While chpos<=len do
  831. begin
  832. While (ChPos<=Len) and (Fmt[chpos]<>'%') do
  833. inc(chpos);
  834. If ChPos>OldPos Then
  835. Result:=Result+Copy(Fmt,OldPos,Chpos-Oldpos);
  836. If ChPos<Len then
  837. begin
  838. FChar:=ReadFormat;
  839. {$ifdef fmtdebug}
  840. DumpFormat(FCHar);
  841. {$endif}
  842. Case FChar of
  843. 'D' : begin
  844. if Checkarg(vtinteger,false) then
  845. Str(Args[Doarg].VInteger,ToAdd)
  846. {$IFNDEF VIRTUALPASCAL}
  847. else if CheckArg(vtInt64,true) then
  848. Str(Args[DoArg].VInt64^,toadd)
  849. {$ENDIF}
  850. ;
  851. Width:=Abs(width);
  852. Index:=Prec-Length(ToAdd);
  853. If ToAdd[1]<>'-' then
  854. ToAdd:=StringOfChar('0',Index)+ToAdd
  855. else
  856. // + 1 to accomodate for - sign in length !!
  857. Insert(StringOfChar('0',Index+1),toadd,2);
  858. end;
  859. 'U' : begin
  860. if Checkarg(vtinteger,false) then
  861. Str(cardinal(Args[Doarg].VInteger),ToAdd)
  862. {$IFNDEF VIRTUALPASCAL}
  863. else if CheckArg(vtInt64,true) then
  864. Str(qword(Args[DoArg].VInt64^),toadd)
  865. {$ENDIF}
  866. ;
  867. Width:=Abs(width);
  868. Index:=Prec-Length(ToAdd);
  869. ToAdd:=StringOfChar('0',Index)+ToAdd
  870. end;
  871. 'E' : begin
  872. CheckArg(vtExtended,true);
  873. ToAdd:=FloatToStrF(Args[doarg].VExtended^,ffexponent,Prec,3);
  874. end;
  875. 'F' : begin
  876. CheckArg(vtExtended,true);
  877. ToAdd:=FloatToStrF(Args[doarg].VExtended^,ffFixed,9999,Prec);
  878. end;
  879. 'G' : begin
  880. CheckArg(vtExtended,true);
  881. ToAdd:=FloatToStrF(Args[doarg].VExtended^,ffGeneral,Prec,3);
  882. end;
  883. 'N' : begin
  884. CheckArg(vtExtended,true);
  885. ToAdd:=FloatToStrF(Args[doarg].VExtended^,ffNumber,9999,Prec);
  886. end;
  887. 'M' : begin
  888. CheckArg(vtExtended,true);
  889. ToAdd:=FloatToStrF(Args[doarg].VExtended^,ffCurrency,9999,Prec);
  890. end;
  891. 'S' : begin
  892. if CheckArg(vtString,false) then
  893. hs:=Args[doarg].VString^
  894. else
  895. if CheckArg(vtChar,false) then
  896. hs:=Args[doarg].VChar
  897. else
  898. if CheckArg(vtPChar,false) then
  899. hs:=Args[doarg].VPChar
  900. else
  901. {$ifndef VER1_0}
  902. if CheckArg(vtPWideChar,false) then
  903. hs:=WideString(Args[doarg].VPWideChar)
  904. else
  905. if CheckArg(vtWideChar,false) then
  906. hs:=WideString(Args[doarg].VWideChar)
  907. else
  908. if CheckArg(vtWidestring,false) then
  909. hs:=WideString(Args[doarg].VWideString)
  910. else
  911. {$endif VER1_0}
  912. if CheckArg(vtAnsiString,true) then
  913. hs:=ansistring(Args[doarg].VAnsiString);
  914. Index:=Length(hs);
  915. If (Prec<>-1) and (Index>Prec) then
  916. Index:=Prec;
  917. ToAdd:=Copy(hs,1,Index);
  918. end;
  919. 'P' : Begin
  920. CheckArg(vtpointer,true);
  921. ToAdd:=HexStr(ptrint(Args[DoArg].VPointer),sizeof(Ptrint)*2);
  922. // Insert ':'. Is this needed in 32 bit ? No it isn't.
  923. // Insert(':',ToAdd,5);
  924. end;
  925. 'X' : begin
  926. if Checkarg(vtinteger,false) then
  927. begin
  928. vl:=Args[Doarg].VInteger;
  929. index:=16;
  930. end
  931. else
  932. begin
  933. CheckArg(vtInt64,true);
  934. vl:=Args[DoArg].VInt64^;
  935. index:=31;
  936. end;
  937. If Prec>index then
  938. ToAdd:=HexStr(vl,index)
  939. else
  940. begin
  941. // determine minimum needed number of hex digits.
  942. Index:=1;
  943. {$Ifdef ver1_0}
  944. While (DWord(1 shl (Index*4))<=DWord(Args[DoArg].VInteger)) and (index<8) do
  945. inc(Index);
  946. {$else}
  947. While (qWord(1 shl (Index*4))<=qWord(vl)) and (index<16) do
  948. inc(Index);
  949. {$endif}
  950. If Index>Prec then
  951. Prec:=Index;
  952. {$ifdef ver1_0}
  953. ToAdd:=HexStr(int64(vl),Prec);
  954. {$else}
  955. ToAdd:=HexStr(qword(vl),Prec);
  956. {$endif}
  957. end;
  958. end;
  959. '%': ToAdd:='%';
  960. end;
  961. If Width<>-1 then
  962. If Length(ToAdd)<Width then
  963. If not Left then
  964. ToAdd:=Space(Width-Length(ToAdd))+ToAdd
  965. else
  966. ToAdd:=ToAdd+space(Width-Length(ToAdd));
  967. Result:=Result+ToAdd;
  968. end;
  969. inc(chpos);
  970. Oldpos:=chpos;
  971. end;
  972. end;
  973. Function FormatBuf (Var Buffer; BufLen : Cardinal;
  974. Const Fmt; fmtLen : Cardinal;
  975. Const Args : Array of const) : Cardinal;
  976. Var S,F : String;
  977. begin
  978. Setlength(F,fmtlen);
  979. if fmtlen > 0 then
  980. Move(fmt,F[1],fmtlen);
  981. S:=Format (F,Args);
  982. If Cardinal(Length(S))<Buflen then
  983. Result:=Length(S)
  984. else
  985. Result:=Buflen;
  986. Move(S[1],Buffer,Result);
  987. end;
  988. Procedure FmtStr(Var Res: String; Const Fmt : String; Const args: Array of const);
  989. begin
  990. Res:=Format(fmt,Args);
  991. end;
  992. Function StrFmt(Buffer,Fmt : PChar; Const args: Array of const) : Pchar;
  993. begin
  994. Buffer[FormatBuf(Buffer^,Maxint,Fmt^,strlen(fmt),args)]:=#0;
  995. Result:=Buffer;
  996. end;
  997. Function StrLFmt(Buffer : PCHar; Maxlen : Cardinal;Fmt : PChar; Const args: Array of const) : Pchar;
  998. begin
  999. Buffer[FormatBuf(Buffer^,MaxLen,Fmt^,strlen(fmt),args)]:=#0;
  1000. Result:=Buffer;
  1001. end;
  1002. Function StrToFloat(Const S: String): Extended;
  1003. Begin
  1004. If Not TextToFloat(Pchar(S),Result) then
  1005. Raise EConvertError.createfmt(SInValidFLoat,[S]);
  1006. End;
  1007. function StrToFloatDef(const S: string; const Default: Extended): Extended;
  1008. begin
  1009. if not TextToFloat(PChar(S),Result,fvExtended) then
  1010. Result:=Default;
  1011. end;
  1012. Function TextToFloat(Buffer: PChar; Var Value: Extended): Boolean;
  1013. Var
  1014. E,P : Integer;
  1015. S : String;
  1016. Begin
  1017. S:=StrPas(Buffer);
  1018. P:=Pos(DecimalSeparator,S);
  1019. If (P<>0) Then
  1020. S[P] := '.';
  1021. Val(S,Value,E);
  1022. Result:=(E=0);
  1023. End;
  1024. Function TextToFloat(Buffer: PChar; Var Value; ValueType: TFloatValue): Boolean;
  1025. Var
  1026. E,P : Integer;
  1027. S : String;
  1028. C : Currency;
  1029. Ext : Extended;
  1030. Begin
  1031. S:=StrPas(Buffer);
  1032. P:=Pos(ThousandSeparator,S);
  1033. While (P<>0) do
  1034. begin
  1035. Delete(S,P,1);
  1036. P:=Pos(ThousandSeparator,S);
  1037. end;
  1038. P:=Pos(DecimalSeparator,S);
  1039. If (P<>0) Then
  1040. S[P] := '.';
  1041. case ValueType of
  1042. fvCurrency:
  1043. Val(S,Currency(Value),E);
  1044. fvExtended:
  1045. Val(S,Extended(Value),E);
  1046. fvDouble:
  1047. Val(S,Double(Value),E);
  1048. fvSingle:
  1049. Val(S,Single(Value),E);
  1050. fvComp:
  1051. Val(S,Comp(Value),E);
  1052. fvReal:
  1053. Val(S,Real(Value),E);
  1054. end;
  1055. Result:=(E=0);
  1056. End;
  1057. Function FloatToStr(Value: Extended): String;
  1058. Begin
  1059. Result := FloatToStrF(Value, ffGeneral, 15, 0);
  1060. End;
  1061. Function FloatToText(Buffer: PChar; Value: Extended; format: TFloatFormat; Precision, Digits: Integer): Longint;
  1062. Var
  1063. Tmp: String[40];
  1064. Begin
  1065. Tmp := FloatToStrF(Value, format, Precision, Digits);
  1066. Result := Length(Tmp);
  1067. Move(Tmp[1], Buffer[0], Result);
  1068. End;
  1069. Function FloatToStrF(Value: Extended; format: TFloatFormat; Precision, Digits: Integer): String;
  1070. Var
  1071. P: Integer;
  1072. Negative, TooSmall, TooLarge: Boolean;
  1073. Begin
  1074. Case format Of
  1075. ffGeneral:
  1076. Begin
  1077. If (Precision = -1) Or (Precision > 15) Then Precision := 15;
  1078. TooSmall := (Abs(Value) < 0.00001) and (Value>0.0);
  1079. If Not TooSmall Then
  1080. Begin
  1081. Str(Value:0:999, Result);
  1082. P := Pos('.', Result);
  1083. Result[P] := DecimalSeparator;
  1084. TooLarge := P > Precision + 1;
  1085. End;
  1086. If TooSmall Or TooLarge Then
  1087. begin
  1088. Result := FloatToStrF(Value, ffExponent, Precision, Digits);
  1089. // Strip unneeded zeroes.
  1090. P:=Pos('E',result)-1;
  1091. If P<>-1 then
  1092. While (P>1) and (Result[P]='0') do
  1093. begin
  1094. system.Delete(Result,P,1);
  1095. Dec(P);
  1096. end;
  1097. end
  1098. else
  1099. begin
  1100. P := Length(Result);
  1101. While Result[P] = '0' Do Dec(P);
  1102. If Result[P] = DecimalSeparator Then Dec(P);
  1103. SetLength(Result, P);
  1104. end;
  1105. End;
  1106. ffExponent:
  1107. Begin
  1108. If (Precision = -1) Or (Precision > 15) Then Precision := 15;
  1109. Str(Value:Precision + 8, Result);
  1110. Result[3] := DecimalSeparator;
  1111. P:=4;
  1112. While (P>0) and (Digits < P) And (Result[Precision + 5] = '0') do
  1113. Begin
  1114. If P<>1 then
  1115. system.Delete(Result, Precision + 5, 1)
  1116. else
  1117. system.Delete(Result, Precision + 3, 3);
  1118. Dec(P);
  1119. end;
  1120. If Result[1] = ' ' Then
  1121. System.Delete(Result, 1, 1);
  1122. End;
  1123. ffFixed:
  1124. Begin
  1125. If Digits = -1 Then Digits := 2
  1126. Else If Digits > 18 Then Digits := 18;
  1127. Str(Value:0:Digits, Result);
  1128. If Result[1] = ' ' Then
  1129. System.Delete(Result, 1, 1);
  1130. P := Pos('.', Result);
  1131. If P <> 0 Then Result[P] := DecimalSeparator;
  1132. End;
  1133. ffNumber:
  1134. Begin
  1135. If Digits = -1 Then Digits := 2
  1136. Else If Digits > 15 Then Digits := 15;
  1137. Str(Value:0:Digits, Result);
  1138. If Result[1] = ' ' Then System.Delete(Result, 1, 1);
  1139. P := Pos('.', Result);
  1140. If P <> 0 Then
  1141. Result[P] := DecimalSeparator
  1142. else
  1143. P := Length(Result)+1;
  1144. Dec(P, 3);
  1145. While (P > 1) Do
  1146. Begin
  1147. If Result[P - 1] <> '-' Then Insert(ThousandSeparator, Result, P);
  1148. Dec(P, 3);
  1149. End;
  1150. End;
  1151. ffCurrency:
  1152. Begin
  1153. If Value < 0 Then
  1154. Begin
  1155. Negative := True;
  1156. Value := -Value;
  1157. End
  1158. Else Negative := False;
  1159. If Digits = -1 Then Digits := CurrencyDecimals
  1160. Else If Digits > 18 Then Digits := 18;
  1161. Str(Value:0:Digits, Result);
  1162. If Result[1] = ' ' Then System.Delete(Result, 1, 1);
  1163. P := Pos('.', Result);
  1164. If P <> 0 Then Result[P] := DecimalSeparator;
  1165. Dec(P, 3);
  1166. While (P > 1) Do
  1167. Begin
  1168. Insert(ThousandSeparator, Result, P);
  1169. Dec(P, 3);
  1170. End;
  1171. If Not Negative Then
  1172. Begin
  1173. Case CurrencyFormat Of
  1174. 0: Result := CurrencyString + Result;
  1175. 1: Result := Result + CurrencyString;
  1176. 2: Result := CurrencyString + ' ' + Result;
  1177. 3: Result := Result + ' ' + CurrencyString;
  1178. End
  1179. End
  1180. Else
  1181. Begin
  1182. Case NegCurrFormat Of
  1183. 0: Result := '(' + CurrencyString + Result + ')';
  1184. 1: Result := '-' + CurrencyString + Result;
  1185. 2: Result := CurrencyString + '-' + Result;
  1186. 3: Result := CurrencyString + Result + '-';
  1187. 4: Result := '(' + Result + CurrencyString + ')';
  1188. 5: Result := '-' + Result + CurrencyString;
  1189. 6: Result := Result + '-' + CurrencyString;
  1190. 7: Result := Result + CurrencyString + '-';
  1191. 8: Result := '-' + Result + ' ' + CurrencyString;
  1192. 9: Result := '-' + CurrencyString + ' ' + Result;
  1193. 10: Result := CurrencyString + ' ' + Result + '-';
  1194. End;
  1195. End;
  1196. End;
  1197. End;
  1198. End;
  1199. Function FloatToDateTime (Const Value : Extended) : TDateTime;
  1200. begin
  1201. If (Value<MinDateTime) or (Value>MaxDateTime) then
  1202. Raise EConvertError.CreateFmt (SInvalidDateTime,[Value]);
  1203. Result:=Value;
  1204. end;
  1205. function TryFloatToCurr(const Value: Extended; var AResult: Currency): Boolean;
  1206. begin
  1207. {$ifndef VER1_0}
  1208. Result:=(Value>=MinCurrency) and (Value<=MaxCurrency);
  1209. if Result then
  1210. AResult := Value;
  1211. {$else VER1_0}
  1212. Result:=false;
  1213. {$endif VER1_0}
  1214. end;
  1215. function FloatToCurr(const Value: Extended): Currency;
  1216. begin
  1217. if not TryFloatToCurr(Value, Result) then
  1218. Raise EConvertError.CreateFmt(SInvalidCurrency, [FloatToStr(Value)]);
  1219. end;
  1220. Function CurrToStr(Value: Currency): string;
  1221. begin
  1222. Result:=FloatToStrF(Value,ffNumber,15,2);
  1223. end;
  1224. function StrToCurr(const S: string): Currency;
  1225. begin
  1226. if not TextToFloat(PChar(S), Result, fvCurrency) then
  1227. Raise EConvertError.createfmt(SInValidFLoat,[S]);
  1228. end;
  1229. function StrToCurrDef(const S: string; Default : Currency): Currency;
  1230. begin
  1231. if not TextToFloat(PChar(S), Result, fvCurrency) then
  1232. Result:=Default;
  1233. end;
  1234. function StrToBool(const S: string): Boolean;
  1235. Var
  1236. Temp : String;
  1237. D : Double;
  1238. {$IFDEF VIRTUALPASCAL}
  1239. Code: longint;
  1240. {$ELSE}
  1241. Code: word;
  1242. {$ENDIF}
  1243. begin
  1244. Temp:=upcase(S);
  1245. Val(temp,D,code);
  1246. If Code=0 then
  1247. Result:=(D<>0.0)
  1248. else If Temp='TRUE' then
  1249. result:=true
  1250. else if Temp='FALSE' then
  1251. result:=false
  1252. else
  1253. Raise EConvertError.CreateFmt(SInvalidBoolean,[S]);
  1254. end;
  1255. function BoolToStr(B: Boolean): string;
  1256. begin
  1257. If B then
  1258. Result:='TRUE'
  1259. else
  1260. Result:='FALSE';
  1261. end;
  1262. Function FloatToTextFmt(Buffer: PChar; Value: Extended; format: PChar): Integer;
  1263. Var
  1264. Digits: String[40]; { String Of Digits }
  1265. Exponent: String[8]; { Exponent strin }
  1266. FmtStart, FmtStop: PChar; { Start And End Of relevant part }
  1267. { Of format String }
  1268. ExpFmt, ExpSize: Integer; { Type And Length Of }
  1269. { exponential format chosen }
  1270. Placehold: Array[1..4] Of Integer; { Number Of placeholders In All }
  1271. { four Sections }
  1272. thousand: Boolean; { thousand separators? }
  1273. UnexpectedDigits: Integer; { Number Of unexpected Digits that }
  1274. { have To be inserted before the }
  1275. { First placeholder. }
  1276. DigitExponent: Integer; { Exponent Of First digit In }
  1277. { Digits Array. }
  1278. { Find end of format section starting at P. False, if empty }
  1279. Function GetSectionEnd(Var P: PChar): Boolean;
  1280. Var
  1281. C: Char;
  1282. SQ, DQ: Boolean;
  1283. Begin
  1284. Result := False;
  1285. SQ := False;
  1286. DQ := False;
  1287. C := P[0];
  1288. While (C<>#0) And ((C<>';') Or SQ Or DQ) Do
  1289. Begin
  1290. Result := True;
  1291. Case C Of
  1292. #34: If Not SQ Then DQ := Not DQ;
  1293. #39: If Not DQ Then SQ := Not SQ;
  1294. End;
  1295. Inc(P);
  1296. C := P[0];
  1297. End;
  1298. End;
  1299. { Find start and end of format section to apply. If section doesn't exist,
  1300. use section 1. If section 2 is used, the sign of value is ignored. }
  1301. Procedure GetSectionRange(section: Integer);
  1302. Var
  1303. Sec: Array[1..3] Of PChar;
  1304. SecOk: Array[1..3] Of Boolean;
  1305. Begin
  1306. Sec[1] := format;
  1307. SecOk[1] := GetSectionEnd(Sec[1]);
  1308. If section > 1 Then
  1309. Begin
  1310. Sec[2] := Sec[1];
  1311. If Sec[2][0] <> #0 Then
  1312. Inc(Sec[2]);
  1313. SecOk[2] := GetSectionEnd(Sec[2]);
  1314. If section > 2 Then
  1315. Begin
  1316. Sec[3] := Sec[2];
  1317. If Sec[3][0] <> #0 Then
  1318. Inc(Sec[3]);
  1319. SecOk[3] := GetSectionEnd(Sec[3]);
  1320. End;
  1321. End;
  1322. If Not SecOk[1] Then
  1323. FmtStart := Nil
  1324. Else
  1325. Begin
  1326. If Not SecOk[section] Then
  1327. section := 1
  1328. Else If section = 2 Then
  1329. Value := -Value; { Remove sign }
  1330. If section = 1 Then FmtStart := format Else
  1331. Begin
  1332. FmtStart := Sec[section - 1];
  1333. Inc(FmtStart);
  1334. End;
  1335. FmtStop := Sec[section];
  1336. End;
  1337. End;
  1338. { Find format section ranging from FmtStart to FmtStop. }
  1339. Procedure GetFormatOptions;
  1340. Var
  1341. Fmt: PChar;
  1342. SQ, DQ: Boolean;
  1343. area: Integer;
  1344. Begin
  1345. SQ := False;
  1346. DQ := False;
  1347. Fmt := FmtStart;
  1348. ExpFmt := 0;
  1349. area := 1;
  1350. thousand := False;
  1351. Placehold[1] := 0;
  1352. Placehold[2] := 0;
  1353. Placehold[3] := 0;
  1354. Placehold[4] := 0;
  1355. While Fmt < FmtStop Do
  1356. Begin
  1357. Case Fmt[0] Of
  1358. #34:
  1359. Begin
  1360. If Not SQ Then
  1361. DQ := Not DQ;
  1362. Inc(Fmt);
  1363. End;
  1364. #39:
  1365. Begin
  1366. If Not DQ Then
  1367. SQ := Not SQ;
  1368. Inc(Fmt);
  1369. End;
  1370. Else
  1371. { This was 'if not SQ or DQ'. Looked wrong... }
  1372. If Not SQ Or DQ Then
  1373. Begin
  1374. Case Fmt[0] Of
  1375. '0':
  1376. Begin
  1377. Case area Of
  1378. 1:
  1379. area := 2;
  1380. 4:
  1381. Begin
  1382. area := 3;
  1383. Inc(Placehold[3], Placehold[4]);
  1384. Placehold[4] := 0;
  1385. End;
  1386. End;
  1387. Inc(Placehold[area]);
  1388. Inc(Fmt);
  1389. End;
  1390. '#':
  1391. Begin
  1392. If area=3 Then
  1393. area:=4;
  1394. Inc(Placehold[area]);
  1395. Inc(Fmt);
  1396. End;
  1397. '.':
  1398. Begin
  1399. If area<3 Then
  1400. area:=3;
  1401. Inc(Fmt);
  1402. End;
  1403. ',':
  1404. Begin
  1405. thousand := True;
  1406. Inc(Fmt);
  1407. End;
  1408. 'e', 'E':
  1409. If ExpFmt = 0 Then
  1410. Begin
  1411. If (Fmt[0]='E') Then
  1412. ExpFmt:=1
  1413. Else
  1414. ExpFmt := 3;
  1415. Inc(Fmt);
  1416. If (Fmt<FmtStop) Then
  1417. Begin
  1418. Case Fmt[0] Of
  1419. '+':
  1420. Begin
  1421. End;
  1422. '-':
  1423. Inc(ExpFmt);
  1424. Else
  1425. ExpFmt := 0;
  1426. End;
  1427. If ExpFmt <> 0 Then
  1428. Begin
  1429. Inc(Fmt);
  1430. ExpSize := 0;
  1431. While (Fmt<FmtStop) And
  1432. (ExpSize<4) And
  1433. (Fmt[0] In ['0'..'9']) Do
  1434. Begin
  1435. Inc(ExpSize);
  1436. Inc(Fmt);
  1437. End;
  1438. End;
  1439. End;
  1440. End
  1441. Else
  1442. Inc(Fmt);
  1443. Else { Case }
  1444. Inc(Fmt);
  1445. End; { Case }
  1446. End; { Begin }
  1447. End; { Case }
  1448. End; { While .. Begin }
  1449. End;
  1450. Procedure FloatToStr;
  1451. Var
  1452. I, J, Exp, Width, Decimals, DecimalPoint, len: Integer;
  1453. Begin
  1454. If ExpFmt = 0 Then
  1455. Begin
  1456. { Fixpoint }
  1457. Decimals:=Placehold[3]+Placehold[4];
  1458. Width:=Placehold[1]+Placehold[2]+Decimals;
  1459. If (Decimals=0) Then
  1460. Str(Value:Width:0,Digits)
  1461. Else
  1462. Str(Value:Width+1:Decimals,Digits);
  1463. len:=Length(Digits);
  1464. { Find the decimal point }
  1465. If (Decimals=0) Then
  1466. DecimalPoint:=len+1
  1467. Else
  1468. DecimalPoint:=len-Decimals;
  1469. { If value is very small, and no decimal places
  1470. are desired, remove the leading 0. }
  1471. If (Abs(Value) < 1) And (Placehold[2] = 0) Then
  1472. Begin
  1473. If (Placehold[1]=0) Then
  1474. Delete(Digits,DecimalPoint-1,1)
  1475. Else
  1476. Digits[DecimalPoint-1]:=' ';
  1477. End;
  1478. { Convert optional zeroes to spaces. }
  1479. I:=len;
  1480. J:=DecimalPoint+Placehold[3];
  1481. While (I>J) And (Digits[I]='0') Do
  1482. Begin
  1483. Digits[I] := ' ';
  1484. Dec(I);
  1485. End;
  1486. { If integer value and no obligatory decimal
  1487. places, remove decimal point. }
  1488. If (DecimalPoint < len) And (Digits[DecimalPoint + 1] = ' ') Then
  1489. Digits[DecimalPoint] := ' ';
  1490. { Convert spaces left from obligatory decimal point to zeroes. }
  1491. I:=DecimalPoint-Placehold[2];
  1492. While (I<DecimalPoint) And (Digits[I]=' ') Do
  1493. Begin
  1494. Digits[I] := '0';
  1495. Inc(I);
  1496. End;
  1497. Exp := 0;
  1498. End
  1499. Else
  1500. Begin
  1501. { Scientific: exactly <Width> Digits With <Precision> Decimals
  1502. And adjusted Exponent. }
  1503. If Placehold[1]+Placehold[2]=0 Then
  1504. Placehold[1]:=1;
  1505. Decimals := Placehold[3] + Placehold[4];
  1506. Width:=Placehold[1]+Placehold[2]+Decimals;
  1507. Str(Value:Width+8,Digits);
  1508. { Find and cut out exponent. Always the
  1509. last 6 characters in the string.
  1510. -> 0000E+0000 }
  1511. I:=Length(Digits)-5;
  1512. Val(Copy(Digits,I+1,5),Exp,J);
  1513. Exp:=Exp+1-(Placehold[1]+Placehold[2]);
  1514. Delete(Digits, I, 6);
  1515. { Str() always returns at least one digit after the decimal point.
  1516. If we don't want it, we have to remove it. }
  1517. If (Decimals=0) And (Placehold[1]+Placehold[2]<= 1) Then
  1518. Begin
  1519. If (Digits[4]>='5') Then
  1520. Begin
  1521. Inc(Digits[2]);
  1522. If (Digits[2]>'9') Then
  1523. Begin
  1524. Digits[2] := '1';
  1525. Inc(Exp);
  1526. End;
  1527. End;
  1528. Delete(Digits, 3, 2);
  1529. DecimalPoint := Length(Digits) + 1;
  1530. End
  1531. Else
  1532. Begin
  1533. { Move decimal point at the desired position }
  1534. Delete(Digits, 3, 1);
  1535. DecimalPoint:=2+Placehold[1]+Placehold[2];
  1536. If (Decimals<>0) Then
  1537. Insert('.',Digits,DecimalPoint);
  1538. End;
  1539. { Convert optional zeroes to spaces. }
  1540. I := Length(Digits);
  1541. J := DecimalPoint + Placehold[3];
  1542. While (I > J) And (Digits[I] = '0') Do
  1543. Begin
  1544. Digits[I] := ' ';
  1545. Dec(I);
  1546. End;
  1547. { If integer number and no obligatory decimal paces, remove decimal point }
  1548. If (DecimalPoint<Length(Digits)) And
  1549. (Digits[DecimalPoint+1]=' ') Then
  1550. Digits[DecimalPoint]:=' ';
  1551. If (Digits[1]=' ') Then
  1552. Begin
  1553. Delete(Digits, 1, 1);
  1554. Dec(DecimalPoint);
  1555. End;
  1556. { Calculate exponent string }
  1557. Str(Abs(Exp), Exponent);
  1558. While Length(Exponent)<ExpSize Do
  1559. Insert('0',Exponent,1);
  1560. If Exp >= 0 Then
  1561. Begin
  1562. If (ExpFmt In [1,3]) Then
  1563. Insert('+', Exponent, 1);
  1564. End
  1565. Else
  1566. Insert('-',Exponent,1);
  1567. If (ExpFmt<3) Then
  1568. Insert('E',Exponent,1)
  1569. Else
  1570. Insert('e',Exponent,1);
  1571. End;
  1572. DigitExponent:=DecimalPoint-2;
  1573. If (Digits[1]='-') Then
  1574. Dec(DigitExponent);
  1575. UnexpectedDigits:=DecimalPoint-1-(Placehold[1]+Placehold[2]);
  1576. End;
  1577. Function PutResult: LongInt;
  1578. Var
  1579. SQ, DQ: Boolean;
  1580. Fmt, Buf: PChar;
  1581. Dig, N: Integer;
  1582. Begin
  1583. SQ := False;
  1584. DQ := False;
  1585. Fmt := FmtStart;
  1586. Buf := Buffer;
  1587. Dig := 1;
  1588. While (Fmt<FmtStop) Do
  1589. Begin
  1590. //Write(Fmt[0]);
  1591. Case Fmt[0] Of
  1592. #34:
  1593. Begin
  1594. If Not SQ Then
  1595. DQ := Not DQ;
  1596. Inc(Fmt);
  1597. End;
  1598. #39:
  1599. Begin
  1600. If Not DQ Then
  1601. SQ := Not SQ;
  1602. Inc(Fmt);
  1603. End;
  1604. Else
  1605. If Not (SQ Or DQ) Then
  1606. Begin
  1607. Case Fmt[0] Of
  1608. '0', '#', '.':
  1609. Begin
  1610. If (Dig=1) And (UnexpectedDigits>0) Then
  1611. Begin
  1612. { Everything unexpected is written before the first digit }
  1613. For N := 1 To UnexpectedDigits Do
  1614. Begin
  1615. Buf[0] := Digits[N];
  1616. Inc(Buf);
  1617. If thousand And (Digits[N]<>'-') Then
  1618. Begin
  1619. If (DigitExponent Mod 3 = 0) And (DigitExponent>0) Then
  1620. Begin
  1621. Buf[0] := ThousandSeparator;
  1622. Inc(Buf);
  1623. End;
  1624. Dec(DigitExponent);
  1625. End;
  1626. End;
  1627. Inc(Dig, UnexpectedDigits);
  1628. End;
  1629. If (Digits[Dig]<>' ') Then
  1630. Begin
  1631. If (Digits[Dig]='.') Then
  1632. Buf[0] := DecimalSeparator
  1633. Else
  1634. Buf[0] := Digits[Dig];
  1635. Inc(Buf);
  1636. If thousand And (DigitExponent Mod 3 = 0) And (DigitExponent > 0) Then
  1637. Begin
  1638. Buf[0] := ThousandSeparator;
  1639. Inc(Buf);
  1640. End;
  1641. End;
  1642. Inc(Dig);
  1643. Dec(DigitExponent);
  1644. Inc(Fmt);
  1645. End;
  1646. 'e', 'E':
  1647. Begin
  1648. If ExpFmt <> 0 Then
  1649. Begin
  1650. Inc(Fmt);
  1651. If Fmt < FmtStop Then
  1652. Begin
  1653. If Fmt[0] In ['+', '-'] Then
  1654. Begin
  1655. Inc(Fmt, ExpSize);
  1656. For N:=1 To Length(Exponent) Do
  1657. Buf[N-1] := Exponent[N];
  1658. Inc(Buf,Length(Exponent));
  1659. ExpFmt:=0;
  1660. End;
  1661. Inc(Fmt);
  1662. End;
  1663. End
  1664. Else
  1665. Begin
  1666. { No legal exponential format.
  1667. Simply write the 'E' to the result. }
  1668. Buf[0] := Fmt[0];
  1669. Inc(Buf);
  1670. Inc(Fmt);
  1671. End;
  1672. End;
  1673. Else { Case }
  1674. { Usual character }
  1675. If (Fmt[0]<>',') Then
  1676. Begin
  1677. Buf[0] := Fmt[0];
  1678. Inc(Buf);
  1679. End;
  1680. Inc(Fmt);
  1681. End; { Case }
  1682. End
  1683. Else { IF }
  1684. Begin
  1685. { Character inside single or double quotes }
  1686. Buf[0] := Fmt[0];
  1687. Inc(Buf);
  1688. Inc(Fmt);
  1689. End;
  1690. End; { Case }
  1691. End; { While .. Begin }
  1692. Result:=PtrInt(Buf)-PtrInt(Buffer);
  1693. End;
  1694. Begin
  1695. If (Value>0) Then
  1696. GetSectionRange(1)
  1697. Else If (Value<0) Then
  1698. GetSectionRange(2)
  1699. Else
  1700. GetSectionRange(3);
  1701. If FmtStart = Nil Then
  1702. Begin
  1703. Result := FloatToText(Buffer, Value, ffGeneral, 15, 4);
  1704. End
  1705. Else
  1706. Begin
  1707. GetFormatOptions;
  1708. If (ExpFmt = 0) And (Abs(Value) >= 1E18) Then
  1709. Result := FloatToText(Buffer, Value, ffGeneral, 15, 4)
  1710. Else
  1711. Begin
  1712. FloatToStr;
  1713. Result := PutResult;
  1714. End;
  1715. End;
  1716. End;
  1717. Procedure FloatToDecimal(Var Result: TFloatRec; Value: Extended; Precision, Decimals : integer);
  1718. Var
  1719. Buffer: String[24];
  1720. Error, N: Integer;
  1721. Begin
  1722. Str(Value:23, Buffer);
  1723. Result.Negative := (Buffer[1] = '-');
  1724. Val(Copy(Buffer, 19, 5), Result.Exponent, Error);
  1725. Inc(Result. Exponent);
  1726. Result.Digits[0] := Buffer[2];
  1727. Move(Buffer[4], Result.Digits[1], 14);
  1728. If Decimals + Result.Exponent < Precision Then
  1729. N := Decimals + Result.Exponent
  1730. Else
  1731. N := Precision;
  1732. If N > 15 Then
  1733. N := 15;
  1734. If N = 0 Then
  1735. Begin
  1736. If Result.Digits[0] >= '5' Then
  1737. Begin
  1738. Result.Digits[0] := '1';
  1739. Result.Digits[1] := #0;
  1740. Inc(Result.Exponent);
  1741. End
  1742. Else
  1743. Result.Digits[0] := #0;
  1744. End
  1745. Else If N > 0 Then
  1746. Begin
  1747. If Result.Digits[N] >= '5' Then
  1748. Begin
  1749. Repeat
  1750. Result.Digits[N] := #0;
  1751. Dec(N);
  1752. Inc(Result.Digits[N]);
  1753. Until (N = 0) Or (Result.Digits[N] < ':');
  1754. If Result.Digits[0] = ':' Then
  1755. Begin
  1756. Result.Digits[0] := '1';
  1757. Inc(Result.Exponent);
  1758. End;
  1759. End
  1760. Else
  1761. Begin
  1762. Result.Digits[N] := '0';
  1763. While (Result.Digits[N] = '0') And (N > -1) Do
  1764. Begin
  1765. Result.Digits[N] := #0;
  1766. Dec(N);
  1767. End;
  1768. End;
  1769. End
  1770. Else
  1771. Result.Digits[0] := #0;
  1772. If Result.Digits[0] = #0 Then
  1773. Begin
  1774. Result.Exponent := 0;
  1775. Result.Negative := False;
  1776. End;
  1777. End;
  1778. Function FormatFloat(Const format: String; Value: Extended): String;
  1779. Var
  1780. Temp: ShortString;
  1781. buf : Array[0..1024] of char;
  1782. Begin
  1783. Buf[FloatToTextFmt(@Buf[0],Value,Pchar(Format))]:=#0;
  1784. Result:=StrPas(@Buf);
  1785. End;
  1786. {==============================================================================}
  1787. { extra functions }
  1788. {==============================================================================}
  1789. { LeftStr returns Count left-most characters from S }
  1790. function LeftStr(const S: string; Count: integer): string;
  1791. begin
  1792. result := Copy(S, 1, Count);
  1793. end ;
  1794. { RightStr returns Count right-most characters from S }
  1795. function RightStr(const S: string; Count: integer): string;
  1796. begin
  1797. If Count>Length(S) then
  1798. Count:=Length(S);
  1799. result := Copy(S, 1 + Length(S) - Count, Count);
  1800. end;
  1801. { BCDToInt converts the BCD value Value to an integer }
  1802. function BCDToInt(Value: integer): integer;
  1803. var i, j: integer;
  1804. begin
  1805. result := 0;
  1806. j := 1;
  1807. for i := 0 to SizeOf(Value) shr 1 - 1 do begin
  1808. result := result + j * (Value and 15);
  1809. j := j * 10;
  1810. Value := Value shr 4;
  1811. end ;
  1812. end ;
  1813. Function LastDelimiter(const Delimiters, S: string): Integer;
  1814. begin
  1815. Result:=Length(S);
  1816. While (Result>0) and (Pos(S[Result],Delimiters)=0) do
  1817. Dec(Result);
  1818. end;
  1819. Function StringReplace(const S, OldPattern, NewPattern: string; Flags: TReplaceFlags): string;
  1820. var
  1821. Srch,OldP,RemS: string; // Srch and Oldp can contain uppercase versions of S,OldPattern
  1822. P : Integer;
  1823. begin
  1824. Srch:=S;
  1825. OldP:=OldPattern;
  1826. if rfIgnoreCase in Flags then
  1827. begin
  1828. Srch:=UpperCase(Srch);
  1829. OldP:=UpperCase(OldP);
  1830. end;
  1831. RemS:=S;
  1832. Result:='';
  1833. while (Length(Srch)<>0) do
  1834. begin
  1835. P:=Pos(OldP, Srch);
  1836. if P=0 then
  1837. begin
  1838. Result:=Result+RemS;
  1839. Srch:='';
  1840. end
  1841. else
  1842. begin
  1843. Result:=Result+Copy(RemS,1,P-1)+NewPattern;
  1844. P:=P+Length(OldP);
  1845. RemS:=Copy(RemS,P,Length(RemS)-P+1);
  1846. if not (rfReplaceAll in Flags) then
  1847. begin
  1848. Result:=Result+RemS;
  1849. Srch:='';
  1850. end
  1851. else
  1852. Srch:=Copy(Srch,P,Length(Srch)-P+1);
  1853. end;
  1854. end;
  1855. end;
  1856. Function IsDelimiter(const Delimiters, S: string; Index: Integer): Boolean;
  1857. begin
  1858. Result:=False;
  1859. If (Index>0) and (Index<=Length(S)) then
  1860. Result:=Pos(S[Index],Delimiters)<>0; // Note we don't do MBCS yet
  1861. end;
  1862. Function ByteToCharLen(const S: string; MaxLen: Integer): Integer;
  1863. begin
  1864. Result:=Length(S);
  1865. If Result>MaxLen then
  1866. Result:=MaxLen;
  1867. end;
  1868. Function ByteToCharIndex(const S: string; Index: Integer): Integer;
  1869. begin
  1870. Result:=Index;
  1871. end;
  1872. Function CharToByteLen(const S: string; MaxLen: Integer): Integer;
  1873. begin
  1874. Result:=Length(S);
  1875. If Result>MaxLen then
  1876. Result:=MaxLen;
  1877. end;
  1878. Function CharToByteIndex(const S: string; Index: Integer): Integer;
  1879. begin
  1880. Result:=Index;
  1881. end;
  1882. Function ByteType(const S: string; Index: Integer): TMbcsByteType;
  1883. begin
  1884. Result:=mbSingleByte;
  1885. end;
  1886. Function StrByteType(Str: PChar; Index: Cardinal): TMbcsByteType;
  1887. begin
  1888. Result:=mbSingleByte;
  1889. end;
  1890. Function FindCmdLineSwitch(const Switch: string; const Chars: TSysCharSet;IgnoreCase: Boolean): Boolean;
  1891. Var
  1892. I,L : Integer;
  1893. S,T : String;
  1894. begin
  1895. Result:=False;
  1896. S:=Switch;
  1897. If IgnoreCase then
  1898. S:=UpperCase(S);
  1899. I:=ParamCount;
  1900. While (Not Result) and (I>0) do
  1901. begin
  1902. L:=Length(Paramstr(I));
  1903. If (L>0) and (ParamStr(I)[1] in Chars) then
  1904. begin
  1905. T:=Copy(ParamStr(I),2,L-1);
  1906. If IgnoreCase then
  1907. T:=UpperCase(T);
  1908. Result:=S=T;
  1909. end;
  1910. Dec(i);
  1911. end;
  1912. end;
  1913. Function FindCmdLineSwitch(const Switch: string; IgnoreCase: Boolean): Boolean;
  1914. begin
  1915. Result:=FindCmdLineSwitch(Switch,SwitchChars,IgnoreCase);
  1916. end;
  1917. Function FindCmdLineSwitch(const Switch: string): Boolean;
  1918. begin
  1919. Result:=FindCmdLineSwitch(Switch,SwitchChars,False);
  1920. end;
  1921. {
  1922. Case Translation Tables
  1923. Can be used in internationalization support.
  1924. Although these tables can be obtained through system calls
  1925. it is better to not use those, since most implementation are not 100%
  1926. WARNING:
  1927. before modifying a translation table make sure that the current codepage
  1928. of the OS corresponds to the one you make changes to
  1929. }
  1930. const
  1931. { upper case translation table for character set 850 }
  1932. CP850UCT: array[128..255] of char =
  1933. ('€', 'š', '�', '¶', 'Ž', '¶', '�', '€', 'Ò', 'Ó', 'Ô', 'Ø', '×', 'Þ', 'Ž', '�',
  1934. '�', '’', '’', 'â', '™', 'ã', 'ê', 'ë', 'Y', '™', 'š', '�', 'œ', '�', 'ž', 'Ÿ',
  1935. 'µ', 'Ö', 'à', 'é', '¥', '¥', '¦', '§', '¨', '©', 'ª', '«', '¬', '­', '®', '¯',
  1936. '°', '±', '²', '³', '´', 'µ', '¶', '·', '¸', '¹', 'º', '»', '¼', '½', '¾', '¿',
  1937. 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Ç', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï',
  1938. 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', '×', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'Þ', 'ß',
  1939. 'à', 'á', 'â', 'ã', 'å', 'å', 'æ', 'í', 'è', 'é', 'ê', 'ë', 'í', 'í', 'î', 'ï',
  1940. 'ð', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', '÷', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'þ', 'ÿ');
  1941. { lower case translation table for character set 850 }
  1942. CP850LCT: array[128..255] of char =
  1943. ('‡', '�', '‚', 'ƒ', '„', '…', '†', '‡', 'ˆ', '‰', 'Š', '‹', 'Œ', '�', '„', '†',
  1944. '‚', '‘', '‘', '“', '”', '•', '–', '—', '˜', '”', '�', '›', 'œ', '›', 'ž', 'Ÿ',
  1945. ' ', '¡', '¢', '£', '¤', '¤', '¦', '§', '¨', '©', 'ª', '«', '¬', '­', '®', '¯',
  1946. '°', '±', '²', '³', '´', ' ', 'ƒ', '…', '¸', '¹', 'º', '»', '¼', '½', '¾', '¿',
  1947. 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Æ', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï',
  1948. 'Ð', 'Ñ', 'ˆ', '‰', 'Š', 'Õ', '¡', 'Œ', '‹', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', '�', 'ß',
  1949. '¢', 'á', '“', '•', 'ä', 'ä', 'æ', 'í', 'è', '£', '–', '—', 'ì', 'ì', 'î', 'ï',
  1950. 'ð', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', '÷', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'þ', 'ÿ');
  1951. { upper case translation table for character set ISO 8859/1 Latin 1 }
  1952. CPISO88591UCT: array[192..255] of char =
  1953. ( #192, #193, #194, #195, #196, #197, #198, #199,
  1954. #200, #201, #202, #203, #204, #205, #206, #207,
  1955. #208, #209, #210, #211, #212, #213, #214, #215,
  1956. #216, #217, #218, #219, #220, #221, #222, #223,
  1957. #192, #193, #194, #195, #196, #197, #198, #199,
  1958. #200, #201, #202, #203, #204, #205, #206, #207,
  1959. #208, #209, #210, #211, #212, #213, #214, #247,
  1960. #216, #217, #218, #219, #220, #221, #222, #89 );
  1961. { lower case translation table for character set ISO 8859/1 Latin 1 }
  1962. CPISO88591LCT: array[192..255] of char =
  1963. ( #224, #225, #226, #227, #228, #229, #230, #231,
  1964. #232, #233, #234, #235, #236, #237, #238, #239,
  1965. #240, #241, #242, #243, #244, #245, #246, #215,
  1966. #248, #249, #250, #251, #252, #253, #254, #223,
  1967. #224, #225, #226, #227, #228, #229, #230, #231,
  1968. #232, #233, #234, #235, #236, #237, #238, #239,
  1969. #240, #241, #242, #243, #244, #245, #246, #247,
  1970. #248, #249, #250, #251, #252, #253, #254, #255 );
  1971. {
  1972. $Log$
  1973. Revision 1.22 2004-12-01 10:34:46 michael
  1974. + Patch from Pete: Dont support widestrings when compiled with 1.0.x and Add additional typecasts to Widestring for widechar/pwidechar
  1975. Revision 1.21 2004/11/30 20:56:27 michael
  1976. + Fix from Alexey Barkovoy for bug 3302
  1977. Revision 1.20 2004/11/22 05:53:44 marco
  1978. * fixed little 1.0.xism
  1979. Revision 1.19 2004/11/21 19:33:20 marco
  1980. * %x 64-bit support
  1981. Revision 1.18 2004/11/21 16:44:01 marco
  1982. * %u
  1983. Revision 1.17 2004/11/16 18:30:35 marco
  1984. * updated ansiexctractquotedstring (more delphi compat, both interface and code)
  1985. Revision 1.16 2004/08/30 18:00:12 michael
  1986. + Extra index check in IsDelimiter
  1987. Revision 1.15 2004/08/07 19:32:35 florian
  1988. * fixed CompareStr with a patch from Michalis Kamburelis
  1989. Revision 1.14 2004/08/07 16:56:28 florian
  1990. + TryStrToInt* added
  1991. Revision 1.13 2004/06/13 10:49:50 florian
  1992. * fixed some bootstrapping problems as well as some 64 bit stuff
  1993. Revision 1.12 2004/06/12 13:57:18 michael
  1994. + Enhanced FloatToStrF to 18 digits (Delphi compatibility, bug 3106
  1995. Revision 1.11 2004/06/12 13:23:17 michael
  1996. + Fixed currency<->string conversion support
  1997. Revision 1.10 2004/04/28 20:48:20 peter
  1998. * ordinal-pointer conversions fixed
  1999. Revision 1.9 2004/02/26 08:46:21 michael
  2000. + Added AnsiSameStr
  2001. Revision 1.8 2003/11/26 22:17:42 michael
  2002. + Merged fixbranch fixes, missing in main branch
  2003. Revision 1.7 2003/11/22 17:18:53 marco
  2004. * johill patch applied
  2005. Revision 1.6 2003/11/22 16:17:26 michael
  2006. + Small optimization in comparemem
  2007. Revision 1.5 2003/11/22 15:46:48 michael
  2008. + Patched CompareMem for case when length is 0
  2009. Revision 1.4 2003/11/09 13:37:42 michael
  2010. + Position specifier in format string affects all later specifiers
  2011. Revision 1.3 2003/11/03 09:42:28 marco
  2012. * Peter's Cardinal<->Longint fixes patch
  2013. Revision 1.2 2003/10/07 12:02:47 marco
  2014. * sametext and ansisametext added. (simple (ansi)comparetext wrappers)
  2015. Revision 1.1 2003/10/06 21:01:06 peter
  2016. * moved classes unit to rtl
  2017. Revision 1.26 2003/09/06 21:22:07 marco
  2018. * More objpas fixes
  2019. Revision 1.25 2002/12/23 23:26:08 florian
  2020. + addition to previous commit, forgot to save in the editor
  2021. Revision 1.23 2002/11/28 22:26:30 michael
  2022. + Fixed float<>string conversion routines
  2023. Revision 1.22 2002/11/28 20:29:26 michael
  2024. + made it compile again
  2025. Revision 1.21 2002/11/28 20:15:37 michael
  2026. + Fixed comparestr (merge from fix)
  2027. Revision 1.20 2002/09/15 17:50:35 peter
  2028. * Fixed AnsiStrComp crashes
  2029. Revision 1.1.2.16 2002/11/28 22:25:01 michael
  2030. + Fixed float<>string conversion routines
  2031. Revision 1.1.2.15 2002/11/28 20:24:11 michael
  2032. + merged some fixes from mainbranch
  2033. Revision 1.19 2002/09/07 16:01:22 peter
  2034. * old logs removed and tabs fixed
  2035. Revision 1.1.2.14 2002/11/28 20:13:10 michael
  2036. + Fixed comparestr
  2037. Revision 1.1.2.13 2002/10/29 23:41:06 michael
  2038. + Added lots of D4 functions
  2039. Revision 1.18 2002/09/02 06:07:16 michael
  2040. + Fix for formatbuf not applied correct
  2041. Revision 1.17 2002/08/29 10:04:48 michael
  2042. + Fix for bug report 2097 in formatbuf
  2043. Revision 1.16 2002/08/29 10:04:25 michael
  2044. + Fix for bug report 2097 in formatbuf
  2045. Revision 1.15 2002/07/06 12:14:03 daniel
  2046. - Changes from Strasbourg
  2047. Revision 1.14 2002/01/24 12:33:53 jonas
  2048. * adapted ranges of native types to int64 (e.g. high cardinal is no
  2049. longer longint($ffffffff), but just $fffffff in psystem)
  2050. * small additional fix in 64bit rangecheck code generation for 32 bit
  2051. processors
  2052. * adaption of ranges required the matching talgorithm used for selecting
  2053. which overloaded procedure to call to be adapted. It should now always
  2054. select the closest match for ordinal parameters.
  2055. + inttostr(qword) in sysstr.inc/sysstrh.inc
  2056. + abs(int64), sqr(int64), sqr(qword) in systemh.inc/generic.inc (previous
  2057. fixes were required to be able to add them)
  2058. * is_in_limit() moved from ncal to types unit, should always be used
  2059. instead of direct comparisons of low/high values of orddefs because
  2060. qword is a special case
  2061. }