sysstr.inc 55 KB

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