sysstr.inc 75 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981
  1. {
  2. *********************************************************************
  3. Copyright (C) 1997, 1998 Gertjan Schouten
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. *********************************************************************
  16. System Utilities For Free Pascal
  17. }
  18. { NewStr creates a new PString and assigns S to it
  19. if length(s) = 0 NewStr returns Nil }
  20. function NewStr(const S: string): PString;
  21. begin
  22. if (S='') then
  23. Result:=nil
  24. else
  25. begin
  26. new(result);
  27. if (Result<>nil) then
  28. Result^:=s;
  29. end;
  30. end;
  31. { declaring this breaks delphi compatibility and e.g. tw3721.pp
  32. FUNCTION NewStr (Const S: ShortString): PShortString;
  33. VAR P: PShortString;
  34. BEGIN
  35. If (S = '') Then
  36. P := Nil
  37. Else
  38. Begin { Return nil }
  39. GetMem(P, Length(S) + 1); { Allocate memory }
  40. If (P<>Nil) Then P^ := S; { Hold string }
  41. End;
  42. NewStr := P; { Return result }
  43. END;
  44. }
  45. { DisposeStr frees the memory occupied by S }
  46. procedure DisposeStr(S: PString);
  47. begin
  48. if S <> Nil then
  49. begin
  50. dispose(s);
  51. S:=nil;
  52. end;
  53. end;
  54. PROCEDURE DisposeStr (S: PShortString);
  55. BEGIN
  56. If (S <> Nil) Then FreeMem(S, Length(S^) + 1); { Release memory }
  57. END;
  58. { AssignStr assigns S to P^ }
  59. procedure AssignStr(var P: PString; const S: string);
  60. begin
  61. P^ := s;
  62. end ;
  63. { AppendStr appends S to Dest }
  64. procedure AppendStr(var Dest: String; const S: string);
  65. begin
  66. Dest := Dest + S;
  67. end ;
  68. { UpperCase returns a copy of S where all lowercase characters ( from a to z )
  69. have been converted to uppercase }
  70. Function UpperCase(Const S : String) : String;
  71. Var
  72. i : Integer;
  73. P : PChar;
  74. begin
  75. Result := S;
  76. if not assigned(pointer(result)) then exit;
  77. UniqueString(Result);
  78. P:=Pchar(pointer(Result));
  79. for i := 1 to Length(Result) do
  80. begin
  81. if (P^ in ['a'..'z']) then P^ := char(byte(p^) - 32);
  82. Inc(P);
  83. end;
  84. end;
  85. { LowerCase returns a copy of S where all uppercase characters ( from A to Z )
  86. have been converted to lowercase }
  87. Function Lowercase(Const S : String) : String;
  88. Var
  89. i : Integer;
  90. P : PChar;
  91. begin
  92. Result := S;
  93. if not assigned(pointer(result)) then exit;
  94. UniqueString(Result);
  95. P:=Pchar(pointer(Result));
  96. for i := 1 to Length(Result) do
  97. begin
  98. if (P^ in ['A'..'Z']) then P^ := char(byte(p^) + 32);
  99. Inc(P);
  100. end;
  101. end;
  102. function LowerCase(const V: variant): string; overload;{$ifdef SYSUTILSINLINE}inline;{$endif}
  103. begin
  104. result:=LowerCase(ansistring(V));
  105. end;
  106. { CompareStr compares S1 and S2, the result is the based on
  107. substraction of the ascii values of the characters in S1 and S2
  108. case result
  109. S1 < S2 < 0
  110. S1 > S2 > 0
  111. S1 = S2 = 0 }
  112. function CompareStr(const S1, S2: string): Integer;
  113. var count, count1, count2: integer;
  114. begin
  115. result := 0;
  116. Count1 := Length(S1);
  117. Count2 := Length(S2);
  118. if Count1>Count2 then
  119. Count:=Count2
  120. else
  121. Count:=Count1;
  122. result := CompareMemRange(Pointer(S1),Pointer(S2), Count);
  123. if result=0 then
  124. result:=Count1-Count2;
  125. end;
  126. { CompareMemRange returns the result of comparison of Length bytes at P1 and P2
  127. case result
  128. P1 < P2 < 0
  129. P1 > P2 > 0
  130. P1 = P2 = 0 }
  131. function CompareMemRange(P1, P2: Pointer; Length: cardinal): integer;
  132. var
  133. i: cardinal;
  134. begin
  135. i := 0;
  136. result := 0;
  137. while (result=0) and (I<length) do
  138. begin
  139. result:=byte(P1^)-byte(P2^);
  140. P1:=pchar(P1)+1; // VP compat.
  141. P2:=pchar(P2)+1;
  142. i := i + 1;
  143. end ;
  144. end ;
  145. function CompareMem(P1, P2: Pointer; Length: cardinal): Boolean;
  146. var
  147. i: cardinal;
  148. begin
  149. Result:=True;
  150. I:=0;
  151. If (P1)<>(P2) then
  152. While Result and (i<Length) do
  153. begin
  154. Result:=PByte(P1)^=PByte(P2)^;
  155. Inc(I);
  156. Inc(pchar(P1));
  157. Inc(pchar(P2));
  158. end;
  159. end;
  160. { CompareText compares S1 and S2, the result is the based on
  161. substraction of the ascii values of characters in S1 and S2
  162. comparison is case-insensitive
  163. case result
  164. S1 < S2 < 0
  165. S1 > S2 > 0
  166. S1 = S2 = 0 }
  167. function CompareText(const S1, S2: string): integer;
  168. var
  169. i, count, count1, count2: integer; Chr1, Chr2: byte;
  170. P1, P2: PChar;
  171. begin
  172. Count1 := Length(S1);
  173. Count2 := Length(S2);
  174. if (Count1>Count2) then
  175. Count := Count2
  176. else
  177. Count := Count1;
  178. i := 0;
  179. if count>0 then
  180. begin
  181. P1 := @S1[1];
  182. P2 := @S2[1];
  183. while i < Count do
  184. begin
  185. Chr1 := byte(p1^);
  186. Chr2 := byte(p2^);
  187. if Chr1 <> Chr2 then
  188. begin
  189. if Chr1 in [97..122] then
  190. dec(Chr1,32);
  191. if Chr2 in [97..122] then
  192. dec(Chr2,32);
  193. if Chr1 <> Chr2 then
  194. Break;
  195. end;
  196. Inc(P1); Inc(P2); Inc(I);
  197. end;
  198. end;
  199. if i < Count then
  200. result := Chr1-Chr2
  201. else
  202. result := count1-count2;
  203. end;
  204. function SameText(const s1,s2:String):Boolean;
  205. begin
  206. Result:=CompareText(S1,S2)=0;
  207. end;
  208. {$ifndef FPC_NOGENERICANSIROUTINES}
  209. {==============================================================================}
  210. { Ansi string functions }
  211. { these functions rely on the character set loaded by the OS }
  212. {==============================================================================}
  213. type
  214. TCaseTranslationTable = array[0..255] of char;
  215. var
  216. { Tables with upper and lowercase forms of character sets.
  217. MUST be initialized with the correct code-pages }
  218. UpperCaseTable: TCaseTranslationTable;
  219. LowerCaseTable: TCaseTranslationTable;
  220. function GenericAnsiUpperCase(const s: string): string;
  221. var
  222. len, i: integer;
  223. begin
  224. len := length(s);
  225. SetLength(result, len);
  226. for i := 1 to len do
  227. result[i] := UpperCaseTable[ord(s[i])];
  228. end;
  229. function GenericAnsiLowerCase(const s: string): string;
  230. var
  231. len, i: integer;
  232. begin
  233. len := length(s);
  234. SetLength(result, len);
  235. for i := 1 to len do
  236. result[i] := LowerCaseTable[ord(s[i])];
  237. end;
  238. function GenericAnsiCompareStr(const S1, S2: string): PtrInt;
  239. Var
  240. I,L1,L2 : SizeInt;
  241. begin
  242. Result:=0;
  243. L1:=Length(S1);
  244. L2:=Length(S2);
  245. I:=1;
  246. While (Result=0) and ((I<=L1) and (I<=L2)) do
  247. begin
  248. Result:=Ord(S1[I])-Ord(S2[I]); //!! Must be replaced by ansi characters !!
  249. Inc(I);
  250. end;
  251. If Result=0 Then
  252. Result:=L1-L2;
  253. end;
  254. function GenericAnsiCompareText(const S1, S2: string): PtrInt;
  255. Var
  256. I,L1,L2 : SizeInt;
  257. begin
  258. Result:=0;
  259. L1:=Length(S1);
  260. L2:=Length(S2);
  261. I:=1;
  262. While (Result=0) and ((I<=L1) and (I<=L2)) do
  263. begin
  264. Result:=Ord(LowerCaseTable[Ord(S1[I])])-Ord(LowerCaseTable[Ord(S2[I])]); //!! Must be replaced by ansi characters !!
  265. Inc(I);
  266. end;
  267. If Result=0 Then
  268. Result:=L1-L2;
  269. end;
  270. function GenericAnsiStrComp(S1, S2: PChar): PtrInt;
  271. begin
  272. Result:=0;
  273. If S1=Nil then
  274. begin
  275. If S2=Nil Then Exit;
  276. result:=-1;
  277. exit;
  278. end;
  279. If S2=Nil then
  280. begin
  281. Result:=1;
  282. exit;
  283. end;
  284. While (Result=0) and (S1^<>#0) and (S2^<>#0) do begin
  285. Result:=Ord(S1^)-Ord(S2^); //!! Must be replaced by ansi characters !!
  286. Inc(S1);
  287. Inc(S2);
  288. end;
  289. if (Result=0) and (S1^<>S2^) then // loop ended because exactly one has #0
  290. if S1^=#0 then // shorter string is smaller
  291. result:=-1
  292. else
  293. result:=1;
  294. end;
  295. function GenericAnsiStrIComp(S1, S2: PChar): PtrInt;
  296. begin
  297. Result:=0;
  298. If S1=Nil then
  299. begin
  300. If S2=Nil Then Exit;
  301. result:=-1;
  302. exit;
  303. end;
  304. If S2=Nil then
  305. begin
  306. Result:=1;
  307. exit;
  308. end;
  309. While (Result=0) and (S1^<>#0) and (S2^<>#0) do begin
  310. Result:=Ord(LowerCaseTable[Ord(S1[0])])-Ord(LowerCaseTable[Ord(S2[0])]); //!! Must be replaced by ansi characters !!
  311. Inc(S1);
  312. Inc(S2);
  313. end;
  314. if (Result=0) and (s1[0]<>s2[0]) then //length(s1)<>length(s2)
  315. if s1[0]=#0 then
  316. Result:=-1 //s1 shorter than s2
  317. else
  318. Result:=1; //s1 longer than s2
  319. end;
  320. function GenericAnsiStrLComp(S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
  321. Var I : cardinal;
  322. begin
  323. Result:=0;
  324. If MaxLen=0 then exit;
  325. If S1=Nil then
  326. begin
  327. If S2=Nil Then Exit;
  328. result:=-1;
  329. exit;
  330. end;
  331. If S2=Nil then
  332. begin
  333. Result:=1;
  334. exit;
  335. end;
  336. I:=0;
  337. Repeat
  338. Result:=Ord(S1[0])-Ord(S2[0]); //!! Must be replaced by ansi characters !!
  339. Inc(S1);
  340. Inc(S2);
  341. Inc(I);
  342. Until (Result<>0) or (I=MaxLen)
  343. end;
  344. function GenericAnsiStrLIComp(S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
  345. Var I : cardinal;
  346. begin
  347. Result:=0;
  348. If MaxLen=0 then exit;
  349. If S1=Nil then
  350. begin
  351. If S2=Nil Then Exit;
  352. result:=-1;
  353. exit;
  354. end;
  355. If S2=Nil then
  356. begin
  357. Result:=1;
  358. exit;
  359. end;
  360. I:=0;
  361. Repeat
  362. Result:=Ord(LowerCaseTable[Ord(S1[0])])-Ord(LowerCaseTable[Ord(S2[0])]); //!! Must be replaced by ansi characters !!
  363. Inc(S1);
  364. Inc(S2);
  365. Inc(I);
  366. Until (Result<>0) or (I=MaxLen)
  367. end;
  368. function GenericAnsiStrLower(Str: PChar): PChar;
  369. begin
  370. result := Str;
  371. if Str <> Nil then begin
  372. while Str^ <> #0 do begin
  373. Str^ := LowerCaseTable[byte(Str^)];
  374. Str := Str + 1;
  375. end;
  376. end;
  377. end;
  378. function GenericAnsiStrUpper(Str: PChar): PChar;
  379. begin
  380. result := Str;
  381. if Str <> Nil then begin
  382. while Str^ <> #0 do begin
  383. Str^ := UpperCaseTable[byte(Str^)];
  384. Str := Str + 1;
  385. end ;
  386. end ;
  387. end ;
  388. {$endif FPC_NOGENERICANSIROUTINES}
  389. function AnsiSameText(const s1,s2:String):Boolean;{$ifdef SYSUTILSINLINE}inline;{$endif}
  390. begin
  391. AnsiSameText:=AnsiCompareText(S1,S2)=0;
  392. end;
  393. function AnsiSameStr(const s1,s2:String):Boolean;{$ifdef SYSUTILSINLINE}inline;{$endif}
  394. begin
  395. AnsiSameStr:=AnsiCompareStr(S1,S2)=0;
  396. end;
  397. function AnsiLastChar(const S: string): PChar;
  398. begin
  399. //!! No multibyte yet, so we return the last one.
  400. result:=StrEnd(Pchar(pointer(S))); // strend checks for nil
  401. Dec(Result);
  402. end ;
  403. function AnsiStrLastChar(Str: PChar): PChar;
  404. begin
  405. //!! No multibyte yet, so we return the last one.
  406. result:=StrEnd(Str);
  407. Dec(Result);
  408. end ;
  409. function AnsiUpperCase(const s: string): string;{$ifdef SYSUTILSINLINE}inline;{$endif}
  410. begin
  411. result:=widestringmanager.UpperAnsiStringProc(s);
  412. end;
  413. function AnsiLowerCase(const s: string): string;{$ifdef SYSUTILSINLINE}inline;{$endif}
  414. begin
  415. result:=widestringmanager.LowerAnsiStringProc(s);
  416. end;
  417. function AnsiCompareStr(const S1, S2: string): integer;{$ifdef SYSUTILSINLINE}inline;{$endif}
  418. begin
  419. result:=widestringmanager.CompareStrAnsiStringProc(s1,s2);
  420. end;
  421. function AnsiCompareText(const S1, S2: string): integer;{$ifdef SYSUTILSINLINE}inline;{$endif}
  422. begin
  423. result:=widestringmanager.CompareTextAnsiStringProc(s1,s2);
  424. end;
  425. function AnsiStrComp(S1, S2: PChar): integer;{$ifdef SYSUTILSINLINE}inline;{$endif}
  426. begin
  427. result:=widestringmanager.StrCompAnsiStringProc(s1,s2);
  428. end;
  429. function AnsiStrIComp(S1, S2: PChar): integer;{$ifdef SYSUTILSINLINE}inline;{$endif}
  430. begin
  431. result:=widestringmanager.StrICompAnsiStringProc(s1,s2);
  432. end;
  433. function AnsiStrLComp(S1, S2: PChar; MaxLen: cardinal): integer;{$ifdef SYSUTILSINLINE}inline;{$endif}
  434. begin
  435. result:=widestringmanager.StrLCompAnsiStringProc(s1,s2,maxlen);
  436. end;
  437. function AnsiStrLIComp(S1, S2: PChar; MaxLen: cardinal): integer;{$ifdef SYSUTILSINLINE}inline;{$endif}
  438. begin
  439. result:=widestringmanager.StrLICompAnsiStringProc(s1,s2,maxlen);
  440. end;
  441. function AnsiStrLower(Str: PChar): PChar;{$ifdef SYSUTILSINLINE}inline;{$endif}
  442. begin
  443. result:=widestringmanager.StrLowerAnsiStringProc(Str);
  444. end;
  445. function AnsiStrUpper(Str: PChar): PChar;{$ifdef SYSUTILSINLINE}inline;{$endif}
  446. begin
  447. result:=widestringmanager.StrUpperAnsiStringProc(Str);
  448. end;
  449. {==============================================================================}
  450. { End of Ansi functions }
  451. {==============================================================================}
  452. { Trim returns a copy of S with blanks characters on the left and right stripped off }
  453. Const WhiteSpace = [#0..' '];
  454. function Trim(const S: string): string;
  455. var Ofs, Len: integer;
  456. begin
  457. len := Length(S);
  458. while (Len>0) and (S[Len] in WhiteSpace) do
  459. dec(Len);
  460. Ofs := 1;
  461. while (Ofs<=Len) and (S[Ofs] in WhiteSpace) do
  462. Inc(Ofs);
  463. result := Copy(S, Ofs, 1 + Len - Ofs);
  464. end ;
  465. { TrimLeft returns a copy of S with all blank characters on the left stripped off }
  466. function TrimLeft(const S: string): string;
  467. var i,l:integer;
  468. begin
  469. l := length(s);
  470. i := 1;
  471. while (i<=l) and (s[i] in whitespace) do
  472. inc(i);
  473. Result := copy(s, i, l);
  474. end ;
  475. { TrimRight returns a copy of S with all blank characters on the right stripped off }
  476. function TrimRight(const S: string): string;
  477. var l:integer;
  478. begin
  479. l := length(s);
  480. while (l>0) and (s[l] in whitespace) do
  481. dec(l);
  482. result := copy(s,1,l);
  483. end ;
  484. { QuotedStr returns S quoted left and right and every single quote in S
  485. replaced by two quotes }
  486. function QuotedStr(const S: string): string;
  487. begin
  488. result := AnsiQuotedStr(s, '''');
  489. end ;
  490. { AnsiQuotedStr returns S quoted left and right by Quote,
  491. and every single occurance of Quote replaced by two }
  492. function AnsiQuotedStr(const S: string; Quote: char): string;
  493. var i, j, count: integer;
  494. begin
  495. result := '' + Quote;
  496. count := length(s);
  497. i := 0;
  498. j := 0;
  499. while i < count do begin
  500. i := i + 1;
  501. if S[i] = Quote then begin
  502. result := result + copy(S, 1 + j, i - j) + Quote;
  503. j := i;
  504. end ;
  505. end ;
  506. if i <> j then
  507. result := result + copy(S, 1 + j, i - j);
  508. result := result + Quote;
  509. end ;
  510. { AnsiExtractQuotedStr returns a copy of Src with quote characters
  511. deleted to the left and right and double occurances
  512. of Quote replaced by a single Quote }
  513. function AnsiExtractQuotedStr(var Src: PChar; Quote: Char): string;
  514. var
  515. P,Q,R: PChar;
  516. begin
  517. P := Src;
  518. Q := StrEnd(P);
  519. result:='';
  520. if P=Q then exit;
  521. if P^<>quote then exit;
  522. inc(p);
  523. setlength(result,(Q-P)+1);
  524. R:=@Result[1];
  525. while P <> Q do
  526. begin
  527. R^:=P^;
  528. inc(R);
  529. if (P^ = Quote) then
  530. begin
  531. P := P + 1;
  532. if (p^ <> Quote) then
  533. begin
  534. dec(R);
  535. break;
  536. end;
  537. end;
  538. P := P + 1;
  539. end ;
  540. src:=p;
  541. SetLength(result, (R-pchar(@Result[1])));
  542. end ;
  543. { AdjustLineBreaks returns S with all CR characters not followed by LF
  544. replaced with CR/LF }
  545. // under Linux all CR characters or CR/LF combinations should be replaced with LF
  546. function AdjustLineBreaks(const S: string): string;
  547. begin
  548. Result:=AdjustLineBreaks(S,DefaultTextLineBreakStyle);
  549. end;
  550. function AdjustLineBreaks(const S: string; Style: TTextLineBreakStyle): string;
  551. var
  552. Source,Dest: PChar;
  553. DestLen: Integer;
  554. I,J,L: Longint;
  555. begin
  556. Source:=Pointer(S);
  557. L:=Length(S);
  558. DestLen:=L;
  559. I:=1;
  560. while (I<=L) do
  561. begin
  562. case S[i] of
  563. #10: if (Style=tlbsCRLF) then
  564. Inc(DestLen);
  565. #13: if (Style=tlbsCRLF) then
  566. if (I<L) and (S[i+1]=#10) then
  567. Inc(I)
  568. else
  569. Inc(DestLen)
  570. else if (I<L) and (S[I+1]=#10) then
  571. Dec(DestLen);
  572. end;
  573. Inc(I);
  574. end;
  575. if (DestLen=L) then
  576. Result:=S
  577. else
  578. begin
  579. SetLength(Result, DestLen);
  580. FillChar(Result[1],DestLen,0);
  581. Dest := Pointer(Result);
  582. J:=0;
  583. I:=0;
  584. While I<L do
  585. case Source[I] of
  586. #10: begin
  587. if Style=tlbsCRLF then
  588. begin
  589. Dest[j]:=#13;
  590. Inc(J);
  591. end;
  592. Dest[J] := #10;
  593. Inc(J);
  594. Inc(I);
  595. end;
  596. #13: begin
  597. if Style=tlbsCRLF then
  598. begin
  599. Dest[j] := #13;
  600. Inc(J);
  601. end;
  602. Dest[j]:=#10;
  603. Inc(J);
  604. Inc(I);
  605. if Source[I]=#10 then
  606. Inc(I);
  607. end;
  608. else
  609. Dest[j]:=Source[i];
  610. Inc(J);
  611. Inc(I);
  612. end;
  613. end;
  614. end;
  615. { IsValidIdent returns true if the first character of Ident is in:
  616. 'A' to 'Z', 'a' to 'z' or '_' and the following characters are
  617. on of: 'A' to 'Z', 'a' to 'z', '0'..'9' or '_' }
  618. function IsValidIdent(const Ident: string): boolean;
  619. var i, len: integer;
  620. begin
  621. result := false;
  622. len := length(Ident);
  623. if len <> 0 then begin
  624. result := Ident[1] in ['A'..'Z', 'a'..'z', '_'];
  625. i := 1;
  626. while (result) and (i < len) do begin
  627. i := i + 1;
  628. result := result and (Ident[i] in ['A'..'Z', 'a'..'z', '0'..'9', '_']);
  629. end ;
  630. end ;
  631. end ;
  632. { IntToStr returns a string representing the value of Value }
  633. function IntToStr(Value: integer): string;
  634. begin
  635. System.Str(Value, result);
  636. end ;
  637. function IntToStr(Value: int64): string;
  638. begin
  639. System.Str(Value, result);
  640. end ;
  641. function IntToStr(Value: QWord): string;
  642. begin
  643. System.Str(Value, result);
  644. end ;
  645. { IntToHex returns a string representing the hexadecimal value of Value }
  646. const
  647. HexDigits: array[0..15] of char = '0123456789ABCDEF';
  648. function IntToHex(Value: integer; Digits: integer): string;
  649. var i: integer;
  650. begin
  651. SetLength(result, digits);
  652. for i := 0 to digits - 1 do
  653. begin
  654. result[digits - i] := HexDigits[value and 15];
  655. value := value shr 4;
  656. end ;
  657. while value <> 0 do begin
  658. result := HexDigits[value and 15] + result;
  659. value := value shr 4;
  660. end;
  661. end ;
  662. function IntToHex(Value: int64; Digits: integer): string;
  663. var i: integer;
  664. begin
  665. SetLength(result, digits);
  666. for i := 0 to digits - 1 do
  667. begin
  668. result[digits - i] := HexDigits[value and 15];
  669. value := value shr 4;
  670. end ;
  671. while value <> 0 do begin
  672. result := HexDigits[value and 15] + result;
  673. value := value shr 4;
  674. end;
  675. end ;
  676. function IntToHex(Value: QWord; Digits: integer): string;
  677. begin
  678. result:=IntToHex(Int64(Value),Digits);
  679. end;
  680. function TryStrToInt(const s: string; out i : integer) : boolean;
  681. var Error : word;
  682. begin
  683. Val(s, i, Error);
  684. TryStrToInt:=Error=0
  685. end;
  686. { StrToInt converts the string S to an integer value,
  687. if S does not represent a valid integer value EConvertError is raised }
  688. function StrToInt(const S: string): integer;
  689. var Error: word;
  690. begin
  691. Val(S, result, Error);
  692. if Error <> 0 then raise EConvertError.createfmt(SInvalidInteger,[S]);
  693. end ;
  694. function StrToInt64(const S: string): int64;
  695. var Error: word;
  696. begin
  697. Val(S, result, Error);
  698. if Error <> 0 then raise EConvertError.createfmt(SInvalidInteger,[S]);
  699. end;
  700. function TryStrToInt64(const s: string; Out i : int64) : boolean;
  701. var Error : word;
  702. begin
  703. Val(s, i, Error);
  704. TryStrToInt64:=Error=0
  705. end;
  706. function StrToQWord(const s: string): QWord;
  707. var Error: word;
  708. begin
  709. Val(S, result, Error);
  710. if Error <> 0 then raise EConvertError.createfmt(SInvalidInteger,[S]);
  711. end;
  712. function TryStrToQWord(const s: string; Out Q: QWord): boolean;
  713. var Error : word;
  714. begin
  715. Val(s, Q, Error);
  716. TryStrToQWord:=Error=0
  717. end;
  718. { StrToIntDef converts the string S to an integer value,
  719. Default is returned in case S does not represent a valid integer value }
  720. function StrToIntDef(const S: string; Default: integer): integer;
  721. var Error: word;
  722. begin
  723. Val(S, result, Error);
  724. if Error <> 0 then result := Default;
  725. end ;
  726. { StrToInt64Def converts the string S to an int64 value,
  727. Default is returned in case S does not represent a valid int64 value }
  728. function StrToInt64Def(const S: string; Default: int64): int64;
  729. var Error: word;
  730. begin
  731. Val(S, result, Error);
  732. if Error <> 0 then result := Default;
  733. end ;
  734. { StrToQWordDef converts the string S to an QWord value,
  735. Default is returned in case S does not represent a valid QWord value }
  736. function StrToQWordDef(const S: string; Default: QWord): QWord;
  737. var Error: word;
  738. begin
  739. Val(S, result, Error);
  740. if Error <> 0 then result := Default;
  741. end;
  742. { LoadStr returns the string resource Ident. }
  743. function LoadStr(Ident: integer): string;
  744. begin
  745. result:='';
  746. end ;
  747. { FmtLoadStr returns the string resource Ident and formats it accordingly }
  748. function FmtLoadStr(Ident: integer; const Args: array of const): string;
  749. begin
  750. result:='';
  751. end;
  752. Const
  753. feInvalidFormat = 1;
  754. feMissingArgument = 2;
  755. feInvalidArgIndex = 3;
  756. {$ifdef fmtdebug}
  757. Procedure Log (Const S: String);
  758. begin
  759. Writeln (S);
  760. end;
  761. {$endif}
  762. Procedure DoFormatError (ErrCode : Longint);
  763. Var
  764. S : String;
  765. begin
  766. //!! must be changed to contain format string...
  767. S:='';
  768. Case ErrCode of
  769. feInvalidFormat : raise EConvertError.Createfmt(SInvalidFormat,[s]);
  770. feMissingArgument : raise EConvertError.Createfmt(SArgumentMissing,[s]);
  771. feInvalidArgIndex : raise EConvertError.Createfmt(SInvalidArgIndex,[s]);
  772. end;
  773. end;
  774. { we've no templates, but with includes we can simulate this :) }
  775. {$macro on}
  776. {$define INFORMAT}
  777. {$define TFormatString:=ansistring}
  778. {$define TFormatChar:=char}
  779. Function Format (Const Fmt : AnsiString; const Args : Array of const; const FormatSettings: TFormatSettings) : AnsiString;
  780. {$i sysformt.inc}
  781. {$undef TFormatString}
  782. {$undef TFormatChar}
  783. {$undef INFORMAT}
  784. {$macro off}
  785. Function Format (Const Fmt : AnsiString; const Args : Array of const) : AnsiString;
  786. begin
  787. Result:=Format(Fmt,Args,DefaultFormatSettings);
  788. end;
  789. Function FormatBuf (Var Buffer; BufLen : Cardinal; Const Fmt; fmtLen : Cardinal; Const Args : Array of const; Const FormatSettings: TFormatSettings) : Cardinal;
  790. Var S,F : String;
  791. begin
  792. Setlength(F,fmtlen);
  793. if fmtlen > 0 then
  794. Move(fmt,F[1],fmtlen);
  795. S:=Format (F,Args,FormatSettings);
  796. If Cardinal(Length(S))<Buflen then
  797. Result:=Length(S)
  798. else
  799. Result:=Buflen;
  800. Move(S[1],Buffer,Result);
  801. end;
  802. Function FormatBuf (Var Buffer; BufLen : Cardinal;
  803. Const Fmt; fmtLen : Cardinal;
  804. Const Args : Array of const) : Cardinal;
  805. begin
  806. Result:=FormatBuf(Buffer,BufLen,Fmt,FmtLen,Args,DefaultFormatSettings);
  807. end;
  808. Procedure FmtStr(Var Res: string; const Fmt : string; Const args: Array of const; Const FormatSettings: TFormatSettings);
  809. begin
  810. Res:=Format(fmt,Args,FormatSettings);
  811. end;
  812. Procedure FmtStr(Var Res: String; Const Fmt : String; Const args: Array of const);
  813. begin
  814. FmtStr(Res,Fmt,Args,DefaultFormatSettings);
  815. end;
  816. Function StrFmt(Buffer,Fmt : PChar; Const args: Array of const) : Pchar;
  817. begin
  818. Result:=StrFmt(Buffer,Fmt,Args,DefaultFormatSettings);
  819. end;
  820. Function StrFmt(Buffer,Fmt : PChar; Const Args: Array of const; Const FormatSettings: TFormatSettings): PChar;
  821. begin
  822. Buffer[FormatBuf(Buffer^,Maxint,Fmt^,strlen(fmt),args,FormatSettings)]:=#0;
  823. Result:=Buffer;
  824. end;
  825. Function StrLFmt(Buffer : PCHar; Maxlen : Cardinal;Fmt : PChar; Const args: Array of const) : Pchar;
  826. begin
  827. Result:=StrLFmt(Buffer,MaxLen,Fmt,Args,DefaultFormatSettings);
  828. end;
  829. Function StrLFmt(Buffer : PCHar; Maxlen : Cardinal;Fmt : PChar; Const args: Array of const; Const FormatSettings: TFormatSettings) : Pchar;
  830. begin
  831. Buffer[FormatBuf(Buffer^,MaxLen,Fmt^,strlen(fmt),args,FormatSettings)]:=#0;
  832. Result:=Buffer;
  833. end;
  834. {$ifndef FPUNONE}
  835. Function StrToFloat(Const S: String): Extended;
  836. begin
  837. Result:=StrToFloat(S,DefaultFormatSettings);
  838. end;
  839. Function StrToFloat(Const S : String; Const FormatSettings: TFormatSettings) : Extended;
  840. Begin // texttofloat handles NIL properly
  841. If Not TextToFloat(Pchar(pointer(S)),Result,FormatSettings) then
  842. Raise EConvertError.createfmt(SInValidFLoat,[S]);
  843. End;
  844. function StrToFloatDef(const S: string; const Default: Extended): Extended;
  845. begin
  846. Result:=StrToFloatDef(S,Default,DefaultFormatSettings);
  847. end;
  848. Function StrToFloatDef(Const S: String; Const Default: Extended; Const FormatSettings: TFormatSettings): Extended;
  849. begin
  850. if not TextToFloat(PChar(pointer(S)),Result,fvExtended,FormatSettings) then
  851. Result:=Default;
  852. end;
  853. Function TextToFloat(Buffer: PChar; Out Value: Extended; Const FormatSettings: TFormatSettings): Boolean;
  854. Var
  855. E,P : Integer;
  856. S : String;
  857. Begin
  858. S:=StrPas(Buffer);
  859. //ThousandSeparator not allowed as by Delphi specs
  860. if (FormatSettings.ThousandSeparator <> FormatSettings.DecimalSeparator) and
  861. (Pos(FormatSettings.ThousandSeparator, S) <> 0) then
  862. begin
  863. Result := False;
  864. Exit;
  865. end;
  866. if (FormatSettings.DecimalSeparator <> '.') and
  867. (Pos('.', S) <>0) then
  868. begin
  869. Result := False;
  870. Exit;
  871. end;
  872. P:=Pos(FormatSettings.DecimalSeparator,S);
  873. If (P<>0) Then
  874. S[P] := '.';
  875. Val(trim(S),Value,E);
  876. Result:=(E=0);
  877. End;
  878. Function TextToFloat(Buffer: PChar; Out Value: Extended): Boolean;
  879. begin
  880. Result:=TextToFloat(Buffer,Value,DefaultFormatSettings);
  881. end;
  882. Function TextToFloat(Buffer: PChar; Out Value; ValueType: TFloatValue): Boolean;
  883. begin
  884. Result:=TextToFloat(Buffer,Value,ValueType,DefaultFormatSettings);
  885. end;
  886. Function TextToFloat(Buffer: PChar; Out Value; ValueType: TFloatValue; Const FormatSettings: TFormatSettings): Boolean;
  887. Var
  888. E,P : Integer;
  889. S : String;
  890. {$ifndef FPC_HAS_STR_CURRENCY}
  891. TempValue: extended;
  892. {$endif FPC_HAS_STR_CURRENCY}
  893. Begin
  894. S:=StrPas(Buffer);
  895. //ThousandSeparator not allowed as by Delphi specs
  896. if (FormatSettings.ThousandSeparator <> FormatSettings.DecimalSeparator) and
  897. (Pos(FormatSettings.ThousandSeparator, S) <> 0) then
  898. begin
  899. Result := False;
  900. Exit;
  901. end;
  902. if (FormatSettings.DecimalSeparator <> '.') and
  903. (Pos('.', S) <>0) then
  904. begin
  905. Result := False;
  906. Exit;
  907. end;
  908. P:=Pos(FormatSettings.DecimalSeparator,S);
  909. If (P<>0) Then
  910. S[P] := '.';
  911. case ValueType of
  912. fvCurrency:
  913. {$ifdef FPC_HAS_STR_CURRENCY}
  914. Val(S,Currency(Value),E);
  915. {$else FPC_HAS_STR_CURRENCY}
  916. begin
  917. // needed for platforms where Currency = Int64
  918. Val(S,TempValue,E);
  919. Currency(Value) := TempValue;
  920. end;
  921. {$endif FPC_HAS_STR_CURRENCY}
  922. fvExtended:
  923. Val(S,Extended(Value),E);
  924. fvDouble:
  925. Val(S,Double(Value),E);
  926. fvSingle:
  927. Val(S,Single(Value),E);
  928. fvComp:
  929. Val(S,Comp(Value),E);
  930. fvReal:
  931. Val(S,Real(Value),E);
  932. end;
  933. Result:=(E=0);
  934. End;
  935. Function TryStrToFloat(Const S : String; Out Value: Single): Boolean;
  936. begin
  937. Result:=TryStrToFloat(S,Value,DefaultFormatSettings);
  938. end;
  939. Function TryStrToFloat(Const S : String; Out Value: Single; Const FormatSettings: TFormatSettings): Boolean;
  940. Begin
  941. Result := TextToFloat(PChar(pointer(S)), Value, fvSingle,FormatSettings);
  942. End;
  943. Function TryStrToFloat(Const S : String; Out Value: Double): Boolean;
  944. begin
  945. Result:=TryStrToFloat(S,Value,DefaultFormatSettings);
  946. end;
  947. Function TryStrToFloat(Const S : String; Out Value: Double; Const FormatSettings: TFormatSettings): Boolean;
  948. Begin
  949. Result := TextToFloat(PChar(pointer(S)), Value, fvDouble,FormatSettings);
  950. End;
  951. {$ifdef FPC_HAS_TYPE_EXTENDED}
  952. Function TryStrToFloat(Const S : String; Out Value: Extended): Boolean;
  953. begin
  954. Result:=TryStrToFloat(S,Value,DefaultFormatSettings);
  955. end;
  956. Function TryStrToFloat(Const S : String; Out Value: Extended; Const FormatSettings: TFormatSettings): Boolean;
  957. Begin
  958. Result := TextToFloat(PChar(pointer(S)), Value,FormatSettings);
  959. End;
  960. {$endif FPC_HAS_TYPE_EXTENDED}
  961. const
  962. {$ifdef FPC_HAS_TYPE_EXTENDED}
  963. maxdigits = 17;
  964. {$else}
  965. maxdigits = 15;
  966. {$endif}
  967. Function FloatToStrFIntl(const Value; format: TFloatFormat; Precision, Digits: Integer; ValueType: TFloatValue; Const FormatSettings: TFormatSettings): String;
  968. Var
  969. P: Integer;
  970. Negative, TooSmall, TooLarge: Boolean;
  971. DS: Char;
  972. Begin
  973. DS:=FormatSettings.DecimalSeparator;
  974. Case format Of
  975. ffGeneral:
  976. Begin
  977. case ValueType of
  978. fvCurrency:
  979. begin
  980. If (Precision = -1) Or (Precision > 19) Then Precision := 19;
  981. TooSmall:=False;
  982. end;
  983. else
  984. begin
  985. If (Precision = -1) Or (Precision > maxdigits) Then Precision := maxdigits;
  986. TooSmall := (Abs(Extended(Value)) < 0.00001) and (Extended(Value)<>0.0);
  987. end;
  988. end;
  989. If Not TooSmall Then
  990. Begin
  991. case ValueType of
  992. fvDouble:
  993. Str(Double(Extended(Value)):0:precision, Result);
  994. fvSingle:
  995. Str(Single(Extended(Value)):0:precision, Result);
  996. fvCurrency:
  997. {$ifdef FPC_HAS_STR_CURRENCY}
  998. Str(Currency(Value):0:precision, Result);
  999. {$else}
  1000. Str(Extended(Currency(Value)):0:precision, Result);
  1001. {$endif FPC_HAS_STR_CURRENCY}
  1002. else
  1003. Str(Extended(Value):0:precision, Result);
  1004. end;
  1005. P := Pos('.', Result);
  1006. if P<>0 then
  1007. Result[P] := DS;
  1008. TooLarge :=(P > Precision + 1) or (Pos('E', Result)<>0);
  1009. End;
  1010. If TooSmall Or TooLarge Then
  1011. begin
  1012. Result := FloatToStrFIntl(Value, ffExponent, Precision, Digits, ValueType,FormatSettings);
  1013. // Strip unneeded zeroes.
  1014. P:=Pos('E',result)-1;
  1015. If P<>-1 then
  1016. begin
  1017. { delete superfluous +? }
  1018. if result[p+2]='+' then
  1019. system.Delete(Result,P+2,1);
  1020. While (P>1) and (Result[P]='0') do
  1021. begin
  1022. system.Delete(Result,P,1);
  1023. Dec(P);
  1024. end;
  1025. If (P>0) and (Result[P]=DS) Then
  1026. begin
  1027. system.Delete(Result,P,1);
  1028. Dec(P);
  1029. end;
  1030. end;
  1031. end
  1032. else if (P<>0) then // we have a decimalseparator
  1033. begin
  1034. { it seems that in this unit "precision" must mean "number of }
  1035. { significant digits" rather than "number of digits after the }
  1036. { decimal point" (as it does in the system unit) -> adjust }
  1037. { (precision+1 to count the decimal point character) }
  1038. if Result[1] = '-' then
  1039. Inc(Precision);
  1040. if (Length(Result) > Precision + 1) and
  1041. (Precision + 1 > P) then
  1042. begin
  1043. P := Precision + 1;
  1044. SetLength(Result,P);
  1045. end;
  1046. P := Length(Result);
  1047. While (P>0) and (Result[P] = '0') Do
  1048. Dec(P);
  1049. If (P>0) and (Result[P]=DS) Then
  1050. Dec(P);
  1051. SetLength(Result, P);
  1052. end;
  1053. End;
  1054. ffExponent:
  1055. Begin
  1056. If (Precision = -1) Or (Precision > maxdigits) Then Precision := maxdigits;
  1057. case ValueType of
  1058. fvDouble:
  1059. Str(Double(Extended(Value)):Precision+7, Result);
  1060. fvSingle:
  1061. Str(Single(Extended(Value)):Precision+6, Result);
  1062. fvCurrency:
  1063. {$ifdef FPC_HAS_STR_CURRENCY}
  1064. Str(Currency(Value):Precision+6, Result);
  1065. {$else}
  1066. Str(Extended(Currency(Value)):Precision+8, Result);
  1067. {$endif FPC_HAS_STR_CURRENCY}
  1068. else
  1069. Str(Extended(Value):Precision+8, Result);
  1070. end;
  1071. { Delete leading spaces }
  1072. while Result[1] = ' ' do
  1073. System.Delete(Result, 1, 1);
  1074. if Result[1] = '-' then
  1075. Result[3] := DS
  1076. else
  1077. Result[2] := DS;
  1078. P:=Pos('E',Result);
  1079. if P <> 0 then
  1080. begin
  1081. Inc(P, 2);
  1082. if Digits > 4 then
  1083. Digits:=4;
  1084. Digits:=Length(Result) - P - Digits + 1;
  1085. if Digits < 0 then
  1086. insert(copy('0000',1,-Digits),Result,P)
  1087. else
  1088. while (Digits > 0) and (Result[P] = '0') do
  1089. begin
  1090. System.Delete(Result, P, 1);
  1091. if P > Length(Result) then
  1092. begin
  1093. System.Delete(Result, P - 2, 2);
  1094. break;
  1095. end;
  1096. Dec(Digits);
  1097. end;
  1098. end;
  1099. End;
  1100. ffFixed:
  1101. Begin
  1102. If Digits = -1 Then Digits := 2
  1103. Else If Digits > 18 Then Digits := 18;
  1104. case ValueType of
  1105. fvDouble:
  1106. Str(Double(Extended(Value)):0:Digits, Result);
  1107. fvSingle:
  1108. Str(Single(Extended(Value)):0:Digits, Result);
  1109. fvCurrency:
  1110. {$ifdef FPC_HAS_STR_CURRENCY}
  1111. Str(Currency(Value):0:Digits, Result);
  1112. {$else}
  1113. Str(Extended(Currency(Value)):0:Digits, Result);
  1114. {$endif FPC_HAS_STR_CURRENCY}
  1115. else
  1116. Str(Extended(Value):0:Digits, Result);
  1117. end;
  1118. If Result[1] = ' ' Then
  1119. System.Delete(Result, 1, 1);
  1120. P := Pos('.', Result);
  1121. If P <> 0 Then Result[P] := DS;
  1122. End;
  1123. ffNumber:
  1124. Begin
  1125. If Digits = -1 Then Digits := 2
  1126. Else If Digits > maxdigits Then Digits := maxdigits;
  1127. case ValueType of
  1128. fvDouble:
  1129. Str(Double(Extended(Value)):0:Digits, Result);
  1130. fvSingle:
  1131. Str(Single(Extended(Value)):0:Digits, Result);
  1132. fvCurrency:
  1133. {$ifdef FPC_HAS_STR_CURRENCY}
  1134. Str(Currency(Value):0:Digits, Result);
  1135. {$else}
  1136. Str(Extended(Currency(Value)):0:Digits, Result);
  1137. {$endif FPC_HAS_STR_CURRENCY}
  1138. else
  1139. Str(Extended(Value):0:Digits, Result);
  1140. end;
  1141. If Result[1] = ' ' Then System.Delete(Result, 1, 1);
  1142. P := Pos('.', Result);
  1143. If P <> 0 Then
  1144. Result[P] := DS
  1145. else
  1146. P := Length(Result)+1;
  1147. Dec(P, 3);
  1148. While (P > 1) Do
  1149. Begin
  1150. If (Result[P - 1] <> '-') And (FormatSettings.ThousandSeparator <> #0) Then
  1151. Insert(FormatSettings.ThousandSeparator, Result, P);
  1152. Dec(P, 3);
  1153. End;
  1154. End;
  1155. ffCurrency:
  1156. Begin
  1157. If Digits = -1 Then Digits := FormatSettings.CurrencyDecimals
  1158. Else If Digits > 18 Then Digits := 18;
  1159. case ValueType of
  1160. fvDouble:
  1161. Str(Double(Extended(Value)):0:Digits, Result);
  1162. fvSingle:
  1163. Str(Single(Extended(Value)):0:Digits, Result);
  1164. fvCurrency:
  1165. {$ifdef FPC_HAS_STR_CURRENCY}
  1166. Str(Currency(Value):0:Digits, Result);
  1167. {$else}
  1168. Str(Extended(Currency(Value)):0:Digits, Result);
  1169. {$endif FPC_HAS_STR_CURRENCY}
  1170. else
  1171. Str(Extended(Value):0:Digits, Result);
  1172. end;
  1173. Negative:=Result[1] = '-';
  1174. if Negative then
  1175. System.Delete(Result, 1, 1);
  1176. P := Pos('.', Result);
  1177. If P <> 0 Then Result[P] := DS;
  1178. Dec(P, 3);
  1179. While (P > 1) Do
  1180. Begin
  1181. If FormatSettings.ThousandSeparator<>#0 Then
  1182. Insert(FormatSettings.ThousandSeparator, Result, P);
  1183. Dec(P, 3);
  1184. End;
  1185. If Not Negative Then
  1186. Begin
  1187. Case FormatSettings.CurrencyFormat Of
  1188. 0: Result := FormatSettings.CurrencyString + Result;
  1189. 1: Result := Result + FormatSettings.CurrencyString;
  1190. 2: Result := FormatSettings.CurrencyString + ' ' + Result;
  1191. 3: Result := Result + ' ' + FormatSettings.CurrencyString;
  1192. End
  1193. End
  1194. Else
  1195. Begin
  1196. Case NegCurrFormat Of
  1197. 0: Result := '(' + FormatSettings.CurrencyString + Result + ')';
  1198. 1: Result := '-' + FormatSettings.CurrencyString + Result;
  1199. 2: Result := FormatSettings.CurrencyString + '-' + Result;
  1200. 3: Result := FormatSettings.CurrencyString + Result + '-';
  1201. 4: Result := '(' + Result + FormatSettings.CurrencyString + ')';
  1202. 5: Result := '-' + Result + FormatSettings.CurrencyString;
  1203. 6: Result := Result + '-' + FormatSettings.CurrencyString;
  1204. 7: Result := Result + FormatSettings.CurrencyString + '-';
  1205. 8: Result := '-' + Result + ' ' + FormatSettings.CurrencyString;
  1206. 9: Result := '-' + FormatSettings.CurrencyString + ' ' + Result;
  1207. 10: Result := FormatSettings.CurrencyString + ' ' + Result + '-';
  1208. End;
  1209. End;
  1210. End;
  1211. End;
  1212. End;
  1213. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1214. Function FloatToStr(Value: Extended; Const FormatSettings: TFormatSettings): String;
  1215. Begin
  1216. Result := FloatToStrFIntl(Value, ffGeneral, 15, 0, fvExtended,FormatSettings);
  1217. End;
  1218. Function FloatToStr(Value: Extended): String;
  1219. begin
  1220. Result:=FloatToStr(Value,DefaultFormatSettings);
  1221. end;
  1222. {$endif FPC_HAS_TYPE_EXTENDED}
  1223. Function FloatToStr(Value: Currency; Const FormatSettings: TFormatSettings): String;
  1224. Begin
  1225. Result := FloatToStrFIntl(Value, ffGeneral, 15, 0, fvCurrency,FormatSettings);
  1226. End;
  1227. Function FloatToStr(Value: Currency): String;
  1228. begin
  1229. Result:=FloatToStr(Value,DefaultFormatSettings);
  1230. end;
  1231. Function FloatToStr(Value: Double; Const FormatSettings: TFormatSettings): String;
  1232. var
  1233. e: Extended;
  1234. Begin
  1235. e := Value;
  1236. Result := FloatToStrFIntl(e, ffGeneral, 15, 0, fvDouble,FormatSettings);
  1237. End;
  1238. Function FloatToStr(Value: Double): String;
  1239. begin
  1240. Result:=FloatToStr(Value,DefaultFormatSettings);
  1241. end;
  1242. Function FloatToStr(Value: Single; Const FormatSettings: TFormatSettings): String;
  1243. var
  1244. e: Extended;
  1245. Begin
  1246. e := Value;
  1247. Result := FloatToStrFIntl(e, ffGeneral, 15, 0, fvSingle,FormatSettings);
  1248. End;
  1249. Function FloatToStr(Value: Single): String;
  1250. begin
  1251. Result:=FloatToStr(Value,DefaultFormatSettings);
  1252. end;
  1253. Function FloatToStr(Value: Comp; Const FormatSettings: TFormatSettings): String;
  1254. var
  1255. e: Extended;
  1256. Begin
  1257. e := Value;
  1258. Result := FloatToStrFIntl(e, ffGeneral, 15, 0, fvComp,FormatSettings);
  1259. End;
  1260. Function FloatToStr(Value: Comp): String;
  1261. begin
  1262. Result:=FloatToStr(Value,DefaultFormatSettings);
  1263. end;
  1264. {$ifndef FPC_COMP_IS_INT64}
  1265. Function FloatToStr(Value: Int64): String;
  1266. begin
  1267. Result:=FloatToStr(Value,DefaultFormatSettings);
  1268. end;
  1269. Function FloatToStr(Value: Int64; Const FormatSettings: TFormatSettings): String;
  1270. var
  1271. e: Extended;
  1272. Begin
  1273. e := Comp(Value);
  1274. Result := FloatToStrFIntl(e, ffGeneral, 15, 0, fvComp,FormatSettings);
  1275. End;
  1276. {$endif FPC_COMP_IS_INT64}
  1277. Function FloatToText(Buffer: PChar; Value: Extended; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): Longint;
  1278. Var
  1279. Tmp: String[40];
  1280. Begin
  1281. Tmp := FloatToStrF(Value, format, Precision, Digits,FormatSettings);
  1282. Result := Length(Tmp);
  1283. Move(Tmp[1], Buffer[0], Result);
  1284. End;
  1285. Function FloatToText(Buffer: PChar; Value: Extended; format: TFloatFormat; Precision, Digits: Integer): Longint;
  1286. begin
  1287. Result:=FloatToText(Buffer,Value,Format,Precision,Digits,DefaultFormatSettings);
  1288. end;
  1289. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1290. Function FloatToStrF(Value: Extended; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
  1291. begin
  1292. Result := FloatToStrFIntl(value,format,precision,digits,fvExtended,FormatSettings);
  1293. end;
  1294. Function FloatToStrF(Value: Extended; format: TFloatFormat; Precision, Digits: Integer): String;
  1295. begin
  1296. Result:=FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
  1297. end;
  1298. {$endif}
  1299. Function FloatToStrF(Value: Currency; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
  1300. begin
  1301. Result := FloatToStrFIntl(value,format,precision,digits,fvCurrency,FormatSettings);
  1302. end;
  1303. Function FloatToStrF(Value: Currency; format: TFloatFormat; Precision, Digits: Integer): String;
  1304. begin
  1305. Result:=FloatToStrF(Value,format,Precision,Digits,DefaultFormatSettings);
  1306. end;
  1307. Function FloatToStrF(Value: Double; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
  1308. var
  1309. e: Extended;
  1310. begin
  1311. e := Value;
  1312. result := FloatToStrFIntl(e,format,precision,digits,fvDouble,FormatSettings);
  1313. end;
  1314. Function FloatToStrF(Value: Double; format: TFloatFormat; Precision, Digits: Integer): String;
  1315. begin
  1316. Result:= FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
  1317. end;
  1318. Function FloatToStrF(Value: Single; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
  1319. var
  1320. e: Extended;
  1321. begin
  1322. e:=Value;
  1323. result := FloatToStrFIntl(e,format,precision,digits,fvSingle,FormatSettings);
  1324. end;
  1325. Function FloatToStrF(Value: Single; format: TFloatFormat; Precision, Digits: Integer): String;
  1326. begin
  1327. Result:= FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
  1328. end;
  1329. Function FloatToStrF(Value: Comp; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
  1330. var
  1331. e: Extended;
  1332. begin
  1333. e := Value;
  1334. Result := FloatToStrFIntl(e,format,precision,digits,fvComp,FormatSettings);
  1335. end;
  1336. Function FloatToStrF(Value: Comp; format: TFloatFormat; Precision, Digits: Integer): String;
  1337. begin
  1338. Result:=FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
  1339. end;
  1340. {$ifndef FPC_COMP_IS_INT64}
  1341. Function FloatToStrF(Value: Int64; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
  1342. var
  1343. e: Extended;
  1344. begin
  1345. e := Comp(Value);
  1346. result := FloatToStrFIntl(e,format,precision,digits,fvComp,FormatSettings);
  1347. end;
  1348. Function FloatToStrF(Value: Int64; format: TFloatFormat; Precision, Digits: Integer): String;
  1349. begin
  1350. Result:=FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
  1351. end;
  1352. {$endif FPC_COMP_IS_INT64}
  1353. Function CurrToStrF(Value: Currency; Format: TFloatFormat; Digits: Integer; Const FormatSettings: TFormatSettings): string;
  1354. begin
  1355. result:=FloatToStrF(Value,Format,19,Digits,FormatSettings);
  1356. end;
  1357. Function CurrToStrF(Value: Currency; Format: TFloatFormat; Digits: Integer): string;
  1358. begin
  1359. Result:=CurrToStrF(Value,Format,Digits,DefaultFormatSettings);
  1360. end;
  1361. Function FloatToDateTime (Const Value : Extended) : TDateTime;
  1362. begin
  1363. If (Value<MinDateTime) or (Value>MaxDateTime) then
  1364. Raise EConvertError.CreateFmt (SInvalidDateTime,[Value]);
  1365. Result:=Value;
  1366. end;
  1367. function TryFloatToCurr(const Value: Extended; var AResult: Currency): Boolean;
  1368. begin
  1369. Result:=(Value>=MinCurrency) and (Value<=MaxCurrency);
  1370. if Result then
  1371. AResult := Value;
  1372. end;
  1373. function FloatToCurr(const Value: Extended): Currency;
  1374. begin
  1375. if not TryFloatToCurr(Value, Result) then
  1376. Raise EConvertError.CreateFmt(SInvalidCurrency, [FloatToStr(Value)]);
  1377. end;
  1378. Function CurrToStr(Value: Currency): string;
  1379. begin
  1380. Result:=FloatToStrF(Value,ffGeneral,-1,0);
  1381. end;
  1382. function StrToCurr(const S: string): Currency;
  1383. begin
  1384. if not TextToFloat(PChar(pointer(S)), Result, fvCurrency) then
  1385. Raise EConvertError.createfmt(SInValidFLoat,[S]);
  1386. end;
  1387. Function TryStrToCurr(Const S : String; Out Value: Currency): Boolean;
  1388. Begin
  1389. Result := TextToFloat(PChar(pointer(S)), Value, fvCurrency);
  1390. End;
  1391. function StrToCurrDef(const S: string; Default : Currency): Currency;
  1392. begin
  1393. if not TextToFloat(PChar(pointer(S)), Result, fvCurrency) then
  1394. Result:=Default;
  1395. end;
  1396. {$endif FPUNONE}
  1397. function AnsiDequotedStr(const S: string; AQuote: Char): string;
  1398. var p : pchar;
  1399. begin
  1400. p:=pchar(pointer(s)); // work around CONST. Ansiextract is safe for nil
  1401. result:=AnsiExtractquotedStr(p,AQuote);
  1402. if result='' Then
  1403. result:=s;
  1404. end;
  1405. function StrToBool(const S: string): Boolean;
  1406. begin
  1407. if not(TryStrToBool(S,Result)) then
  1408. Raise EConvertError.CreateFmt(SInvalidBoolean,[S]);
  1409. end;
  1410. function BoolToStr(B: Boolean;UseBoolStrs:Boolean=False): string;
  1411. procedure CheckStrs;
  1412. begin
  1413. If Length(TrueBoolStrs)=0 then
  1414. begin
  1415. SetLength(TrueBoolStrs,1);
  1416. TrueBoolStrs[0]:='True';
  1417. end;
  1418. If Length(FalseBoolStrs)=0 then
  1419. begin
  1420. SetLength(FalseBoolStrs,1);
  1421. FalseBoolStrs[0]:='False';
  1422. end;
  1423. end;
  1424. begin
  1425. if UseBoolStrs Then
  1426. begin
  1427. CheckStrs;
  1428. if B then
  1429. Result:=TrueBoolStrs[0]
  1430. else
  1431. Result:=FalseBoolStrs[0];
  1432. end
  1433. else
  1434. If B then
  1435. Result:='-1'
  1436. else
  1437. Result:='0';
  1438. end;
  1439. // from textmode IDE util funcs.
  1440. function BoolToStr(B: boolean; const TrueS, FalseS: string): string;
  1441. begin
  1442. if B then Result:=TrueS else BoolToStr:=FalseS;
  1443. end;
  1444. function StrToBoolDef(const S: string; Default: Boolean): Boolean;
  1445. begin
  1446. if not(TryStrToBool(S,Result)) then
  1447. Result:=Default;
  1448. end;
  1449. function TryStrToBool(const S: string; out Value: Boolean): Boolean;
  1450. Var
  1451. Temp : String;
  1452. {$ifdef FPUNONE}
  1453. D : Longint;
  1454. {$else}
  1455. D : Double;
  1456. {$endif}
  1457. Code: word;
  1458. begin
  1459. Temp:=upcase(S);
  1460. Val(temp,D,code);
  1461. Result:=true;
  1462. If Code=0 then
  1463. {$ifdef FPUNONE}
  1464. Value:=(D<>0)
  1465. {$else}
  1466. Value:=(D<>0.0)
  1467. {$endif}
  1468. else If Temp='TRUE' then
  1469. Value:=true
  1470. else if Temp='FALSE' then
  1471. Value:=false
  1472. else
  1473. Result:=false;
  1474. end;
  1475. {$ifndef FPUNONE}
  1476. Function FloatToTextFmt(Buffer: PChar; Value: Extended; format: PChar): Integer;
  1477. begin
  1478. Result:=FloatToTextFmt(Buffer,Value,Format,DefaultFormatSettings);
  1479. end;
  1480. Function FloatToTextFmt(Buffer: PChar; Value: Extended; format: PChar;FormatSettings : TFormatSettings): Integer;
  1481. Var
  1482. Digits: String[40]; { String Of Digits }
  1483. Exponent: String[8]; { Exponent strin }
  1484. FmtStart, FmtStop: PChar; { Start And End Of relevant part }
  1485. { Of format String }
  1486. ExpFmt, ExpSize: Integer; { Type And Length Of }
  1487. { exponential format chosen }
  1488. Placehold: Array[1..4] Of Integer; { Number Of placeholders In All }
  1489. { four Sections }
  1490. thousand: Boolean; { thousand separators? }
  1491. UnexpectedDigits: Integer; { Number Of unexpected Digits that }
  1492. { have To be inserted before the }
  1493. { First placeholder. }
  1494. DigitExponent: Integer; { Exponent Of First digit In }
  1495. { Digits Array. }
  1496. { Find end of format section starting at P. False, if empty }
  1497. Function GetSectionEnd(Var P: PChar): Boolean;
  1498. Var
  1499. C: Char;
  1500. SQ, DQ: Boolean;
  1501. Begin
  1502. Result := False;
  1503. SQ := False;
  1504. DQ := False;
  1505. C := P[0];
  1506. While (C<>#0) And ((C<>';') Or SQ Or DQ) Do
  1507. Begin
  1508. Result := True;
  1509. Case C Of
  1510. #34: If Not SQ Then DQ := Not DQ;
  1511. #39: If Not DQ Then SQ := Not SQ;
  1512. End;
  1513. Inc(P);
  1514. C := P[0];
  1515. End;
  1516. End;
  1517. { Find start and end of format section to apply. If section doesn't exist,
  1518. use section 1. If section 2 is used, the sign of value is ignored. }
  1519. Procedure GetSectionRange(section: Integer);
  1520. Var
  1521. Sec: Array[1..3] Of PChar;
  1522. SecOk: Array[1..3] Of Boolean;
  1523. Begin
  1524. Sec[1] := format;
  1525. SecOk[1] := GetSectionEnd(Sec[1]);
  1526. If section > 1 Then
  1527. Begin
  1528. Sec[2] := Sec[1];
  1529. If Sec[2][0] <> #0 Then
  1530. Inc(Sec[2]);
  1531. SecOk[2] := GetSectionEnd(Sec[2]);
  1532. If section > 2 Then
  1533. Begin
  1534. Sec[3] := Sec[2];
  1535. If Sec[3][0] <> #0 Then
  1536. Inc(Sec[3]);
  1537. SecOk[3] := GetSectionEnd(Sec[3]);
  1538. End;
  1539. End;
  1540. If Not SecOk[1] Then
  1541. FmtStart := Nil
  1542. Else
  1543. Begin
  1544. If Not SecOk[section] Then
  1545. section := 1
  1546. Else If section = 2 Then
  1547. Value := -Value; { Remove sign }
  1548. If section = 1 Then FmtStart := format Else
  1549. Begin
  1550. FmtStart := Sec[section - 1];
  1551. Inc(FmtStart);
  1552. End;
  1553. FmtStop := Sec[section];
  1554. End;
  1555. End;
  1556. { Find format section ranging from FmtStart to FmtStop. }
  1557. Procedure GetFormatOptions;
  1558. Var
  1559. Fmt: PChar;
  1560. SQ, DQ: Boolean;
  1561. area: Integer;
  1562. Begin
  1563. SQ := False;
  1564. DQ := False;
  1565. Fmt := FmtStart;
  1566. ExpFmt := 0;
  1567. area := 1;
  1568. thousand := False;
  1569. Placehold[1] := 0;
  1570. Placehold[2] := 0;
  1571. Placehold[3] := 0;
  1572. Placehold[4] := 0;
  1573. While Fmt < FmtStop Do
  1574. Begin
  1575. Case Fmt[0] Of
  1576. #34:
  1577. Begin
  1578. If Not SQ Then
  1579. DQ := Not DQ;
  1580. Inc(Fmt);
  1581. End;
  1582. #39:
  1583. Begin
  1584. If Not DQ Then
  1585. SQ := Not SQ;
  1586. Inc(Fmt);
  1587. End;
  1588. Else
  1589. { if not in quotes, then interpret}
  1590. If Not (SQ Or DQ) Then
  1591. Begin
  1592. Case Fmt[0] Of
  1593. '0':
  1594. Begin
  1595. Case area Of
  1596. 1:
  1597. area := 2;
  1598. 4:
  1599. Begin
  1600. area := 3;
  1601. Inc(Placehold[3], Placehold[4]);
  1602. Placehold[4] := 0;
  1603. End;
  1604. End;
  1605. Inc(Placehold[area]);
  1606. Inc(Fmt);
  1607. End;
  1608. '#':
  1609. Begin
  1610. If area=3 Then
  1611. area:=4;
  1612. Inc(Placehold[area]);
  1613. Inc(Fmt);
  1614. End;
  1615. '.':
  1616. Begin
  1617. If area<3 Then
  1618. area:=3;
  1619. Inc(Fmt);
  1620. End;
  1621. ',':
  1622. Begin
  1623. thousand := DefaultFormatSettings.ThousandSeparator<>#0;
  1624. Inc(Fmt);
  1625. End;
  1626. 'e', 'E':
  1627. If ExpFmt = 0 Then
  1628. Begin
  1629. If (Fmt[0]='E') Then
  1630. ExpFmt:=1
  1631. Else
  1632. ExpFmt := 3;
  1633. Inc(Fmt);
  1634. If (Fmt<FmtStop) Then
  1635. Begin
  1636. Case Fmt[0] Of
  1637. '+':
  1638. Begin
  1639. End;
  1640. '-':
  1641. Inc(ExpFmt);
  1642. Else
  1643. ExpFmt := 0;
  1644. End;
  1645. If ExpFmt <> 0 Then
  1646. Begin
  1647. Inc(Fmt);
  1648. ExpSize := 0;
  1649. While (Fmt<FmtStop) And
  1650. (ExpSize<4) And
  1651. (Fmt[0] In ['0'..'9']) Do
  1652. Begin
  1653. Inc(ExpSize);
  1654. Inc(Fmt);
  1655. End;
  1656. End;
  1657. End;
  1658. End
  1659. Else
  1660. Inc(Fmt);
  1661. Else { Case }
  1662. Inc(Fmt);
  1663. End; { Case }
  1664. End { Begin }
  1665. Else
  1666. Inc(Fmt);
  1667. End; { Case }
  1668. End; { While .. Begin }
  1669. End;
  1670. Procedure FloatToStr;
  1671. Var
  1672. I, J, Exp, Width, Decimals, DecimalPoint, len: Integer;
  1673. Begin
  1674. If ExpFmt = 0 Then
  1675. Begin
  1676. { Fixpoint }
  1677. Decimals:=Placehold[3]+Placehold[4];
  1678. Width:=Placehold[1]+Placehold[2]+Decimals;
  1679. If (Decimals=0) Then
  1680. Str(Value:Width:0,Digits)
  1681. Else if Value>=0 then
  1682. Str(Value:Width+1:Decimals,Digits)
  1683. else
  1684. Str(Value:Width+2:Decimals,Digits);
  1685. len:=Length(Digits);
  1686. { Find the decimal point }
  1687. If (Decimals=0) Then
  1688. DecimalPoint:=len+1
  1689. Else
  1690. DecimalPoint:=len-Decimals;
  1691. { If value is very small, and no decimal places
  1692. are desired, remove the leading 0. }
  1693. If (Abs(Value) < 1) And (Placehold[2] = 0) Then
  1694. Begin
  1695. If (Placehold[1]=0) Then
  1696. Delete(Digits,DecimalPoint-1,1)
  1697. Else
  1698. Digits[DecimalPoint-1]:=' ';
  1699. End;
  1700. { Convert optional zeroes to spaces. }
  1701. I:=len;
  1702. J:=DecimalPoint+Placehold[3];
  1703. While (I>J) And (Digits[I]='0') Do
  1704. Begin
  1705. Digits[I] := ' ';
  1706. Dec(I);
  1707. End;
  1708. { If integer value and no obligatory decimal
  1709. places, remove decimal point. }
  1710. If (DecimalPoint < len) And (Digits[DecimalPoint + 1] = ' ') Then
  1711. Digits[DecimalPoint] := ' ';
  1712. { Convert spaces left from obligatory decimal point to zeroes.
  1713. MVC : If - sign is encountered, replace it too, and put at position 1}
  1714. I:=DecimalPoint-Placehold[2];
  1715. J:=0;
  1716. While (I<DecimalPoint) And (Digits[I] in [' ','-']) Do
  1717. Begin
  1718. If Digits[i]='-' then
  1719. J:=I;
  1720. Digits[I] := '0';
  1721. Inc(I);
  1722. End;
  1723. If (J<>0) then
  1724. Digits[1]:='-';
  1725. Exp := 0;
  1726. End
  1727. Else
  1728. Begin
  1729. { Scientific: exactly <Width> Digits With <Precision> Decimals
  1730. And adjusted Exponent. }
  1731. If Placehold[1]+Placehold[2]=0 Then
  1732. Placehold[1]:=1;
  1733. Decimals := Placehold[3] + Placehold[4];
  1734. Width:=Placehold[1]+Placehold[2]+Decimals;
  1735. { depending on the maximally supported precision, the exponent field }
  1736. { is longer/shorter }
  1737. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1738. Str(Value:Width+8,Digits);
  1739. {$else FPC_HAS_TYPE_EXTENDED}
  1740. {$ifdef FPC_HAS_TYPE_DOUBLE}
  1741. Str(Value:Width+7,Digits);
  1742. {$else FPC_HAS_TYPE_DOUBLE}
  1743. Str(Value:Width+6,Digits);
  1744. {$endif FPC_HAS_TYPE_DOUBLE}
  1745. {$endif FPC_HAS_TYPE_EXTENDED}
  1746. { Find and cut out exponent. Always the
  1747. last 6 characters in the string.
  1748. -> 0000E+0000
  1749. *** No, not always the last 6 characters, this depends on
  1750. the maximally supported precision (JM)}
  1751. I:=Pos('E',Digits);
  1752. Val(Copy(Digits,I+1,255),Exp,J);
  1753. Exp:=Exp+1-(Placehold[1]+Placehold[2]);
  1754. Delete(Digits, I, 255);
  1755. { Str() always returns at least one digit after the decimal point.
  1756. If we don't want it, we have to remove it. }
  1757. If (Decimals=0) And (Placehold[1]+Placehold[2]<= 1) Then
  1758. Begin
  1759. If (Digits[4]>='5') Then
  1760. Begin
  1761. Inc(Digits[2]);
  1762. If (Digits[2]>'9') Then
  1763. Begin
  1764. Digits[2] := '1';
  1765. Inc(Exp);
  1766. End;
  1767. End;
  1768. Delete(Digits, 3, 2);
  1769. DecimalPoint := Length(Digits) + 1;
  1770. End
  1771. Else
  1772. Begin
  1773. { Move decimal point at the desired position }
  1774. Delete(Digits, 3, 1);
  1775. DecimalPoint:=2+Placehold[1]+Placehold[2];
  1776. If (Decimals<>0) Then
  1777. Insert('.',Digits,DecimalPoint);
  1778. End;
  1779. { Convert optional zeroes to spaces. }
  1780. I := Length(Digits);
  1781. J := DecimalPoint + Placehold[3];
  1782. While (I > J) And (Digits[I] = '0') Do
  1783. Begin
  1784. Digits[I] := ' ';
  1785. Dec(I);
  1786. End;
  1787. { If integer number and no obligatory decimal paces, remove decimal point }
  1788. If (DecimalPoint<Length(Digits)) And
  1789. (Digits[DecimalPoint+1]=' ') Then
  1790. Digits[DecimalPoint]:=' ';
  1791. If (Digits[1]=' ') Then
  1792. Begin
  1793. Delete(Digits, 1, 1);
  1794. Dec(DecimalPoint);
  1795. End;
  1796. { Calculate exponent string }
  1797. Str(Abs(Exp), Exponent);
  1798. While Length(Exponent)<ExpSize Do
  1799. Insert('0',Exponent,1);
  1800. If Exp >= 0 Then
  1801. Begin
  1802. If (ExpFmt In [1,3]) Then
  1803. Insert('+', Exponent, 1);
  1804. End
  1805. Else
  1806. Insert('-',Exponent,1);
  1807. If (ExpFmt<3) Then
  1808. Insert('E',Exponent,1)
  1809. Else
  1810. Insert('e',Exponent,1);
  1811. End;
  1812. DigitExponent:=DecimalPoint-2;
  1813. If (Digits[1]='-') Then
  1814. Dec(DigitExponent);
  1815. UnexpectedDigits:=DecimalPoint-1-(Placehold[1]+Placehold[2]);
  1816. End;
  1817. Function PutResult: LongInt;
  1818. Var
  1819. SQ, DQ: Boolean;
  1820. Fmt, Buf: PChar;
  1821. Dig, N: Integer;
  1822. Begin
  1823. SQ := False;
  1824. DQ := False;
  1825. Fmt := FmtStart;
  1826. Buf := Buffer;
  1827. Dig := 1;
  1828. While (Fmt<FmtStop) Do
  1829. Begin
  1830. //Write(Fmt[0]);
  1831. Case Fmt[0] Of
  1832. #34:
  1833. Begin
  1834. If Not SQ Then
  1835. DQ := Not DQ;
  1836. Inc(Fmt);
  1837. End;
  1838. #39:
  1839. Begin
  1840. If Not DQ Then
  1841. SQ := Not SQ;
  1842. Inc(Fmt);
  1843. End;
  1844. Else
  1845. If Not (SQ Or DQ) Then
  1846. Begin
  1847. Case Fmt[0] Of
  1848. '0', '#', '.':
  1849. Begin
  1850. If (Dig=1) And (UnexpectedDigits>0) Then
  1851. Begin
  1852. { Everything unexpected is written before the first digit }
  1853. For N := 1 To UnexpectedDigits Do
  1854. Begin
  1855. Buf[0] := Digits[N];
  1856. Inc(Buf);
  1857. If thousand And (Digits[N]<>'-') Then
  1858. Begin
  1859. If (DigitExponent Mod 3 = 0) And (DigitExponent>0) Then
  1860. Begin
  1861. Buf[0] := FormatSettings.ThousandSeparator;
  1862. Inc(Buf);
  1863. End;
  1864. Dec(DigitExponent);
  1865. End;
  1866. End;
  1867. Inc(Dig, UnexpectedDigits);
  1868. End;
  1869. If (Digits[Dig]<>' ') Then
  1870. Begin
  1871. If (Digits[Dig]='.') Then
  1872. Buf[0] := FormatSettings.DecimalSeparator
  1873. Else
  1874. Buf[0] := Digits[Dig];
  1875. Inc(Buf);
  1876. If thousand And (DigitExponent Mod 3 = 0) And (DigitExponent > 0) and (Digits[Dig]<>'-') Then
  1877. Begin
  1878. Buf[0] := FormatSettings.ThousandSeparator;
  1879. Inc(Buf);
  1880. End;
  1881. End;
  1882. Inc(Dig);
  1883. Dec(DigitExponent);
  1884. Inc(Fmt);
  1885. End;
  1886. 'e', 'E':
  1887. Begin
  1888. If ExpFmt <> 0 Then
  1889. Begin
  1890. Inc(Fmt);
  1891. If Fmt < FmtStop Then
  1892. Begin
  1893. If Fmt[0] In ['+', '-'] Then
  1894. Begin
  1895. Inc(Fmt, ExpSize);
  1896. For N:=1 To Length(Exponent) Do
  1897. Buf[N-1] := Exponent[N];
  1898. Inc(Buf,Length(Exponent));
  1899. ExpFmt:=0;
  1900. End;
  1901. Inc(Fmt);
  1902. End;
  1903. End
  1904. Else
  1905. Begin
  1906. { No legal exponential format.
  1907. Simply write the 'E' to the result. }
  1908. Buf[0] := Fmt[0];
  1909. Inc(Buf);
  1910. Inc(Fmt);
  1911. End;
  1912. End;
  1913. Else { Case }
  1914. { Usual character }
  1915. If (Fmt[0]<>',') Then
  1916. Begin
  1917. Buf[0] := Fmt[0];
  1918. Inc(Buf);
  1919. End;
  1920. Inc(Fmt);
  1921. End; { Case }
  1922. End
  1923. Else { IF }
  1924. Begin
  1925. { Character inside single or double quotes }
  1926. Buf[0] := Fmt[0];
  1927. Inc(Buf);
  1928. Inc(Fmt);
  1929. End;
  1930. End; { Case }
  1931. End; { While .. Begin }
  1932. Result:=PtrUInt(Buf)-PtrUInt(Buffer);
  1933. End;
  1934. Begin
  1935. If (Value>0) Then
  1936. GetSectionRange(1)
  1937. Else If (Value<0) Then
  1938. GetSectionRange(2)
  1939. Else
  1940. GetSectionRange(3);
  1941. If FmtStart = Nil Then
  1942. Begin
  1943. Result := FloatToText(Buffer, Value, ffGeneral, 15, 4, FormatSettings);
  1944. End
  1945. Else
  1946. Begin
  1947. GetFormatOptions;
  1948. If (ExpFmt = 0) And (Abs(Value) >= 1E18) Then
  1949. Result := FloatToText(Buffer, Value, ffGeneral, 15, 4, FormatSettings)
  1950. Else
  1951. Begin
  1952. FloatToStr;
  1953. Result := PutResult;
  1954. End;
  1955. End;
  1956. End;
  1957. Procedure FloatToDecimal(Out Result: TFloatRec; const Value; ValueType: TFloatValue; Precision, Decimals : integer);
  1958. var
  1959. Buffer: String[254]; //Though str func returns only 25 chars, this might change in the future
  1960. InfNan: string[3];
  1961. Error, N, L, Start, C: Integer;
  1962. GotNonZeroBeforeDot, BeforeDot : boolean;
  1963. begin
  1964. case ValueType of
  1965. fvExtended:
  1966. Str(Extended(Value):25, Buffer);
  1967. fvDouble,
  1968. fvReal:
  1969. Str(Double(Value):23, Buffer);
  1970. fvSingle:
  1971. Str(Single(Value):16, Buffer);
  1972. fvCurrency:
  1973. Str(Currency(Value):25, Buffer);
  1974. fvComp:
  1975. Str(Currency(Value):23, Buffer);
  1976. end;
  1977. N := 1;
  1978. L := Byte(Buffer[0]);
  1979. while Buffer[N]=' ' do
  1980. Inc(N);
  1981. Result.Negative := (Buffer[N] = '-');
  1982. if Result.Negative then
  1983. Inc(N)
  1984. else if (Buffer[N] = '+') then
  1985. inc(N);
  1986. { special cases for Inf and Nan }
  1987. if (L>=N+2) then
  1988. begin
  1989. InfNan:=copy(Buffer,N,3);
  1990. if (InfNan='Inf') then
  1991. begin
  1992. Result.Digits[0]:=#0;
  1993. Result.Exponent:=32767;
  1994. exit
  1995. end;
  1996. if (InfNan='Nan') then
  1997. begin
  1998. Result.Digits[0]:=#0;
  1999. Result.Exponent:=-32768;
  2000. exit
  2001. end;
  2002. end;
  2003. Start := N; //Start of digits
  2004. Result.Exponent := 0; BeforeDot := true;
  2005. GotNonZeroBeforeDot := false;
  2006. while (L>=N) and (Buffer[N]<>'E') do
  2007. begin
  2008. if Buffer[N]='.' then
  2009. BeforeDot := false
  2010. else
  2011. begin
  2012. if BeforeDot then
  2013. begin // Currently this is always 1 char
  2014. Inc(Result.Exponent);
  2015. Result.Digits[N-Start] := Buffer[N];
  2016. if Buffer[N] <> '0' then
  2017. GotNonZeroBeforeDot := true;
  2018. end
  2019. else
  2020. Result.Digits[N-Start-1] := Buffer[N]
  2021. end;
  2022. Inc(N);
  2023. end;
  2024. Inc(N); // Pass through 'E'
  2025. if N<=L then
  2026. begin
  2027. Val(Copy(Buffer, N, L-N+1), C, Error); // Get exponent after 'E'
  2028. Inc(Result.Exponent, C);
  2029. end;
  2030. // Calculate number of digits we have from str
  2031. if BeforeDot then
  2032. N := N - Start - 1
  2033. else
  2034. N := N - Start - 2;
  2035. L := SizeOf(Result.Digits);
  2036. if N<L then
  2037. FillChar(Result.Digits[N], L-N, '0'); //Zero remaining space
  2038. if Decimals + Result.Exponent < Precision Then //After this it is the same as in FloatToDecimal
  2039. N := Decimals + Result.Exponent
  2040. Else
  2041. N := Precision;
  2042. if N >= L Then
  2043. N := L-1;
  2044. if N = 0 Then
  2045. begin
  2046. if Result.Digits[0] >= '5' Then
  2047. begin
  2048. Result.Digits[0] := '1';
  2049. Result.Digits[1] := #0;
  2050. Inc(Result.Exponent);
  2051. end
  2052. Else
  2053. Result.Digits[0] := #0;
  2054. end //N=0
  2055. Else if N > 0 Then
  2056. begin
  2057. if Result.Digits[N] >= '5' Then
  2058. begin
  2059. Repeat
  2060. Result.Digits[N] := #0;
  2061. Dec(N);
  2062. Inc(Result.Digits[N]);
  2063. Until (N = 0) Or (Result.Digits[N] < ':');
  2064. If Result.Digits[0] = ':' Then
  2065. begin
  2066. Result.Digits[0] := '1';
  2067. Inc(Result.Exponent);
  2068. end;
  2069. end
  2070. Else
  2071. begin
  2072. Result.Digits[N] := '0';
  2073. While (N > -1) And (Result.Digits[N] = '0') Do
  2074. begin
  2075. Result.Digits[N] := #0;
  2076. Dec(N);
  2077. end;
  2078. end;
  2079. end //N>0
  2080. Else
  2081. Result.Digits[0] := #0;
  2082. if (Result.Digits[0] = #0) and
  2083. not GotNonZeroBeforeDot then
  2084. begin
  2085. Result.Exponent := 0;
  2086. Result.Negative := False;
  2087. end;
  2088. end;
  2089. Procedure FloatToDecimal(Out Result: TFloatRec; Value: Extended; Precision, Decimals : integer);
  2090. begin
  2091. FloatToDecimal(Result,Value,fvExtended,Precision,Decimals);
  2092. end;
  2093. Function FormatFloat(Const Format : String; Value : Extended; Const FormatSettings: TFormatSettings) : String;
  2094. Var
  2095. buf : Array[0..1024] of char;
  2096. Begin // not changed to pchar(pointer(). Possibly not safe
  2097. Buf[FloatToTextFmt(@Buf[0],Value,Pchar(Format),FormatSettings)]:=#0;
  2098. Result:=StrPas(@Buf[0]);
  2099. End;
  2100. Function FormatFloat(Const format: String; Value: Extended): String;
  2101. begin
  2102. Result:=FormatFloat(Format,Value,DefaultFormatSettings);
  2103. end;
  2104. Function FormatCurr(const Format: string; Value: Currency; Const FormatSettings: TFormatSettings): string;
  2105. begin
  2106. Result := FormatFloat(Format, Value,FormatSettings);
  2107. end;
  2108. function FormatCurr(const Format: string; Value: Currency): string;
  2109. begin
  2110. Result:=FormatCurr(Format,Value,DefaultFormatSettings);
  2111. end;
  2112. {$endif}
  2113. {==============================================================================}
  2114. { extra functions }
  2115. {==============================================================================}
  2116. { LeftStr returns Count left-most characters from S }
  2117. function LeftStr(const S: string; Count: integer): string;
  2118. begin
  2119. result := Copy(S, 1, Count);
  2120. end ;
  2121. { RightStr returns Count right-most characters from S }
  2122. function RightStr(const S: string; Count: integer): string;
  2123. begin
  2124. If Count>Length(S) then
  2125. Count:=Length(S);
  2126. result := Copy(S, 1 + Length(S) - Count, Count);
  2127. end;
  2128. { BCDToInt converts the BCD value Value to an integer }
  2129. function BCDToInt(Value: integer): integer;
  2130. var i, j, digit: integer;
  2131. begin
  2132. result := 0;
  2133. j := 1;
  2134. for i := 0 to SizeOf(Value) shl 1 - 1 do begin
  2135. digit := Value and 15;
  2136. if digit > $9 then
  2137. begin
  2138. if i = 0 then
  2139. begin
  2140. if digit in [$B, $D] then j := -1
  2141. end
  2142. else raise EConvertError.createfmt(SInvalidBCD,[Value]);
  2143. end
  2144. else
  2145. begin
  2146. result := result + j * digit;
  2147. j := j * 10;
  2148. end ;
  2149. Value := Value shr 4;
  2150. end ;
  2151. end ;
  2152. Function LastDelimiter(const Delimiters, S: string): Integer;
  2153. var
  2154. chs: TSysCharSet;
  2155. I: LongInt;
  2156. begin
  2157. chs := [];
  2158. for I := 1 to Length(Delimiters) do
  2159. Include(chs, Delimiters[I]);
  2160. Result:=Length(S);
  2161. While (Result>0) and not (S[Result] in chs) do
  2162. Dec(Result);
  2163. end;
  2164. Function StringReplace(const S, OldPattern, NewPattern: string; Flags: TReplaceFlags): string;
  2165. var
  2166. Srch,OldP,RemS: string; // Srch and Oldp can contain uppercase versions of S,OldPattern
  2167. P : Integer;
  2168. begin
  2169. Srch:=S;
  2170. OldP:=OldPattern;
  2171. if rfIgnoreCase in Flags then
  2172. begin
  2173. Srch:=AnsiUpperCase(Srch);
  2174. OldP:=AnsiUpperCase(OldP);
  2175. end;
  2176. RemS:=S;
  2177. Result:='';
  2178. while (Length(Srch)<>0) do
  2179. begin
  2180. P:=AnsiPos(OldP, Srch);
  2181. if P=0 then
  2182. begin
  2183. Result:=Result+RemS;
  2184. Srch:='';
  2185. end
  2186. else
  2187. begin
  2188. Result:=Result+Copy(RemS,1,P-1)+NewPattern;
  2189. P:=P+Length(OldP);
  2190. RemS:=Copy(RemS,P,Length(RemS)-P+1);
  2191. if not (rfReplaceAll in Flags) then
  2192. begin
  2193. Result:=Result+RemS;
  2194. Srch:='';
  2195. end
  2196. else
  2197. Srch:=Copy(Srch,P,Length(Srch)-P+1);
  2198. end;
  2199. end;
  2200. end;
  2201. Function IsDelimiter(const Delimiters, S: string; Index: Integer): Boolean;
  2202. begin
  2203. Result:=False;
  2204. If (Index>0) and (Index<=Length(S)) then
  2205. Result:=Pos(S[Index],Delimiters)<>0; // Note we don't do MBCS yet
  2206. end;
  2207. Function ByteToCharLen(const S: string; MaxLen: Integer): Integer;
  2208. begin
  2209. Result:=Length(S);
  2210. If Result>MaxLen then
  2211. Result:=MaxLen;
  2212. end;
  2213. Function ByteToCharIndex(const S: string; Index: Integer): Integer;
  2214. begin
  2215. Result:=Index;
  2216. end;
  2217. Function CharToByteLen(const S: string; MaxLen: Integer): Integer;
  2218. begin
  2219. Result:=Length(S);
  2220. If Result>MaxLen then
  2221. Result:=MaxLen;
  2222. end;
  2223. Function CharToByteIndex(const S: string; Index: Integer): Integer;
  2224. begin
  2225. Result:=Index;
  2226. end;
  2227. Function ByteType(const S: string; Index: Integer): TMbcsByteType;
  2228. begin
  2229. Result:=mbSingleByte;
  2230. end;
  2231. Function StrByteType(Str: PChar; Index: Cardinal): TMbcsByteType;
  2232. begin
  2233. Result:=mbSingleByte;
  2234. end;
  2235. Function StrCharLength(const Str: PChar): Integer;
  2236. begin
  2237. result:=widestringmanager.CharLengthPCharProc(Str);
  2238. end;
  2239. function StrNextChar(const Str: PChar): PChar;
  2240. begin
  2241. result:=Str+StrCharLength(Str);
  2242. end;
  2243. Function FindCmdLineSwitch(const Switch: string; const Chars: TSysCharSet;IgnoreCase: Boolean): Boolean;
  2244. Var
  2245. I,L : Integer;
  2246. S,T : String;
  2247. begin
  2248. Result:=False;
  2249. S:=Switch;
  2250. If IgnoreCase then
  2251. S:=UpperCase(S);
  2252. I:=ParamCount;
  2253. While (Not Result) and (I>0) do
  2254. begin
  2255. L:=Length(Paramstr(I));
  2256. If (L>0) and (ParamStr(I)[1] in Chars) then
  2257. begin
  2258. T:=Copy(ParamStr(I),2,L-1);
  2259. If IgnoreCase then
  2260. T:=UpperCase(T);
  2261. Result:=S=T;
  2262. end;
  2263. Dec(i);
  2264. end;
  2265. end;
  2266. Function FindCmdLineSwitch(const Switch: string; IgnoreCase: Boolean): Boolean;
  2267. begin
  2268. Result:=FindCmdLineSwitch(Switch,SwitchChars,IgnoreCase);
  2269. end;
  2270. Function FindCmdLineSwitch(const Switch: string): Boolean;
  2271. begin
  2272. Result:=FindCmdLineSwitch(Switch,SwitchChars,False);
  2273. end;
  2274. function WrapText(const Line, BreakStr: string; const BreakChars: TSysCharSet; MaxCol: Integer): string;
  2275. const
  2276. Quotes = ['''', '"'];
  2277. Var
  2278. L : String;
  2279. C,LQ,BC : Char;
  2280. P,BLen,Len : Integer;
  2281. HB,IBC : Boolean;
  2282. begin
  2283. Result:='';
  2284. L:=Line;
  2285. Blen:=Length(BreakStr);
  2286. If (BLen>0) then
  2287. BC:=BreakStr[1]
  2288. else
  2289. BC:=#0;
  2290. Len:=Length(L);
  2291. While (Len>0) do
  2292. begin
  2293. P:=1;
  2294. LQ:=#0;
  2295. HB:=False;
  2296. IBC:=False;
  2297. While ((P<=Len) and ((P<=MaxCol) or not IBC)) and ((LQ<>#0) or Not HB) do
  2298. begin
  2299. C:=L[P];
  2300. If (C=LQ) then
  2301. LQ:=#0
  2302. else If (C in Quotes) then
  2303. LQ:=C;
  2304. If (LQ<>#0) then
  2305. Inc(P)
  2306. else
  2307. begin
  2308. HB:=((C=BC) and (BreakStr=Copy(L,P,BLen)));
  2309. If HB then
  2310. Inc(P,Blen)
  2311. else
  2312. begin
  2313. If (P>MaxCol) then
  2314. IBC:=C in BreakChars;
  2315. Inc(P);
  2316. end;
  2317. end;
  2318. // Writeln('"',C,'" : IBC : ',IBC,' HB : ',HB,' LQ : ',LQ,' P>MaxCol : ',P>MaxCol);
  2319. end;
  2320. Result:=Result+Copy(L,1,P-1);
  2321. If Not HB then
  2322. Result:=Result+BreakStr;
  2323. Delete(L,1,P-1);
  2324. Len:=Length(L);
  2325. end;
  2326. end;
  2327. function WrapText(const Line: string; MaxCol: Integer): string;
  2328. begin
  2329. Result:=WrapText(Line,sLineBreak, [' ', '-', #9], MaxCol);
  2330. end;
  2331. {$ifndef FPC_NOGENERICANSIROUTINES}
  2332. {
  2333. Case Translation Tables
  2334. Can be used in internationalization support.
  2335. Although these tables can be obtained through system calls
  2336. cd it is better to not use those, since most implementation are not 100%
  2337. WARNING:
  2338. before modifying a translation table make sure that the current codepage
  2339. of the OS corresponds to the one you make changes to
  2340. }
  2341. const
  2342. { upper case translation table for character set 850 }
  2343. CP850UCT: array[128..255] of char =
  2344. (#128,#154,#144,#182,#142,#182,#143,#128,#210,#211,#212,#216,#215,#222,#142,#143,
  2345. #144,#146,#146,#226,#153,#227,#234,#235,'Y',#153,#154,#157,#156,#157,#158,#159,
  2346. #181,#214,#224,#233,#165,#165,#166,#167,#168,#169,#170,#171,#172,#173,#174,#175,
  2347. #176,#177,#178,#179,#180,#181,#182,#183,#184,#185,#186,#187,#188,#189,#190,#191,
  2348. #192,#193,#194,#195,#196,#197,#199,#199,#200,#201,#202,#203,#204,#205,#206,#207,
  2349. #208,#209,#210,#211,#212,#213,#214,#215,#216,#217,#218,#219,#220,#221,#222,#223,
  2350. #224,#225,#226,#227,#229,#229,#230,#237,#232,#233,#234,#235,#237,#237,#238,#239,
  2351. #240,#241,#242,#243,#244,#245,#246,#247,#248,#249,#250,#251,#252,#253,#254,#255);
  2352. { lower case translation table for character set 850 }
  2353. CP850LCT: array[128..255] of char =
  2354. (#135,#129,#130,#131,#132,#133,#134,#135,#136,#137,#138,#139,#140,#141,#132,#134,
  2355. #130,#145,#145,#147,#148,#149,#150,#151,#152,#148,#129,#155,#156,#155,#158,#159,
  2356. #160,#161,#162,#163,#164,#164,#166,#167,#168,#169,#170,#171,#172,#173,#174,#175,
  2357. #176,#177,#178,#179,#180,#160,#131,#133,#184,#185,#186,#187,#188,#189,#190,#191,
  2358. #192,#193,#194,#195,#196,#197,#198,#198,#200,#201,#202,#203,#204,#205,#206,#207,
  2359. #208,#209,#136,#137,#138,#213,#161,#140,#139,#217,#218,#219,#220,#221,#141,#223,
  2360. #162,#225,#147,#149,#228,#228,#230,#237,#232,#163,#150,#151,#236,#236,#238,#239,
  2361. #240,#241,#242,#243,#244,#245,#246,#247,#248,#249,#250,#251,#252,#253,#254,#255);
  2362. { upper case translation table for character set ISO 8859/1 Latin 1 }
  2363. CPISO88591UCT: array[192..255] of char =
  2364. ( #192, #193, #194, #195, #196, #197, #198, #199,
  2365. #200, #201, #202, #203, #204, #205, #206, #207,
  2366. #208, #209, #210, #211, #212, #213, #214, #215,
  2367. #216, #217, #218, #219, #220, #221, #222, #223,
  2368. #192, #193, #194, #195, #196, #197, #198, #199,
  2369. #200, #201, #202, #203, #204, #205, #206, #207,
  2370. #208, #209, #210, #211, #212, #213, #214, #247,
  2371. #216, #217, #218, #219, #220, #221, #222, #89 );
  2372. { lower case translation table for character set ISO 8859/1 Latin 1 }
  2373. CPISO88591LCT: array[192..255] of char =
  2374. ( #224, #225, #226, #227, #228, #229, #230, #231,
  2375. #232, #233, #234, #235, #236, #237, #238, #239,
  2376. #240, #241, #242, #243, #244, #245, #246, #215,
  2377. #248, #249, #250, #251, #252, #253, #254, #223,
  2378. #224, #225, #226, #227, #228, #229, #230, #231,
  2379. #232, #233, #234, #235, #236, #237, #238, #239,
  2380. #240, #241, #242, #243, #244, #245, #246, #247,
  2381. #248, #249, #250, #251, #252, #253, #254, #255 );
  2382. {$endif FPC_NOGENERICANSIROUTINES}
  2383. function sscanf(const s: string; const fmt : string;const Pointers : array of Pointer) : Integer;
  2384. var
  2385. i,j,n,m : SizeInt;
  2386. s1 : string;
  2387. function GetInt(unsigned : boolean=false) : Integer;
  2388. begin
  2389. s1 := '';
  2390. while (Length(s) > n) and (s[n] = ' ') do
  2391. inc(n);
  2392. { read sign }
  2393. if (Length(s)>= n) and (s[n] in ['+', '-']) then
  2394. begin
  2395. { don't accept - when reading unsigned }
  2396. if unsigned and (s[n]='-') then
  2397. begin
  2398. result:=length(s1);
  2399. exit;
  2400. end
  2401. else
  2402. begin
  2403. s1:=s1+s[n];
  2404. inc(n);
  2405. end;
  2406. end;
  2407. { read numbers }
  2408. while (Length(s) >= n) and
  2409. (s[n] in ['0'..'9']) do
  2410. begin
  2411. s1 := s1+s[n];
  2412. inc(n);
  2413. end;
  2414. Result := Length(s1);
  2415. end;
  2416. function GetFloat : Integer;
  2417. begin
  2418. s1 := '';
  2419. while (Length(s) > n) and (s[n] = ' ') do
  2420. inc(n);
  2421. while (Length(s) >= n) and
  2422. (s[n] in ['0'..'9', '+', '-', DecimalSeparator, 'e', 'E']) do
  2423. begin
  2424. s1 := s1+s[n];
  2425. inc(n);
  2426. end;
  2427. Result := Length(s1);
  2428. end;
  2429. function GetString : Integer;
  2430. begin
  2431. s1 := '';
  2432. while (Length(s) > n) and (s[n] = ' ') do
  2433. inc(n);
  2434. while (Length(s) >= n) and (s[n] <> ' ')do
  2435. begin
  2436. s1 := s1+s[n];
  2437. inc(n);
  2438. end;
  2439. Result := Length(s1);
  2440. end;
  2441. function ScanStr(c : Char) : Boolean;
  2442. begin
  2443. while (Length(s) > n) and (s[n] <> c) do
  2444. inc(n);
  2445. inc(n);
  2446. If (n <= Length(s)) then
  2447. Result := True
  2448. else
  2449. Result := False;
  2450. end;
  2451. function GetFmt : Integer;
  2452. begin
  2453. Result := -1;
  2454. while true do
  2455. begin
  2456. while (Length(fmt) > m) and (fmt[m] = ' ') do
  2457. inc(m);
  2458. if (m >= Length(fmt)) then
  2459. break;
  2460. if (fmt[m] = '%') then
  2461. begin
  2462. inc(m);
  2463. case fmt[m] of
  2464. 'd':
  2465. Result:=vtInteger;
  2466. {$ifndef FPUNONE}
  2467. 'f':
  2468. Result:=vtExtended;
  2469. {$endif}
  2470. 's':
  2471. Result:=vtString;
  2472. 'c':
  2473. Result:=vtChar;
  2474. else
  2475. raise EFormatError.CreateFmt(SInvalidFormat,[fmt]);
  2476. end;
  2477. inc(m);
  2478. break;
  2479. end;
  2480. if not(ScanStr(fmt[m])) then
  2481. break;
  2482. inc(m);
  2483. end;
  2484. end;
  2485. begin
  2486. n := 1;
  2487. m := 1;
  2488. Result := 0;
  2489. for i:=0 to High(Pointers) do
  2490. begin
  2491. j := GetFmt;
  2492. case j of
  2493. vtInteger :
  2494. begin
  2495. if GetInt>0 then
  2496. begin
  2497. pLongint(Pointers[i])^:=StrToInt(s1);
  2498. inc(Result);
  2499. end
  2500. else
  2501. break;
  2502. end;
  2503. vtchar :
  2504. begin
  2505. if Length(s)>n then
  2506. begin
  2507. pchar(Pointers[i])^:=s[n];
  2508. inc(n);
  2509. inc(Result);
  2510. end
  2511. else
  2512. break;
  2513. end;
  2514. {$ifndef FPUNONE}
  2515. vtExtended :
  2516. begin
  2517. if GetFloat>0 then
  2518. begin
  2519. pextended(Pointers[i])^:=StrToFloat(s1);
  2520. inc(Result);
  2521. end
  2522. else
  2523. break;
  2524. end;
  2525. {$endif}
  2526. vtString :
  2527. begin
  2528. if GetString > 0 then
  2529. begin
  2530. pansistring(Pointers[i])^:=s1;
  2531. inc(Result);
  2532. end
  2533. else
  2534. break;
  2535. end;
  2536. else
  2537. break;
  2538. end;
  2539. end;
  2540. end;