sysstr.inc 52 KB

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