sysstr.inc 55 KB

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