sysstr.inc 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951
  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. result := Nil;
  24. {
  25. if Length(S) <> 0 then begin
  26. result := New(PString);
  27. result^ := S;
  28. end ;
  29. }
  30. end ;
  31. { DisposeStr frees the memory occupied by S }
  32. procedure DisposeStr(S: PString);
  33. begin
  34. {
  35. if S <> Nil then begin
  36. Dispose(S);
  37. S := Nil;
  38. end ;
  39. }
  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: PString; 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 i, count, count1, count2: integer;
  83. begin
  84. result := 0;
  85. Count1 := Length(S1);
  86. Count2 := Length(S2);
  87. if Count1 > Count2 then Count := Count2
  88. else Count := Count1;
  89. result := CompareMem(@S1[1], @S2[1], Count);
  90. if (result = 0) and (Count1 <> Count2) then begin
  91. if Count1 > Count2 then result := ord(s1[Count1 + 1])
  92. else result := -ord(s2[Count2 + 1]);
  93. end ;
  94. end ;
  95. { CompareMem 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 CompareMem(P1, P2: Pointer; Length: cardinal): integer;
  101. var i: integer;
  102. begin
  103. i := 0;
  104. result := 0;
  105. while (result = 0) and (i < length) do begin
  106. result := byte(P1^) - byte(P2^);
  107. P1 := P1 + 1;
  108. P2 := P2 + 1;
  109. i := i + 1;
  110. end ;
  111. end ;
  112. { CompareText compares S1 and S2, the result is the based on
  113. substraction of the ascii values of characters in S1 and S2
  114. comparison is case-insensitive
  115. case result
  116. S1 < S2 < 0
  117. S1 > S2 > 0
  118. S1 = S2 = 0 }
  119. function CompareText(const S1, S2: string): integer;
  120. var i, count, count1, count2: integer; Chr1, Chr2: byte;
  121. begin
  122. result := 0;
  123. Count1 := Length(S1);
  124. Count2 := Length(S2);
  125. if Count1 > Count2 then Count := Count2
  126. else Count := Count1;
  127. i := 0;
  128. while (result = 0) and (i < count) do begin
  129. i := i + 1;
  130. Chr1 := byte(s1[i]);
  131. Chr2 := byte(s2[i]);
  132. if Chr1 in [97..122] then Chr1 := Chr1 - 32;
  133. if Chr2 in [97..122] then Chr2 := Chr2 - 32;
  134. result := Chr1 - Chr2;
  135. end ;
  136. if (result = 0) and (Count1 <> Count2) then begin
  137. if Count1 > Count2 then result := byte(UpCase(s1[Count1 + 1]))
  138. else result := -byte(UpCase(s2[Count2 + 1]));
  139. end ;
  140. end ;
  141. {==============================================================================}
  142. { Ansi string functions }
  143. { these functions rely on the character set loaded by the OS }
  144. {==============================================================================}
  145. type
  146. TCaseTranslationTable = array[0..255] of char;
  147. var
  148. UpperCaseTable: TCaseTranslationTable;
  149. LowerCaseTable: TCaseTranslationTable;
  150. function AnsiUpperCase(const s: string): string;
  151. var len, i: integer;
  152. begin
  153. len := length(s);
  154. SetLength(result, len);
  155. for i := 1 to len do
  156. result[i] := UpperCaseTable[ord(s[i])];
  157. end ;
  158. function AnsiLowerCase(const s: string): string;
  159. var len, i: integer;
  160. begin
  161. len := length(s);
  162. SetLength(result, len);
  163. for i := 1 to len do
  164. result[i] := LowerCaseTable[ord(s[i])];
  165. end ;
  166. function AnsiCompareStr(const S1, S2: string): integer;
  167. begin
  168. end ;
  169. function AnsiCompareText(const S1, S2: string): integer;
  170. begin
  171. end ;
  172. function AnsiStrComp(S1, S2: PChar): integer;
  173. begin
  174. end ;
  175. function AnsiStrIComp(S1, S2: PChar): integer;
  176. begin
  177. end ;
  178. function AnsiStrLComp(S1, S2: PChar; MaxLen: cardinal): integer;
  179. begin
  180. end ;
  181. function AnsiStrLIComp(S1, S2: PChar; MaxLen: cardinal): integer;
  182. begin
  183. end ;
  184. function AnsiStrLower(Str: PChar): PChar;
  185. begin
  186. if Str <> Nil then begin
  187. while Str^ <> #0 do begin
  188. Str^ := LowerCaseTable[byte(Str^)];
  189. Str := Str + 1;
  190. end ;
  191. end ;
  192. result := Str;
  193. end ;
  194. function AnsiStrUpper(Str: PChar): PChar;
  195. begin
  196. if Str <> Nil then begin
  197. while Str^ <> #0 do begin
  198. Str^ := UpperCaseTable[byte(Str^)];
  199. Str := Str + 1;
  200. end ;
  201. end ;
  202. result := Str;
  203. end ;
  204. function AnsiLastChar(const S: string): PChar;
  205. begin
  206. end ;
  207. function AnsiStrLastChar(Str: PChar): PChar;
  208. begin
  209. end ;
  210. {==============================================================================}
  211. { End of Ansi functions }
  212. {==============================================================================}
  213. { Trim returns a copy of S with blanks characters on the left and right stripped off }
  214. function Trim(const S: string): string;
  215. var Ofs, Len: integer;
  216. begin
  217. len := Length(S);
  218. while (S[Len] = ' ') and (Len > 0) do
  219. dec(Len);
  220. Ofs := 1;
  221. while (S[Ofs] = ' ') and (Ofs <= Len) do
  222. Inc(Ofs);
  223. result := Copy(S, Ofs, 1 + Len - Ofs);
  224. end ;
  225. { TrimLeft returns a copy of S with all blank characters on the left stripped off }
  226. function TrimLeft(const S: string): string;
  227. var i,l:integer;
  228. begin
  229. l := length(s);
  230. i := 1;
  231. while (s[i] = ' ') and (i <= l) do inc(i);
  232. Result := copy(s, i, l);
  233. end ;
  234. { TrimRight returns a copy of S with all blank characters on the right stripped off }
  235. function TrimRight(const S: string): string;
  236. var l:integer;
  237. begin
  238. l := length(s);
  239. while (s[l] = ' ') and (l > 0) do dec(l);
  240. result := copy(s,1,l);
  241. end ;
  242. { QuotedStr returns S quoted left and right and every single quote in S
  243. replaced by two quotes }
  244. function QuotedStr(const S: string): string;
  245. begin
  246. result := AnsiQuotedStr(s, '''');
  247. end ;
  248. { AnsiQuotedStr returns S quoted left and right by Quote,
  249. and every single occurance of Quote replaced by two }
  250. function AnsiQuotedStr(const S: string; Quote: char): string;
  251. var i, j, count: integer;
  252. begin
  253. result := '' + Quote;
  254. count := length(s);
  255. i := 0;
  256. j := 0;
  257. while i < count do begin
  258. i := i + 1;
  259. if S[i] = Quote then begin
  260. result := result + copy(S, 1 + j, i - j) + Quote;
  261. j := i;
  262. end ;
  263. end ;
  264. if i <> j then
  265. result := result + copy(S, 1 + j, i - j);
  266. result := result + Quote;
  267. end ;
  268. { AnsiExtractQuotedStr returns a copy of Src with quote characters
  269. deleted to the left and right and double occurances
  270. of Quote replaced by a single Quote }
  271. function AnsiExtractQuotedStr(var Src: PChar; Quote: Char): string;
  272. var i: integer; P, Q: PChar;
  273. begin
  274. P := Src;
  275. if Src^ = Quote then P := P + 1;
  276. Q := StrEnd(P);
  277. if PChar(Q - 1)^ = Quote then Q := Q - 1;
  278. SetLength(result, Q - P);
  279. i := 0;
  280. while P <> Q do begin
  281. i := i + 1;
  282. result[i] := P^;
  283. if (P^ = Quote) and (PChar(P + 1)^ = Quote) then
  284. P := P + 1;
  285. P := P + 1;
  286. end ;
  287. SetLength(result, i);
  288. end ;
  289. { AdjustLineBreaks returns S with all CR characters not followed by LF
  290. replaced with CR/LF }
  291. // under Linux all CR characters or CR/LF combinations should be replaced with LF
  292. function AdjustLineBreaks(const S: string): string;
  293. var i, j, count: integer;
  294. begin
  295. result := '';
  296. i := 0;
  297. j := 0;
  298. count := Length(S);
  299. while i < count do begin
  300. i := i + 1;
  301. if (S[i] = #13) and ((i = count) or (S[i + 1] <> #10)) then begin
  302. result := result + Copy(S, 1 + j, i - j) + #10;
  303. j := i;
  304. end ;
  305. end ;
  306. if j <> i then
  307. result := result + copy(S, 1 + j, i - j);
  308. end ;
  309. { IsValidIdent returns true if the first character of Ident is in:
  310. 'A' to 'Z', 'a' to 'z' or '_' and the following characters are
  311. on of: 'A' to 'Z', 'a' to 'z', '0'..'9' or '_' }
  312. function IsValidIdent(const Ident: string): boolean;
  313. var i, len: integer;
  314. begin
  315. result := false;
  316. len := length(Ident);
  317. if len <> 0 then begin
  318. result := Ident[1] in ['A'..'Z', 'a'..'z', '_'];
  319. i := 1;
  320. while (result) and (i < len) do begin
  321. i := i + 1;
  322. result := result and (Ident[i] in ['A'..'Z', 'a'..'z', '0'..'9', '_']);
  323. end ;
  324. end ;
  325. end ;
  326. { IntToStr returns a string representing the value of Value }
  327. function IntToStr(Value: integer): string;
  328. begin
  329. System.Str(Value, result);
  330. end ;
  331. { IntToHex returns a string representing the hexadecimal value of Value }
  332. const
  333. HexDigits: array[0..15] of char = '0123456789ABCDEF';
  334. function IntToHex(Value: integer; Digits: integer): string;
  335. var i: integer;
  336. begin
  337. SetLength(result, digits);
  338. for i := 0 to digits - 1 do begin
  339. result[digits - i] := HexDigits[value and 15];
  340. value := value shr 4;
  341. end ;
  342. end ;
  343. { StrToInt converts the string S to an integer value,
  344. if S does not represent a valid integer value EConvertError is raised }
  345. function StrToInt(const S: string): integer;
  346. var Error: word;
  347. begin
  348. Val(S, result, Error);
  349. {$ifdef autoobjpas}
  350. if Error <> 0 then raise EConvertError.createfmt(SInValidInteger,[S]);
  351. {$else}
  352. if Error <> 0 then raise EConvertError.create(s + ' is not a valid integer');
  353. {$endif}
  354. end ;
  355. { StrToIntDef converts the string S to an integer value,
  356. Default is returned in case S does not represent a valid integer value }
  357. function StrToIntDef(const S: string; Default: integer): integer;
  358. var Error: word;
  359. begin
  360. Val(S, result, Error);
  361. if Error <> 0 then result := Default;
  362. end ;
  363. { LoadStr returns the string resource Ident. }
  364. function LoadStr(Ident: integer): string;
  365. begin
  366. end ;
  367. { FmtLoadStr returns the string resource Ident and formats it accordingly }
  368. {$ifdef autoobjpas}
  369. function FmtLoadStr(Ident: integer; const Args: array of const): string;
  370. begin
  371. end;
  372. {$endif}
  373. Const
  374. feInvalidFormat = 1;
  375. feMissingArgument = 2;
  376. feInvalidArgIndex = 3;
  377. Procedure Log (Const S: String);
  378. begin
  379. {$ifdef debug}
  380. Writeln (S);
  381. {$endif}
  382. end;
  383. Procedure DoFormatError (ErrCode : Longint);
  384. Var S : String;
  385. begin
  386. //!! must be changed to contain format string...
  387. S:='';
  388. {$ifdef autoobjpas}
  389. Case ErrCode of
  390. feInvalidFormat : EConvertError.Createfmt(SInvalidFormat,[s]);
  391. feMissingArgument : EConvertError.Createfmt(SArgumentMissing,[s]);
  392. feInvalidArgIndex : EConvertError.Createfmt(SInvalidArgIndex,[s]);
  393. end;
  394. {$else}
  395. EConvertError.Create('Invalid format encountered : '+S);
  396. {$endif}
  397. end;
  398. {$ifdef AUTOOBJPAS}
  399. Function Format (Const Fmt : String; const Args : Array of const) : String;
  400. Var ChPos,OldPos,ArgPos,DoArg,Len : Longint;
  401. ToAdd : String;
  402. Index,Width,Prec : Longint;
  403. Left : Boolean;
  404. ExtVal: Extended;
  405. Fchar : char;
  406. {
  407. ReadFormat reads the format string. It returns the type character in
  408. uppercase, and sets index, Width, Prec to their correct values,
  409. or -1 if not set. It sets Left to true if left alignment was requested.
  410. In case of an error, DoFormatError is called.
  411. }
  412. Function ReadFormat : Char;
  413. Var Value : longint;
  414. Procedure ReadInteger;
  415. Var Code : Word;
  416. begin
  417. If Value<>-1 then exit; // Was already read.
  418. OldPos:=chPos;
  419. While (Chpos<Len) and
  420. (Pos(Fmt[chpos],'1234567890')<>0) do inc(chpos);
  421. If Chpos=len then DoFormatError(feInvalidFormat);
  422. If Fmt[Chpos]='*' then
  423. begin
  424. If (Chpos>OldPos) or (ArgPos>High(Args))
  425. or (Args[ArgPos].Vtype<>vtInteger) then
  426. DoFormatError(feInvalidFormat);
  427. Value:=Args[ArgPos].VInteger;
  428. Inc(ArgPos);
  429. Inc(chPos);
  430. end
  431. else
  432. begin
  433. If (OldPos<chPos) Then
  434. begin
  435. Val (Copy(Fmt,OldPos,ChPos-OldPos),value,code);
  436. // This should never happen !!
  437. If Code>0 then DoFormatError (feInvalidFormat);
  438. end
  439. else
  440. Value:=-1;
  441. end;
  442. end;
  443. Procedure ReadIndex;
  444. begin
  445. ReadInteger;
  446. If Fmt[ChPos]=':' then
  447. begin
  448. If Value=-1 then DoFormatError(feMissingArgument);
  449. Index:=Value;
  450. Value:=-1;
  451. Inc(Chpos);
  452. end;
  453. Log ('Read index');
  454. end;
  455. Procedure ReadLeft;
  456. begin
  457. If Fmt[chpos]='-' then
  458. begin
  459. left:=True;
  460. Inc(chpos);
  461. end
  462. else
  463. Left:=False;
  464. Log ('Read Left');
  465. end;
  466. Procedure ReadWidth;
  467. begin
  468. ReadInteger;
  469. If Value<>-1 then
  470. begin
  471. Width:=Value;
  472. Value:=-1;
  473. end;
  474. Log ('Read width');
  475. end;
  476. Procedure ReadPrec;
  477. begin
  478. If Fmt[chpos]='.' then
  479. begin
  480. inc(chpos);
  481. ReadInteger;
  482. If Value=-1 then DoFormaterror(feMissingArgument);
  483. prec:=Value;
  484. end;
  485. Log ('Read precision');
  486. end;
  487. begin
  488. Log ('Start format');
  489. Index:=-1;
  490. Width:=-1;
  491. Prec:=-1;
  492. Value:=-1;
  493. inc(chpos);
  494. If Fmt[Chpos]='%' then exit('%');
  495. ReadIndex;
  496. ReadLeft;
  497. ReadWidth;
  498. ReadPrec;
  499. ReadFormat:=Upcase(Fmt[ChPos]);
  500. Log ('End format');
  501. end;
  502. Procedure DumpFormat (C : char);
  503. begin
  504. Write ('Fmt : ',fmt:10);
  505. Write (' Index : ',Index:3);
  506. Write (' Left : ',left:5);
  507. Write (' Width : ',Width:3);
  508. Write (' Prec : ',prec:3);
  509. Writeln (' Type : ',C);
  510. end;
  511. Procedure Checkarg (AT : Longint);
  512. {
  513. Check if argument INDEX is of correct type (AT)
  514. If Index=-1, ArgPos is used, and argpos is augmented with 1
  515. DoArg is set to the argument that must be used.
  516. }
  517. begin
  518. If Index=-1 then
  519. begin
  520. DoArg:=Argpos;
  521. inc(ArgPos);
  522. end
  523. else
  524. DoArg:=Index;
  525. If (Doarg>High(Args)) or (Args[Doarg].Vtype<>AT) then
  526. DoFormatError(feInvalidArgindex);
  527. end;
  528. Const Zero = '000000000000000000000000000000000000000000000000000000000000000';
  529. begin
  530. Result:='';
  531. Len:=Length(Fmt)+1;
  532. Chpos:=1;
  533. OldPos:=1;
  534. ArgPos:=0;
  535. While chpos<len do
  536. begin
  537. // uses shortcut evaluation !!
  538. While (ChPos<=Len) and (Fmt[chpos]<>'%') do inc(chpos);
  539. If ChPos>OldPos Then
  540. Result:=Result+Copy(Fmt,OldPos,Chpos-Oldpos);
  541. If ChPos<Len then
  542. begin
  543. FChar:=ReadFormat;
  544. {$ifdef debug}
  545. DumpFormat(FCHar);
  546. {$endif}
  547. Case FChar of
  548. 'D' : begin
  549. Checkarg(vtinteger);
  550. Width:=Abs(width);
  551. Str(Args[Doarg].VInteger,ToAdd);
  552. While Length(ToAdd)<Prec do
  553. begin
  554. Index:=Prec-Length(ToAdd);
  555. If Index>64 then Index:=64;
  556. ToAdd:=Copy(Zero,1,Index)+ToAdd;
  557. end;
  558. end;
  559. 'E' : begin
  560. CheckArg(vtExtended);
  561. If Prec=-1 then prec:=15;
  562. ExtVal:=Args[doarg].VExtended^;
  563. Prec:=Prec+5; // correct dot, eXXX
  564. If ExtVal<0 then Inc(Prec); // Corect for minus sign
  565. If Abs(Extval)<1 then Inc(Prec); // correct for - in E
  566. Writeln('STRING ',prec);
  567. Str(Args[doarg].VExtended^:prec,ToAdd);
  568. WRITELN('DID');
  569. end;
  570. 'F' : begin
  571. end;
  572. 'S' : begin
  573. CheckArg(vtString);
  574. Index:=Length(Args[doarg].VString^);
  575. If (Prec<>-1) and (Index>Prec) then
  576. Index:=Prec;
  577. ToAdd:=Copy(Args[DoArg].VString^,1,Index);
  578. end;
  579. 'P' : Begin
  580. CheckArg(vtpointer);
  581. ToAdd:=HexStr(Longint(Args[DoArg].VPointer),8);
  582. // Insert ':'. Is this needed in 32 bit ? No it isn't.
  583. // Insert(':',ToAdd,5);
  584. end;
  585. 'X' : begin
  586. Checkarg(vtinteger);
  587. If Prec>32 then
  588. ToAdd:=HexStr(Args[Doarg].VInteger,Prec)
  589. else
  590. begin
  591. // determine minimum needed number of hex digits.
  592. Index:=1;
  593. While (1 shl (Index*4))<Args[DoArg].VInteger do
  594. inc(Index);
  595. If Index>Prec then
  596. Prec:=Index;
  597. ToAdd:=HexStr(Args[DoArg].VInteger,Prec);
  598. end;
  599. end;
  600. '%': ToAdd:='%';
  601. end;
  602. If Width<>-1 then
  603. If Length(ToAdd)<Width then
  604. If not Left then
  605. ToAdd:=Space(Width-Length(ToAdd))+ToAdd
  606. else
  607. ToAdd:=ToAdd+space(Width-Length(ToAdd));
  608. Result:=Result+ToAdd;
  609. end;
  610. inc(chpos);
  611. Oldpos:=chpos;
  612. end;
  613. end;
  614. {$endif}
  615. {==============================================================================}
  616. { extra functions }
  617. {==============================================================================}
  618. { SetLength sets the length of S to NewLength }
  619. // SetLength should be in the system unit
  620. // which lacks the ShortString version of SetLength
  621. function SetLength(var S: string; NewLength: integer): integer;
  622. begin
  623. if (NewLength > 255) then
  624. NewLength := 255;
  625. S[0] := char(NewLength);
  626. Result := Ord(S[0]);
  627. end ;
  628. { LeftStr returns Count left-most characters from S }
  629. function LeftStr(const S: string; Count: integer): string;
  630. begin
  631. result := Copy(S, 1, Count);
  632. end ;
  633. { RightStr returns Count right-most characters from S }
  634. function RightStr(const S: string; Count: integer): string;
  635. begin
  636. result := Copy(S, 1 + Length(S) - Count, Count);
  637. end ;
  638. { BCDToInt converts the BCD value Value to an integer }
  639. function BCDToInt(Value: integer): integer;
  640. var i, j: integer;
  641. begin
  642. result := 0;
  643. j := 1;
  644. for i := 0 to SizeOf(Value) shr 1 - 1 do begin
  645. result := result + j * (Value and 15);
  646. j := j * 10;
  647. Value := Value shr 4;
  648. end ;
  649. end ;
  650. { Case Translation Tables }
  651. { Although these tables can be obtained through system calls }
  652. { it is better to not use those, since most implementation are not 100% }
  653. { WARNING: }
  654. { before modifying a translation table make sure that the current codepage }
  655. { of the OS corresponds to the one you make changes to }
  656. const
  657. { upper case translation table for character set 850 }
  658. CP850UCT: array[128..255] of char =
  659. ('€', 'š', '�', '¶', 'Ž', '¶', '�', '€', 'Ò', 'Ó', 'Ô', 'Ø', '×', 'Þ', 'Ž', '�',
  660. '�', '’', '’', 'â', '™', 'ã', 'ê', 'ë', 'Y', '™', 'š', '�', 'œ', '�', 'ž', 'Ÿ',
  661. 'µ', 'Ö', 'à', 'é', '¥', '¥', '¦', '§', '¨', '©', 'ª', '«', '¬', '­', '®', '¯',
  662. '°', '±', '²', '³', '´', 'µ', '¶', '·', '¸', '¹', 'º', '»', '¼', '½', '¾', '¿',
  663. 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Ç', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï',
  664. 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', '×', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'Þ', 'ß',
  665. 'à', 'á', 'â', 'ã', 'å', 'å', 'æ', 'í', 'è', 'é', 'ê', 'ë', 'í', 'í', 'î', 'ï',
  666. 'ð', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', '÷', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'þ', 'ÿ');
  667. { lower case translation table for character set 850 }
  668. CP850LCT: array[128..255] of char =
  669. ('‡', '�', '‚', 'ƒ', '„', '…', '†', '‡', 'ˆ', '‰', 'Š', '‹', 'Œ', '�', '„', '†',
  670. '‚', '‘', '‘', '“', '”', '•', '–', '—', '˜', '”', '�', '›', 'œ', '›', 'ž', 'Ÿ',
  671. ' ', '¡', '¢', '£', '¤', '¤', '¦', '§', '¨', '©', 'ª', '«', '¬', '­', '®', '¯',
  672. '°', '±', '²', '³', '´', ' ', 'ƒ', '…', '¸', '¹', 'º', '»', '¼', '½', '¾', '¿',
  673. 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Æ', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï',
  674. 'Ð', 'Ñ', 'ˆ', '‰', 'Š', 'Õ', '¡', 'Œ', '‹', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', '�', 'ß',
  675. '¢', 'á', '“', '•', 'ä', 'ä', 'æ', 'í', 'è', '£', '–', '—', 'ì', 'ì', 'î', 'ï',
  676. 'ð', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', '÷', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'þ', 'ÿ');
  677. { upper case translation table for character set ISO 8859/1 Latin 1 }
  678. CPISO88591UCT: array[192..255] of char =
  679. ( #192, #193, #194, #195, #196, #197, #198, #199,
  680. #200, #201, #202, #203, #204, #205, #206, #207,
  681. #208, #209, #210, #211, #212, #213, #214, #215,
  682. #216, #217, #218, #219, #220, #221, #222, #223,
  683. #192, #193, #194, #195, #196, #197, #198, #199,
  684. #200, #201, #202, #203, #204, #205, #206, #207,
  685. #208, #209, #210, #211, #212, #213, #214, #247,
  686. #216, #217, #218, #219, #220, #221, #222, #89 );
  687. { lower case translation table for character set ISO 8859/1 Latin 1 }
  688. CPISO88591LCT: array[192..255] of char =
  689. ( #224, #225, #226, #227, #228, #229, #230, #231,
  690. #232, #233, #234, #235, #236, #237, #238, #239,
  691. #240, #241, #242, #243, #244, #245, #246, #215,
  692. #248, #249, #250, #251, #252, #253, #254, #223,
  693. #224, #225, #226, #227, #228, #229, #230, #231,
  694. #232, #233, #234, #235, #236, #237, #238, #239,
  695. #240, #241, #242, #243, #244, #245, #246, #247,
  696. #248, #249, #250, #251, #252, #253, #254, #255 );
  697. {$IFDEF GO32V2}
  698. { Codepage constants }
  699. const
  700. CP_US = 437;
  701. CP_MultiLingual = 850;
  702. CP_SlavicLatin2 = 852;
  703. CP_Turkish = 857;
  704. CP_Portugal = 860;
  705. CP_IceLand = 861;
  706. CP_Canada = 863;
  707. CP_NorwayDenmark = 865;
  708. { CountryInfo }
  709. {$PACKRECORDS 1}
  710. type
  711. TCountryInfo = record
  712. InfoId: byte;
  713. case integer of
  714. 1: ( Size: word;
  715. CountryId: word;
  716. CodePage: word;
  717. CountryInfo: array[0..33] of byte );
  718. 2: ( UpperCaseTable: longint );
  719. 4: ( FilenameUpperCaseTable: longint );
  720. 5: ( FilecharacterTable: longint );
  721. 6: ( CollatingTable: longint );
  722. 7: ( DBCSLeadByteTable: longint );
  723. end ;
  724. {$PACKRECORDS NORMAL}
  725. procedure GetExtendedCountryInfo(InfoId: integer; CodePage, CountryId: word; var CountryInfo: TCountryInfo);
  726. var Regs: Registers;
  727. begin
  728. Regs.AH := $65;
  729. Regs.AL := InfoId;
  730. Regs.BX := CodePage;
  731. Regs.DX := CountryId;
  732. Regs.ES := transfer_buffer div 16;
  733. Regs.DI := transfer_buffer and 15;
  734. Regs.CX := SizeOf(TCountryInfo);
  735. RealIntr($21, Regs);
  736. DosMemGet(transfer_buffer shr 16, transfer_buffer and 65535, CountryInfo, Regs.CX );
  737. end ;
  738. procedure InitAnsi;
  739. var CountryInfo: TCountryInfo; i: integer;
  740. begin
  741. { Fill table entries 0 to 127 }
  742. for i := 0 to 96 do
  743. UpperCaseTable[i] := chr(i);
  744. for i := 97 to 122 do
  745. UpperCaseTable[i] := chr(i - 32);
  746. for i := 123 to 127 do
  747. UpperCaseTable[i] := chr(i);
  748. for i := 0 to 64 do
  749. LowerCaseTable[i] := chr(i);
  750. for i := 65 to 90 do
  751. LowerCaseTable[i] := chr(i + 32);
  752. for i := 91 to 255 do
  753. LowerCaseTable[i] := chr(i);
  754. { Get country and codepage info }
  755. GetExtendedCountryInfo(1, $FFFF, $FFFF, CountryInfo);
  756. if CountryInfo.CodePage = 850 then begin
  757. Move(CP850UCT, UpperCaseTable[128], 128);
  758. Move(CP850LCT, LowerCaseTable[128], 128);
  759. end
  760. else begin
  761. { this needs to be checked !!
  762. this is correct only if UpperCaseTable is
  763. and Offset:Segment word record (PM) }
  764. { get the uppercase table from dosmemory }
  765. GetExtendedCountryInfo(2, $FFFF, $FFFF, CountryInfo);
  766. DosMemGet(CountryInfo.UpperCaseTable shr 16, 2 + CountryInfo.UpperCaseTable and 65535, UpperCaseTable[128], 128);
  767. for i := 128 to 255 do begin
  768. if UpperCaseTable[i] <> chr(i) then
  769. LowerCaseTable[ord(UpperCaseTable[i])] := chr(i);
  770. end ;
  771. end ;
  772. end ;
  773. {$ELSE}
  774. // {$IFDEF LINUX}
  775. procedure InitAnsi;
  776. begin
  777. end ;
  778. // {$ENDIF}
  779. {$ENDIF}
  780. {
  781. $Log$
  782. Revision 1.8 1998-10-02 13:57:38 michael
  783. Format error now causes exception
  784. Revision 1.7 1998/10/02 12:17:17 michael
  785. + Made sure it compiles with official 0.99.8
  786. Revision 1.6 1998/10/02 10:42:17 michael
  787. + Initial implementation of format
  788. Revision 1.5 1998/10/01 16:05:37 michael
  789. Added (empty) format function
  790. Revision 1.4 1998/09/17 12:39:52 michael
  791. + Further fixes from GertJan Schouten
  792. Revision 1.3 1998/09/16 14:34:37 pierre
  793. * go32v2 did not compile
  794. * wrong code in systr.inc corrected
  795. Revision 1.2 1998/09/16 08:28:42 michael
  796. Update from gertjan Schouten, plus small fix for linux
  797. $Log$
  798. Revision 1.8 1998-10-02 13:57:38 michael
  799. Format error now causes exception
  800. Revision 1.7 1998/10/02 12:17:17 michael
  801. + Made sure it compiles with official 0.99.8
  802. Revision 1.6 1998/10/02 10:42:17 michael
  803. + Initial implementation of format
  804. Revision 1.5 1998/10/01 16:05:37 michael
  805. Added (empty) format function
  806. Revision 1.4 1998/09/17 12:39:52 michael
  807. + Further fixes from GertJan Schouten
  808. Revision 1.1 1998/04/10 15:17:46 michael
  809. + Initial implementation; Donated by Gertjan Schouten
  810. His file was split into several files, to keep it a little bit structured.
  811. }