sysstr.inc 61 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476
  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. {$ifdef ver1_0}
  672. vl : int64;
  673. {$else}
  674. vq : qword;
  675. {$endif}
  676. {
  677. ReadFormat reads the format string. It returns the type character in
  678. uppercase, and sets index, Width, Prec to their correct values,
  679. or -1 if not set. It sets Left to true if left alignment was requested.
  680. In case of an error, DoFormatError is called.
  681. }
  682. Function ReadFormat : Char;
  683. Var Value : longint;
  684. Procedure ReadInteger;
  685. {$IFDEF VIRTUALPASCAL}
  686. var Code: longint;
  687. {$ELSE}
  688. var Code: word;
  689. {$ENDIF}
  690. begin
  691. If Value<>-1 then exit; // Was already read.
  692. OldPos:=chPos;
  693. While (Chpos<=Len) and
  694. (Pos(Fmt[chpos],'1234567890')<>0) do inc(chpos);
  695. If Chpos>len then
  696. DoFormatError(feInvalidFormat);
  697. If Fmt[Chpos]='*' then
  698. begin
  699. If (Chpos>OldPos) or (ArgPos>High(Args))
  700. or (Args[ArgPos].Vtype<>vtInteger) then
  701. DoFormatError(feInvalidFormat);
  702. Value:=Args[ArgPos].VInteger;
  703. Inc(ArgPos);
  704. Inc(chPos);
  705. end
  706. else
  707. begin
  708. If (OldPos<chPos) Then
  709. begin
  710. Val (Copy(Fmt,OldPos,ChPos-OldPos),value,code);
  711. // This should never happen !!
  712. If Code>0 then DoFormatError (feInvalidFormat);
  713. end
  714. else
  715. Value:=-1;
  716. end;
  717. end;
  718. Procedure ReadIndex;
  719. begin
  720. ReadInteger;
  721. If Fmt[ChPos]=':' then
  722. begin
  723. If Value=-1 then DoFormatError(feMissingArgument);
  724. Index:=Value;
  725. Value:=-1;
  726. Inc(Chpos);
  727. end;
  728. {$ifdef fmtdebug}
  729. Log ('Read index');
  730. {$endif}
  731. end;
  732. Procedure ReadLeft;
  733. begin
  734. If Fmt[chpos]='-' then
  735. begin
  736. left:=True;
  737. Inc(chpos);
  738. end
  739. else
  740. Left:=False;
  741. {$ifdef fmtdebug}
  742. Log ('Read Left');
  743. {$endif}
  744. end;
  745. Procedure ReadWidth;
  746. begin
  747. ReadInteger;
  748. If Value<>-1 then
  749. begin
  750. Width:=Value;
  751. Value:=-1;
  752. end;
  753. {$ifdef fmtdebug}
  754. Log ('Read width');
  755. {$endif}
  756. end;
  757. Procedure ReadPrec;
  758. begin
  759. If Fmt[chpos]='.' then
  760. begin
  761. inc(chpos);
  762. ReadInteger;
  763. If Value=-1 then
  764. Value:=0;
  765. prec:=Value;
  766. end;
  767. {$ifdef fmtdebug}
  768. Log ('Read precision');
  769. {$endif}
  770. end;
  771. begin
  772. {$ifdef fmtdebug}
  773. Log ('Start format');
  774. {$endif}
  775. Index:=-1;
  776. Width:=-1;
  777. Prec:=-1;
  778. Value:=-1;
  779. inc(chpos);
  780. If Fmt[Chpos]='%' then
  781. begin
  782. Result:='%';
  783. exit; // VP fix
  784. end;
  785. ReadIndex;
  786. ReadLeft;
  787. ReadWidth;
  788. ReadPrec;
  789. ReadFormat:=Upcase(Fmt[ChPos]);
  790. {$ifdef fmtdebug}
  791. Log ('End format');
  792. {$endif}
  793. end;
  794. {$ifdef fmtdebug}
  795. Procedure DumpFormat (C : char);
  796. begin
  797. Write ('Fmt : ',fmt:10);
  798. Write (' Index : ',Index:3);
  799. Write (' Left : ',left:5);
  800. Write (' Width : ',Width:3);
  801. Write (' Prec : ',prec:3);
  802. Writeln (' Type : ',C);
  803. end;
  804. {$endif}
  805. function Checkarg (AT : Longint;err:boolean):boolean;
  806. {
  807. Check if argument INDEX is of correct type (AT)
  808. If Index=-1, ArgPos is used, and argpos is augmented with 1
  809. DoArg is set to the argument that must be used.
  810. }
  811. begin
  812. result:=false;
  813. if Index=-1 then
  814. DoArg:=Argpos
  815. else
  816. DoArg:=Index;
  817. ArgPos:=DoArg+1;
  818. If (Doarg>High(Args)) or (Args[Doarg].Vtype<>AT) then
  819. begin
  820. if err then
  821. DoFormatError(feInvalidArgindex);
  822. dec(ArgPos);
  823. exit;
  824. end;
  825. result:=true;
  826. end;
  827. Const Zero = '000000000000000000000000000000000000000000000000000000000000000';
  828. begin
  829. Result:='';
  830. Len:=Length(Fmt);
  831. Chpos:=1;
  832. OldPos:=1;
  833. ArgPos:=0;
  834. While chpos<=len do
  835. begin
  836. While (ChPos<=Len) and (Fmt[chpos]<>'%') do
  837. inc(chpos);
  838. If ChPos>OldPos Then
  839. Result:=Result+Copy(Fmt,OldPos,Chpos-Oldpos);
  840. If ChPos<Len then
  841. begin
  842. FChar:=ReadFormat;
  843. {$ifdef fmtdebug}
  844. DumpFormat(FCHar);
  845. {$endif}
  846. Case FChar of
  847. 'D' : begin
  848. if Checkarg(vtinteger,false) then
  849. Str(Args[Doarg].VInteger,ToAdd)
  850. {$IFNDEF VIRTUALPASCAL}
  851. else if CheckArg(vtInt64,true) then
  852. Str(Args[DoArg].VInt64^,toadd)
  853. {$ENDIF}
  854. ;
  855. Width:=Abs(width);
  856. Index:=Prec-Length(ToAdd);
  857. If ToAdd[1]<>'-' then
  858. ToAdd:=StringOfChar('0',Index)+ToAdd
  859. else
  860. // + 1 to accomodate for - sign in length !!
  861. Insert(StringOfChar('0',Index+1),toadd,2);
  862. end;
  863. 'U' : begin
  864. if Checkarg(vtinteger,false) then
  865. Str(cardinal(Args[Doarg].VInteger),ToAdd)
  866. {$IFNDEF VIRTUALPASCAL}
  867. else if CheckArg(vtInt64,true) then
  868. Str(qword(Args[DoArg].VInt64^),toadd)
  869. {$ENDIF}
  870. ;
  871. Width:=Abs(width);
  872. Index:=Prec-Length(ToAdd);
  873. ToAdd:=StringOfChar('0',Index)+ToAdd
  874. end;
  875. 'E' : begin
  876. CheckArg(vtExtended,true);
  877. ToAdd:=FloatToStrF(Args[doarg].VExtended^,ffexponent,Prec,3);
  878. end;
  879. 'F' : begin
  880. CheckArg(vtExtended,true);
  881. ToAdd:=FloatToStrF(Args[doarg].VExtended^,ffFixed,9999,Prec);
  882. end;
  883. 'G' : begin
  884. CheckArg(vtExtended,true);
  885. ToAdd:=FloatToStrF(Args[doarg].VExtended^,ffGeneral,Prec,3);
  886. end;
  887. 'N' : begin
  888. CheckArg(vtExtended,true);
  889. ToAdd:=FloatToStrF(Args[doarg].VExtended^,ffNumber,9999,Prec);
  890. end;
  891. 'M' : begin
  892. CheckArg(vtExtended,true);
  893. ToAdd:=FloatToStrF(Args[doarg].VExtended^,ffCurrency,9999,Prec);
  894. end;
  895. 'S' : begin
  896. if CheckArg(vtString,false) then
  897. hs:=Args[doarg].VString^
  898. else
  899. if CheckArg(vtChar,false) then
  900. hs:=Args[doarg].VChar
  901. else
  902. if CheckArg(vtPChar,false) then
  903. hs:=Args[doarg].VPChar
  904. else
  905. {$ifndef VER1_0}
  906. if CheckArg(vtPWideChar,false) then
  907. hs:=WideString(Args[doarg].VPWideChar)
  908. else
  909. if CheckArg(vtWideChar,false) then
  910. hs:=WideString(Args[doarg].VWideChar)
  911. else
  912. if CheckArg(vtWidestring,false) then
  913. hs:=WideString(Args[doarg].VWideString)
  914. else
  915. {$endif VER1_0}
  916. if CheckArg(vtAnsiString,true) then
  917. hs:=ansistring(Args[doarg].VAnsiString);
  918. Index:=Length(hs);
  919. If (Prec<>-1) and (Index>Prec) then
  920. Index:=Prec;
  921. ToAdd:=Copy(hs,1,Index);
  922. end;
  923. 'P' : Begin
  924. CheckArg(vtpointer,true);
  925. ToAdd:=HexStr(ptrint(Args[DoArg].VPointer),sizeof(Ptrint)*2);
  926. // Insert ':'. Is this needed in 32 bit ? No it isn't.
  927. // Insert(':',ToAdd,5);
  928. end;
  929. 'X' : begin
  930. {$ifdef ver1_0}
  931. if Checkarg(vtinteger,false) then
  932. begin
  933. vl:=Args[Doarg].VInteger and int64($ffffffff);
  934. index:=16;
  935. end
  936. else
  937. begin
  938. CheckArg(vtInt64,true);
  939. vl:=Args[DoArg].VInt64^;
  940. index:=31;
  941. end;
  942. If Prec>index then
  943. ToAdd:=HexStr(vl,index)
  944. else
  945. begin
  946. // determine minimum needed number of hex digits.
  947. Index:=1;
  948. While (DWord(1 shl (Index*4))<=DWord(Args[DoArg].VInteger)) and (index<8) do
  949. inc(Index);
  950. If Index>Prec then
  951. Prec:=Index;
  952. ToAdd:=HexStr(int64(vl),Prec);
  953. end;
  954. {$else}
  955. if Checkarg(vtinteger,false) then
  956. begin
  957. vq:=Cardinal(Args[Doarg].VInteger);
  958. index:=16;
  959. end
  960. else
  961. begin
  962. CheckArg(vtInt64,true);
  963. vq:=Qword(Args[DoArg].VInt64^);
  964. index:=31;
  965. end;
  966. If Prec>index then
  967. ToAdd:=HexStr(vq,index)
  968. else
  969. begin
  970. // determine minimum needed number of hex digits.
  971. Index:=1;
  972. While (qWord(1) shl (Index*4)<=vq) and (index<16) do
  973. inc(Index);
  974. If Index>Prec then
  975. Prec:=Index;
  976. ToAdd:=HexStr(vq,Prec);
  977. end;
  978. {$endif}
  979. end;
  980. '%': ToAdd:='%';
  981. end;
  982. If Width<>-1 then
  983. If Length(ToAdd)<Width then
  984. If not Left then
  985. ToAdd:=Space(Width-Length(ToAdd))+ToAdd
  986. else
  987. ToAdd:=ToAdd+space(Width-Length(ToAdd));
  988. Result:=Result+ToAdd;
  989. end;
  990. inc(chpos);
  991. Oldpos:=chpos;
  992. end;
  993. end;
  994. Function FormatBuf (Var Buffer; BufLen : Cardinal;
  995. Const Fmt; fmtLen : Cardinal;
  996. Const Args : Array of const) : Cardinal;
  997. Var S,F : String;
  998. begin
  999. Setlength(F,fmtlen);
  1000. if fmtlen > 0 then
  1001. Move(fmt,F[1],fmtlen);
  1002. S:=Format (F,Args);
  1003. If Cardinal(Length(S))<Buflen then
  1004. Result:=Length(S)
  1005. else
  1006. Result:=Buflen;
  1007. Move(S[1],Buffer,Result);
  1008. end;
  1009. Procedure FmtStr(Var Res: String; Const Fmt : String; Const args: Array of const);
  1010. begin
  1011. Res:=Format(fmt,Args);
  1012. end;
  1013. Function StrFmt(Buffer,Fmt : PChar; Const args: Array of const) : Pchar;
  1014. begin
  1015. Buffer[FormatBuf(Buffer^,Maxint,Fmt^,strlen(fmt),args)]:=#0;
  1016. Result:=Buffer;
  1017. end;
  1018. Function StrLFmt(Buffer : PCHar; Maxlen : Cardinal;Fmt : PChar; Const args: Array of const) : Pchar;
  1019. begin
  1020. Buffer[FormatBuf(Buffer^,MaxLen,Fmt^,strlen(fmt),args)]:=#0;
  1021. Result:=Buffer;
  1022. end;
  1023. Function StrToFloat(Const S: String): Extended;
  1024. Begin
  1025. If Not TextToFloat(Pchar(S),Result) then
  1026. Raise EConvertError.createfmt(SInValidFLoat,[S]);
  1027. End;
  1028. function StrToFloatDef(const S: string; const Default: Extended): Extended;
  1029. begin
  1030. if not TextToFloat(PChar(S),Result,fvExtended) then
  1031. Result:=Default;
  1032. end;
  1033. Function TextToFloat(Buffer: PChar; Var Value: Extended): Boolean;
  1034. Var
  1035. E,P : Integer;
  1036. S : String;
  1037. Begin
  1038. S:=StrPas(Buffer);
  1039. P:=Pos(DecimalSeparator,S);
  1040. If (P<>0) Then
  1041. S[P] := '.';
  1042. Val(S,Value,E);
  1043. Result:=(E=0);
  1044. End;
  1045. Function TextToFloat(Buffer: PChar; Var Value; ValueType: TFloatValue): Boolean;
  1046. Var
  1047. E,P : Integer;
  1048. S : String;
  1049. C : Currency;
  1050. Ext : Extended;
  1051. Begin
  1052. S:=StrPas(Buffer);
  1053. P:=Pos(ThousandSeparator,S);
  1054. While (P<>0) do
  1055. begin
  1056. Delete(S,P,1);
  1057. P:=Pos(ThousandSeparator,S);
  1058. end;
  1059. P:=Pos(DecimalSeparator,S);
  1060. If (P<>0) Then
  1061. S[P] := '.';
  1062. case ValueType of
  1063. fvCurrency:
  1064. Val(S,Currency(Value),E);
  1065. fvExtended:
  1066. Val(S,Extended(Value),E);
  1067. fvDouble:
  1068. Val(S,Double(Value),E);
  1069. fvSingle:
  1070. Val(S,Single(Value),E);
  1071. fvComp:
  1072. Val(S,Comp(Value),E);
  1073. fvReal:
  1074. Val(S,Real(Value),E);
  1075. end;
  1076. Result:=(E=0);
  1077. End;
  1078. Function TryStrToFloat(Const S : String; Var Value: Single): Boolean;
  1079. Begin
  1080. Result := TextToFloat(PChar(S), Value, fvSingle);
  1081. End;
  1082. Function TryStrToFloat(Const S : String; Var Value: Double): Boolean;
  1083. Begin
  1084. Result := TextToFloat(PChar(S), Value, fvDouble);
  1085. End;
  1086. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1087. Function TryStrToFloat(Const S : String; Var Value: Extended): Boolean;
  1088. Begin
  1089. Result := TextToFloat(PChar(S), Value);
  1090. End;
  1091. {$endif FPC_HAS_TYPE_EXTENDED}
  1092. Function FloatToStr(Value: Extended): String;
  1093. Begin
  1094. Result := FloatToStrF(Value, ffGeneral, 15, 0);
  1095. End;
  1096. Function FloatToText(Buffer: PChar; Value: Extended; format: TFloatFormat; Precision, Digits: Integer): Longint;
  1097. Var
  1098. Tmp: String[40];
  1099. Begin
  1100. Tmp := FloatToStrF(Value, format, Precision, Digits);
  1101. Result := Length(Tmp);
  1102. Move(Tmp[1], Buffer[0], Result);
  1103. End;
  1104. Function FloatToStrF(Value: Extended; format: TFloatFormat; Precision, Digits: Integer): String;
  1105. Var
  1106. P: Integer;
  1107. Negative, TooSmall, TooLarge: Boolean;
  1108. Begin
  1109. Case format Of
  1110. ffGeneral:
  1111. Begin
  1112. If (Precision = -1) Or (Precision > 15) Then Precision := 15;
  1113. TooSmall := (Abs(Value) < 0.00001) and (Value>0.0);
  1114. If Not TooSmall Then
  1115. Begin
  1116. Str(Value:0:999, Result);
  1117. P := Pos('.', Result);
  1118. Result[P] := DecimalSeparator;
  1119. TooLarge := P > Precision + 1;
  1120. End;
  1121. If TooSmall Or TooLarge Then
  1122. begin
  1123. Result := FloatToStrF(Value, ffExponent, Precision, Digits);
  1124. // Strip unneeded zeroes.
  1125. P:=Pos('E',result)-1;
  1126. If P<>-1 then
  1127. While (P>1) and (Result[P]='0') do
  1128. begin
  1129. system.Delete(Result,P,1);
  1130. Dec(P);
  1131. end;
  1132. end
  1133. else
  1134. begin
  1135. P := Length(Result);
  1136. While Result[P] = '0' Do Dec(P);
  1137. If Result[P] = DecimalSeparator Then Dec(P);
  1138. SetLength(Result, P);
  1139. end;
  1140. End;
  1141. ffExponent:
  1142. Begin
  1143. If (Precision = -1) Or (Precision > 15) Then Precision := 15;
  1144. Str(Value:Precision + 8, Result);
  1145. Result[3] := DecimalSeparator;
  1146. P:=4;
  1147. While (P>0) and (Digits < P) And (Result[Precision + 5] = '0') do
  1148. Begin
  1149. If P<>1 then
  1150. system.Delete(Result, Precision + 5, 1)
  1151. else
  1152. system.Delete(Result, Precision + 3, 3);
  1153. Dec(P);
  1154. end;
  1155. If Result[1] = ' ' Then
  1156. System.Delete(Result, 1, 1);
  1157. End;
  1158. ffFixed:
  1159. Begin
  1160. If Digits = -1 Then Digits := 2
  1161. Else If Digits > 18 Then Digits := 18;
  1162. Str(Value:0:Digits, Result);
  1163. If Result[1] = ' ' Then
  1164. System.Delete(Result, 1, 1);
  1165. P := Pos('.', Result);
  1166. If P <> 0 Then Result[P] := DecimalSeparator;
  1167. End;
  1168. ffNumber:
  1169. Begin
  1170. If Digits = -1 Then Digits := 2
  1171. Else If Digits > 15 Then Digits := 15;
  1172. Str(Value:0:Digits, Result);
  1173. If Result[1] = ' ' Then System.Delete(Result, 1, 1);
  1174. P := Pos('.', Result);
  1175. If P <> 0 Then
  1176. Result[P] := DecimalSeparator
  1177. else
  1178. P := Length(Result)+1;
  1179. Dec(P, 3);
  1180. While (P > 1) Do
  1181. Begin
  1182. If Result[P - 1] <> '-' Then Insert(ThousandSeparator, Result, P);
  1183. Dec(P, 3);
  1184. End;
  1185. End;
  1186. ffCurrency:
  1187. Begin
  1188. If Value < 0 Then
  1189. Begin
  1190. Negative := True;
  1191. Value := -Value;
  1192. End
  1193. Else Negative := False;
  1194. If Digits = -1 Then Digits := CurrencyDecimals
  1195. Else If Digits > 18 Then Digits := 18;
  1196. Str(Value:0:Digits, Result);
  1197. If Result[1] = ' ' Then System.Delete(Result, 1, 1);
  1198. P := Pos('.', Result);
  1199. If P <> 0 Then Result[P] := DecimalSeparator;
  1200. Dec(P, 3);
  1201. While (P > 1) Do
  1202. Begin
  1203. Insert(ThousandSeparator, Result, P);
  1204. Dec(P, 3);
  1205. End;
  1206. If Not Negative Then
  1207. Begin
  1208. Case CurrencyFormat Of
  1209. 0: Result := CurrencyString + Result;
  1210. 1: Result := Result + CurrencyString;
  1211. 2: Result := CurrencyString + ' ' + Result;
  1212. 3: Result := Result + ' ' + CurrencyString;
  1213. End
  1214. End
  1215. Else
  1216. Begin
  1217. Case NegCurrFormat Of
  1218. 0: Result := '(' + CurrencyString + Result + ')';
  1219. 1: Result := '-' + CurrencyString + Result;
  1220. 2: Result := CurrencyString + '-' + Result;
  1221. 3: Result := CurrencyString + Result + '-';
  1222. 4: Result := '(' + Result + CurrencyString + ')';
  1223. 5: Result := '-' + Result + CurrencyString;
  1224. 6: Result := Result + '-' + CurrencyString;
  1225. 7: Result := Result + CurrencyString + '-';
  1226. 8: Result := '-' + Result + ' ' + CurrencyString;
  1227. 9: Result := '-' + CurrencyString + ' ' + Result;
  1228. 10: Result := CurrencyString + ' ' + Result + '-';
  1229. End;
  1230. End;
  1231. End;
  1232. End;
  1233. End;
  1234. Function FloatToDateTime (Const Value : Extended) : TDateTime;
  1235. begin
  1236. If (Value<MinDateTime) or (Value>MaxDateTime) then
  1237. Raise EConvertError.CreateFmt (SInvalidDateTime,[Value]);
  1238. Result:=Value;
  1239. end;
  1240. function TryFloatToCurr(const Value: Extended; var AResult: Currency): Boolean;
  1241. begin
  1242. {$ifndef VER1_0}
  1243. Result:=(Value>=MinCurrency) and (Value<=MaxCurrency);
  1244. if Result then
  1245. AResult := Value;
  1246. {$else VER1_0}
  1247. Result:=false;
  1248. {$endif VER1_0}
  1249. end;
  1250. function FloatToCurr(const Value: Extended): Currency;
  1251. begin
  1252. if not TryFloatToCurr(Value, Result) then
  1253. Raise EConvertError.CreateFmt(SInvalidCurrency, [FloatToStr(Value)]);
  1254. end;
  1255. Function CurrToStr(Value: Currency): string;
  1256. begin
  1257. Result:=FloatToStrF(Value,ffNumber,15,2);
  1258. end;
  1259. function StrToCurr(const S: string): Currency;
  1260. begin
  1261. if not TextToFloat(PChar(S), Result, fvCurrency) then
  1262. Raise EConvertError.createfmt(SInValidFLoat,[S]);
  1263. end;
  1264. function StrToCurrDef(const S: string; Default : Currency): Currency;
  1265. begin
  1266. if not TextToFloat(PChar(S), Result, fvCurrency) then
  1267. Result:=Default;
  1268. end;
  1269. function StrToBool(const S: string): Boolean;
  1270. Var
  1271. Temp : String;
  1272. D : Double;
  1273. {$IFDEF VIRTUALPASCAL}
  1274. Code: longint;
  1275. {$ELSE}
  1276. Code: word;
  1277. {$ENDIF}
  1278. begin
  1279. Temp:=upcase(S);
  1280. Val(temp,D,code);
  1281. If Code=0 then
  1282. Result:=(D<>0.0)
  1283. else If Temp='TRUE' then
  1284. result:=true
  1285. else if Temp='FALSE' then
  1286. result:=false
  1287. else
  1288. Raise EConvertError.CreateFmt(SInvalidBoolean,[S]);
  1289. end;
  1290. function BoolToStr(B: Boolean): string;
  1291. begin
  1292. If B then
  1293. Result:='TRUE'
  1294. else
  1295. Result:='FALSE';
  1296. end;
  1297. Function FloatToTextFmt(Buffer: PChar; Value: Extended; format: PChar): Integer;
  1298. Var
  1299. Digits: String[40]; { String Of Digits }
  1300. Exponent: String[8]; { Exponent strin }
  1301. FmtStart, FmtStop: PChar; { Start And End Of relevant part }
  1302. { Of format String }
  1303. ExpFmt, ExpSize: Integer; { Type And Length Of }
  1304. { exponential format chosen }
  1305. Placehold: Array[1..4] Of Integer; { Number Of placeholders In All }
  1306. { four Sections }
  1307. thousand: Boolean; { thousand separators? }
  1308. UnexpectedDigits: Integer; { Number Of unexpected Digits that }
  1309. { have To be inserted before the }
  1310. { First placeholder. }
  1311. DigitExponent: Integer; { Exponent Of First digit In }
  1312. { Digits Array. }
  1313. { Find end of format section starting at P. False, if empty }
  1314. Function GetSectionEnd(Var P: PChar): Boolean;
  1315. Var
  1316. C: Char;
  1317. SQ, DQ: Boolean;
  1318. Begin
  1319. Result := False;
  1320. SQ := False;
  1321. DQ := False;
  1322. C := P[0];
  1323. While (C<>#0) And ((C<>';') Or SQ Or DQ) Do
  1324. Begin
  1325. Result := True;
  1326. Case C Of
  1327. #34: If Not SQ Then DQ := Not DQ;
  1328. #39: If Not DQ Then SQ := Not SQ;
  1329. End;
  1330. Inc(P);
  1331. C := P[0];
  1332. End;
  1333. End;
  1334. { Find start and end of format section to apply. If section doesn't exist,
  1335. use section 1. If section 2 is used, the sign of value is ignored. }
  1336. Procedure GetSectionRange(section: Integer);
  1337. Var
  1338. Sec: Array[1..3] Of PChar;
  1339. SecOk: Array[1..3] Of Boolean;
  1340. Begin
  1341. Sec[1] := format;
  1342. SecOk[1] := GetSectionEnd(Sec[1]);
  1343. If section > 1 Then
  1344. Begin
  1345. Sec[2] := Sec[1];
  1346. If Sec[2][0] <> #0 Then
  1347. Inc(Sec[2]);
  1348. SecOk[2] := GetSectionEnd(Sec[2]);
  1349. If section > 2 Then
  1350. Begin
  1351. Sec[3] := Sec[2];
  1352. If Sec[3][0] <> #0 Then
  1353. Inc(Sec[3]);
  1354. SecOk[3] := GetSectionEnd(Sec[3]);
  1355. End;
  1356. End;
  1357. If Not SecOk[1] Then
  1358. FmtStart := Nil
  1359. Else
  1360. Begin
  1361. If Not SecOk[section] Then
  1362. section := 1
  1363. Else If section = 2 Then
  1364. Value := -Value; { Remove sign }
  1365. If section = 1 Then FmtStart := format Else
  1366. Begin
  1367. FmtStart := Sec[section - 1];
  1368. Inc(FmtStart);
  1369. End;
  1370. FmtStop := Sec[section];
  1371. End;
  1372. End;
  1373. { Find format section ranging from FmtStart to FmtStop. }
  1374. Procedure GetFormatOptions;
  1375. Var
  1376. Fmt: PChar;
  1377. SQ, DQ: Boolean;
  1378. area: Integer;
  1379. Begin
  1380. SQ := False;
  1381. DQ := False;
  1382. Fmt := FmtStart;
  1383. ExpFmt := 0;
  1384. area := 1;
  1385. thousand := False;
  1386. Placehold[1] := 0;
  1387. Placehold[2] := 0;
  1388. Placehold[3] := 0;
  1389. Placehold[4] := 0;
  1390. While Fmt < FmtStop Do
  1391. Begin
  1392. Case Fmt[0] Of
  1393. #34:
  1394. Begin
  1395. If Not SQ Then
  1396. DQ := Not DQ;
  1397. Inc(Fmt);
  1398. End;
  1399. #39:
  1400. Begin
  1401. If Not DQ Then
  1402. SQ := Not SQ;
  1403. Inc(Fmt);
  1404. End;
  1405. Else
  1406. { This was 'if not SQ or DQ'. Looked wrong... }
  1407. If Not SQ Or DQ Then
  1408. Begin
  1409. Case Fmt[0] Of
  1410. '0':
  1411. Begin
  1412. Case area Of
  1413. 1:
  1414. area := 2;
  1415. 4:
  1416. Begin
  1417. area := 3;
  1418. Inc(Placehold[3], Placehold[4]);
  1419. Placehold[4] := 0;
  1420. End;
  1421. End;
  1422. Inc(Placehold[area]);
  1423. Inc(Fmt);
  1424. End;
  1425. '#':
  1426. Begin
  1427. If area=3 Then
  1428. area:=4;
  1429. Inc(Placehold[area]);
  1430. Inc(Fmt);
  1431. End;
  1432. '.':
  1433. Begin
  1434. If area<3 Then
  1435. area:=3;
  1436. Inc(Fmt);
  1437. End;
  1438. ',':
  1439. Begin
  1440. thousand := True;
  1441. Inc(Fmt);
  1442. End;
  1443. 'e', 'E':
  1444. If ExpFmt = 0 Then
  1445. Begin
  1446. If (Fmt[0]='E') Then
  1447. ExpFmt:=1
  1448. Else
  1449. ExpFmt := 3;
  1450. Inc(Fmt);
  1451. If (Fmt<FmtStop) Then
  1452. Begin
  1453. Case Fmt[0] Of
  1454. '+':
  1455. Begin
  1456. End;
  1457. '-':
  1458. Inc(ExpFmt);
  1459. Else
  1460. ExpFmt := 0;
  1461. End;
  1462. If ExpFmt <> 0 Then
  1463. Begin
  1464. Inc(Fmt);
  1465. ExpSize := 0;
  1466. While (Fmt<FmtStop) And
  1467. (ExpSize<4) And
  1468. (Fmt[0] In ['0'..'9']) Do
  1469. Begin
  1470. Inc(ExpSize);
  1471. Inc(Fmt);
  1472. End;
  1473. End;
  1474. End;
  1475. End
  1476. Else
  1477. Inc(Fmt);
  1478. Else { Case }
  1479. Inc(Fmt);
  1480. End; { Case }
  1481. End; { Begin }
  1482. End; { Case }
  1483. End; { While .. Begin }
  1484. End;
  1485. Procedure FloatToStr;
  1486. Var
  1487. I, J, Exp, Width, Decimals, DecimalPoint, len: Integer;
  1488. Begin
  1489. If ExpFmt = 0 Then
  1490. Begin
  1491. { Fixpoint }
  1492. Decimals:=Placehold[3]+Placehold[4];
  1493. Width:=Placehold[1]+Placehold[2]+Decimals;
  1494. If (Decimals=0) Then
  1495. Str(Value:Width:0,Digits)
  1496. Else
  1497. Str(Value:Width+1:Decimals,Digits);
  1498. len:=Length(Digits);
  1499. { Find the decimal point }
  1500. If (Decimals=0) Then
  1501. DecimalPoint:=len+1
  1502. Else
  1503. DecimalPoint:=len-Decimals;
  1504. { If value is very small, and no decimal places
  1505. are desired, remove the leading 0. }
  1506. If (Abs(Value) < 1) And (Placehold[2] = 0) Then
  1507. Begin
  1508. If (Placehold[1]=0) Then
  1509. Delete(Digits,DecimalPoint-1,1)
  1510. Else
  1511. Digits[DecimalPoint-1]:=' ';
  1512. End;
  1513. { Convert optional zeroes to spaces. }
  1514. I:=len;
  1515. J:=DecimalPoint+Placehold[3];
  1516. While (I>J) And (Digits[I]='0') Do
  1517. Begin
  1518. Digits[I] := ' ';
  1519. Dec(I);
  1520. End;
  1521. { If integer value and no obligatory decimal
  1522. places, remove decimal point. }
  1523. If (DecimalPoint < len) And (Digits[DecimalPoint + 1] = ' ') Then
  1524. Digits[DecimalPoint] := ' ';
  1525. { Convert spaces left from obligatory decimal point to zeroes. }
  1526. I:=DecimalPoint-Placehold[2];
  1527. While (I<DecimalPoint) And (Digits[I]=' ') Do
  1528. Begin
  1529. Digits[I] := '0';
  1530. Inc(I);
  1531. End;
  1532. Exp := 0;
  1533. End
  1534. Else
  1535. Begin
  1536. { Scientific: exactly <Width> Digits With <Precision> Decimals
  1537. And adjusted Exponent. }
  1538. If Placehold[1]+Placehold[2]=0 Then
  1539. Placehold[1]:=1;
  1540. Decimals := Placehold[3] + Placehold[4];
  1541. Width:=Placehold[1]+Placehold[2]+Decimals;
  1542. Str(Value:Width+8,Digits);
  1543. { Find and cut out exponent. Always the
  1544. last 6 characters in the string.
  1545. -> 0000E+0000 }
  1546. I:=Length(Digits)-5;
  1547. Val(Copy(Digits,I+1,5),Exp,J);
  1548. Exp:=Exp+1-(Placehold[1]+Placehold[2]);
  1549. Delete(Digits, I, 6);
  1550. { Str() always returns at least one digit after the decimal point.
  1551. If we don't want it, we have to remove it. }
  1552. If (Decimals=0) And (Placehold[1]+Placehold[2]<= 1) Then
  1553. Begin
  1554. If (Digits[4]>='5') Then
  1555. Begin
  1556. Inc(Digits[2]);
  1557. If (Digits[2]>'9') Then
  1558. Begin
  1559. Digits[2] := '1';
  1560. Inc(Exp);
  1561. End;
  1562. End;
  1563. Delete(Digits, 3, 2);
  1564. DecimalPoint := Length(Digits) + 1;
  1565. End
  1566. Else
  1567. Begin
  1568. { Move decimal point at the desired position }
  1569. Delete(Digits, 3, 1);
  1570. DecimalPoint:=2+Placehold[1]+Placehold[2];
  1571. If (Decimals<>0) Then
  1572. Insert('.',Digits,DecimalPoint);
  1573. End;
  1574. { Convert optional zeroes to spaces. }
  1575. I := Length(Digits);
  1576. J := DecimalPoint + Placehold[3];
  1577. While (I > J) And (Digits[I] = '0') Do
  1578. Begin
  1579. Digits[I] := ' ';
  1580. Dec(I);
  1581. End;
  1582. { If integer number and no obligatory decimal paces, remove decimal point }
  1583. If (DecimalPoint<Length(Digits)) And
  1584. (Digits[DecimalPoint+1]=' ') Then
  1585. Digits[DecimalPoint]:=' ';
  1586. If (Digits[1]=' ') Then
  1587. Begin
  1588. Delete(Digits, 1, 1);
  1589. Dec(DecimalPoint);
  1590. End;
  1591. { Calculate exponent string }
  1592. Str(Abs(Exp), Exponent);
  1593. While Length(Exponent)<ExpSize Do
  1594. Insert('0',Exponent,1);
  1595. If Exp >= 0 Then
  1596. Begin
  1597. If (ExpFmt In [1,3]) Then
  1598. Insert('+', Exponent, 1);
  1599. End
  1600. Else
  1601. Insert('-',Exponent,1);
  1602. If (ExpFmt<3) Then
  1603. Insert('E',Exponent,1)
  1604. Else
  1605. Insert('e',Exponent,1);
  1606. End;
  1607. DigitExponent:=DecimalPoint-2;
  1608. If (Digits[1]='-') Then
  1609. Dec(DigitExponent);
  1610. UnexpectedDigits:=DecimalPoint-1-(Placehold[1]+Placehold[2]);
  1611. End;
  1612. Function PutResult: LongInt;
  1613. Var
  1614. SQ, DQ: Boolean;
  1615. Fmt, Buf: PChar;
  1616. Dig, N: Integer;
  1617. Begin
  1618. SQ := False;
  1619. DQ := False;
  1620. Fmt := FmtStart;
  1621. Buf := Buffer;
  1622. Dig := 1;
  1623. While (Fmt<FmtStop) Do
  1624. Begin
  1625. //Write(Fmt[0]);
  1626. Case Fmt[0] Of
  1627. #34:
  1628. Begin
  1629. If Not SQ Then
  1630. DQ := Not DQ;
  1631. Inc(Fmt);
  1632. End;
  1633. #39:
  1634. Begin
  1635. If Not DQ Then
  1636. SQ := Not SQ;
  1637. Inc(Fmt);
  1638. End;
  1639. Else
  1640. If Not (SQ Or DQ) Then
  1641. Begin
  1642. Case Fmt[0] Of
  1643. '0', '#', '.':
  1644. Begin
  1645. If (Dig=1) And (UnexpectedDigits>0) Then
  1646. Begin
  1647. { Everything unexpected is written before the first digit }
  1648. For N := 1 To UnexpectedDigits Do
  1649. Begin
  1650. Buf[0] := Digits[N];
  1651. Inc(Buf);
  1652. If thousand And (Digits[N]<>'-') Then
  1653. Begin
  1654. If (DigitExponent Mod 3 = 0) And (DigitExponent>0) Then
  1655. Begin
  1656. Buf[0] := ThousandSeparator;
  1657. Inc(Buf);
  1658. End;
  1659. Dec(DigitExponent);
  1660. End;
  1661. End;
  1662. Inc(Dig, UnexpectedDigits);
  1663. End;
  1664. If (Digits[Dig]<>' ') Then
  1665. Begin
  1666. If (Digits[Dig]='.') Then
  1667. Buf[0] := DecimalSeparator
  1668. Else
  1669. Buf[0] := Digits[Dig];
  1670. Inc(Buf);
  1671. If thousand And (DigitExponent Mod 3 = 0) And (DigitExponent > 0) Then
  1672. Begin
  1673. Buf[0] := ThousandSeparator;
  1674. Inc(Buf);
  1675. End;
  1676. End;
  1677. Inc(Dig);
  1678. Dec(DigitExponent);
  1679. Inc(Fmt);
  1680. End;
  1681. 'e', 'E':
  1682. Begin
  1683. If ExpFmt <> 0 Then
  1684. Begin
  1685. Inc(Fmt);
  1686. If Fmt < FmtStop Then
  1687. Begin
  1688. If Fmt[0] In ['+', '-'] Then
  1689. Begin
  1690. Inc(Fmt, ExpSize);
  1691. For N:=1 To Length(Exponent) Do
  1692. Buf[N-1] := Exponent[N];
  1693. Inc(Buf,Length(Exponent));
  1694. ExpFmt:=0;
  1695. End;
  1696. Inc(Fmt);
  1697. End;
  1698. End
  1699. Else
  1700. Begin
  1701. { No legal exponential format.
  1702. Simply write the 'E' to the result. }
  1703. Buf[0] := Fmt[0];
  1704. Inc(Buf);
  1705. Inc(Fmt);
  1706. End;
  1707. End;
  1708. Else { Case }
  1709. { Usual character }
  1710. If (Fmt[0]<>',') Then
  1711. Begin
  1712. Buf[0] := Fmt[0];
  1713. Inc(Buf);
  1714. End;
  1715. Inc(Fmt);
  1716. End; { Case }
  1717. End
  1718. Else { IF }
  1719. Begin
  1720. { Character inside single or double quotes }
  1721. Buf[0] := Fmt[0];
  1722. Inc(Buf);
  1723. Inc(Fmt);
  1724. End;
  1725. End; { Case }
  1726. End; { While .. Begin }
  1727. Result:=PtrInt(Buf)-PtrInt(Buffer);
  1728. End;
  1729. Begin
  1730. If (Value>0) Then
  1731. GetSectionRange(1)
  1732. Else If (Value<0) Then
  1733. GetSectionRange(2)
  1734. Else
  1735. GetSectionRange(3);
  1736. If FmtStart = Nil Then
  1737. Begin
  1738. Result := FloatToText(Buffer, Value, ffGeneral, 15, 4);
  1739. End
  1740. Else
  1741. Begin
  1742. GetFormatOptions;
  1743. If (ExpFmt = 0) And (Abs(Value) >= 1E18) Then
  1744. Result := FloatToText(Buffer, Value, ffGeneral, 15, 4)
  1745. Else
  1746. Begin
  1747. FloatToStr;
  1748. Result := PutResult;
  1749. End;
  1750. End;
  1751. End;
  1752. Procedure FloatToDecimal(Var Result: TFloatRec; Value: Extended; Precision, Decimals : integer);
  1753. Var
  1754. Buffer: String[24];
  1755. Error, N: Integer;
  1756. Begin
  1757. Str(Value:23, Buffer);
  1758. Result.Negative := (Buffer[1] = '-');
  1759. Val(Copy(Buffer, 19, 5), Result.Exponent, Error);
  1760. Inc(Result. Exponent);
  1761. Result.Digits[0] := Buffer[2];
  1762. Move(Buffer[4], Result.Digits[1], 14);
  1763. If Decimals + Result.Exponent < Precision Then
  1764. N := Decimals + Result.Exponent
  1765. Else
  1766. N := Precision;
  1767. If N > 15 Then
  1768. N := 15;
  1769. If N = 0 Then
  1770. Begin
  1771. If Result.Digits[0] >= '5' Then
  1772. Begin
  1773. Result.Digits[0] := '1';
  1774. Result.Digits[1] := #0;
  1775. Inc(Result.Exponent);
  1776. End
  1777. Else
  1778. Result.Digits[0] := #0;
  1779. End
  1780. Else If N > 0 Then
  1781. Begin
  1782. If Result.Digits[N] >= '5' Then
  1783. Begin
  1784. Repeat
  1785. Result.Digits[N] := #0;
  1786. Dec(N);
  1787. Inc(Result.Digits[N]);
  1788. Until (N = 0) Or (Result.Digits[N] < ':');
  1789. If Result.Digits[0] = ':' Then
  1790. Begin
  1791. Result.Digits[0] := '1';
  1792. Inc(Result.Exponent);
  1793. End;
  1794. End
  1795. Else
  1796. Begin
  1797. Result.Digits[N] := '0';
  1798. While (Result.Digits[N] = '0') And (N > -1) Do
  1799. Begin
  1800. Result.Digits[N] := #0;
  1801. Dec(N);
  1802. End;
  1803. End;
  1804. End
  1805. Else
  1806. Result.Digits[0] := #0;
  1807. If Result.Digits[0] = #0 Then
  1808. Begin
  1809. Result.Exponent := 0;
  1810. Result.Negative := False;
  1811. End;
  1812. End;
  1813. Function FormatFloat(Const format: String; Value: Extended): String;
  1814. Var
  1815. Temp: ShortString;
  1816. buf : Array[0..1024] of char;
  1817. Begin
  1818. Buf[FloatToTextFmt(@Buf[0],Value,Pchar(Format))]:=#0;
  1819. Result:=StrPas(@Buf);
  1820. End;
  1821. {==============================================================================}
  1822. { extra functions }
  1823. {==============================================================================}
  1824. { LeftStr returns Count left-most characters from S }
  1825. function LeftStr(const S: string; Count: integer): string;
  1826. begin
  1827. result := Copy(S, 1, Count);
  1828. end ;
  1829. { RightStr returns Count right-most characters from S }
  1830. function RightStr(const S: string; Count: integer): string;
  1831. begin
  1832. If Count>Length(S) then
  1833. Count:=Length(S);
  1834. result := Copy(S, 1 + Length(S) - Count, Count);
  1835. end;
  1836. { BCDToInt converts the BCD value Value to an integer }
  1837. function BCDToInt(Value: integer): integer;
  1838. var i, j: integer;
  1839. begin
  1840. result := 0;
  1841. j := 1;
  1842. for i := 0 to SizeOf(Value) shr 1 - 1 do begin
  1843. result := result + j * (Value and 15);
  1844. j := j * 10;
  1845. Value := Value shr 4;
  1846. end ;
  1847. end ;
  1848. Function LastDelimiter(const Delimiters, S: string): Integer;
  1849. begin
  1850. Result:=Length(S);
  1851. While (Result>0) and (Pos(S[Result],Delimiters)=0) do
  1852. Dec(Result);
  1853. end;
  1854. Function StringReplace(const S, OldPattern, NewPattern: string; Flags: TReplaceFlags): string;
  1855. var
  1856. Srch,OldP,RemS: string; // Srch and Oldp can contain uppercase versions of S,OldPattern
  1857. P : Integer;
  1858. begin
  1859. Srch:=S;
  1860. OldP:=OldPattern;
  1861. if rfIgnoreCase in Flags then
  1862. begin
  1863. Srch:=UpperCase(Srch);
  1864. OldP:=UpperCase(OldP);
  1865. end;
  1866. RemS:=S;
  1867. Result:='';
  1868. while (Length(Srch)<>0) do
  1869. begin
  1870. P:=Pos(OldP, Srch);
  1871. if P=0 then
  1872. begin
  1873. Result:=Result+RemS;
  1874. Srch:='';
  1875. end
  1876. else
  1877. begin
  1878. Result:=Result+Copy(RemS,1,P-1)+NewPattern;
  1879. P:=P+Length(OldP);
  1880. RemS:=Copy(RemS,P,Length(RemS)-P+1);
  1881. if not (rfReplaceAll in Flags) then
  1882. begin
  1883. Result:=Result+RemS;
  1884. Srch:='';
  1885. end
  1886. else
  1887. Srch:=Copy(Srch,P,Length(Srch)-P+1);
  1888. end;
  1889. end;
  1890. end;
  1891. Function IsDelimiter(const Delimiters, S: string; Index: Integer): Boolean;
  1892. begin
  1893. Result:=False;
  1894. If (Index>0) and (Index<=Length(S)) then
  1895. Result:=Pos(S[Index],Delimiters)<>0; // Note we don't do MBCS yet
  1896. end;
  1897. Function ByteToCharLen(const S: string; MaxLen: Integer): Integer;
  1898. begin
  1899. Result:=Length(S);
  1900. If Result>MaxLen then
  1901. Result:=MaxLen;
  1902. end;
  1903. Function ByteToCharIndex(const S: string; Index: Integer): Integer;
  1904. begin
  1905. Result:=Index;
  1906. end;
  1907. Function CharToByteLen(const S: string; MaxLen: Integer): Integer;
  1908. begin
  1909. Result:=Length(S);
  1910. If Result>MaxLen then
  1911. Result:=MaxLen;
  1912. end;
  1913. Function CharToByteIndex(const S: string; Index: Integer): Integer;
  1914. begin
  1915. Result:=Index;
  1916. end;
  1917. Function ByteType(const S: string; Index: Integer): TMbcsByteType;
  1918. begin
  1919. Result:=mbSingleByte;
  1920. end;
  1921. Function StrByteType(Str: PChar; Index: Cardinal): TMbcsByteType;
  1922. begin
  1923. Result:=mbSingleByte;
  1924. end;
  1925. Function FindCmdLineSwitch(const Switch: string; const Chars: TSysCharSet;IgnoreCase: Boolean): Boolean;
  1926. Var
  1927. I,L : Integer;
  1928. S,T : String;
  1929. begin
  1930. Result:=False;
  1931. S:=Switch;
  1932. If IgnoreCase then
  1933. S:=UpperCase(S);
  1934. I:=ParamCount;
  1935. While (Not Result) and (I>0) do
  1936. begin
  1937. L:=Length(Paramstr(I));
  1938. If (L>0) and (ParamStr(I)[1] in Chars) then
  1939. begin
  1940. T:=Copy(ParamStr(I),2,L-1);
  1941. If IgnoreCase then
  1942. T:=UpperCase(T);
  1943. Result:=S=T;
  1944. end;
  1945. Dec(i);
  1946. end;
  1947. end;
  1948. Function FindCmdLineSwitch(const Switch: string; IgnoreCase: Boolean): Boolean;
  1949. begin
  1950. Result:=FindCmdLineSwitch(Switch,SwitchChars,IgnoreCase);
  1951. end;
  1952. Function FindCmdLineSwitch(const Switch: string): Boolean;
  1953. begin
  1954. Result:=FindCmdLineSwitch(Switch,SwitchChars,False);
  1955. end;
  1956. function WrapText(const Line, BreakStr: string; const BreakChars: TSysCharSet; MaxCol: Integer): string;
  1957. const
  1958. Quotes = ['''', '"'];
  1959. Var
  1960. L : String;
  1961. C,LQ,BC : Char;
  1962. P,BLen,Len : Integer;
  1963. HB,IBC : Boolean;
  1964. begin
  1965. Result:='';
  1966. L:=Line;
  1967. Blen:=Length(BreakStr);
  1968. If (BLen>0) then
  1969. BC:=BreakStr[1]
  1970. else
  1971. BC:=#0;
  1972. Len:=Length(L);
  1973. While (Len>0) do
  1974. begin
  1975. P:=1;
  1976. LQ:=#0;
  1977. HB:=False;
  1978. IBC:=False;
  1979. While ((P<=Len) and ((P<=MaxCol) or not IBC)) and ((LQ<>#0) or Not HB) do
  1980. begin
  1981. C:=L[P];
  1982. If (C=LQ) then
  1983. LQ:=#0
  1984. else If (C in Quotes) then
  1985. LQ:=C;
  1986. If (LQ<>#0) then
  1987. Inc(P)
  1988. else
  1989. begin
  1990. HB:=((C=BC) and (BreakStr=Copy(L,P,BLen)));
  1991. If HB then
  1992. Inc(P,Blen)
  1993. else
  1994. begin
  1995. If (P>MaxCol) then
  1996. IBC:=C in BreakChars;
  1997. Inc(P);
  1998. end;
  1999. end;
  2000. // Writeln('"',C,'" : IBC : ',IBC,' HB : ',HB,' LQ : ',LQ,' P>MaxCol : ',P>MaxCol);
  2001. end;
  2002. Result:=Result+Copy(L,1,P-1);
  2003. If Not HB then
  2004. Result:=Result+BreakStr;
  2005. Delete(L,1,P-1);
  2006. Len:=Length(L);
  2007. end;
  2008. end;
  2009. function WrapText(const Line: string; MaxCol: Integer): string;
  2010. begin
  2011. Result:=WrapText(Line,sLineBreak, [' ', '-', #9], MaxCol);
  2012. end;
  2013. {
  2014. Case Translation Tables
  2015. Can be used in internationalization support.
  2016. Although these tables can be obtained through system calls
  2017. it is better to not use those, since most implementation are not 100%
  2018. WARNING:
  2019. before modifying a translation table make sure that the current codepage
  2020. of the OS corresponds to the one you make changes to
  2021. }
  2022. const
  2023. { upper case translation table for character set 850 }
  2024. CP850UCT: array[128..255] of char =
  2025. ('€', 'š', '�', '¶', 'Ž', '¶', '�', '€', 'Ò', 'Ó', 'Ô', 'Ø', '×', 'Þ', 'Ž', '�',
  2026. '�', '’', '’', 'â', '™', 'ã', 'ê', 'ë', 'Y', '™', 'š', '�', 'œ', '�', 'ž', 'Ÿ',
  2027. 'µ', 'Ö', 'à', 'é', '¥', '¥', '¦', '§', '¨', '©', 'ª', '«', '¬', '­', '®', '¯',
  2028. '°', '±', '²', '³', '´', 'µ', '¶', '·', '¸', '¹', 'º', '»', '¼', '½', '¾', '¿',
  2029. 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Ç', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï',
  2030. 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', '×', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'Þ', 'ß',
  2031. 'à', 'á', 'â', 'ã', 'å', 'å', 'æ', 'í', 'è', 'é', 'ê', 'ë', 'í', 'í', 'î', 'ï',
  2032. 'ð', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', '÷', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'þ', 'ÿ');
  2033. { lower case translation table for character set 850 }
  2034. CP850LCT: array[128..255] of char =
  2035. ('‡', '�', '‚', 'ƒ', '„', '…', '†', '‡', 'ˆ', '‰', 'Š', '‹', 'Œ', '�', '„', '†',
  2036. '‚', '‘', '‘', '“', '”', '•', '–', '—', '˜', '”', '�', '›', 'œ', '›', 'ž', 'Ÿ',
  2037. ' ', '¡', '¢', '£', '¤', '¤', '¦', '§', '¨', '©', 'ª', '«', '¬', '­', '®', '¯',
  2038. '°', '±', '²', '³', '´', ' ', 'ƒ', '…', '¸', '¹', 'º', '»', '¼', '½', '¾', '¿',
  2039. 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Æ', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï',
  2040. 'Ð', 'Ñ', 'ˆ', '‰', 'Š', 'Õ', '¡', 'Œ', '‹', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', '�', 'ß',
  2041. '¢', 'á', '“', '•', 'ä', 'ä', 'æ', 'í', 'è', '£', '–', '—', 'ì', 'ì', 'î', 'ï',
  2042. 'ð', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', '÷', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'þ', 'ÿ');
  2043. { upper case translation table for character set ISO 8859/1 Latin 1 }
  2044. CPISO88591UCT: array[192..255] of char =
  2045. ( #192, #193, #194, #195, #196, #197, #198, #199,
  2046. #200, #201, #202, #203, #204, #205, #206, #207,
  2047. #208, #209, #210, #211, #212, #213, #214, #215,
  2048. #216, #217, #218, #219, #220, #221, #222, #223,
  2049. #192, #193, #194, #195, #196, #197, #198, #199,
  2050. #200, #201, #202, #203, #204, #205, #206, #207,
  2051. #208, #209, #210, #211, #212, #213, #214, #247,
  2052. #216, #217, #218, #219, #220, #221, #222, #89 );
  2053. { lower case translation table for character set ISO 8859/1 Latin 1 }
  2054. CPISO88591LCT: array[192..255] of char =
  2055. ( #224, #225, #226, #227, #228, #229, #230, #231,
  2056. #232, #233, #234, #235, #236, #237, #238, #239,
  2057. #240, #241, #242, #243, #244, #245, #246, #215,
  2058. #248, #249, #250, #251, #252, #253, #254, #223,
  2059. #224, #225, #226, #227, #228, #229, #230, #231,
  2060. #232, #233, #234, #235, #236, #237, #238, #239,
  2061. #240, #241, #242, #243, #244, #245, #246, #247,
  2062. #248, #249, #250, #251, #252, #253, #254, #255 );
  2063. {
  2064. $Log$
  2065. Revision 1.26 2005-01-17 18:38:48 peter
  2066. * extended overload disabled for powerpc
  2067. Revision 1.25 2005/01/16 17:53:27 michael
  2068. + Patch from Colin Western to implemenet TryStrToFLoat
  2069. Revision 1.24 2004/12/26 13:04:30 peter
  2070. * fix bugs 3477, 3478, 3479
  2071. Revision 1.23 2004/12/19 17:55:38 michael
  2072. + Implemented wraptext
  2073. Revision 1.22 2004/12/01 10:34:46 michael
  2074. + Patch from Pete: Dont support widestrings when compiled with 1.0.x and Add additional typecasts to Widestring for widechar/pwidechar
  2075. Revision 1.21 2004/11/30 20:56:27 michael
  2076. + Fix from Alexey Barkovoy for bug 3302
  2077. Revision 1.20 2004/11/22 05:53:44 marco
  2078. * fixed little 1.0.xism
  2079. Revision 1.19 2004/11/21 19:33:20 marco
  2080. * %x 64-bit support
  2081. Revision 1.18 2004/11/21 16:44:01 marco
  2082. * %u
  2083. Revision 1.17 2004/11/16 18:30:35 marco
  2084. * updated ansiexctractquotedstring (more delphi compat, both interface and code)
  2085. Revision 1.16 2004/08/30 18:00:12 michael
  2086. + Extra index check in IsDelimiter
  2087. Revision 1.15 2004/08/07 19:32:35 florian
  2088. * fixed CompareStr with a patch from Michalis Kamburelis
  2089. Revision 1.14 2004/08/07 16:56:28 florian
  2090. + TryStrToInt* added
  2091. Revision 1.13 2004/06/13 10:49:50 florian
  2092. * fixed some bootstrapping problems as well as some 64 bit stuff
  2093. Revision 1.12 2004/06/12 13:57:18 michael
  2094. + Enhanced FloatToStrF to 18 digits (Delphi compatibility, bug 3106
  2095. Revision 1.11 2004/06/12 13:23:17 michael
  2096. + Fixed currency<->string conversion support
  2097. Revision 1.10 2004/04/28 20:48:20 peter
  2098. * ordinal-pointer conversions fixed
  2099. Revision 1.9 2004/02/26 08:46:21 michael
  2100. + Added AnsiSameStr
  2101. Revision 1.8 2003/11/26 22:17:42 michael
  2102. + Merged fixbranch fixes, missing in main branch
  2103. Revision 1.7 2003/11/22 17:18:53 marco
  2104. * johill patch applied
  2105. Revision 1.6 2003/11/22 16:17:26 michael
  2106. + Small optimization in comparemem
  2107. Revision 1.5 2003/11/22 15:46:48 michael
  2108. + Patched CompareMem for case when length is 0
  2109. Revision 1.4 2003/11/09 13:37:42 michael
  2110. + Position specifier in format string affects all later specifiers
  2111. Revision 1.3 2003/11/03 09:42:28 marco
  2112. * Peter's Cardinal<->Longint fixes patch
  2113. Revision 1.2 2003/10/07 12:02:47 marco
  2114. * sametext and ansisametext added. (simple (ansi)comparetext wrappers)
  2115. Revision 1.1 2003/10/06 21:01:06 peter
  2116. * moved classes unit to rtl
  2117. Revision 1.26 2003/09/06 21:22:07 marco
  2118. * More objpas fixes
  2119. Revision 1.25 2002/12/23 23:26:08 florian
  2120. + addition to previous commit, forgot to save in the editor
  2121. Revision 1.23 2002/11/28 22:26:30 michael
  2122. + Fixed float<>string conversion routines
  2123. Revision 1.22 2002/11/28 20:29:26 michael
  2124. + made it compile again
  2125. Revision 1.21 2002/11/28 20:15:37 michael
  2126. + Fixed comparestr (merge from fix)
  2127. Revision 1.20 2002/09/15 17:50:35 peter
  2128. * Fixed AnsiStrComp crashes
  2129. Revision 1.1.2.16 2002/11/28 22:25:01 michael
  2130. + Fixed float<>string conversion routines
  2131. Revision 1.1.2.15 2002/11/28 20:24:11 michael
  2132. + merged some fixes from mainbranch
  2133. Revision 1.19 2002/09/07 16:01:22 peter
  2134. * old logs removed and tabs fixed
  2135. Revision 1.1.2.14 2002/11/28 20:13:10 michael
  2136. + Fixed comparestr
  2137. Revision 1.1.2.13 2002/10/29 23:41:06 michael
  2138. + Added lots of D4 functions
  2139. Revision 1.18 2002/09/02 06:07:16 michael
  2140. + Fix for formatbuf not applied correct
  2141. Revision 1.17 2002/08/29 10:04:48 michael
  2142. + Fix for bug report 2097 in formatbuf
  2143. Revision 1.16 2002/08/29 10:04:25 michael
  2144. + Fix for bug report 2097 in formatbuf
  2145. Revision 1.15 2002/07/06 12:14:03 daniel
  2146. - Changes from Strasbourg
  2147. Revision 1.14 2002/01/24 12:33:53 jonas
  2148. * adapted ranges of native types to int64 (e.g. high cardinal is no
  2149. longer longint($ffffffff), but just $fffffff in psystem)
  2150. * small additional fix in 64bit rangecheck code generation for 32 bit
  2151. processors
  2152. * adaption of ranges required the matching talgorithm used for selecting
  2153. which overloaded procedure to call to be adapted. It should now always
  2154. select the closest match for ordinal parameters.
  2155. + inttostr(qword) in sysstr.inc/sysstrh.inc
  2156. + abs(int64), sqr(int64), sqr(qword) in systemh.inc/generic.inc (previous
  2157. fixes were required to be able to add them)
  2158. * is_in_limit() moved from ncal to types unit, should always be used
  2159. instead of direct comparisons of low/high values of orddefs because
  2160. qword is a special case
  2161. }