sysstr.inc 58 KB

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