sysstr.inc 52 KB

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