1 |
|
---|
2 | {ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
|
---|
3 | º º
|
---|
4 | º Sibyl Portable Component Classes º
|
---|
5 | º º
|
---|
6 | º Copyright (C) 1995,97 SpeedSoft Germany, All rights reserved. º
|
---|
7 | º º
|
---|
8 | ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍŒ}
|
---|
9 |
|
---|
10 | {*******************************************************}
|
---|
11 | { }
|
---|
12 | { System Utilities Unit (Delphi compatible) }
|
---|
13 | { }
|
---|
14 | { (C) 1995-96 Joerg Pleumann }
|
---|
15 | { (C) 1996 SpeedSoft }
|
---|
16 | { }
|
---|
17 | { Please mail All bugs And suggestions To: }
|
---|
18 | { }
|
---|
19 | { Internet: sa021pl @ uni-duisburg.de }
|
---|
20 | { FidoNet: Joerg Pleumann @ 2:2448/136.6 }
|
---|
21 | { }
|
---|
22 | {*******************************************************}
|
---|
23 |
|
---|
24 | Unit SysUtils;
|
---|
25 |
|
---|
26 |
|
---|
27 | Interface
|
---|
28 |
|
---|
29 | { define Compiler symbol GUI To Include FUNCTIONs from
|
---|
30 | OS/2 PM API. If you need A Version Of SysUtils that
|
---|
31 | Uses only OS/2 base API FUNCTIONs (And therefore lacks
|
---|
32 | Some features), comment This Line out And recompile the
|
---|
33 | Unit. Change This To produce programs that Run without
|
---|
34 | the OS/2 PM being Active (may also need changes In
|
---|
35 | System Unit). Normally you shouldn't Change This. }
|
---|
36 |
|
---|
37 | {$DEFINE GUI}
|
---|
38 |
|
---|
39 | {$IFDEF OS2}
|
---|
40 | {$IFDEF GUI}
|
---|
41 | Uses
|
---|
42 | Os2Def,BseDos, BseErr, PmWin, PMSHL;
|
---|
43 | {$ELSE GUI}
|
---|
44 | Uses
|
---|
45 | Os2Def,BseDos, BseErr;
|
---|
46 | {$ENDIF GUI}
|
---|
47 | {$ENDIF OS2}
|
---|
48 |
|
---|
49 | {$IFDEF Win95}
|
---|
50 | Uses
|
---|
51 | WinNt, WinBase, WinUser;
|
---|
52 | {$ENDIF Win95}
|
---|
53 |
|
---|
54 | { constants For SPCC Notification And Error Messages And Month / Day Names. }
|
---|
55 | {$I SPCC.Inc}
|
---|
56 |
|
---|
57 | Type
|
---|
58 | { Pointer To floating Point Value. }
|
---|
59 | PExtended = ^Extended;
|
---|
60 |
|
---|
61 | Type
|
---|
62 | //Override Exception definition from System To allow formatted Create...
|
---|
63 | Exception=Class(SysException)
|
---|
64 | Public
|
---|
65 | Constructor CreateFmt(Const Msg:String;Const Args:Array Of Const);
|
---|
66 | Constructor CreateRes(Ident:Word);
|
---|
67 | Constructor CreateResFmt(Ident:Word;Const Args:Array Of Const);
|
---|
68 | Constructor CreateResNLS(Ident:Word);
|
---|
69 | Constructor CreateResNLSFmt(Ident:Word;Const Args:Array Of Const);
|
---|
70 | Constructor CreateHelp(Const Msg:String;AHelpContext:LongInt);
|
---|
71 | Constructor CreateFmtHelp(Const Msg:String;Const Args:Array Of Const;AHelpContext:LongInt);
|
---|
72 | Constructor CreateResHelp(Ident:Word;AHelpContext:LongInt);
|
---|
73 | Constructor CreateResFmtHelp(Ident:Word;Const Args:Array Of Const;AHelpContext:LongInt);
|
---|
74 | Constructor CreateResNLSHelp(Ident:Word;AHelpContext:LongInt);
|
---|
75 | Constructor CreateResNLSFmtHelp(Ident:Word;Const Args:Array Of Const;AHelpContext:LongInt);
|
---|
76 | End;
|
---|
77 |
|
---|
78 | ExceptClass = Class Of Exception;
|
---|
79 |
|
---|
80 | EConvertError = Class(Exception);
|
---|
81 |
|
---|
82 | Const
|
---|
83 |
|
---|
84 | { File Open modes - A legal File Open Mode Is A logical combination
|
---|
85 | Of an Open Mode And A sharing Mode. Please note that OS/2 Normally
|
---|
86 | doesn't allow fmShareCompat, but For reasons Of compatibility the
|
---|
87 | File FUNCTIONs automatically replace This constant by
|
---|
88 | fmShareDenyNone. }
|
---|
89 |
|
---|
90 | {$IFDEF OS2}
|
---|
91 | fmOpenRead = $0000;
|
---|
92 | fmOpenWrite = $0001;
|
---|
93 | fmOpenReadWrite = $0002;
|
---|
94 | fmShareCompat = $0000;
|
---|
95 | fmShareExclusive = $0010;
|
---|
96 | fmShareDenyWrite = $0020;
|
---|
97 | fmShareDenyRead = $0030;
|
---|
98 | fmShareDenyNone = $0040;
|
---|
99 | {$ENDIF}
|
---|
100 |
|
---|
101 | {$IFDEF Win95}
|
---|
102 | fmOpenRead = $80000000;
|
---|
103 | fmOpenWrite = $40000000;
|
---|
104 | fmOpenReadWrite = $C0000000;
|
---|
105 | fmShareCompat = $00000003;
|
---|
106 | fmShareExclusive = $00000000;
|
---|
107 | fmShareDenyWrite = $00000001;
|
---|
108 | fmShareDenyRead = $00000002;
|
---|
109 | fmShareDenyNone = $00000003;
|
---|
110 | {$ENDIF}
|
---|
111 |
|
---|
112 | { File Record}
|
---|
113 | Type
|
---|
114 | TFileRec=FileRec;
|
---|
115 |
|
---|
116 | { File attribute constants - Please note that there Is no constant
|
---|
117 | faVolumeID, since OS/2 handles volume Ids In another way than Dos
|
---|
118 | does. }
|
---|
119 | Const
|
---|
120 | faReadOnly = $0001;
|
---|
121 | faHidden = $0002;
|
---|
122 | faSysFile = $0004;
|
---|
123 | faDirectory = $0010;
|
---|
124 | faArchive = $0020;
|
---|
125 |
|
---|
126 | faAnyFile = faReadOnly Or faHidden Or faSysFile Or faDirectory Or faArchive;
|
---|
127 |
|
---|
128 | { 'Must' attribute constants - OS/2-specific File attribute constants
|
---|
129 | For searching files. Use these constants In logical combination
|
---|
130 | With the normal File Attributes when calling FindFirst() To restrict
|
---|
131 | the Search results. }
|
---|
132 |
|
---|
133 | faMustReadOnly = $0100;
|
---|
134 | faMustHidden = $0200;
|
---|
135 | faMustSysFile = $0400;
|
---|
136 | faMustDirectory = $1000;
|
---|
137 | faMustArchive = $2000;
|
---|
138 |
|
---|
139 | Const
|
---|
140 |
|
---|
141 | { File Lock-TimeOut - This TimeOut Value Is used when performing File
|
---|
142 | locking / unlocking operations. Value Is given In ms. }
|
---|
143 |
|
---|
144 | LockTimeout: LongInt = 5000;
|
---|
145 |
|
---|
146 | Type
|
---|
147 |
|
---|
148 | { support For date And Time operations - both values are stored In
|
---|
149 | one floating Point Value. the Integer part Contains the days passed
|
---|
150 | since 31-Dec-0000, assuming that the Gregorian calendar has always
|
---|
151 | been used. the fractional part Contains the part Of the Day since
|
---|
152 | 00:00:00. the Time part Is always equal To Or greater than Zero
|
---|
153 | And smaller than one. }
|
---|
154 |
|
---|
155 | TDateTime = Extended;
|
---|
156 |
|
---|
157 | Const
|
---|
158 |
|
---|
159 | SecsPerDay = 24 * 60 * 60;
|
---|
160 | MSecsPerDay = SecsPerDay * 1000;
|
---|
161 |
|
---|
162 | Type
|
---|
163 |
|
---|
164 | { Some Type conversion records. }
|
---|
165 |
|
---|
166 | WordRec = Record
|
---|
167 | Lo, Hi: Byte;
|
---|
168 | End;
|
---|
169 |
|
---|
170 | LongRec = Record
|
---|
171 | Lo, Hi: Word;
|
---|
172 | End;
|
---|
173 |
|
---|
174 | TMethod = Record
|
---|
175 | Code, Data: Pointer;
|
---|
176 | End;
|
---|
177 |
|
---|
178 | { Some useful arrays. }
|
---|
179 |
|
---|
180 | PByteArray = ^TByteArray;
|
---|
181 | TByteArray = Array[0..MaxLongInt] Of Byte;
|
---|
182 |
|
---|
183 | PWordArray = ^TWordArray;
|
---|
184 | TWordArray = Array[0..MaxLongInt Div 2] Of Word;
|
---|
185 |
|
---|
186 | { Generic Procedure Type. }
|
---|
187 |
|
---|
188 | TProcedure = Procedure;
|
---|
189 |
|
---|
190 | { Generic FileName Type }
|
---|
191 |
|
---|
192 | TFileName = String;
|
---|
193 |
|
---|
194 | { File Search Record - This Is the Data structure internally used
|
---|
195 | by the FindFirst, FindNext, And FindClose FUNCTIONs. }
|
---|
196 |
|
---|
197 | TSearchRec = Record
|
---|
198 | {$IFDEF Win95}
|
---|
199 | InternalAttr:LongWord;
|
---|
200 | SearchRecIntern:WIN32_FIND_DATA;
|
---|
201 | {$ENDIF}
|
---|
202 | HDir: LongWord;
|
---|
203 | Attr: Byte;
|
---|
204 | Time: LongInt;
|
---|
205 | Size: LongInt;
|
---|
206 | Name: String;
|
---|
207 | End;
|
---|
208 |
|
---|
209 | { FloatToText codes - these codes are used To specify the basic
|
---|
210 | Output format Of the various FUNCTIONs that Convert floating
|
---|
211 | Point values To Strings. }
|
---|
212 |
|
---|
213 | TFloatFormat = (ffGeneral, ffExponent, ffFixed, ffNumber, ffCurrency);
|
---|
214 |
|
---|
215 | { FloatToDecimal Result Record - This Record Is used To hold the return
|
---|
216 | Value Of the FloatToDecimal Function. }
|
---|
217 |
|
---|
218 | TFloatRec = Record
|
---|
219 | Exponent: Integer;
|
---|
220 | Negative: Boolean;
|
---|
221 | Digits: Array[0..18] Of Char;
|
---|
222 | End;
|
---|
223 |
|
---|
224 | Const
|
---|
225 |
|
---|
226 | { Empty String And Pointer To Empty String - used internally by various
|
---|
227 | String FUNCTIONs. }
|
---|
228 |
|
---|
229 | EmptyStr: String[1] = '';
|
---|
230 | NullStr: PString = @EmptyStr;
|
---|
231 |
|
---|
232 | Var
|
---|
233 |
|
---|
234 | { --- date, Time, And currency defaults ---
|
---|
235 |
|
---|
236 | the following global variables contain Default values For formatting
|
---|
237 | date, Time, And currency values. most Of them are queried from the
|
---|
238 | System At Program startup. Some others are taken from the
|
---|
239 | application's resources. }
|
---|
240 |
|
---|
241 | { DateSeparator - the character used To separate Year, Month, And Day,
|
---|
242 | when converting A TDateTime Value To Text. queried from the System
|
---|
243 | At Program startup. }
|
---|
244 |
|
---|
245 | DateSeparator: Char;
|
---|
246 |
|
---|
247 | { ShortDateFormat - the Default format String used when converting a
|
---|
248 | TDateTime Value To Text. This one Is used whenever A short Result
|
---|
249 | Is desired. the Value Is computed At Program startup. }
|
---|
250 |
|
---|
251 | ShortDateFormat: String[15];
|
---|
252 |
|
---|
253 | { LongDateFormat - the Default format String used when converting a
|
---|
254 | TDateTime Value To Text. This one Is used whenever A LONG Result
|
---|
255 | Is desired. the Value Is computed At Program startup. }
|
---|
256 |
|
---|
257 | LongDateFormat: String[31];
|
---|
258 |
|
---|
259 | { ShortMonthNames - Abbreviations For Month Names used when converting
|
---|
260 | A TDateTime Value To Text. the Names are taken from the program's
|
---|
261 | resources. }
|
---|
262 |
|
---|
263 | ShortMonthNames: Array[1..12] Of String[7];
|
---|
264 |
|
---|
265 | { LongMonthNames - the full Month Names used when converting a
|
---|
266 | TDateTime Value To Text. the Names are taken from the program's
|
---|
267 | resources. }
|
---|
268 |
|
---|
269 | LongMonthNames: Array[1..12] Of String[15];
|
---|
270 |
|
---|
271 | { ShortDayNames - Abbreviations For Day Names used when converting
|
---|
272 | A TDateTime Value To Text. the Names are taken from the program's
|
---|
273 | resources. }
|
---|
274 |
|
---|
275 | ShortDayNames: Array[1..7] Of String[7];
|
---|
276 |
|
---|
277 | { LongDayNames - the full Day Names used when converting A TDateTime
|
---|
278 | Value To Text. the Names are taken from the program's resources. }
|
---|
279 |
|
---|
280 | LongDayNames: Array[1..7] Of String[15];
|
---|
281 |
|
---|
282 | { DateOrder - the order Of Year, Month, And Day assumed when trying To
|
---|
283 | extract date information from A String. queried from the System At
|
---|
284 | Program startup. }
|
---|
285 |
|
---|
286 | DateOrder: Byte;
|
---|
287 |
|
---|
288 | { TimeSeparator - the character used To separate Hour, Minute, And
|
---|
289 | Second, when converting A TDateTime Value To Text. queried from the
|
---|
290 | System At Program startup. }
|
---|
291 |
|
---|
292 | TimeSeparator: Char;
|
---|
293 |
|
---|
294 | { TimeAMString - the String appended To Time values between 00:00 And
|
---|
295 | 11:59 when converting A DateTime Value To Text. only used when
|
---|
296 | 12-Hour clock format Is used. queried from the System At Program
|
---|
297 | startup. }
|
---|
298 |
|
---|
299 | TimeAMString: String[7];
|
---|
300 |
|
---|
301 | { TimePMString - the String appended To Time values between 12:00 And
|
---|
302 | 23:59 when converting A DateTime Value To Text. only used when
|
---|
303 | 12-Hour clock format Is used. queried from the System At Program
|
---|
304 | startup. }
|
---|
305 |
|
---|
306 | TimePMString: String[7];
|
---|
307 |
|
---|
308 | { ShortTimeFormat - the Default format String used when converting a
|
---|
309 | TDateTime Value To Text. This one Is used whenever A shorter Result
|
---|
310 | Is desired. queried from the System At Program startup. }
|
---|
311 |
|
---|
312 | ShortTimeFormat: String[15];
|
---|
313 |
|
---|
314 | { LongTimeFormat - the Default format String used when converting a
|
---|
315 | TDateTime Value To Text. This one Is used whenever A longer Result
|
---|
316 | Is desired. queried from the System At Program startup. }
|
---|
317 |
|
---|
318 | LongTimeFormat: String[31];
|
---|
319 |
|
---|
320 | { TwelveHours - Indicates whether 12-Hour clock format Is used when
|
---|
321 | trying To extract Time information from A String. queried from
|
---|
322 | the System At Program startup. }
|
---|
323 |
|
---|
324 | TwelveHours: Boolean;
|
---|
325 |
|
---|
326 | { CurrencyString - the local currency String used when converting
|
---|
327 | currency values To Text. Default Value Is queried from the System
|
---|
328 | At Program startup. }
|
---|
329 |
|
---|
330 | CurrencyString: String[7];
|
---|
331 |
|
---|
332 | { CurrencyFormat - the order Of currency Value, currency String, And
|
---|
333 | separating space used when converting currency values To Text.
|
---|
334 | Default Value Is queried from the System At Program startup.
|
---|
335 |
|
---|
336 | the following values four are possible, With the fifth one
|
---|
337 | being an additional Value that Is only supported by OS/2:
|
---|
338 |
|
---|
339 | 0 = '$1' 1 = '1$' 2 = '$ 1' 3 = '1 $'
|
---|
340 |
|
---|
341 | 4 = currency String replaces DECIMAL indicator }
|
---|
342 |
|
---|
343 | CurrencyFormat: Byte;
|
---|
344 |
|
---|
345 | { NegCurrFormat - Corresponds To CurrencyFormat, but Is used when
|
---|
346 | converting Negative currency values To Text. queried from the
|
---|
347 | System At Program startup.
|
---|
348 |
|
---|
349 | the following values are possible:
|
---|
350 |
|
---|
351 | 0 = '($1)' 1 = '-$1' 2 = '$-1' 3 = '$1-'
|
---|
352 | 4 = '(1$)' 5 = '-1$' 6 = '1-$' 7 = '1$-'
|
---|
353 | 8 = '-1 $' 9 = '-$ 1' 10 = '$ 1-'
|
---|
354 |
|
---|
355 | since OS/2 doesn't support A Special format For Negative currency
|
---|
356 | values, A format Is chosen that matches the CurrencyFormat With
|
---|
357 | A preceding '-'. the following List shows the possible values:
|
---|
358 |
|
---|
359 | CurrencyFormat NegCurrFormat
|
---|
360 |
|
---|
361 | 0 = '$1' 1 = -$1
|
---|
362 | 1 = '1$' 5 = -1$
|
---|
363 | 2 = '$ 1' 9 = -$ 1
|
---|
364 | 3 = '1 $' 8 = -1 $ }
|
---|
365 |
|
---|
366 | NegCurrFormat: Byte;
|
---|
367 |
|
---|
368 | { ThousandSeparator - the character used To separate blocks Of three
|
---|
369 | Digits when converting floating Point values To Text. queried from
|
---|
370 | the System At Program startup. }
|
---|
371 |
|
---|
372 | ThousandSeparator: Char;
|
---|
373 |
|
---|
374 | { DecimalSeparator - the character used To separate the Integer part
|
---|
375 | from the fractional part when converting floating Point values To
|
---|
376 | Text. queried from the System At Program startup. }
|
---|
377 |
|
---|
378 | DecimalSeparator: Char;
|
---|
379 |
|
---|
380 | { CurrencyDigits - the Number Of Digits used In the fractional part
|
---|
381 | Of A currency Value when converting A currency Value To Text.
|
---|
382 | queried from the System At Program startup. }
|
---|
383 |
|
---|
384 | CurrencyDecimals: Byte;
|
---|
385 |
|
---|
386 | { ListSeparator - the character To Use when separating Items In A List.
|
---|
387 | Currently Not used by any Function. }
|
---|
388 |
|
---|
389 | ListSeparator: Char;
|
---|
390 |
|
---|
391 | { --- Memory management --- }
|
---|
392 |
|
---|
393 | { AllocMem - Allocates A Memory block Of the desired Size ON the heap.
|
---|
394 | In contrast To the GetMem Standard Procedure, AllocMem fills the
|
---|
395 | whole block With zeroes. }
|
---|
396 |
|
---|
397 | Function AllocMem(Size: Cardinal): Pointer;
|
---|
398 |
|
---|
399 | { ReAllocMem - re-Allocates A previously allocated Memory block And
|
---|
400 | changes its Size. copies the contents Of the old block into the
|
---|
401 | New one. CurSize And NewSize specify the Current And the New Size
|
---|
402 | Of the block. If the New Size Is larger than the Current Size, the
|
---|
403 | additional Bytes are zeroed. the old Memory block Is automatically
|
---|
404 | disposed. note that the resulting Pointer will always be different
|
---|
405 | from the old Pointer, even If the Size isn't changed. the Function
|
---|
406 | can Handle Nil pointers And Zero blocks. }
|
---|
407 |
|
---|
408 | Function ReAllocMem(P: Pointer; CurSize, NewSize: Cardinal): Pointer;
|
---|
409 |
|
---|
410 | { --- Exit Procedure Handling --- }
|
---|
411 |
|
---|
412 | { AddExitProc - Adds A parameterless Procedure To the List Of
|
---|
413 | procedures To be called when the Program Is Terminated. note that
|
---|
414 | the Procedure that Is added Last will be called First. }
|
---|
415 |
|
---|
416 | Procedure AddExitProc(Proc: TProcedure);
|
---|
417 |
|
---|
418 | { CallExitProcs - calls All procedures that were installed by
|
---|
419 | AddExitProc And deletes them from the List. note that the
|
---|
420 | Procedure that was added Last will be called First. }
|
---|
421 |
|
---|
422 | Procedure CallExitProcs;
|
---|
423 |
|
---|
424 | { --- String Handling --- }
|
---|
425 |
|
---|
426 | { NewStr - Allocates A block Of Memory ON the heap And fills it With
|
---|
427 | the given String, returns A PString To the Memory block. the Memory
|
---|
428 | block's Size will be exactly one Byte more than the string's Real
|
---|
429 | Length. Empty Strings don't Use any heap space, the Function returns
|
---|
430 | NullStr In This Case. since NullStr Points To EmptyStr, the Function
|
---|
431 | never returns Nil, So you can always de-Reference the resulting
|
---|
432 | Pointer. Use DisposeStr To Free the Memory block. }
|
---|
433 |
|
---|
434 | Function NewStr(Const S: String): PString;
|
---|
435 |
|
---|
436 | { DisposeStr - Disposes A block Of Memory ON the heap that Contains
|
---|
437 | A String. the block MUST have been allocated by A call To NewStr.
|
---|
438 | If the given Pointer Is NullStr (And thereby references the Empty
|
---|
439 | String) Or Nil, the Function does absolutely Nothing. }
|
---|
440 |
|
---|
441 | Procedure DisposeStr(P: PString);
|
---|
442 |
|
---|
443 | { AssignStr - Assigns A New Value To A String Pointer that has been
|
---|
444 | previously allocated by A call To NewStr, Or Is Nil. the old String
|
---|
445 | Is disposed by DisposeStr, And the New one Is allocated by NewStr. }
|
---|
446 |
|
---|
447 | Procedure AssignStr(Var P: PString; Const S: String);
|
---|
448 |
|
---|
449 | { AppendStr - Appends A String To the End Of another. }
|
---|
450 |
|
---|
451 | Procedure AppendStr(Var Dest: String; Const S: String);
|
---|
452 |
|
---|
453 | { uppercase - Converts A String To upper Case by simply Changing All
|
---|
454 | occurences Of 'a'..'z' To the corresponding upper Case characters.
|
---|
455 | If you want A conversion that also considers international Special
|
---|
456 | characters, Use AnsiUpperCase. }
|
---|
457 |
|
---|
458 | Function uppercase(Const S: String): String;
|
---|
459 |
|
---|
460 | { lowercase - Converts A String To lower Case by simply Changing All
|
---|
461 | occurences Of 'A'..'Z' To the corresponding lower Case characters.
|
---|
462 | If you want A conversion that also considers international Special
|
---|
463 | characters, Use AnsiLowerCase. }
|
---|
464 |
|
---|
465 | Function lowercase(Const S: String): String;
|
---|
466 |
|
---|
467 | { CompareStr - Compares two Strings And returns an Integer Value
|
---|
468 | As In the following Table:
|
---|
469 |
|
---|
470 | s1 < s2 Result < 0
|
---|
471 | s1 = s2 Result = 0
|
---|
472 | s1 > s2 Result > 0
|
---|
473 |
|
---|
474 | CompareStr Is Case-sensitive, but does Not take international
|
---|
475 | Special characters Or the Currently Selected codepage into account. }
|
---|
476 |
|
---|
477 | Function CompareStr(Const s1, s2: String): Integer;
|
---|
478 |
|
---|
479 | { CompareText - Compares two Strings And returns an Integer Value
|
---|
480 | As In the following Table:
|
---|
481 |
|
---|
482 | s1 < s2 Result < 0
|
---|
483 | s1 = s2 Result = 0
|
---|
484 | s1 > s2 Result > 0
|
---|
485 |
|
---|
486 | CompareText Is Case-insensitive, And does Not take international
|
---|
487 | Special characters Or the Currently Selected codepage into account. }
|
---|
488 |
|
---|
489 | Function CompareText(Const s1, s2: String): Integer;
|
---|
490 |
|
---|
491 | { AnsiUpperCase - Converts A String To upper Case. This Function
|
---|
492 | also takes international Special characters And the Currently
|
---|
493 | Selected codepage into account. If you don't want This, Use
|
---|
494 | uppercase. }
|
---|
495 |
|
---|
496 | Function AnsiUpperCase(Const S: String): String;
|
---|
497 |
|
---|
498 | { AnsiLowerCase - Converts A String To lower Case. This Function
|
---|
499 | also takes international Special characters And the Currently
|
---|
500 | Selected codepage into account. If you don't want This, Use
|
---|
501 | lowercase. note that AnsiLowerCase Is Not available under OS/2. }
|
---|
502 |
|
---|
503 | {$IFNDEF OS2}
|
---|
504 | Function AnsiLowerCase(Const S: String): String;
|
---|
505 | {$ENDIF}
|
---|
506 |
|
---|
507 | { AnsiCompareStr - Compares two Strings And returns an Integer Value
|
---|
508 | As In the following Table:
|
---|
509 |
|
---|
510 | s1 < s2 Result < 0
|
---|
511 | s1 = s2 Result = 0
|
---|
512 | s1 > s2 Result > 0
|
---|
513 |
|
---|
514 | AnsiCompareStr Is Case-sensitive, And takes international Special
|
---|
515 | characters And the Currently Selected codepage into account. note
|
---|
516 | that the Function Is Not available under OS/2. }
|
---|
517 |
|
---|
518 | {$IFNDEF OS2}
|
---|
519 | Function AnsiCompareStr(Const s1, s2: String): Integer;
|
---|
520 | {$ENDIF}
|
---|
521 |
|
---|
522 | { AnsiCompareText - Compares two Strings And returns an Integer Value
|
---|
523 | As In the following Table:
|
---|
524 |
|
---|
525 | s1 < s2 Result < 0
|
---|
526 | s1 = s2 Result = 0
|
---|
527 | s1 > s2 Result > 0
|
---|
528 |
|
---|
529 | AnsiCompareText Is Case-insensitive, And takes international Special
|
---|
530 | characters And the Currently Selected codepage into account. }
|
---|
531 |
|
---|
532 | Function AnsiCompareText(Const s1, s2: String): Integer;
|
---|
533 |
|
---|
534 | { Trim - Removes leading And trailing spaces And Control characters. }
|
---|
535 |
|
---|
536 | Function Trim(Const S: String): String;
|
---|
537 |
|
---|
538 | { TrimLeft - Removes leading spaces And Control characters. }
|
---|
539 |
|
---|
540 | Function TrimLeft(Const S: String): String;
|
---|
541 |
|
---|
542 | { TrimRight - Removes trailing spaces And Control characters. }
|
---|
543 |
|
---|
544 | Function TrimRight(Const S: String): String;
|
---|
545 |
|
---|
546 | { QuotedStr - returns the given String enclosed In quotes. quotes already
|
---|
547 | included In the String are returned As two quote characters. }
|
---|
548 |
|
---|
549 | Function QuotedStr(Const S: String): String;
|
---|
550 |
|
---|
551 | { IsValidIdent - Checks whether the given String Contains A legal
|
---|
552 | Pascal identifier. check your Speed-Pascal manual To See what A
|
---|
553 | legal identifier looks like. :-) }
|
---|
554 |
|
---|
555 | Function IsValidIdent(Const Ident: String): Boolean;
|
---|
556 |
|
---|
557 | { IntToStr - Converts an Integer Value To A String Of Digits. }
|
---|
558 |
|
---|
559 | Function IntToStr(Value: LongInt): String;
|
---|
560 |
|
---|
561 | { IntToHex - Converts an Integer Value To A String Of hexadecimal
|
---|
562 | Digits. the minimum desired Number Of Digits can be specified.
|
---|
563 | If the Result Contains less Digits, it Is Left-padded With zeroes. }
|
---|
564 |
|
---|
565 | Function IntToHex(Value: LongInt; Digits: Integer): String;
|
---|
566 |
|
---|
567 | { StrToInt - Extracts an Integer Value from A String. If the String
|
---|
568 | doesn't contain A legal Integer Value, Exception EConvertError
|
---|
569 | Is raised. }
|
---|
570 |
|
---|
571 | Function StrToInt(Const S: String): LongInt;
|
---|
572 |
|
---|
573 | { StrToIntDef - Extracts an Integer Value from A String. If the String
|
---|
574 | doesn't contain A legal Integer Value, the desired Default Value
|
---|
575 | Is returned instead. }
|
---|
576 |
|
---|
577 | {$IFDEF GUI}
|
---|
578 | Function StrToIntDef(Const S: String; Default: LongInt): LongInt;
|
---|
579 | {$ENDIF GUI}
|
---|
580 |
|
---|
581 | { LoadStr - Loads A String from the application's resources. the
|
---|
582 | String Is retrieved by an Integer Number. If the resources don't
|
---|
583 | contain A String With the given Number, LoadStr returns an Empty
|
---|
584 | String. }
|
---|
585 |
|
---|
586 | {$IFDEF GUI}
|
---|
587 | Function LoadStr(Ident: Word): String;
|
---|
588 | {$ENDIF GUI}
|
---|
589 |
|
---|
590 | { LoadNLSStr - Loads A String from the application's Current Language Table. the
|
---|
591 | String Is retrieved by an Integer Number. If the resources don't
|
---|
592 | contain A String With the given Number, LoadStr returns an Empty
|
---|
593 | String. }
|
---|
594 |
|
---|
595 | Function LoadNLSStr(Ident: Word): String;
|
---|
596 |
|
---|
597 | { LoadTableStr - Loads A String from the specified String Table. the
|
---|
598 | String Is retrieved by an Integer Number. If the resources don't
|
---|
599 | contain A String With the given Number, LoadStr returns an Empty
|
---|
600 | String. }
|
---|
601 |
|
---|
602 | Function LoadTableStr(Const Table:String;Ident: Word): String;
|
---|
603 |
|
---|
604 | { FmtLoadStr - Loads A String from the application's resources And
|
---|
605 | replaces Some placeholders by values given In an Open-Array. the
|
---|
606 | String Is retrieved by an Integer Number. If the resources don't
|
---|
607 | contain A String With the given Number, FmtLoadStr returns an
|
---|
608 | Empty String. }
|
---|
609 |
|
---|
610 | {$IFDEF GUI}
|
---|
611 | Function FmtLoadStr(Ident: Word; Const Args: Array Of Const): String;
|
---|
612 | {$ENDIF GUI}
|
---|
613 |
|
---|
614 | { FmtLoadNLSStr - Loads A String from the application's Current Language Table And
|
---|
615 | replaces Some placeholders by values given In an Open-Array. the
|
---|
616 | String Is retrieved by an Integer Number. If the resources don't
|
---|
617 | contain A String With the given Number, FmtLoadStr returns an
|
---|
618 | Empty String. }
|
---|
619 |
|
---|
620 | Function FmtLoadNLSStr(Ident: Word; Const Args: Array Of Const): String;
|
---|
621 |
|
---|
622 | { FmtLoadTableStr - Loads A String from the specified String Table And
|
---|
623 | replaces Some placeholders by values given In an Open-Array. the
|
---|
624 | String Is retrieved by an Integer Number. If the resources don't
|
---|
625 | contain A String With the given Number, FmtLoadStr returns an
|
---|
626 | Empty String. }
|
---|
627 |
|
---|
628 | Function FmtLoadTableStr(Const Table:String;Ident: Word; Const Args: Array Of Const): String;
|
---|
629 |
|
---|
630 |
|
---|
631 | { SysErrorMessage - returns A System Error Message. }
|
---|
632 |
|
---|
633 | {$IFDEF OS2}
|
---|
634 | Function SysErrorMessage(MsgNum: LongInt): String;
|
---|
635 | {$ENDIF OS2}
|
---|
636 |
|
---|
637 | { --- File management --- }
|
---|
638 |
|
---|
639 | { FileOpen - Opens an existing File With A given File Mode. the File
|
---|
640 | Mode Is A logical combination Of one Of the File Open constants
|
---|
641 | (fmOpenXXX) And one Of the sharing Mode constants (fmShareXXX). If
|
---|
642 | the File Is successfully opended, the resulting Integer Value Is
|
---|
643 | positive And Contains the File Handle. Otherwise the Result Is the
|
---|
644 | Negative Value Of the Error Code returned by the operating System. }
|
---|
645 |
|
---|
646 | Function FileOpen(Const FileName: String; Mode: Word): LongInt;
|
---|
647 |
|
---|
648 | { FileCreate - creates A New File Or overwrites an existing one. no
|
---|
649 | File Mode can be specified, So the File Is always created With
|
---|
650 | fmOpenWrite Or fmShareExclusive. If the File Is successfully
|
---|
651 | created, the resulting Integer Value Is positive And Contains the
|
---|
652 | File Handle. Otherwiese the Result Is the Negative Value Of the
|
---|
653 | Error Code returned by the operating System. }
|
---|
654 |
|
---|
655 | Function FileCreate(Const FileName: String): LongInt;
|
---|
656 |
|
---|
657 | { FileOpenOrCreate - Opens Or creates A File, depending ON whether
|
---|
658 | the File already exists Or Not. A File Mode can be specified. the
|
---|
659 | File Mode Is A logical combination Of one Of the File Open constants
|
---|
660 | (fmOpenXXX) And one Of the sharing Mode constants (fmShareXXX). If
|
---|
661 | the File Is successfully opended Or created, the resulting Integer
|
---|
662 | Value Is positive And Contains the File Handle. Otherwise the
|
---|
663 | Result Is the Negative Value Of the Error Code returned by the
|
---|
664 | operating System. }
|
---|
665 |
|
---|
666 | Function FileOpenOrCreate(Const FileName: String; Mode: Word): LongInt;
|
---|
667 |
|
---|
668 | { FileCreateIfNew - creates A File If there's Not already A File With
|
---|
669 | the same Name. A File Mode can be specified. the File Mode Is a
|
---|
670 | logical combination Of one Of the File Open constants (fmOpenXXX)
|
---|
671 | And one Of the sharing Mode constants (fmShareXXX). If the New File
|
---|
672 | Is successfully created, the resulting Integer Value Is positive And
|
---|
673 | Contains the File Handle. Otherwise the Result Is the Negative Value
|
---|
674 | Of the Error Code returned by the operating System. note that This
|
---|
675 | Function also fails If the File already exists. }
|
---|
676 |
|
---|
677 | Function FileCreateIfNew(Const FileName: String; Mode: Word): LongInt;
|
---|
678 |
|
---|
679 | { FileRead - Attempts To Read up To Count Bytes from the given File
|
---|
680 | Handle And returns the Number Of Bytes actually Read. If an Error
|
---|
681 | occurs, the Result Is -1. }
|
---|
682 |
|
---|
683 | Function FileRead(Handle: LongInt; Var Buffer; Count: LongInt): LongInt;
|
---|
684 |
|
---|
685 | { FileWrite - Attempts To Write up To Count Bytes To the given File
|
---|
686 | Handle And returns the Number Of Bytes actually written. If an Error
|
---|
687 | occurs, the Result Is -1. }
|
---|
688 |
|
---|
689 | Function FileWrite(Handle: LongInt; Const Buffer; Count: LongInt): LongInt;
|
---|
690 |
|
---|
691 | { FileSeek - changes the Current Position Of A File Handle by Count
|
---|
692 | Bytes. the actual Movement depends ON the Value Of Origin, according
|
---|
693 | To the following Table:
|
---|
694 |
|
---|
695 | Origin Action
|
---|
696 |
|
---|
697 | 0 Move relative To the file's beginning
|
---|
698 | 1 Move relative To the Current Position
|
---|
699 | 2 Move relative To the file's End
|
---|
700 |
|
---|
701 | the Function returns the New Position, Or -1 If an Error occured. }
|
---|
702 |
|
---|
703 | Function FileSeek(Handle: LongInt; Offset: LongInt; Origin: Integer): LongInt;
|
---|
704 |
|
---|
705 | { FileClose - Closes A File And frees the Handle. }
|
---|
706 |
|
---|
707 | Procedure FileClose(Handle: LongInt);
|
---|
708 |
|
---|
709 | { FileLock - Locks A Range Of A File For exclusive access by the
|
---|
710 | Application. returns A Boolean Value indicating Success Or
|
---|
711 | failure. note that the Function waits up To the Time specified
|
---|
712 | In the LockTimeout global variable before it fails. }
|
---|
713 |
|
---|
714 | Function FileLock(Handle, Offset, Range: LongInt): Boolean;
|
---|
715 |
|
---|
716 | { FileUnLock - Unlocks A Range Of A File that was previously locked
|
---|
717 | For exclusive access by the Application. returns A Boolean Value
|
---|
718 | indicating Success Or failure. }
|
---|
719 |
|
---|
720 | Function FileUnLock(Handle, Offset, Range: LongInt): Boolean;
|
---|
721 |
|
---|
722 | { FileAge - returns the date And Time Of A file's Last modification.
|
---|
723 |
|
---|
724 | If the File doesn't exist, -1 Is returned instead.
|
---|
725 |
|
---|
726 | To Use date / Time formatting FUNCTIONs For This Value, Convert it
|
---|
727 | To A TDateTime by A call To FileDateToDateTime First. }
|
---|
728 |
|
---|
729 | Function FileAge(Const FileName: String): LongInt;
|
---|
730 |
|
---|
731 | { FileExists - Indicates whether A File exists Or Not. }
|
---|
732 |
|
---|
733 | Function FileExists(Const FileName: String): Boolean;
|
---|
734 |
|
---|
735 | { FindFirst - Starts A Search For files specified by A Name Pattern
|
---|
736 | And File Attributes.
|
---|
737 |
|
---|
738 | any Pattern that Is allowed ON the Command Line Is also A legal
|
---|
739 | argument For Path.
|
---|
740 |
|
---|
741 | Attr Is A logical combination Of File Attributes (faXXX) And
|
---|
742 | File-MUST Attributes (faMustXXX), the latter being available only
|
---|
743 | under OS/2.
|
---|
744 |
|
---|
745 | the Var SearchRec will contain Name And Attributes Of the First File
|
---|
746 | that matched the given specs. In This Case the Function returns 0.
|
---|
747 | If an Error occurs, the Result Is the Negative Value Of the Error
|
---|
748 | Code returned by the operating System.
|
---|
749 |
|
---|
750 | Use FindNext To Find more files And FindClose To End the File
|
---|
751 | Search. note that you MUST Use FindClose, Or you may Run out Of
|
---|
752 | handles after A While. }
|
---|
753 |
|
---|
754 | Function FindFirst(Const Path: String; Attr: Integer; Var SearchRec: TSearchRec): LongInt;
|
---|
755 |
|
---|
756 | { FindNext - after A call To FindNext, the Var SearchRec Contains the
|
---|
757 | Next File that matches the specs Of A File Search previously started
|
---|
758 | by FindFirst.
|
---|
759 |
|
---|
760 | A return Value Of 0 Indicates Success. you may call FindNext Until
|
---|
761 | an Error occures (With the Negative Value Of the operating system's
|
---|
762 | Error Code returned), Or Until no more matching files are found
|
---|
763 | (usually indicated by A return Value Of -18.) }
|
---|
764 |
|
---|
765 | Function FindNext(Var SearchRec: TSearchRec): LongInt;
|
---|
766 |
|
---|
767 | { FindClose - Ends A File Search previously started by FindFirst. note
|
---|
768 | that you MUST Use FindClose, Or you may Run out Of handles after a
|
---|
769 | While. }
|
---|
770 |
|
---|
771 | Procedure FindClose(Var SearchRec: TSearchRec);
|
---|
772 |
|
---|
773 | { FileGetDate - returns the date And Time Of A file's Last
|
---|
774 | modification. If the given File Handle Is invalid, -1 Is returned
|
---|
775 | instead.
|
---|
776 |
|
---|
777 | To Use date / Time formatting FUNCTIONs For the Result, Convert
|
---|
778 | it To A TDateTime by A call To FileDateToDateTime First. }
|
---|
779 |
|
---|
780 | Function FileGetDate(Handle: LongInt): LongInt;
|
---|
781 |
|
---|
782 | { FileSetDate - changes the date And Time Of A file's Last
|
---|
783 | modification. If the Operation fails due To an invalid Handle Or
|
---|
784 | an illegal Age Parameter, the date And Time remain unchanged.
|
---|
785 |
|
---|
786 | This Procedure doesn't Accept TDateTime values. you have To Convert
|
---|
787 | them To A LongInt by DateTimeToFileDate First. }
|
---|
788 |
|
---|
789 | Procedure FileSetDate(Handle: Integer; Age: LongInt);
|
---|
790 |
|
---|
791 | { FileGetAttr - returns A file's Attributes. the Result Value Is a
|
---|
792 | logical combination Of File attribute constants (faXXX). If the
|
---|
793 | Function fails due To A non-existing File Or another Error
|
---|
794 | condition, the Result Is the Negative Value Of the operating
|
---|
795 | system's Error Code. }
|
---|
796 |
|
---|
797 | Function FileGetAttr(Const FileName: String): LongInt;
|
---|
798 |
|
---|
799 | { FileSetAttr - changes A file's Attributes. the Attr Parameter may
|
---|
800 | contain any logical combination Of File attribute constants
|
---|
801 | (faXXX). A Result Value Of 0 Indicates Success. If the Function
|
---|
802 | fails due To A non-existing File Or another Error condition, the
|
---|
803 | Result Is the Negative Value Of the operating system's Error Code. }
|
---|
804 |
|
---|
805 | Function FileSetAttr(Const FileName: String; Attr: Integer): Integer;
|
---|
806 |
|
---|
807 | { CopyFile - copies A File. Result Is A Boolean indicating Success Or
|
---|
808 | failure. }
|
---|
809 |
|
---|
810 | Function CopyFile(Const SourceName, DestName: String): Boolean;
|
---|
811 |
|
---|
812 | { DeleteFile - deletes A File. Result Is A Boolean indicating Success
|
---|
813 | Or failure. }
|
---|
814 |
|
---|
815 | Function DeleteFile(Const FileName: String): Boolean;
|
---|
816 |
|
---|
817 | { RenameFile - Renames A File. Result Is A Boolean indicating Success
|
---|
818 | Or failure. you may Use RenameFile To Move A File To A New location,
|
---|
819 | but only If the Drive stays the same. }
|
---|
820 |
|
---|
821 | Function RenameFile(Const OldName, NewName: String): Boolean;
|
---|
822 |
|
---|
823 | { ChangeFileExt - changes the extension Of A given FileName. the
|
---|
824 | extension Is the part from the rightmost dot To the End Of the
|
---|
825 | FileName. If the old FileName doesn't contain an extension, it
|
---|
826 | Is simply added. the extension MUST Start With A dot.
|
---|
827 |
|
---|
828 | note that the Function only handles A String, but does Not Perform
|
---|
829 | any Physical changes To files. }
|
---|
830 |
|
---|
831 | Function ChangeFileExt(Const FileName, extension: String): String;
|
---|
832 |
|
---|
833 | { ExtractFilePath - returns the Drive And Directory parts Of a
|
---|
834 | FileName, that Is, everything from the Start To the rightmost colon
|
---|
835 | Or backslash In the String. If the FileName doesn't contain Drive Or
|
---|
836 | Directory information, an Empty String Is returned. }
|
---|
837 |
|
---|
838 | Function ExtractFilePath(Const FileName: String): String;
|
---|
839 |
|
---|
840 | { ExtractFileName - returns the Name And extension parts Of A
|
---|
841 | FileName, that Is, everything from rightmost colon Or backslash To
|
---|
842 | the End Of the String. If the FileName doesn't contain A Name Or
|
---|
843 | extension, an Empty String Is returned. }
|
---|
844 |
|
---|
845 | Function ExtractFileName(Const FileName: String): String;
|
---|
846 |
|
---|
847 | { ExtractFileExt - returns the extension part Of A FileName, that Is,
|
---|
848 | everything from rightmost dot To the End Of the String. If the
|
---|
849 | FileName doesn't contain A dot, an Empty String Is returned. }
|
---|
850 |
|
---|
851 | Function ExtractFileExt(Const FileName: String): String;
|
---|
852 |
|
---|
853 | { ConcatFileName - Concatenates two filenames, assuming the First
|
---|
854 | one specifies Some Kind Of Directory information, And the Second
|
---|
855 | one A FileName. the Result Is A Complete legal pathname. the
|
---|
856 | Function automatically inserts A backslash, If necessary. }
|
---|
857 |
|
---|
858 | Function ConcatFileName(Const pathname, FileName: String): String;
|
---|
859 |
|
---|
860 | { ExpandFileName - Expands A FileName To an Absolute FileName, that
|
---|
861 | Is, A FileName containing A Drive letter, Directory information
|
---|
862 | relative To the root Of the Drive, And the FileName. Embedded '..'
|
---|
863 | are removed. }
|
---|
864 |
|
---|
865 | Function ExpandFileName(FileName: String): String;
|
---|
866 |
|
---|
867 | { EditFileName - changes A FileName using A Pattern possibly
|
---|
868 | containing the wildcards '*' And '?'. everything that would
|
---|
869 | be Accepted by the Copy Command should be legal For Name And
|
---|
870 | edit. }
|
---|
871 |
|
---|
872 | Function EditFileName(Const Name, edit: String): String;
|
---|
873 |
|
---|
874 | { FileSearch - Searches For A File Name In A List Of directories
|
---|
875 | given by DirList. the Directory entries MUST be separated by
|
---|
876 | semicolons, just like the system's Path. the working Directory
|
---|
877 | Is implicitly prepended To the List Of directories. the Result
|
---|
878 | String Is either the First occurence Of the File Complete With
|
---|
879 | the Directory it was found In, Or the Empty String, If the File
|
---|
880 | could Not be found. }
|
---|
881 |
|
---|
882 | Function FileSearch(Const Name, DirList: String): String;
|
---|
883 |
|
---|
884 | { DiskFree - returns the Free space Of the given disk Drive. Drive 0
|
---|
885 | Is the Current Drive, Drive 1 Is 'A:', And So ON. If the given Drive
|
---|
886 | Is invalid Or cannot be Read, -1 Is returned, Otherwise the Result
|
---|
887 | Contains the Number Of Bytes Free. }
|
---|
888 |
|
---|
889 | Function DiskFree(Drive: Byte): LongInt;
|
---|
890 |
|
---|
891 | { DiskSize - returns the disk Size Of the given disk Drive. Drive 0
|
---|
892 | Is the Current Drive, Drive 1 Is 'A:', And So ON. If the given Drive
|
---|
893 | Is invalid Or cannot be Read, -1 Is returned, Otherwise the Result
|
---|
894 | Contains the Number Of Bytes that can be potentially used For File
|
---|
895 | storage. }
|
---|
896 |
|
---|
897 | Function DiskSize(Drive: Byte): LongInt;
|
---|
898 |
|
---|
899 | { FileDateToDateTime - Converts A File date / Time Value To a
|
---|
900 | TDateTime that can be used within formatting operations. }
|
---|
901 |
|
---|
902 | Function FileDateToDateTime(FileDate: LongInt): TDateTime;
|
---|
903 |
|
---|
904 | { FileDateToDateTime - Converts A TDateTime To A File date / Time
|
---|
905 | Value that can be used within File FUNCTIONs. }
|
---|
906 |
|
---|
907 | Function DateTimeToFileDate(DateTime: TDateTime): LongInt;
|
---|
908 |
|
---|
909 | { --- 'C'-like String Handling --- }
|
---|
910 |
|
---|
911 | { StrLen - returns the Length Of Str, ignoring the terminating Zero. }
|
---|
912 |
|
---|
913 | Function StrLen(Str: PChar): Cardinal;
|
---|
914 |
|
---|
915 | { StrEnd - returns A Pointer To the terminating Zero Of Str. }
|
---|
916 |
|
---|
917 | Function StrEnd(Str: PChar): PChar;
|
---|
918 |
|
---|
919 | { StrMove - copies exactly Count characters from Source To Dest. It's
|
---|
920 | okay when Source And Dest overlap, StrMove can Handle This. }
|
---|
921 |
|
---|
922 | Function StrMove(Dest, Source: PChar; Count: Cardinal): PChar;
|
---|
923 |
|
---|
924 | { StrCopy - copies Source To Dest And returns Dest. }
|
---|
925 |
|
---|
926 | Function StrCopy(Dest, Source: PChar): PChar;
|
---|
927 |
|
---|
928 | { StrECopy - copies Source To Dest And returns A Pointer To the
|
---|
929 | terminating Zero Of the resulting String. }
|
---|
930 |
|
---|
931 | Function StrECopy(Dest, Source: PChar): PChar;
|
---|
932 |
|
---|
933 | { StrLCopy - copies A maximum Of MaxLen characters from Source To Dest
|
---|
934 | And returns Dest. }
|
---|
935 |
|
---|
936 | Function StrLCopy(Dest, Source: PChar; MaxLen: Cardinal): PChar;
|
---|
937 |
|
---|
938 | { StrPCopy - copies A Pascal String Source To A PChar Dest And returns
|
---|
939 | Dest. }
|
---|
940 |
|
---|
941 | Function StrPCopy(Dest: PChar; Const Source: String): PChar;
|
---|
942 |
|
---|
943 | { StrPLCopy - copies A maximum Of MaxLen characters from A Pascal
|
---|
944 | String Source To A PChar Dest. returns Dest. }
|
---|
945 |
|
---|
946 | Function StrPLCopy(Dest: PChar; Const Source: String; MaxLen: Cardinal): PChar;
|
---|
947 |
|
---|
948 | { StrCat - Concatenates Dest And Source, that Is, Appends Source To
|
---|
949 | the End Of Dest, And returns Dest. }
|
---|
950 |
|
---|
951 | Function StrCat(Dest, Source: PChar): PChar;
|
---|
952 |
|
---|
953 | { StrLCat - Concatenates Dest And Source, that Is, Appends Source To
|
---|
954 | the End Of Dest, but copies only So many characters that the
|
---|
955 | resulting String does Not exceed MaxLen characters. returns Dest. }
|
---|
956 |
|
---|
957 | Function StrLCat(Dest, Source: PChar; MaxLen: Cardinal): PChar;
|
---|
958 |
|
---|
959 | { StrComp - Compares two Strings And returns an Integer Value
|
---|
960 | As In the following Table:
|
---|
961 |
|
---|
962 | Str1 < Str2 Result < 0
|
---|
963 | Str1 = Str2 Result = 0
|
---|
964 | Str1 > Str2 Result > 0
|
---|
965 |
|
---|
966 | StrComp Is Case-sensitive, but does Not take international Special
|
---|
967 | characters Or the Currently Selected codepage into account. }
|
---|
968 |
|
---|
969 | Function StrComp(Str1, Str2: PChar): Integer;
|
---|
970 |
|
---|
971 | { StrIComp - Compares two Strings And returns an Integer Value
|
---|
972 | As In the following Table:
|
---|
973 |
|
---|
974 | Str1 < Str2 Result < 0
|
---|
975 | Str1 = Str2 Result = 0
|
---|
976 | Str1 > Str2 Result > 0
|
---|
977 |
|
---|
978 | StrComp Is Case-insensitive, And does Not take international
|
---|
979 | Special characters Or the Currently Selected codepage into account. }
|
---|
980 |
|
---|
981 | Function StrIComp(Str1, Str2: PChar): Integer;
|
---|
982 |
|
---|
983 | { StrLComp - Compares up To MaxLen characters Of two Strings And
|
---|
984 | returns an Integer Value As In the following Table:
|
---|
985 |
|
---|
986 | Str1 < Str2 Result < 0
|
---|
987 | Str1 = Str2 Result = 0
|
---|
988 | Str1 > Str2 Result > 0
|
---|
989 |
|
---|
990 | StrLComp Is Case-sensitive, but does Not take international Special
|
---|
991 | characters Or the Currently Selected codepage into account. }
|
---|
992 |
|
---|
993 | Function StrLComp(Str1, Str2: PChar; MaxLen: Cardinal): Integer;
|
---|
994 |
|
---|
995 | { StrLIComp - Compares up To MaxLen characters Of two Strings And
|
---|
996 | returns an Integer Value As In the following Table:
|
---|
997 |
|
---|
998 | Str1 < Str2 Result < 0
|
---|
999 | Str1 = Str2 Result = 0
|
---|
1000 | Str1 > Str2 Result > 0
|
---|
1001 |
|
---|
1002 | StrLComp Is Case-insensitive, And does Not take international
|
---|
1003 | Special characters Or the Currently Selected codepage into account. }
|
---|
1004 |
|
---|
1005 | Function StrLIComp(Str1, Str2: PChar; MaxLen: Cardinal): Integer;
|
---|
1006 |
|
---|
1007 | { StrScan - Searches For the First occurence Of A character In A
|
---|
1008 | String. returns the Pointer To the occurence, Or Nil, If the
|
---|
1009 | character cannot be found. }
|
---|
1010 |
|
---|
1011 | Function StrScan(Str: PChar; Chr: Char): PChar;
|
---|
1012 |
|
---|
1013 | { StrRScan - Searches For the Last occurence Of A character In A
|
---|
1014 | String. returns the Pointer To the occurence, Or Nil, If the
|
---|
1015 | character cannot be found. }
|
---|
1016 |
|
---|
1017 | Function StrRScan(Str: PChar; Chr: Char): PChar;
|
---|
1018 |
|
---|
1019 | { StrScan - Searches For the First occurence Of A SubStr In A given
|
---|
1020 | String Str. returns the Pointer To the occurence, Or Nil, If the
|
---|
1021 | SubStr cannot be found. }
|
---|
1022 |
|
---|
1023 | Function StrPos(Str, SubStr: PChar): PChar;
|
---|
1024 |
|
---|
1025 | { StrUpper - Converts A String To upper Case by simply Changing All
|
---|
1026 | occurences Of 'a'..'z' To the corresponding upper Case characters.
|
---|
1027 | returns A Pointer To the String. changes the Source String, does
|
---|
1028 | Not Create A New String. does also Not take international Special
|
---|
1029 | characters Or the Currently Selected codepage into account. }
|
---|
1030 |
|
---|
1031 | Function StrUpper(Str: PChar): PChar;
|
---|
1032 |
|
---|
1033 | { StrLower - Converts A String To lower Case by simply Changing All
|
---|
1034 | occurences Of 'A'..'Z' To the corresponding lower Case characters.
|
---|
1035 | returns A Pointer To the String. changes the Source String, does
|
---|
1036 | Not Create A New String. does also Not take international Special
|
---|
1037 | characters Or the Currently Selected codepage into account. }
|
---|
1038 |
|
---|
1039 | Function StrLower(Str: PChar): PChar;
|
---|
1040 |
|
---|
1041 | { StrPas - Converts A PChar Str To A Pascal String. }
|
---|
1042 |
|
---|
1043 | Function StrPas(Str: PChar): String;
|
---|
1044 |
|
---|
1045 | { StrAlloc - Allocates A block Of Memory For storing PChars. the Size
|
---|
1046 | Is specified And stored In A Double Word that preceeds the Buffer.
|
---|
1047 | Use StrDispose To Free the Buffer. }
|
---|
1048 |
|
---|
1049 | Function StrAlloc(Size: Cardinal): PChar;
|
---|
1050 |
|
---|
1051 | { StrBufSize - returns the Size Of A PChar Buffer that has been
|
---|
1052 | previously allocated by StrAlloc. }
|
---|
1053 |
|
---|
1054 | Function StrBufSize(Str: PChar): Cardinal;
|
---|
1055 |
|
---|
1056 | { StrNew - creates A Copy Of A given String. In contrast To StrCopy,
|
---|
1057 | StrNew Allocates A Memory block that can hold the String, by a
|
---|
1058 | call To StrAlloc. Then it copies the Source String. the New
|
---|
1059 | String can be disposed by A call To StrDispose. }
|
---|
1060 |
|
---|
1061 | Function StrNew(Str: PChar): PChar;
|
---|
1062 |
|
---|
1063 | { StrDispose - Disposes A PChar Buffer that has been previously
|
---|
1064 | allocated by A call To StrAlloc. }
|
---|
1065 |
|
---|
1066 | Procedure StrDispose(Str: PChar);
|
---|
1067 |
|
---|
1068 | { --- String formatting --- }
|
---|
1069 |
|
---|
1070 | { format - formats A String And replaces placeholders by arguments.
|
---|
1071 |
|
---|
1072 | the format String can contain arbitrary Text. This Text Is simply
|
---|
1073 | copied into the Result. everything that Starts With A '%' Is
|
---|
1074 | considered A placeholder. placeholders are replaced by the
|
---|
1075 | Parameters given In the variant-Type Open-Array Args. the First
|
---|
1076 | placeholder Is replaced by the First argument, the Second one
|
---|
1077 | by the Second argument, And So ON. you MUST specify At least As many
|
---|
1078 | Parameters As there are placeholders, Otherwise an Exception
|
---|
1079 | EConvertError will be raised.
|
---|
1080 |
|
---|
1081 | the way A placeholder / argument pair will be Handled Is controlled
|
---|
1082 | by Some optional specifiers. the Line below shows the possibilities.
|
---|
1083 |
|
---|
1084 | Text In " " MUST appear literally, 'index', 'width' And 'precision'
|
---|
1085 | MUST be replaced by Integer numbers, And 'type' MUST be replaced by
|
---|
1086 | A character that specifies the argument Type.
|
---|
1087 |
|
---|
1088 | parts enclosed In angular brackets are optional, the angular
|
---|
1089 | brackets MUST Not appear In the format specifier, they are only used
|
---|
1090 | To Show the syntax.
|
---|
1091 |
|
---|
1092 | "%" [Index ":"] ["-"] [Width] ["." Precision] Type
|
---|
1093 |
|
---|
1094 | the different parts Of the format specifier MUST appear In the
|
---|
1095 | given order, And they have the following meaning:
|
---|
1096 |
|
---|
1097 | "%" Begins the format specifier
|
---|
1098 |
|
---|
1099 | Index ":" takes the Next argument from the Array entry
|
---|
1100 | given by Integer Value Index. Normally the
|
---|
1101 | arguments are used one after the other. This
|
---|
1102 | part Of the format specifier allows To Change
|
---|
1103 | This behaviour.
|
---|
1104 |
|
---|
1105 | "-" Left-Justifies the Text inserted For the format
|
---|
1106 | specifier. Normally the Text Is justified To
|
---|
1107 | the Right. only applies If the String Is Left-
|
---|
1108 | padded With spaces by the Width-specifier.
|
---|
1109 |
|
---|
1110 | Width Integer Value that specifies the Width being
|
---|
1111 | reserved For the argument. If the String
|
---|
1112 | resulting from the conversion Of the argument
|
---|
1113 | Contains less than Width characters, it Is
|
---|
1114 | Left padded With spaces To achieve This minimum
|
---|
1115 | Length. If "-" Is used To Activate Left-
|
---|
1116 | justification, the String Is padded To the
|
---|
1117 | Right rather than To the Left. If the String
|
---|
1118 | already has A Length equal To Or greater than
|
---|
1119 | Width, no padding Is Needed.
|
---|
1120 |
|
---|
1121 | "." Precision Integer Value that specifies the Precision
|
---|
1122 | used when converting the argument. the actual
|
---|
1123 | consequences Of Precision depend ON the
|
---|
1124 | argument Type. See descriptions below For
|
---|
1125 | Details.
|
---|
1126 |
|
---|
1127 | the Index, Width, And Precision specifiers can also contain an
|
---|
1128 | asterisk ('*'). In This Case, the Real Value Is taken from the
|
---|
1129 | Next argument Array entry, which has To be an Integer Value, Or
|
---|
1130 | EConvertError will be raised.
|
---|
1131 |
|
---|
1132 | following are the characters allowed To specify the argument Type.
|
---|
1133 | note that 'decimal point' And 'thousand separator' mean that the
|
---|
1134 | characters contained In the global variables DecimalSeparator And
|
---|
1135 | ThousandSeparator will be inserted.
|
---|
1136 |
|
---|
1137 | D DECIMAL format. the corresponding argument MUST
|
---|
1138 | be an Integer Value, Otherwise EConvertError Is
|
---|
1139 | raised. the argument Is converted To A DECIMAL
|
---|
1140 | String. If A Precision Is specified, the String
|
---|
1141 | Is guaranteed To have At least A Number Of
|
---|
1142 | Digits equal To Precision. If the String Is
|
---|
1143 | shorter, it Is padded With zeroes.
|
---|
1144 |
|
---|
1145 | E Scientific (exponential) format. the
|
---|
1146 | corresponding argument MUST be A floating Point
|
---|
1147 | Value, Otherwise EConvertError Is raised. the
|
---|
1148 | argument Is converted To A DECIMAL String using
|
---|
1149 | Scientific notation. the String Starts With a
|
---|
1150 | minus sign, If the argument Is Negative. one
|
---|
1151 | digit always precedes the DECIMAL Point. the
|
---|
1152 | Number Of Digits following the DECIMAL Point Is
|
---|
1153 | controlled by the optional Precision specifier.
|
---|
1154 | the total Number Of Digits Is always equal To
|
---|
1155 | Precision. If Precision Is Not specified, a
|
---|
1156 | Default Of 15 Is assumed, resulting In 1 digit
|
---|
1157 | before And 14 after the DECIMAL Point.
|
---|
1158 | following Is the exponential 'E' With A plus Or
|
---|
1159 | A minus sign And up To 3 Digits indicating the
|
---|
1160 | Exponent.
|
---|
1161 |
|
---|
1162 | F FIXED Point format. the corresponding argument
|
---|
1163 | MUST be A floating Point Value, Otherwise
|
---|
1164 | EConvertError Is raised. the argument Is
|
---|
1165 | converted To A String using FIXED notation. it
|
---|
1166 | Starts With A minus sign, If the argument Is
|
---|
1167 | Negative. All Digits Of the argument's Integer
|
---|
1168 | part appear In the Result. following Is a
|
---|
1169 | DECIMAL separator And A Number Of Digits equal
|
---|
1170 | To Precision. If no Precision Is specified, a
|
---|
1171 | Default Of 2 DECIMAL places Is assumed.
|
---|
1172 |
|
---|
1173 | G General Number format. the argument MUST be a
|
---|
1174 | floating Point Value, Otherwise EConvertError
|
---|
1175 | Is raised. the argument Is converted To a
|
---|
1176 | String using either FIXED Or Scientific format,
|
---|
1177 | depending ON which results In A shorter String.
|
---|
1178 | the optional Precision specifier Controls the
|
---|
1179 | Number Of significant Digits (used For
|
---|
1180 | rounding) With A Default Of 15. the Result will
|
---|
1181 | contain neither unnecessary zeroes nor an
|
---|
1182 | unnecessary DECIMAL Point. If the argument
|
---|
1183 | Value Is greater than Or equal To 0.00001, And
|
---|
1184 | If the Number Of Digits To the Left Of the
|
---|
1185 | DECIMAL Point Is less than Or equal To the
|
---|
1186 | Precision, FIXED format Is used. Otherwise the
|
---|
1187 | Result Uses Scientific format.
|
---|
1188 |
|
---|
1189 | M currency (money) format. the corresponding
|
---|
1190 | argument MUST be A floating Point Value,
|
---|
1191 | Otherwise EConvertError Is raised. the argument
|
---|
1192 | Is converted To A String using the following
|
---|
1193 | global variables:
|
---|
1194 |
|
---|
1195 | CurrencyString
|
---|
1196 | CurrencyFormat
|
---|
1197 | NegCurrFormat
|
---|
1198 | CurrencyDecimals
|
---|
1199 |
|
---|
1200 | If A Precision Is specified, it overrides the
|
---|
1201 | Default Value Of CurrencyDecimals.
|
---|
1202 |
|
---|
1203 | N Number format. equal To FIXED, but the Result
|
---|
1204 | String will contain thousand separators.
|
---|
1205 |
|
---|
1206 | P Pointer format. the corresponding argument MUST
|
---|
1207 | be A Pointer Value, Otherwise EConvertError Is
|
---|
1208 | raised. the Value Is converted To A String
|
---|
1209 | containing the hexadecimal representation Of
|
---|
1210 | the Pointer, With an additional ':' In the
|
---|
1211 | middle. the resulting String has always a
|
---|
1212 | Length Of 9 characters. since we are dealing
|
---|
1213 | With flat Memory model, we have A full 32-bit
|
---|
1214 | Pointer With no segment part, only Offset.
|
---|
1215 |
|
---|
1216 | S String format. the corresponding argument MUST
|
---|
1217 | be A Single character, A String Or A PChar Value,
|
---|
1218 | Otherwise EConvertError Is raised. the argument
|
---|
1219 | Is simply copied To the destination String. If
|
---|
1220 | A Precision Is specified, it Is considered the
|
---|
1221 | maximum Length Of the argument String. longer
|
---|
1222 | Strings will be truncated.
|
---|
1223 |
|
---|
1224 | X hexadecimal format. the corresponding argument
|
---|
1225 | MUST be an Integer Value, Otherwise EConvertError
|
---|
1226 | Is raised. the argument Is converted To a
|
---|
1227 | hexadecimal String. If A Precision Is specified,
|
---|
1228 | the String Is guaranteed To have At least a
|
---|
1229 | Number Of Digits equal To Precision. If the
|
---|
1230 | String Is shorter, it Is padded With zeroes. }
|
---|
1231 |
|
---|
1232 | Function format(Const format: String; Const Args: Array Of Const): String;
|
---|
1233 |
|
---|
1234 | { FmtStr - formats A String And replaces placeholders by arguments.
|
---|
1235 | See format For A detailed description Of the format String And the
|
---|
1236 | argument Array. }
|
---|
1237 |
|
---|
1238 | Procedure FmtStr(Var Result: String; Const format: String;
|
---|
1239 | Const Args: Array Of Const);
|
---|
1240 |
|
---|
1241 | { StrFmt - formats A String And replaces placeholders by arguments.
|
---|
1242 | note that the Buffer MUST be large enough To hold the Complete
|
---|
1243 | Result, Otherwise A protection fault (EGPFault) may occur. See
|
---|
1244 | format For A detailed description Of the format String And the
|
---|
1245 | argument Array. }
|
---|
1246 |
|
---|
1247 | Function StrFmt(Buffer, format: PChar; Const Args: Array Of Const): PChar;
|
---|
1248 |
|
---|
1249 | { StrLFmt - formats A String And replaces placeholders by arguments.
|
---|
1250 | the Function ensures that the Size Of the Output String written into
|
---|
1251 | Buffer won't exceed MaxLen characters. the function's Result Is also
|
---|
1252 | A Pointer To Buffer. See format For A detailed description Of the
|
---|
1253 | format String And the argument Array. }
|
---|
1254 |
|
---|
1255 | Function StrLFmt(Buffer: PChar; MaxLen: Cardinal; format: PChar;
|
---|
1256 | Const Args: Array Of Const): PChar;
|
---|
1257 |
|
---|
1258 | { FormatBuf - formats A String And replaces placeholders by arguments.
|
---|
1259 | format And Buffer Strings are given As untyped Var / Const
|
---|
1260 | Parameters. their sizes are given In BufLen And FmtLen. the Function
|
---|
1261 | ensures that the Size Of the Output String written into Buffer won't
|
---|
1262 | exceed BufLen characters. the Result Value Is the Number Of
|
---|
1263 | characters actually written into Buffer. See format For A detailed
|
---|
1264 | description Of the format String And the argument Array. }
|
---|
1265 |
|
---|
1266 | Function FormatBuf(Var Buffer; BufLen: Cardinal; Const format;
|
---|
1267 | FmtLen: Cardinal; Const Args: Array Of Const): Cardinal;
|
---|
1268 |
|
---|
1269 | { --- floating Point conversion --- }
|
---|
1270 |
|
---|
1271 | { FloatToStrF - Converts A floating Point Number To A String. the
|
---|
1272 | appearance Of the Result String can be controlled by specifying
|
---|
1273 | A basic format To apply, A Precision, And A Number Of Digits.
|
---|
1274 | the Precision Parameter should be less than Or equal To 18. the
|
---|
1275 | meaning Of the Digits Parameter depends ON the format chosen.
|
---|
1276 |
|
---|
1277 | following Is A detailed description Of the possible formats:
|
---|
1278 |
|
---|
1279 | ffCurrency money (currency) format. the argument Is converted
|
---|
1280 | To A String using the following global variables:
|
---|
1281 |
|
---|
1282 | CurrencyString
|
---|
1283 | CurrencyFormat
|
---|
1284 | NegCurrFormat
|
---|
1285 |
|
---|
1286 | the Digits Parameter specifies the Number Of Digits
|
---|
1287 | following the DECIMAL Point (0 To 18 being legal
|
---|
1288 | values).
|
---|
1289 |
|
---|
1290 | ffExponent Scientific (exponential) format. the argument Is
|
---|
1291 | converted To A DECIMAL String using Scientific
|
---|
1292 | notation. the String Starts With A minus sign, If
|
---|
1293 | the argument Is Negative. one digit precedes the
|
---|
1294 | DECIMAL Point. the Number Of Digits following the
|
---|
1295 | DECIMAL Point Is controlled by Precision. the total
|
---|
1296 | Number Of Digits Is always equal To Precision.
|
---|
1297 | following Is the exponential 'E' With A plus Or a
|
---|
1298 | minus sign And the Exponent With A minimum Length
|
---|
1299 | Of Digits characters (0 To 4 being legal values).
|
---|
1300 |
|
---|
1301 | ffFixed FIXED Point format. the argument Is converted To a
|
---|
1302 | String using FIXED Point notation. it Starts With a
|
---|
1303 | minus sign, If the argument Is Negative. All Digits
|
---|
1304 | Of the argument's Integer part appear In the Result.
|
---|
1305 | following Is A comma And A Number Of DECIMAL Digits
|
---|
1306 | equal To Digits (0 To 18 being legal values). If
|
---|
1307 | the Number Of Digits To the Left Of the DECIMAL
|
---|
1308 | Point Is greater than Precision, the Output will be
|
---|
1309 | In Scientific format.
|
---|
1310 |
|
---|
1311 | ffGeneral General Number format. the argument Is converted
|
---|
1312 | To A String using either FIXED Or Scientific
|
---|
1313 | format, depending ON which results In A shorter
|
---|
1314 | String. the Result will contain neither trailing
|
---|
1315 | zeroes nor an unnecessary DECIMAL Point. If the
|
---|
1316 | argument Value Is greater than Or equal To 0.00001,
|
---|
1317 | And If the Number Of Digits To the Left Of the
|
---|
1318 | DECIMAL Point Is less than Or equal To Precision,
|
---|
1319 | FIXED format Is used. Otherwise the Result Is
|
---|
1320 | formatted In Scientific format With Digits
|
---|
1321 | specifying the minimum Number Of Digits In the
|
---|
1322 | Exponent (0 To 4 being legal values).
|
---|
1323 |
|
---|
1324 | ffNumber Number format. equal To FIXED, but the Result
|
---|
1325 | String will contain thousand separators.
|
---|
1326 |
|
---|
1327 | If the Value Is Not-A-Number, positive infinity, Or Negative
|
---|
1328 | infinity, Then the Output String will also be NAN, INF, Or -INF. }
|
---|
1329 |
|
---|
1330 | Function FloatToStrF(Value: Extended; format: TFloatFormat;
|
---|
1331 | Precision, Digits: Integer): String;
|
---|
1332 |
|
---|
1333 | { FloatToStr - Converts A floating Point Value To A String using
|
---|
1334 | General Number format And 15 significant Digits. See FloatToStrF
|
---|
1335 | For more Details. }
|
---|
1336 |
|
---|
1337 | Function FloatToStr(Value: Extended): String;
|
---|
1338 |
|
---|
1339 | { FloatToText - Converts A floating Point Number To A String. the
|
---|
1340 | Result Is written To Buffer without A Zero teminator being
|
---|
1341 | appended. the caller has To ensure that the Buffer Is large
|
---|
1342 | enough To hold the Result. the Result can be controlled using
|
---|
1343 | format, Precision And Digits Parameters. See FloatToStrF For
|
---|
1344 | A detailed description Of these Parameters. }
|
---|
1345 |
|
---|
1346 | Function FloatToText(Buffer: PChar; Value: Extended; format: TFloatFormat;
|
---|
1347 | Precision, Digits: Integer): Integer;
|
---|
1348 |
|
---|
1349 | { FormatFloat - Converts A floating Point Value To A String using a
|
---|
1350 | specified format.
|
---|
1351 |
|
---|
1352 | the Parameter format Controls the appearance Of the Result String.
|
---|
1353 |
|
---|
1354 | format can contain up To three Sections, separated from each other
|
---|
1355 | by semicolons. the First section holds the format String used For
|
---|
1356 | positive values, the Second one holds the format For Negative
|
---|
1357 | values, And the third one Is applied To Zero values. If one Of
|
---|
1358 | the Sections Is missing Or Empty, the First section Is used
|
---|
1359 | instead. If All Sections are missing Or Empty, General Number
|
---|
1360 | format Is used With A Precision Of 15. See FloatToStrF For more
|
---|
1361 | Details about General Number format.
|
---|
1362 |
|
---|
1363 | each Of the three Sections can contain arbitrary Text, which Is
|
---|
1364 | simply copied To the Result String. Some characters have A Special
|
---|
1365 | meaning, they serve As placeholders For inserting Data from the
|
---|
1366 | Value Parameter.
|
---|
1367 |
|
---|
1368 | the following List shows All placeholders And their meaning:
|
---|
1369 |
|
---|
1370 | 0 Mandatory digit. If the Value has A digit At This
|
---|
1371 | Position, it Is copied To the Result. Otherwise a
|
---|
1372 | 0 Is inserted.
|
---|
1373 |
|
---|
1374 | # optional digit. If the Value has A digit At This
|
---|
1375 | Position, it Is copied To the Result. Otherwise
|
---|
1376 | This Position Of the format String will be ignored.
|
---|
1377 |
|
---|
1378 | . DECIMAL separator. the First occurence Of '.' In the
|
---|
1379 | format String determines the Position At which A DECIMAL
|
---|
1380 | separator will be inserted. the DECIMAL separator Is
|
---|
1381 | taken from the global variable DecimalSeparator. further
|
---|
1382 | occurences Of '.' will be ignored.
|
---|
1383 |
|
---|
1384 | , thousand separator. any occurence Of ',' activates the
|
---|
1385 | insertion Of thousand separators into the Result, where
|
---|
1386 | necessary. the thousand separator Is taken from the
|
---|
1387 | global variable DecimalSeparator.
|
---|
1388 |
|
---|
1389 | E+ E- Scientific (exponential) format. If any Of the four
|
---|
1390 | E+ E- Strings To the Left occur In the format String, the
|
---|
1391 | Result will be formatted using Scientific notation.
|
---|
1392 | the exponential E will have the same Case As In the
|
---|
1393 | format String. the Exponent itself will always be
|
---|
1394 | preceded by its sign, If E+ Or E+ are used. E- And E-
|
---|
1395 | contain A sign only If the Exponent Value Is Negative.
|
---|
1396 | up To four digit placeholders can be used To specify the
|
---|
1397 | minimum Number Of Digits used For the Exponent.
|
---|
1398 |
|
---|
1399 | '...' characters enclosed In Single Or Double quotes will
|
---|
1400 | "..." simply be copied To the Result (without quotes).
|
---|
1401 |
|
---|
1402 | the floating Point Value Is rounded With A Precision equal To the
|
---|
1403 | total Number Of digit placeholders In the format String. optional
|
---|
1404 | digit placeholders between the leftmost And rightmost Mandatory
|
---|
1405 | digit placeholders will be taken As Mandatory Digits, So it makes
|
---|
1406 | no sense To specify one ore more '#' between zeroes. If the rounded
|
---|
1407 | Value Contains more Digits In the Integer part than there are
|
---|
1408 | placeholders Left Of the DECIMAL separator, the additional Digits
|
---|
1409 | will be inserted before the First placeholder. }
|
---|
1410 |
|
---|
1411 | Function FormatFloat(Const format: String; Value: Extended): String;
|
---|
1412 |
|
---|
1413 | { FloatToTextFmt - Converts A floating Point Value To A String using a
|
---|
1414 | specified format. the Result Is written To Buffer without a
|
---|
1415 | terminating Zero. the caller has To ensure that the Buffer Is large
|
---|
1416 | enough To hold the Result. the Number Of characters actually written
|
---|
1417 | To Buffer Is returned. See FormatFloat For A description Of the
|
---|
1418 | format Parameter. }
|
---|
1419 |
|
---|
1420 | Function FloatToTextFmt(Buffer: PChar; Value: Extended;
|
---|
1421 | format: PChar): Integer;
|
---|
1422 |
|
---|
1423 | { StrToFloat - Converts A String To A floating Point Value. the String
|
---|
1424 | MUST contain A legal floating Point Value, With the DECIMAL Point
|
---|
1425 | being the same character As In the global variable DecimalSeparator.
|
---|
1426 | it MUST Not contain thousand separators Or currency symbols. leading
|
---|
1427 | And trailing spaces are allowed. If the String does Not conform
|
---|
1428 | these restrictions, EConvertError Is raised. }
|
---|
1429 |
|
---|
1430 | Function StrToFloat(Const S: String): Extended;
|
---|
1431 |
|
---|
1432 | { TextToFloat - Converts A Zero-Terminated String To A floating Point
|
---|
1433 | Value. the String MUST contain A legal floating Point Value, With
|
---|
1434 | the DECIMAL Point being the same character As In the global variable
|
---|
1435 | DecimalSeparator. it MUST Not contain thousand separators Or
|
---|
1436 | currency symbols. leading And trailing spaces are allowed. If the
|
---|
1437 | String does Not conform these restrictions, EConvertError Is raised. }
|
---|
1438 |
|
---|
1439 | Function TextToFloat(Buffer: PChar; Var Value: Extended): Boolean;
|
---|
1440 |
|
---|
1441 | { FloatToDecimal - Converts A floating Point Value To A TFloatRec
|
---|
1442 | Record which separates Digits, sign, And Exponent. the Precision
|
---|
1443 | Parameter specifies the Number Of significant Digits (With 1..18
|
---|
1444 | being legal values), the Decimals Parameter specifies the desired
|
---|
1445 | minimum Number Of Digits In the fractional part. rounding Is
|
---|
1446 | controlled by Precision As well As by Decimals. To force A Number
|
---|
1447 | Of significant Digits even With large values, specify 9999 For
|
---|
1448 | Decimals.
|
---|
1449 |
|
---|
1450 | the resulting TFloatRec will contain the following information:
|
---|
1451 |
|
---|
1452 | Exponent - the result's Exponent. an Exponent Value Of -32768
|
---|
1453 | Indicates that the Value Is Not-A-Number (NAN). positive Or
|
---|
1454 | Negative infinity (INF / -INF) Is indicated by an Exponent
|
---|
1455 | Value Of 32767.
|
---|
1456 |
|
---|
1457 | Negative - Indicates whether the Value Is Negative Or Not. Use
|
---|
1458 | This To distinguish positive from Negative infinity, too. Zero
|
---|
1459 | Is assumed To be non-Negative.
|
---|
1460 |
|
---|
1461 | Digits - Contains the significant Digits With A terminating
|
---|
1462 | Zero (Chr(0)). does Not contain the DECIMAL separator. Empty,
|
---|
1463 | If the Value Is Not-A-Number, Or positive, Or Negative infinity. }
|
---|
1464 |
|
---|
1465 | Procedure FloatToDecimal(Var Result: TFloatRec; Value: Extended;
|
---|
1466 | Precision, Decimals: Integer);
|
---|
1467 |
|
---|
1468 | { --- date / Time Handling --- }
|
---|
1469 |
|
---|
1470 | { EncodeDate - Encodes the given Year, Month, And Day into A Single
|
---|
1471 | TDateTime Value. the Result Contains the Number Of days passed since
|
---|
1472 | the 31-Dec-0000 And the given date, assuming Gregorian calendar has
|
---|
1473 | always been used. If any Parameter Contains an illegal Value,
|
---|
1474 | EConvertError Is raised. }
|
---|
1475 |
|
---|
1476 | Function EncodeDate(Year, Month, Day: Word): TDateTime;
|
---|
1477 |
|
---|
1478 | { EncodeTime - Encodes the given Hour, Minute, Second And millisecond
|
---|
1479 | into A Single TDateTime Value. the Result Contains the fractional
|
---|
1480 | part Of the Day passed since 00:00:00. it Is always A Value equal To
|
---|
1481 | Or greater than Zero And And smaller that one. If any Parameter
|
---|
1482 | Contains an illegal Value, EConvertError Is raised. }
|
---|
1483 |
|
---|
1484 | Function EncodeTime(Hour, Min, Sec, MSec: Word): TDateTime;
|
---|
1485 |
|
---|
1486 | { DecodeDate - Extracts Year, Month, And Day from A given TDateTime
|
---|
1487 | Value. }
|
---|
1488 |
|
---|
1489 | Procedure DecodeDate(date: TDateTime; Var Year, Month, Day: Word);
|
---|
1490 |
|
---|
1491 | { DecodeTime - Extracts Hour, Minute, Second, And millisecond from a
|
---|
1492 | given TDateTime Value. }
|
---|
1493 |
|
---|
1494 | Procedure DecodeTime(Time: TDateTime; Var Hour, Min, Sec, MSec: Word);
|
---|
1495 |
|
---|
1496 | { DayOfWeek - Extracts the Day Of the week from A given TDateTime
|
---|
1497 | Value. the days are numbered from 1 To 7 In the following order:
|
---|
1498 |
|
---|
1499 | Sun / Mon / Tue / Wed / Thu / Fri / Sat }
|
---|
1500 |
|
---|
1501 | Function DayOfWeek(date: TDateTime): Integer;
|
---|
1502 |
|
---|
1503 | { date - Queries the Current System date. }
|
---|
1504 |
|
---|
1505 | Function date: TDateTime;
|
---|
1506 |
|
---|
1507 | { Time - Queries the Current System Time. }
|
---|
1508 |
|
---|
1509 | Function Time: TDateTime;
|
---|
1510 |
|
---|
1511 | { now - Queries the Current System date And Time. }
|
---|
1512 |
|
---|
1513 | Function now: TDateTime;
|
---|
1514 |
|
---|
1515 | { DateToStr - Converts the date part Of the given TDateTime Value
|
---|
1516 | To A String, using the format specified In the global variable
|
---|
1517 | ShortDateFormat. }
|
---|
1518 |
|
---|
1519 | Function DateToStr(date: TDateTime): String;
|
---|
1520 |
|
---|
1521 | { TimeToStr - Converts the Time part ao the given TDateTime Value
|
---|
1522 | To A String, using the format specified In the global variable
|
---|
1523 | LongTimeFormat. }
|
---|
1524 |
|
---|
1525 | Function TimeToStr(Time: TDateTime): String;
|
---|
1526 |
|
---|
1527 | { DateTimeToStr - Converts the given TDateTime Value To A String
|
---|
1528 | using the formats specified In the global variables ShortDateFormat
|
---|
1529 | And LongTimeFormat. the Time Is only appended, If the TDateTime
|
---|
1530 | Value Contains A (fractional) Time part different from 00:00:00. }
|
---|
1531 |
|
---|
1532 | Function DateTimeToStr(DateTime: TDateTime): String;
|
---|
1533 |
|
---|
1534 | { StrToDate - Tries To exctract date information from A String.
|
---|
1535 | the FUNCTIONs expects the String To contain two Or three numbers
|
---|
1536 | separated by the character given In the global variable
|
---|
1537 | DateSeparator. the order In which Day, Month, And Year are
|
---|
1538 | expected Is determined by the global variable DateOrder.
|
---|
1539 | If only two numbers are found, they are assumed To specify
|
---|
1540 | A Month And Day Of the Current Year. If the Year Is smaller
|
---|
1541 | than 100, it Is assumed To be A Year Of the Current century.
|
---|
1542 | If no legal date can be extracted from the String,
|
---|
1543 | EConvertError Is raised. }
|
---|
1544 |
|
---|
1545 | Function StrToDate(Const S: String): TDateTime;
|
---|
1546 |
|
---|
1547 | { StrToTime - Tries To exctract Time information from A String.
|
---|
1548 | the FUNCTIONs expects the String To contain two Or three numbers
|
---|
1549 | separated by the character given In the global variable
|
---|
1550 | TimeSeparator, optionally followed by 'AM' Or 'PM' To indicate
|
---|
1551 | 12-Hour format. the First two numbers are taken As Hour And
|
---|
1552 | Minute, the optional third one As Second. If no indicator For
|
---|
1553 | 12-Hour format Is found, the Time Is assumed To be In 24-Hour
|
---|
1554 | format. If no legal Time can be extracted from the String,
|
---|
1555 | EConvertError Is raised. }
|
---|
1556 |
|
---|
1557 | Function StrToTime(Const S: String): TDateTime;
|
---|
1558 |
|
---|
1559 | { StrToDateTime - Tries To extract date And Time information from A
|
---|
1560 | String. the Function expects the String To contain A date optionally
|
---|
1561 | followed by A Time. See StrToDate And StrToTime For more Details
|
---|
1562 | about the string's contents. If no legal date And Time can be
|
---|
1563 | extracted from the String, EConvertError Is raised. }
|
---|
1564 |
|
---|
1565 | Function StrToDateTime(Const S: String): TDateTime;
|
---|
1566 |
|
---|
1567 | { FormatDateTime - Converts A TDateTime Value To A String using a
|
---|
1568 | format specified by the Parameter format.
|
---|
1569 |
|
---|
1570 | the format String may contain arbitrary Text, which Is simply
|
---|
1571 | copies To the Result String. Some characters Or character
|
---|
1572 | sequences have A Special meaning, they serve As placeholders And
|
---|
1573 | are replaced by values extracted from DateTime.
|
---|
1574 |
|
---|
1575 | the following placeholders are allowed In the format String. their
|
---|
1576 | Case doesn't matter. If the format String Is Empty, 'c' Is assumed
|
---|
1577 | the Default format.
|
---|
1578 |
|
---|
1579 | C replaced by the date formatted As specified In the
|
---|
1580 | global variable ShortDateFormat. If the (fractional)
|
---|
1581 | Time part Is different from 00:00:00, the Time Is
|
---|
1582 | appended using the format specified In the global
|
---|
1583 | variable LongTimeFormat.
|
---|
1584 |
|
---|
1585 | D replaced by A Number indicating the Day Of the Month,
|
---|
1586 | With no leading Zero.
|
---|
1587 |
|
---|
1588 | dd replaced by A Number indicating the Day Of the Month,
|
---|
1589 | With leading Zero.
|
---|
1590 |
|
---|
1591 | ddd replaced by the Day Of the week's Name taken from the
|
---|
1592 | global Array ShortDayNames, resulting In an abbreviation
|
---|
1593 | Of the day's Name.
|
---|
1594 |
|
---|
1595 | dddd replaced by the Day Of the week's Name taken from the
|
---|
1596 | global Array LongDayNames, resulting In the day's full
|
---|
1597 | Name.
|
---|
1598 |
|
---|
1599 | ddddd replaced by the date formatted As specified In the
|
---|
1600 | global variable ShortDateFormat.
|
---|
1601 |
|
---|
1602 | dddddd replaced by the date formatted As specified In the
|
---|
1603 | global variable LongDateFormat.
|
---|
1604 |
|
---|
1605 | M when used immediately after an Hour placeholder,
|
---|
1606 | replaced by the Minute. Otherwise replaced by A
|
---|
1607 | Number indicating the Month. no leading zeroes.
|
---|
1608 |
|
---|
1609 | mm when used immediately after an Hour placeholder,
|
---|
1610 | replaced by the Minute. Otherwise replaced by A
|
---|
1611 | Number indicating the Month. leading zeroes.
|
---|
1612 |
|
---|
1613 | mmm replaced by the month's Name taken from the global Array
|
---|
1614 | ShortMonthNames, resulting In an abbreviation Of the
|
---|
1615 | month's Name.
|
---|
1616 |
|
---|
1617 | mmmm replaced by the month's Name taken from the global Array
|
---|
1618 | LongMonthNames, resulting In the month's full Name.
|
---|
1619 |
|
---|
1620 | yy replaced by two Digits indicating the Year. leading
|
---|
1621 | zeroes.
|
---|
1622 |
|
---|
1623 | yyyy replaced by four Digits indicating the Year. leading
|
---|
1624 | zeroes.
|
---|
1625 |
|
---|
1626 | H replaced by the Hour without leading Zero.
|
---|
1627 |
|
---|
1628 | hh replaced by the Hour With leading Zero.
|
---|
1629 |
|
---|
1630 | N replaced by the Minute without leading Zero.
|
---|
1631 |
|
---|
1632 | nn replaced by the Minute With leading Zero.
|
---|
1633 |
|
---|
1634 | S replaced by the Second without leading Zero.
|
---|
1635 |
|
---|
1636 | SS replaced by the Second With leading Zero.
|
---|
1637 |
|
---|
1638 | T replaced by the Time formatted As specified In the
|
---|
1639 | global variable ShortTimeFormat.
|
---|
1640 |
|
---|
1641 | tt replaced by the Time formatted As specified In the
|
---|
1642 | global variable LongTimeFormat.
|
---|
1643 |
|
---|
1644 | am/PM Indicates that 12-Hour format should be used For the
|
---|
1645 | preceding Hour placeholder. replaced by 'am' Or 'pm',
|
---|
1646 | depending ON the Time, With the same Case As specified.
|
---|
1647 |
|
---|
1648 | A/P Indicates that 12-Hour format should be used For the
|
---|
1649 | preceding Hour placeholder. replaced by 'a' Or 'p',
|
---|
1650 | depending ON the Time, With the same Case As specified.
|
---|
1651 |
|
---|
1652 | ampm Indicates that 12-Hour format should be used For the
|
---|
1653 | preceding Hour placeholder. replaced by A String taken
|
---|
1654 | from the global variables TimeAMString Or TimePMString,
|
---|
1655 | depending ON the Time.
|
---|
1656 |
|
---|
1657 | / replaced by the date separator As specified In the global
|
---|
1658 | variable DateSeparator.
|
---|
1659 |
|
---|
1660 | : replaced by the Time separator As specified In the global
|
---|
1661 | variable TimeSeparator.
|
---|
1662 |
|
---|
1663 | '...' characters enclosed In Single Or Double quotes will
|
---|
1664 | "..." simply be copied To the Result (without quotes). }
|
---|
1665 |
|
---|
1666 | Function FormatDateTime(Const format: String; DateTime: TDateTime): String;
|
---|
1667 |
|
---|
1668 | { DateTimeToString - Converts A TDateTime Value To A String using A
|
---|
1669 | format specified by the format Parameter . See FormatDateTime For
|
---|
1670 | A detailed description Of the format String. }
|
---|
1671 |
|
---|
1672 | Procedure DateTimeToString(Var Result: String; Const format: String;
|
---|
1673 | DateTime: TDateTime);
|
---|
1674 |
|
---|
1675 | { --- System profile support --- }
|
---|
1676 |
|
---|
1677 | {$IFDEF GUI}
|
---|
1678 |
|
---|
1679 | { GetProfileStr - Reads A String from the operating system's user
|
---|
1680 | profile. If section Or entry don't exist, A Default Value Is
|
---|
1681 | returned instead. }
|
---|
1682 |
|
---|
1683 | Function GetProfileStr(Const Section, Entry, Default: String): String;
|
---|
1684 |
|
---|
1685 | { GetProfileChar - Reads A character from the operating system's user
|
---|
1686 | profile. If section Or entry don't exist, A Default Value Is
|
---|
1687 | returned instead. }
|
---|
1688 |
|
---|
1689 | Function GetProfileChar(Const Section, Entry: String; Default: Char): Char;
|
---|
1690 |
|
---|
1691 | { GetProfileInt - Reads an Integer from the operating system's user
|
---|
1692 | profile. If section Or entry don't exist, A Default Value Is
|
---|
1693 | returned instead. }
|
---|
1694 |
|
---|
1695 | Function GetProfileInt(Const Section, Entry: string; Default: Integer): Integer;
|
---|
1696 |
|
---|
1697 | { GetFormatSettings - Queries A lot Of Default values used For
|
---|
1698 | formatting FUNCTIONs from the Operation System. called automatically
|
---|
1699 | In the SysUtils startup Code, So an Application that Uses SysUtils
|
---|
1700 | can always access these values immediately after Program startup. }
|
---|
1701 |
|
---|
1702 | {$ENDIF GUI}
|
---|
1703 |
|
---|
1704 | Procedure GetFormatSettings;
|
---|
1705 |
|
---|
1706 | { ConvertError - Raises EConvertError With the given Error Message. }
|
---|
1707 |
|
---|
1708 | Procedure ConvertError(Const Msg: String);
|
---|
1709 |
|
---|
1710 | { --- Some routines that belong into System.PAS --- }
|
---|
1711 |
|
---|
1712 | { SetLength - changes the Length Of A String. Please Use This
|
---|
1713 | Procedure instead Of writing S[0] := NewLength To maintain
|
---|
1714 | compatibility With the forthcoming LONG Strings that won't contain
|
---|
1715 | A Length-Byte any more. }
|
---|
1716 |
|
---|
1717 | { Procedure SetLength(Var S: String; NewLength: Byte); }
|
---|
1718 |
|
---|
1719 | { StringOfChars - returns A String that consists Of
|
---|
1720 | Count occurences Of the given character CH. }
|
---|
1721 |
|
---|
1722 | Function StringOfChars(CH: Char; Count: Integer): String;
|
---|
1723 |
|
---|
1724 | { SetCurrentLanguageTable - sets the Language Table Name To the specified Language.
|
---|
1725 | the Name MUST Start With "SIBYL_NLS_". A Table With the Name MUST exist. If the Table
|
---|
1726 | cannot be found Or Some other Error occurs This Function returns False, otherise True.
|
---|
1727 | by convention the Table MUST Include All Sibyl Default Language identifiers
|
---|
1728 | (See /Language Directory For examples).}
|
---|
1729 |
|
---|
1730 | Function SetCurrentLanguageTable(Const Table:String):Boolean;
|
---|
1731 |
|
---|
1732 | { GetCurrentLanguageTable - gets the Current Language Table Name. }
|
---|
1733 |
|
---|
1734 | Function GetCurrentLanguageTable:String;
|
---|
1735 |
|
---|
1736 | { GetCurrentLanguage - returns the Currently Set Language. the Language String Is
|
---|
1737 | retrieved from the Current Language Table With the "SLanguage" Index. This Function
|
---|
1738 | returns an Empty String ON Error. }
|
---|
1739 |
|
---|
1740 | Function GetCurrentLanguage:String;
|
---|
1741 |
|
---|
1742 | {GetPhysicalDrives - returns information about logical drives connected
|
---|
1743 | to the system. The drives are encoded bitwise starting with bit 0 for
|
---|
1744 | drive A. A enabled bit indicates that the appropriate drive is present}
|
---|
1745 | Function GetPhysicalDrives:LongWord;
|
---|
1746 |
|
---|
1747 | {$IFDEF WIN32}
|
---|
1748 | Procedure StrOemToAnsi(Var s:String);
|
---|
1749 | {$ENDIF}
|
---|
1750 |
|
---|
1751 | Implementation
|
---|
1752 |
|
---|
1753 | {$IFDEF WIN32}
|
---|
1754 | Procedure StrOemToAnsi(Var s:String);
|
---|
1755 | Var Found:Boolean;
|
---|
1756 | c:CString;
|
---|
1757 | Begin
|
---|
1758 | Found:=True;
|
---|
1759 | Asm
|
---|
1760 | MOV EDI,s
|
---|
1761 | MOVZXB ECX,[EDI]
|
---|
1762 | INC EDI
|
---|
1763 | CMP ECX,0
|
---|
1764 | JE !End1
|
---|
1765 | !Lo1:
|
---|
1766 | //Check for ä,ö,ü,Ä,Ö,Ü,ß
|
---|
1767 | CMPB [EDI],132
|
---|
1768 | JE !End2
|
---|
1769 | CMPB [EDI],142
|
---|
1770 | JE !End2
|
---|
1771 | CMPB [EDI],148
|
---|
1772 | JE !End2
|
---|
1773 | CMPB [EDI],153
|
---|
1774 | JE !End2
|
---|
1775 | CMPB [EDI],129
|
---|
1776 | JE !End2
|
---|
1777 | CMPB [EDI],154
|
---|
1778 | JE !End2
|
---|
1779 | CMPB [EDI],225
|
---|
1780 | JE !End2
|
---|
1781 |
|
---|
1782 | INC EDI
|
---|
1783 | LOOP !Lo1
|
---|
1784 | !End1:
|
---|
1785 | MOVB Found,0
|
---|
1786 | !End2:
|
---|
1787 | End;
|
---|
1788 |
|
---|
1789 | If Found Then
|
---|
1790 | Begin
|
---|
1791 | c:=s;
|
---|
1792 | OemToAnsi(c,c);
|
---|
1793 | s:=c;
|
---|
1794 | End;
|
---|
1795 | End;
|
---|
1796 | {$ENDIF}
|
---|
1797 |
|
---|
1798 | Uses
|
---|
1799 | Language;
|
---|
1800 |
|
---|
1801 |
|
---|
1802 | Function GetPhysicalDrives:LongWord;
|
---|
1803 | {$IFDEF OS2}
|
---|
1804 | Var
|
---|
1805 | ActualDrive:LongWord;
|
---|
1806 | {$ENDIF}
|
---|
1807 | Begin
|
---|
1808 | {$IFDEF OS2}
|
---|
1809 | DosQueryCurrentDisk(ActualDrive,Result);
|
---|
1810 | {$ENDIF}
|
---|
1811 | {$IFDEF Win95}
|
---|
1812 | result := GetLogicalDrives;
|
---|
1813 | {$ENDIF}
|
---|
1814 | End;
|
---|
1815 |
|
---|
1816 | { Current Language String Table identifier. Name has preceding SIBYL_NLS_ String !}
|
---|
1817 | Var
|
---|
1818 | CurrentLanguageTable:String;
|
---|
1819 |
|
---|
1820 | Function SetCurrentLanguageTable(Const Table:String):Boolean;
|
---|
1821 | Var P:Pointer;
|
---|
1822 | len:LongWord;
|
---|
1823 | Begin
|
---|
1824 | P:=FindStringTableRes(Table,len);
|
---|
1825 | Result:=P<>Nil;
|
---|
1826 | If Result Then CurrentLanguageTable:=Table;
|
---|
1827 | End;
|
---|
1828 |
|
---|
1829 | Function GetCurrentLanguageTable:String;
|
---|
1830 | Begin
|
---|
1831 | Result:=CurrentLanguageTable;
|
---|
1832 | End;
|
---|
1833 |
|
---|
1834 | Function GetCurrentLanguage:String;
|
---|
1835 | Begin
|
---|
1836 | Result:=LoadNLSStr(SLanguage);
|
---|
1837 | End;
|
---|
1838 |
|
---|
1839 | Const
|
---|
1840 |
|
---|
1841 | { Array With Number Of days passed since beginning Of the Year
|
---|
1842 | Until the 1st Of Every Month. used For date/Time conversions. }
|
---|
1843 |
|
---|
1844 | DaysPassed: Array[False..True, 1..13] Of Integer =
|
---|
1845 | ((0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365),
|
---|
1846 | (0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366));
|
---|
1847 |
|
---|
1848 | ShareModes = fmShareExclusive
|
---|
1849 | Or fmShareDenyRead
|
---|
1850 | Or fmShareDenyWrite
|
---|
1851 | Or fmShareDenyNone;
|
---|
1852 |
|
---|
1853 | Var
|
---|
1854 |
|
---|
1855 | { Collating sequence. Needed For sorting when OS/2 base API FUNCTIONs are used. }
|
---|
1856 |
|
---|
1857 | CollatingSequence: Array[#0..#255] Of Byte;
|
---|
1858 |
|
---|
1859 | Const
|
---|
1860 |
|
---|
1861 | { Array For creation Of hexadecimal numbers }
|
---|
1862 |
|
---|
1863 | Hexadecimals: Array[0..15] Of Char = '0123456789ABCDEF';
|
---|
1864 |
|
---|
1865 | Procedure ConvertError(Const Msg: String);
|
---|
1866 | Begin
|
---|
1867 | Raise EConvertError.Create(Msg);
|
---|
1868 | End;
|
---|
1869 |
|
---|
1870 | Procedure FmtLoadConvertError(Ident: Integer; Args: Array Of Const);
|
---|
1871 | Var
|
---|
1872 | Msg: String;
|
---|
1873 | Begin
|
---|
1874 | {$IFDEF GUI}
|
---|
1875 | Try
|
---|
1876 | Msg := FmtLoadNLSStr(Ident, Args);
|
---|
1877 | Except
|
---|
1878 | Msg := LoadNLSStr(Ident) + ' [!]';
|
---|
1879 | End;
|
---|
1880 | {$ELSE GUI}
|
---|
1881 | Msg := 'SysUtils conversion error #' + IntToStr(Ident);
|
---|
1882 | {$ENDIF GUI}
|
---|
1883 | ConvertError(Msg);
|
---|
1884 | End;
|
---|
1885 |
|
---|
1886 | { --- String / PChar Utility FUNCTIONs --- }
|
---|
1887 |
|
---|
1888 | Assembler
|
---|
1889 |
|
---|
1890 | { This Function returns the Length Of A String And A Pointer To the
|
---|
1891 | Zero terminator.
|
---|
1892 |
|
---|
1893 | Input: EDI holds Pointer String
|
---|
1894 | Output: EDI hols Pointer To Zero terminator, EAX holds String Length
|
---|
1895 | changes: EAX, EBX, ECX, EDI }
|
---|
1896 |
|
---|
1897 | SysUtils.!StringLength Proc NEAR32
|
---|
1898 |
|
---|
1899 | MOV EBX, EDI
|
---|
1900 | Xor EAX, EAX
|
---|
1901 | CMP EDI, 0
|
---|
1902 | JE !Out!StringLength
|
---|
1903 | MOV ECX, $FFFFFFFF
|
---|
1904 | CLD
|
---|
1905 | REPNE SCASB
|
---|
1906 | Not ECX
|
---|
1907 | MOV EAX, ECX
|
---|
1908 | Dec EAX
|
---|
1909 | Dec EDI
|
---|
1910 |
|
---|
1911 | !Out!StringLength:
|
---|
1912 | RETN32
|
---|
1913 |
|
---|
1914 | SysUtils.!StringLength ENDP
|
---|
1915 |
|
---|
1916 | { This FUNCTIONs copies A maximum Number Of characters from one String
|
---|
1917 | To another.
|
---|
1918 |
|
---|
1919 | Input: ESI holds Source, EDI holds destination, ECX hold maximum
|
---|
1920 | Number Of characters
|
---|
1921 | Output: EDI holds End Of destination String
|
---|
1922 | changes: EAX, EBX, ECX, EDX, ESI, EDI }
|
---|
1923 |
|
---|
1924 | SysUtils.!StringCopy Proc NEAR32
|
---|
1925 |
|
---|
1926 | MOV EBX, ECX // EBX now contains max chars
|
---|
1927 | MOV EDX, EDI // edx now contains destination
|
---|
1928 | Xor EAX, EAX // set eax=0
|
---|
1929 |
|
---|
1930 | // Check parameters
|
---|
1931 | CMP EDI, 0 // if destination is null, exit
|
---|
1932 | JE !Out!StringCopy
|
---|
1933 | CMP ESI, 0 // if destination is null, exit
|
---|
1934 | JE !Out!StringCopy
|
---|
1935 |
|
---|
1936 | MOV EDI, ESI // load source into EDI
|
---|
1937 | CLD
|
---|
1938 |
|
---|
1939 | // look for 0 terminator, starting from EDI
|
---|
1940 | // or stop at max chars, when ECX = 0
|
---|
1941 | REPNE SCASB
|
---|
1942 | // ECX is now (max chars - length) or 0 if limit reached
|
---|
1943 |
|
---|
1944 | SUB EBX, ECX // (max - ( max - length ) ) = length to copy
|
---|
1945 |
|
---|
1946 | // BX now contains number of chars
|
---|
1947 | // to copy INCLUDING null terminator
|
---|
1948 |
|
---|
1949 | // if reached max chars then
|
---|
1950 | // count will not include zero terminator
|
---|
1951 | CMP ECX, 0
|
---|
1952 | JE !ReachedMaxChars
|
---|
1953 | DEC EBX // Don't want to copy null teriminator
|
---|
1954 | !ReachedMaxChars:
|
---|
1955 |
|
---|
1956 | MOV ECX, EBX // Load count into ecx
|
---|
1957 | Shr ECX, 2 // divide by 4 to find number of dwords to copy
|
---|
1958 | MOV EDI, EDX // load destination into EDI
|
---|
1959 |
|
---|
1960 | REP MOVSD // copy (ECX * 4 bytes) from ESI to EDI
|
---|
1961 | MOV ECX, EBX // get num chars to copy, again
|
---|
1962 | And ECX, 3 // AND with 3 to get remaining bytes to copy
|
---|
1963 | REP MOVSB // Copy remaining bytes
|
---|
1964 |
|
---|
1965 | STOSB // zero terminate result
|
---|
1966 | Dec EDI
|
---|
1967 |
|
---|
1968 | !Out!StringCopy:
|
---|
1969 | RETN32
|
---|
1970 |
|
---|
1971 | SysUtils.!StringCopy ENDP
|
---|
1972 |
|
---|
1973 | // This Function Compares A maximum Number Of characters
|
---|
1974 | // this IS case SENSITIVE.
|
---|
1975 |
|
---|
1976 | SysUtils.!StringCompare Proc NEAR32
|
---|
1977 |
|
---|
1978 | REPE CMPSB
|
---|
1979 | Xor EAX, EAX
|
---|
1980 | MOV AL, [ESI - 1]
|
---|
1981 | MOV BL, [EDI - 1]
|
---|
1982 | SUB EAX, EBX
|
---|
1983 | RETN32
|
---|
1984 |
|
---|
1985 | SysUtils.!StringCompare ENDP
|
---|
1986 |
|
---|
1987 | // Compare a maximum number of characters,
|
---|
1988 | // ignoring case
|
---|
1989 | SysUtils.!StringICompare Proc NEAR32
|
---|
1990 |
|
---|
1991 | Xor EAX, EAX;
|
---|
1992 |
|
---|
1993 | !Loop!StringICompare:
|
---|
1994 |
|
---|
1995 | REPE CMPSB
|
---|
1996 | JE !Out!StringICompare
|
---|
1997 |
|
---|
1998 | Xor EBX, EBX
|
---|
1999 | MOV BL, [ESI - 1]
|
---|
2000 | CMP BL, 'A'
|
---|
2001 | JL !UpcaseSecondChar!StringICompare
|
---|
2002 | CMP BL, 'Z'
|
---|
2003 | JG !UpcaseSecondChar!StringICompare
|
---|
2004 | Or BL, 32
|
---|
2005 |
|
---|
2006 | !UpcaseSecondChar!StringICompare:
|
---|
2007 |
|
---|
2008 | Xor EDX, EDX
|
---|
2009 | MOV DL, [EDI - 1]
|
---|
2010 | CMP DL, 'A'
|
---|
2011 | JL !CompareSingleChar!StringICompare
|
---|
2012 | CMP DL, 'Z'
|
---|
2013 | JG !CompareSingleChar!StringICompare
|
---|
2014 | Or DL, 32
|
---|
2015 |
|
---|
2016 | !CompareSingleChar!StringICompare:
|
---|
2017 |
|
---|
2018 | SUB EBX, EDX
|
---|
2019 | JE !Loop!StringICompare
|
---|
2020 | MOV EAX, EBX
|
---|
2021 |
|
---|
2022 | !Out!StringICompare:
|
---|
2023 |
|
---|
2024 | RETN32
|
---|
2025 |
|
---|
2026 | SysUtils.!StringICompare ENDP
|
---|
2027 |
|
---|
2028 | // Compares two zero terminated strings, case insensitively
|
---|
2029 | // ESI : Str1
|
---|
2030 | // EDI : Str2
|
---|
2031 | // Returns in EAX: 0 : strings equal
|
---|
2032 | // <0 : str1 > str2
|
---|
2033 | // >0 : str2 > str1
|
---|
2034 |
|
---|
2035 | SysUtils.!ZeroTerminatedStringICompare Proc NEAR32
|
---|
2036 |
|
---|
2037 | Xor EAX, EAX; // set result (EAX) to 0 i.e. match
|
---|
2038 |
|
---|
2039 | !Loop!StringICompare:
|
---|
2040 |
|
---|
2041 | Xor EBX, EBX // Set EBX to 0
|
---|
2042 | MOV BL, [ESI] // load char out of str1 into BL
|
---|
2043 |
|
---|
2044 | Xor EDX, EDX // set EDX to 0
|
---|
2045 | MOV DL, [EDI] // load char out of str2 into DL
|
---|
2046 | CMP EDX, 0
|
---|
2047 | jne !Str2NotTerminated!StringICompare // str2 not ended
|
---|
2048 | // str2 has ended.
|
---|
2049 | CMP EBX, 0 // Has str1 also ended?
|
---|
2050 | je !Out!StringICompare // Yes, strings are equal
|
---|
2051 | // no, str1 is continuing,
|
---|
2052 | // so it's "greater"
|
---|
2053 | MOV EAX, $ffffffff // set result = -1
|
---|
2054 | RETN32 // exit
|
---|
2055 |
|
---|
2056 | !Str2NotTerminated!StringICompare: // str2 continues
|
---|
2057 | CMP EBX, 0 // has str2 ended?
|
---|
2058 | jne !Str1NotTerminated!StringICompare
|
---|
2059 | MOV EAX, 1 // set result = 1
|
---|
2060 | RETN32 // exit
|
---|
2061 |
|
---|
2062 | !Str1NotTerminated!StringICompare:
|
---|
2063 | // Neither string has ended
|
---|
2064 | INC esi // increment str1 and str2 pointers
|
---|
2065 | INC edi
|
---|
2066 |
|
---|
2067 | CMP EBX, EDX // char1 = char2?
|
---|
2068 | JE !Loop!StringICompare // yes, continue loop
|
---|
2069 | // no, check case insensitive
|
---|
2070 | // Convert char1 to lowercase, if needed
|
---|
2071 | CMP BL, 'A'
|
---|
2072 | JL !Char1Converted!StringICompare
|
---|
2073 | CMP BL, 'Z'
|
---|
2074 | JG !Char1Converted!StringICompare
|
---|
2075 | Or BL, 32 // change to lower case
|
---|
2076 | !Char1Converted!StringICompare:
|
---|
2077 |
|
---|
2078 | // Convert char2 to lowercase, if needed
|
---|
2079 | CMP DL, 'A'
|
---|
2080 | JL !Char2Converted!StringICompare
|
---|
2081 | CMP DL, 'Z'
|
---|
2082 | JG !Char2Converted!StringICompare
|
---|
2083 | Or DL, 32 // change to lowercase
|
---|
2084 | !Char2Converted!StringICompare:
|
---|
2085 |
|
---|
2086 | SUB EBX, EDX // Subtract char2 from char1
|
---|
2087 | JE !Loop!StringICompare // if chars same, continue loop
|
---|
2088 | MOV EAX, EBX // load difference into EAX
|
---|
2089 |
|
---|
2090 | !Out!StringICompare:
|
---|
2091 |
|
---|
2092 | RETN32
|
---|
2093 |
|
---|
2094 | SysUtils.!ZeroTerminatedStringICompare ENDP
|
---|
2095 |
|
---|
2096 | End;
|
---|
2097 |
|
---|
2098 | { --- Memory management --- }
|
---|
2099 |
|
---|
2100 | Function AllocMem(Size: Cardinal): Pointer;
|
---|
2101 | Begin
|
---|
2102 | GetMem(Result, Size);
|
---|
2103 | FillChar(Result^, Size, 0);
|
---|
2104 | End;
|
---|
2105 |
|
---|
2106 | Function ReAllocMem(P: Pointer; CurSize, NewSize: Cardinal): Pointer;
|
---|
2107 | Var
|
---|
2108 | Q: PByteArray;
|
---|
2109 | Begin
|
---|
2110 | If NewSize <> 0 Then GetMem(Q, NewSize) Else Q := Nil;
|
---|
2111 |
|
---|
2112 | If NewSize > 0 Then
|
---|
2113 | Begin
|
---|
2114 | If NewSize > CurSize Then
|
---|
2115 | Begin
|
---|
2116 | FillChar(Q^[CurSize], NewSize - CurSize, 0);
|
---|
2117 | NewSize := CurSize;
|
---|
2118 | End;
|
---|
2119 | If NewSize <> 0 Then Move(P^, Q^, NewSize);
|
---|
2120 | End;
|
---|
2121 | If CurSize <> 0 Then FreeMem(P, CurSize);
|
---|
2122 | Result := Q;
|
---|
2123 | End;
|
---|
2124 |
|
---|
2125 | { Exit Procedure Handling }
|
---|
2126 |
|
---|
2127 | Type
|
---|
2128 | PExitNode = ^TExitNode;
|
---|
2129 | TExitNode = Record
|
---|
2130 | Next: PExitNode;
|
---|
2131 | Proc: TProcedure;
|
---|
2132 | End;
|
---|
2133 |
|
---|
2134 | Const
|
---|
2135 | ExitChain: PExitNode = Nil;
|
---|
2136 |
|
---|
2137 | Var
|
---|
2138 | SaveExitProc: Pointer;
|
---|
2139 |
|
---|
2140 | Procedure CallExitProcs;
|
---|
2141 | Var
|
---|
2142 | First: PExitNode;
|
---|
2143 | Proc: TProcedure;
|
---|
2144 | Begin
|
---|
2145 | While ExitChain <> Nil Do
|
---|
2146 | Begin
|
---|
2147 | First := ExitChain;
|
---|
2148 | Proc := First^.Proc;
|
---|
2149 | ExitChain := First^.Next;
|
---|
2150 | ExitProc := Nil; { Avoids recursion! }
|
---|
2151 | Dispose(First);
|
---|
2152 | Proc;
|
---|
2153 | End;
|
---|
2154 | ExitProc := SaveExitProc;
|
---|
2155 | End;
|
---|
2156 |
|
---|
2157 | Procedure AddExitProc(Proc: TProcedure);
|
---|
2158 | Var
|
---|
2159 | NewNode: PExitNode;
|
---|
2160 | Begin
|
---|
2161 | If ExitChain = Nil Then SaveExitProc := ExitProc;
|
---|
2162 | New(NewNode);
|
---|
2163 | NewNode^.Next := ExitChain;
|
---|
2164 | NewNode^.Proc := Proc;
|
---|
2165 | ExitChain := NewNode;
|
---|
2166 | ExitProc := @CallExitProcs;
|
---|
2167 | End;
|
---|
2168 |
|
---|
2169 | { --- Pascal String Handling --- }
|
---|
2170 |
|
---|
2171 | Function NewStr(Const S: String): PString;
|
---|
2172 | Begin
|
---|
2173 | If Length(S) = 0 Then Result := NullStr
|
---|
2174 | Else
|
---|
2175 | Begin
|
---|
2176 | GetMem(Result, Length(S) + 1);
|
---|
2177 | Result^ := S;
|
---|
2178 | End;
|
---|
2179 | End;
|
---|
2180 |
|
---|
2181 | Procedure DisposeStr(P: PString);
|
---|
2182 | Begin
|
---|
2183 | If (P <> NullStr) And (P <> Nil) Then FreeMem(P, Length(P^) + 1);
|
---|
2184 | End;
|
---|
2185 |
|
---|
2186 | Procedure AssignStr(Var P: PString; Const S: String);
|
---|
2187 | Begin
|
---|
2188 | DisposeStr(P);
|
---|
2189 | P := NewStr(S);
|
---|
2190 | End;
|
---|
2191 |
|
---|
2192 | Procedure AppendStr(Var Dest: String; Const S: String);
|
---|
2193 | Begin
|
---|
2194 | Insert(S, Dest, Length(Dest) + 1);
|
---|
2195 | End;
|
---|
2196 |
|
---|
2197 | Function uppercase(Const S: String): String;
|
---|
2198 | Var
|
---|
2199 | N, C: Integer;
|
---|
2200 | Begin
|
---|
2201 | Result := S;
|
---|
2202 | For N := 1 To Length(Result) Do
|
---|
2203 | Begin
|
---|
2204 | C := Ord(Result[N]);
|
---|
2205 | If (C >= Ord('a')) And (C <= Ord('z')) Then Result[N] := Chr(C And Not 32);
|
---|
2206 | End;
|
---|
2207 | End;
|
---|
2208 |
|
---|
2209 | Function lowercase(Const S: String): String;
|
---|
2210 | Var
|
---|
2211 | N, C: Integer;
|
---|
2212 | Begin
|
---|
2213 | Result := S;
|
---|
2214 | For N := 1 To Length(Result) Do
|
---|
2215 | Begin
|
---|
2216 | C := Ord(Result[N]);
|
---|
2217 | If (C >= Ord('A')) And (C <= Ord('Z')) Then Result[N] := Chr(C Or 32);
|
---|
2218 | End;
|
---|
2219 | End;
|
---|
2220 |
|
---|
2221 | Function CompareStr(Const s1, s2: String): Integer;
|
---|
2222 | Begin
|
---|
2223 | If s1 <= s2 Then
|
---|
2224 | Begin
|
---|
2225 | If s1 = s2 Then Result := 0 Else Result := -1;
|
---|
2226 | End
|
---|
2227 | Else Result := +1
|
---|
2228 | End;
|
---|
2229 |
|
---|
2230 | Function CompareText(Const s1, s2: String): Integer;
|
---|
2231 | Var
|
---|
2232 | l1, l2, L: Integer;
|
---|
2233 | Begin
|
---|
2234 | l1 := Length(s1);
|
---|
2235 | l2 := Length(s2);
|
---|
2236 | If l1 <= l2 Then L := l1 Else L := l2;
|
---|
2237 | Result := StrLIComp(@s1[1], @s2[1], L);
|
---|
2238 | If Result = 0 Then
|
---|
2239 | Begin
|
---|
2240 | If l1 < l2 Then Result := -1 Else If l1 > l2 Then Result := 1;
|
---|
2241 | End;
|
---|
2242 | End;
|
---|
2243 |
|
---|
2244 | {$IFDEF OS2}
|
---|
2245 | {$IFDEF GUI}
|
---|
2246 | Function AnsiUpperCase(Const S: String): String;
|
---|
2247 | Var
|
---|
2248 | Temp: cstring;
|
---|
2249 | Begin
|
---|
2250 | Temp := S;
|
---|
2251 | WinUpper(AppHandle, 0, 0, Temp);
|
---|
2252 | Result := Temp;
|
---|
2253 | End;
|
---|
2254 | {$ELSE GUI}
|
---|
2255 | Function AnsiUpperCase(Const S: String): String;
|
---|
2256 | Var
|
---|
2257 | cc: COUNTRYCODE;
|
---|
2258 | Begin
|
---|
2259 | Result := S;
|
---|
2260 | cc.country := 0;
|
---|
2261 | cc.codepage := 0;
|
---|
2262 | DosMapCase(Length(Result), cc, Result[1]);
|
---|
2263 | End;
|
---|
2264 | {$ENDIF GUI}
|
---|
2265 | {$ENDIF OS2}
|
---|
2266 |
|
---|
2267 | {$IFDEF Win95}
|
---|
2268 | Function AnsiUpperCase(Const S: String): String;
|
---|
2269 | Var
|
---|
2270 | s1: cstring;
|
---|
2271 | Begin
|
---|
2272 | s1 := S;
|
---|
2273 | AnsiUpperBuff(s1, Length(s));
|
---|
2274 | AnsiUpperCase:=s1;
|
---|
2275 | End;
|
---|
2276 | {$ENDIF Win95}
|
---|
2277 |
|
---|
2278 | {$IFDEF Win95}
|
---|
2279 | Function AnsiLowerCase(Const S: String): String;
|
---|
2280 | Var
|
---|
2281 | s1: cstring;
|
---|
2282 | Begin
|
---|
2283 | s1 := S;
|
---|
2284 | AnsiLowerBuff(s1, Length(s));
|
---|
2285 | Result := s1;
|
---|
2286 | End;
|
---|
2287 | {$ENDIF Win95}
|
---|
2288 |
|
---|
2289 | {$IFDEF OS2}
|
---|
2290 | {$IFDEF GUI}
|
---|
2291 | Function AnsiCompareText(Const s1, s2: String): Integer;
|
---|
2292 | Var
|
---|
2293 | Temp1, Temp2: cstring[256];
|
---|
2294 | Begin
|
---|
2295 | Temp1 := s1;
|
---|
2296 | Temp2 := s2;
|
---|
2297 | Case WinCompareStrings(AppHandle, 0, 0, Temp1, Temp2, 0) Of
|
---|
2298 | WCS_LT: Result := -1;
|
---|
2299 | WCS_EQ: Result := 0;
|
---|
2300 | WCS_GT: Result := 1;
|
---|
2301 | End;
|
---|
2302 | End;
|
---|
2303 | {$ELSE GUI}
|
---|
2304 | Function AnsiCompareText(Const s1, s2: String): Integer;
|
---|
2305 | Var
|
---|
2306 | N, l1, l2: Integer;
|
---|
2307 | Begin
|
---|
2308 | N := 1;
|
---|
2309 | l1 := Length(s1);
|
---|
2310 | l2 := Length(s2);
|
---|
2311 | While (N <= l1) And (N <= l2)
|
---|
2312 | And (CollatingSequence[s1[N]] = CollatingSequence[s2[N]]) Do Inc(N);
|
---|
2313 |
|
---|
2314 | If (N <= l1) And (N <= l2) Then
|
---|
2315 | Begin
|
---|
2316 | If CollatingSequence[s1[N]] < CollatingSequence[s2[N]] Then Result := -1
|
---|
2317 | Else If CollatingSequence[s1[N]] > CollatingSequence[s2[N]] Then Result := 1
|
---|
2318 | Else Result := 0;
|
---|
2319 | End
|
---|
2320 | Else
|
---|
2321 | Begin
|
---|
2322 | If l1 < l2 Then Result := -1
|
---|
2323 | Else If l1 > l2 Then Result := 1
|
---|
2324 | Else Result := 0;
|
---|
2325 | End;
|
---|
2326 | End;
|
---|
2327 | {$ENDIF GUI}
|
---|
2328 | {$ENDIF OS2}
|
---|
2329 |
|
---|
2330 | {$IFDEF Win95}
|
---|
2331 | Function AnsiCompareText(Const s1, s2: String): Integer;
|
---|
2332 | Var
|
---|
2333 | Temp1, Temp2: Array[0..255] Of Char;
|
---|
2334 | Begin
|
---|
2335 | AnsiCompareText:=lstrcmpi(StrPCopy(Temp1,s1)^,
|
---|
2336 | StrPCopy(Temp2,s2)^);
|
---|
2337 | End;
|
---|
2338 | {$ENDIF Win95}
|
---|
2339 |
|
---|
2340 | {$IFDEF Win95}
|
---|
2341 | Function AnsiCompareStr(Const s1, s2: String): Integer;
|
---|
2342 | Var
|
---|
2343 | Temp1, Temp2: Array[0..255] Of Char;
|
---|
2344 | Begin
|
---|
2345 | Result := lstrcmp(StrPCopy(Temp1,s1)^, StrPCopy(Temp2,s2)^);
|
---|
2346 | End;
|
---|
2347 | {$ENDIF Win95}
|
---|
2348 |
|
---|
2349 | Function IsValidIdent(Const Ident: String): Boolean;
|
---|
2350 | Var
|
---|
2351 | L, N: Integer;
|
---|
2352 | Begin
|
---|
2353 | L := Length(Ident);
|
---|
2354 | If L = 0 Then IsValidIdent := False
|
---|
2355 | Else
|
---|
2356 | Begin
|
---|
2357 | If Ident[1] In ['a'..'z', 'A'..'Z', '_'] Then
|
---|
2358 | Begin
|
---|
2359 | N := 2;
|
---|
2360 | While (N <= L) And (Ident[N] In ['a'..'z', 'A'..'Z', '_', '0'..'9']) Do Inc(N);
|
---|
2361 | If N > L Then IsValidIdent := True
|
---|
2362 | Else IsValidIdent := False;
|
---|
2363 | End
|
---|
2364 | Else IsValidIdent := False;
|
---|
2365 | End;
|
---|
2366 | End;
|
---|
2367 |
|
---|
2368 | Function IntToStr(Value: LongInt): String;
|
---|
2369 | Begin
|
---|
2370 | Str(Value, Result);
|
---|
2371 | End;
|
---|
2372 |
|
---|
2373 | Function IntToHex(Value: LongInt; Digits: Integer): String;
|
---|
2374 | Begin
|
---|
2375 | Result := '';
|
---|
2376 | Repeat
|
---|
2377 | Dec(Digits);
|
---|
2378 | Result := Hexadecimals[Value And $0F] + Result;
|
---|
2379 | Value := Value Shr 4;
|
---|
2380 | Until Value = 0;
|
---|
2381 | If Digits > 0 Then
|
---|
2382 | Begin
|
---|
2383 | Move(Result[1], Result[1 + Digits], Byte(Result[0]));
|
---|
2384 | FillChar(Result[1], Digits, '0');
|
---|
2385 | Inc(Byte(Result[0]), Digits);
|
---|
2386 | End;
|
---|
2387 | End;
|
---|
2388 |
|
---|
2389 | Function StrToInt(Const S: String): LongInt;
|
---|
2390 | Var
|
---|
2391 | err: Integer;
|
---|
2392 | Begin
|
---|
2393 | Val(S, Result, err);
|
---|
2394 | If err <> 0 Then FmtLoadConvertError(SInvalidInteger, [S]);
|
---|
2395 | End;
|
---|
2396 |
|
---|
2397 | Function StrToIntDef(Const S: String; Default: LongInt): LongInt;
|
---|
2398 | Var
|
---|
2399 | err: Integer;
|
---|
2400 | Begin
|
---|
2401 | Val(S, Result, err);
|
---|
2402 | If err <> 0 Then Result := Default;
|
---|
2403 | End;
|
---|
2404 |
|
---|
2405 | {$IFDEF OS2}
|
---|
2406 | Function LoadStr(Ident: Word): String;
|
---|
2407 | Var
|
---|
2408 | Buffer: cstring;
|
---|
2409 | Begin
|
---|
2410 | {$IFDEF GUI}
|
---|
2411 | WinLoadString(AppHandle, 0, Ident, 256, Buffer);
|
---|
2412 | Result := Buffer;
|
---|
2413 | {$ELSE}
|
---|
2414 | Result := 'SysUtils Msg #' + IntToStr(Ident);
|
---|
2415 | {$ENDIF GUI}
|
---|
2416 | End;
|
---|
2417 |
|
---|
2418 | Function FmtLoadStr(Ident: Word; Const Args: Array Of Const): String;
|
---|
2419 | Begin
|
---|
2420 | FmtStr(Result, LoadStr(Ident), Args);
|
---|
2421 | End;
|
---|
2422 | {$ENDIF OS2}
|
---|
2423 |
|
---|
2424 | Function LoadTableStr(Const Table:String;Ident: Word): String;
|
---|
2425 | Begin
|
---|
2426 | Result:=GetStringTableEntry(Table,Ident);
|
---|
2427 | End;
|
---|
2428 |
|
---|
2429 | Function LoadNLSStr(Ident: Word): String;
|
---|
2430 | Begin
|
---|
2431 | Result:=GetStringTableEntry(CurrentLanguageTable,Ident);
|
---|
2432 | //If the above failed, Try To Load from Default Table...
|
---|
2433 | If Result='' Then Result:=GetStringTableEntry('SIBYL_NLS_Default',Ident);
|
---|
2434 | End;
|
---|
2435 |
|
---|
2436 | Function FmtLoadTableStr(Const Table:String;Ident: Word; Const Args: Array Of Const): String;
|
---|
2437 | Begin
|
---|
2438 | FmtStr(Result, LoadTableStr(Table,Ident), Args);
|
---|
2439 | End;
|
---|
2440 |
|
---|
2441 | Function FmtLoadNLSStr(Ident: Word; Const Args: Array Of Const): String;
|
---|
2442 | Begin
|
---|
2443 | FmtStr(Result, LoadNLSStr(Ident), Args);
|
---|
2444 | End;
|
---|
2445 |
|
---|
2446 | {$IFDEF Win95}
|
---|
2447 | Function LoadStr(Ident: Word): String;
|
---|
2448 | Begin
|
---|
2449 | Result[0] := Char(LoadString(DllModule,Ident,cstring(Result[1]),254));
|
---|
2450 | End;
|
---|
2451 |
|
---|
2452 | Function FmtLoadStr(Ident: Word; Const Args: Array Of Const): String;
|
---|
2453 | Begin
|
---|
2454 | FmtStr(Result, LoadStr(Ident), Args);
|
---|
2455 | End;
|
---|
2456 | {$ENDIF}
|
---|
2457 |
|
---|
2458 | {$IFDEF OS2}
|
---|
2459 | Function SysErrorMessage(MsgNum: LongInt): String;
|
---|
2460 | Begin
|
---|
2461 | Result := System.SysErrorMessage( MsgNum );
|
---|
2462 | End;
|
---|
2463 | {$ENDIF}
|
---|
2464 |
|
---|
2465 | {
|
---|
2466 | Procedure SetLength(Var S: String; NewLength: Byte);
|
---|
2467 | Begin
|
---|
2468 | Byte(S[0]) := NewLength;
|
---|
2469 | End;
|
---|
2470 | }
|
---|
2471 |
|
---|
2472 | Function Trim(Const S: String): String;
|
---|
2473 | Var
|
---|
2474 | L, R: Integer;
|
---|
2475 | Begin
|
---|
2476 | R := Length(S);
|
---|
2477 | While (R > 0) And (S[R] <= ' ') Do Dec(R);
|
---|
2478 | L := 1;
|
---|
2479 | While (L <= R) And (S[L] <= ' ') Do Inc(L);
|
---|
2480 | Result := Copy(S, L, R - L + 1);
|
---|
2481 | End;
|
---|
2482 |
|
---|
2483 | Function TrimLeft(Const S: String): String;
|
---|
2484 | Var
|
---|
2485 | L, R: Integer;
|
---|
2486 | Begin
|
---|
2487 | R := Length(S);
|
---|
2488 | L := 1;
|
---|
2489 | While (L <= R) And (S[L] <= ' ') Do Inc(L);
|
---|
2490 | Result := Copy(S, L, R - L + 1);
|
---|
2491 | End;
|
---|
2492 |
|
---|
2493 | Function TrimRight(Const S: String): String;
|
---|
2494 | Var
|
---|
2495 | R: Integer;
|
---|
2496 | Begin
|
---|
2497 | R := Length(S);
|
---|
2498 | While (R > 0) And (S[R] <= ' ') Do Dec(R);
|
---|
2499 | Result := Copy(S, 1, R);
|
---|
2500 | End;
|
---|
2501 |
|
---|
2502 | Function QuotedStr(Const S: String): String;
|
---|
2503 | Var
|
---|
2504 | N: Integer;
|
---|
2505 | Begin
|
---|
2506 | Result := #39;
|
---|
2507 | For N := 1 To Length(S) Do
|
---|
2508 | Begin
|
---|
2509 | Result := Result + S[N];
|
---|
2510 | If S[N] = #39 Then Result := Result + #39;
|
---|
2511 | End;
|
---|
2512 | Result := Result + #39;
|
---|
2513 | End;
|
---|
2514 |
|
---|
2515 | { --- File management --- }
|
---|
2516 |
|
---|
2517 | Function FileOpen(Const FileName: String; Mode: Word): LongInt;
|
---|
2518 | {$IFDEF OS2}
|
---|
2519 | Const
|
---|
2520 | Action = OPEN_ACTION_OPEN_IF_EXISTS Or OPEN_ACTION_FAIL_IF_NEW;
|
---|
2521 | Var
|
---|
2522 | ActionTaken, Handle: LongWord;
|
---|
2523 | {$ENDIF}
|
---|
2524 | {$IFDEF Win95}
|
---|
2525 | Const
|
---|
2526 | Action = OPEN_EXISTING;
|
---|
2527 | VAR SA:SECURITY_ATTRIBUTES;
|
---|
2528 | {$ENDIF}
|
---|
2529 | Var
|
---|
2530 | FileNameZ: cstring[256];
|
---|
2531 | Begin
|
---|
2532 | FileNameZ := FileName;
|
---|
2533 | If Mode And ShareModes = 0 Then Mode := Mode Or fmShareDenyNone;
|
---|
2534 | {$IFDEF OS2}
|
---|
2535 | Result := - DosOpen(FileNameZ, Handle, ActionTaken, 0, 0, Action, Mode, Nil);
|
---|
2536 | If Result = NO_ERROR Then Result := Handle;
|
---|
2537 | {$ENDIF}
|
---|
2538 | {$IFDEF Win95}
|
---|
2539 | SA.nLength:=sizeof(SA);
|
---|
2540 | SA.lpSecurityDescriptor:=Nil;
|
---|
2541 | SA.bInheritHandle:=True;
|
---|
2542 | Result:=CreateFile(FileNameZ,Mode And Not 3,Mode And 3,SA,Action,
|
---|
2543 | FILE_ATTRIBUTE_NORMAL,0);
|
---|
2544 | {$ENDIF}
|
---|
2545 | End;
|
---|
2546 |
|
---|
2547 | Function FileOpenOrCreate(Const FileName: String; Mode: Word): LongInt;
|
---|
2548 | {$IFDEF OS2}
|
---|
2549 | Const
|
---|
2550 | Action = OPEN_ACTION_OPEN_IF_EXISTS Or OPEN_ACTION_CREATE_IF_NEW;
|
---|
2551 | Var
|
---|
2552 | ActionTaken, Handle: LongWord;
|
---|
2553 | {$ENDIF}
|
---|
2554 | {$IFDEF Win95}
|
---|
2555 | Const
|
---|
2556 | Action = OPEN_ALWAYS;
|
---|
2557 | Var SA:SECURITY_ATTRIBUTES;
|
---|
2558 | {$ENDIF}
|
---|
2559 | Var
|
---|
2560 | FileNameZ: cstring[256];
|
---|
2561 | Begin
|
---|
2562 | FileNameZ := FileName;
|
---|
2563 | If Mode And ShareModes = 0 Then Mode := Mode Or fmShareDenyNone;
|
---|
2564 | {$IFDEF OS2}
|
---|
2565 | Result := - DosOpen(FileNameZ, Handle, ActionTaken, 0, 0, Action, Mode, Nil);
|
---|
2566 | If Result = NO_ERROR Then Result := Handle;
|
---|
2567 | {$ENDIF}
|
---|
2568 | {$IFDEF Win95}
|
---|
2569 | SA.nLength:=sizeof(SA);
|
---|
2570 | SA.lpSecurityDescriptor:=Nil;
|
---|
2571 | SA.bInheritHandle:=True;
|
---|
2572 | Result:=CreateFile(FileNameZ,Mode And Not 3,Mode And 3,SA,Action,
|
---|
2573 | FILE_ATTRIBUTE_NORMAL,0);
|
---|
2574 | {$ENDIF}
|
---|
2575 | End;
|
---|
2576 |
|
---|
2577 | Function FileCreateIfNew(Const FileName: String; Mode: Word): LongInt;
|
---|
2578 | {$IFDEF OS2}
|
---|
2579 | Const
|
---|
2580 | Action = OPEN_ACTION_FAIL_IF_EXISTS Or OPEN_ACTION_CREATE_IF_NEW;
|
---|
2581 | Var
|
---|
2582 | ActionTaken, Handle: LongWord;
|
---|
2583 | {$ENDIF}
|
---|
2584 | {$IFDEF Win95}
|
---|
2585 | Const
|
---|
2586 | Action = CREATE_NEW;
|
---|
2587 | Var SA:SECURITY_ATTRIBUTES;
|
---|
2588 | {$ENDIF}
|
---|
2589 | Var
|
---|
2590 | FileNameZ: cstring[256];
|
---|
2591 | Begin
|
---|
2592 | FileNameZ := FileName;
|
---|
2593 | If Mode And ShareModes = 0 Then Mode := Mode Or fmShareDenyNone;
|
---|
2594 | {$IFDEF OS2}
|
---|
2595 | Result := - DosOpen(FileNameZ, Handle, ActionTaken, 0, 0, Action, Mode, Nil);
|
---|
2596 | If Result = NO_ERROR Then Result := Handle;
|
---|
2597 | {$ENDIF}
|
---|
2598 | {$IFDEF Win95}
|
---|
2599 | SA.nLength:=sizeof(SA);
|
---|
2600 | SA.lpSecurityDescriptor:=Nil;
|
---|
2601 | SA.bInheritHandle:=True;
|
---|
2602 | Result:=CreateFile(FileNameZ,Mode And Not 3,Mode And 3,SA,Action,
|
---|
2603 | FILE_ATTRIBUTE_NORMAL,0);
|
---|
2604 | {$ENDIF}
|
---|
2605 | End;
|
---|
2606 |
|
---|
2607 | Function FileCreate(Const FileName: String): LongInt;
|
---|
2608 | {$IFDEF OS2}
|
---|
2609 | Const
|
---|
2610 | Action = OPEN_ACTION_REPLACE_IF_EXISTS Or OPEN_ACTION_CREATE_IF_NEW;
|
---|
2611 | Var
|
---|
2612 | ActionTaken, Handle: LongWord;
|
---|
2613 | {$ENDIF}
|
---|
2614 | {$IFDEF Win95}
|
---|
2615 | Const
|
---|
2616 | Action = CREATE_ALWAYS;
|
---|
2617 | Var SA:SECURITY_ATTRIBUTES;
|
---|
2618 | {$ENDIF}
|
---|
2619 | Const
|
---|
2620 | Mode = fmOpenReadWrite Or fmShareExclusive;
|
---|
2621 | Var
|
---|
2622 | FileNameZ: cstring[256];
|
---|
2623 | Begin
|
---|
2624 | FileNameZ := FileName;
|
---|
2625 | {$IFDEF OS2}
|
---|
2626 | Result := - DosOpen(FileNameZ, Handle, ActionTaken, 0, 0, Action, Mode, Nil);
|
---|
2627 | If Result = NO_ERROR Then Result := Handle;
|
---|
2628 | {$ENDIF}
|
---|
2629 | {$IFDEF Win95}
|
---|
2630 | SA.nLength:=sizeof(SA);
|
---|
2631 | SA.lpSecurityDescriptor:=Nil;
|
---|
2632 | SA.bInheritHandle:=True;
|
---|
2633 | Result:=CreateFile(FileNameZ,Mode And Not 3,Mode And 3,SA,Action,
|
---|
2634 | FILE_ATTRIBUTE_NORMAL,0);
|
---|
2635 | {$ENDIF}
|
---|
2636 | End;
|
---|
2637 |
|
---|
2638 | Function FileRead(Handle: LongInt; Var Buffer; Count: LongInt): LongInt;
|
---|
2639 | Var
|
---|
2640 | Result: LongWord;
|
---|
2641 | Begin
|
---|
2642 | {$IFDEF OS2}
|
---|
2643 | If DosRead(Handle, Buffer, Count, Result) = NO_ERROR Then FileRead := Result
|
---|
2644 | Else FileRead := -1;
|
---|
2645 | {$ENDIF}
|
---|
2646 | {$IFDEF Win95}
|
---|
2647 | If ReadFile(Handle,Buffer,Count,Result,Nil) Then FileRead := Result
|
---|
2648 | Else FileRead := -1;
|
---|
2649 | {$ENDIF}
|
---|
2650 | End;
|
---|
2651 |
|
---|
2652 | Function FileWrite(Handle: LongInt; Const Buffer; Count: LongInt): LongInt;
|
---|
2653 | Var
|
---|
2654 | Result:LongWord;
|
---|
2655 | Begin
|
---|
2656 | {$IFDEF OS2}
|
---|
2657 | If DosWrite(Handle, Buffer, Count, Result) = NO_ERROR Then FileWrite := Result
|
---|
2658 | Else FileWrite := -1;
|
---|
2659 | {$ENDIF}
|
---|
2660 | {$IFDEF Win95}
|
---|
2661 | If Not WriteFile(Handle,Buffer,Count,Result,Nil) Then Result := -1
|
---|
2662 | Else FileWrite := Result;
|
---|
2663 | {$ENDIF}
|
---|
2664 | End;
|
---|
2665 |
|
---|
2666 | Function FileSeek(Handle: LongInt; Offset: LongInt; Origin: Integer): LongInt;
|
---|
2667 | {$IFDEF OS2}
|
---|
2668 | Var
|
---|
2669 | NewPos: LongWord;
|
---|
2670 | {$ENDIF}
|
---|
2671 | Begin
|
---|
2672 | {$IFDEF OS2}
|
---|
2673 | If DosSetFilePtr(Handle, Offset, Origin, NewPos) = NO_ERROR Then FileSeek := NewPos
|
---|
2674 | Else FileSeek := -1;
|
---|
2675 | {$ENDIF}
|
---|
2676 | {$IFDEF Win95}
|
---|
2677 | Result:=SetFilePointer(Handle,Offset,Nil,Origin);
|
---|
2678 | {$ENDIF}
|
---|
2679 | End;
|
---|
2680 |
|
---|
2681 | Procedure FileClose(Handle: LongInt);
|
---|
2682 | Begin
|
---|
2683 | {$IFDEF OS2}
|
---|
2684 | DosClose(Handle);
|
---|
2685 | {$ENDIF}
|
---|
2686 | {$IFDEF Win95}
|
---|
2687 | CloseHandle(Handle);
|
---|
2688 | {$ENDIF}
|
---|
2689 | End;
|
---|
2690 |
|
---|
2691 | Function FileLock(Handle, Offset, Range: LongInt): Boolean;
|
---|
2692 | {$IFDEF OS2}
|
---|
2693 | Var
|
---|
2694 | Lock, UnLock: BseDos.FileLock;
|
---|
2695 | {$ENDIF}
|
---|
2696 | Begin
|
---|
2697 | {$IFDEF OS2}
|
---|
2698 | Lock.LOffset := Offset;
|
---|
2699 | Lock.LRange := Range;
|
---|
2700 | UnLock.LOffset := 0;
|
---|
2701 | UnLock.LRange := 0;
|
---|
2702 | Result := (DosSetFileLocks(Handle, UnLock, Lock, LockTimeout, 0) = NO_ERROR);
|
---|
2703 | {$ENDIF}
|
---|
2704 | {$IFDEF Win95}
|
---|
2705 | Result := LockFile(Handle,Offset,0,Range,0);
|
---|
2706 | {$ENDIF}
|
---|
2707 | End;
|
---|
2708 |
|
---|
2709 | Function FileUnLock(Handle, Offset, Range: LongInt): Boolean;
|
---|
2710 | {$IFDEF OS2}
|
---|
2711 | Var
|
---|
2712 | Lock, UnLock: BseDos.FileLock;
|
---|
2713 | {$ENDIF}
|
---|
2714 | Begin
|
---|
2715 | {$IFDEF OS2}
|
---|
2716 | UnLock.LOffset := Offset;
|
---|
2717 | UnLock.LRange := Range;
|
---|
2718 | Lock.LOffset := 0;
|
---|
2719 | Lock.LRange := 0;
|
---|
2720 | Result := (DosSetFileLocks(Handle, UnLock, Lock, LockTimeout, 0) = NO_ERROR);
|
---|
2721 | {$ENDIF}
|
---|
2722 | {$IFDEF Win95}
|
---|
2723 | Result := UnlockFile(Handle,Offset,0,Range,0);
|
---|
2724 | {$ENDIF}
|
---|
2725 | End;
|
---|
2726 |
|
---|
2727 | Function FileAge(Const FileName: String): LongInt;
|
---|
2728 | Var
|
---|
2729 | FileNameZ: cstring;
|
---|
2730 | {$IFDEF OS2}
|
---|
2731 | Buffer: FILESTATUS3;
|
---|
2732 | {$ENDIF}
|
---|
2733 | {$IFDEF Win95}
|
---|
2734 | Handle:LongWord;
|
---|
2735 | LastAccess,creation,LastWrite,actual:FILETIME;
|
---|
2736 | date,Time:Word;
|
---|
2737 | {$ENDIF}
|
---|
2738 | Begin
|
---|
2739 | FileNameZ := FileName;
|
---|
2740 | {$IFDEF OS2}
|
---|
2741 | If DosQueryPathInfo(FileNameZ, FIL_STANDARD, Buffer, SizeOf(Buffer)) = NO_ERROR Then
|
---|
2742 | FileAge := (Buffer.fdateLastWrite Shl 16) Or Buffer.ftimeLastWrite
|
---|
2743 | Else FileAge := -1;
|
---|
2744 | {$ENDIF}
|
---|
2745 | {$IFDEF Win95}
|
---|
2746 | Handle:=CreateFile(FileNameZ,GENERIC_READ,0,Nil,OPEN_EXISTING,
|
---|
2747 | FILE_ATTRIBUTE_NORMAL,0);
|
---|
2748 | If Handle=-1 Then
|
---|
2749 | Begin
|
---|
2750 | FileAge:=-1;
|
---|
2751 | Exit;
|
---|
2752 | End;
|
---|
2753 | If Not GetFileTime(Handle,creation,LastAccess,LastWrite) Then
|
---|
2754 | Begin
|
---|
2755 | CloseHandle(Handle);
|
---|
2756 | FileAge:=-1;
|
---|
2757 | Exit;
|
---|
2758 | End;
|
---|
2759 | CloseHandle(Handle);
|
---|
2760 | FileTimeToLocalFileTime(LastWrite,actual);
|
---|
2761 | FileTimeToDosDateTime(actual,date,Time);
|
---|
2762 | FileAge := (date Shl 16) Or Time;
|
---|
2763 | {$ENDIF}
|
---|
2764 | End;
|
---|
2765 |
|
---|
2766 | Function FileExists(Const FileName: String): Boolean;
|
---|
2767 | Var
|
---|
2768 | SearchRec: TSearchRec;
|
---|
2769 | Begin
|
---|
2770 | If FindFirst(FileName, faAnyFile, SearchRec) = 0 Then
|
---|
2771 | Begin
|
---|
2772 | FileExists := True;
|
---|
2773 | FindClose(SearchRec);
|
---|
2774 | End
|
---|
2775 | Else FileExists := False;
|
---|
2776 | End;
|
---|
2777 |
|
---|
2778 | Function FindFirst(Const Path: String; Attr: Integer; Var SearchRec: TSearchRec): LongInt;
|
---|
2779 | {$IFDEF OS2}
|
---|
2780 | Var
|
---|
2781 | OS2SearchRec: FILEFINDBUF3;
|
---|
2782 | Result, Count: LongWord;
|
---|
2783 | Const
|
---|
2784 | Size = SizeOf(OS2SearchRec);
|
---|
2785 | {$ENDIF}
|
---|
2786 | {$IFDEF WIN32}
|
---|
2787 | Var Actual:FILETIME;
|
---|
2788 | date,time:word;
|
---|
2789 | {$ENDIF}
|
---|
2790 | Var
|
---|
2791 | PathZ: cstring;
|
---|
2792 | Begin
|
---|
2793 | PathZ := Path;
|
---|
2794 | {$IFDEF OS2}
|
---|
2795 | SearchRec.HDir := HDIR_CREATE;
|
---|
2796 | Count := 1;
|
---|
2797 | Result := DosFindFirst(PathZ, SearchRec.HDir, Attr, OS2SearchRec, Size, Count, FIL_STANDARD);
|
---|
2798 | If Result = NO_ERROR Then
|
---|
2799 | Begin
|
---|
2800 | With OS2SearchRec Do
|
---|
2801 | Begin
|
---|
2802 | SearchRec.Name := achName;
|
---|
2803 | SearchRec.Size := cbFile;
|
---|
2804 | SearchRec.Attr := attrFile;
|
---|
2805 | SearchRec.Time := fdateLastWrite;
|
---|
2806 | SearchRec.Time := SearchRec.Time Shl 16 + ftimeLastWrite;
|
---|
2807 | End;
|
---|
2808 | FindFirst := 0;
|
---|
2809 | End
|
---|
2810 | Else FindFirst := -Result;
|
---|
2811 | {$ENDIF}
|
---|
2812 | {$IFDEF Win95}
|
---|
2813 | SearchRec.InternalAttr:=Attr;
|
---|
2814 | SearchRec.HDir:=FindFirstFile(PathZ,SearchRec.SearchRecIntern);
|
---|
2815 | If SearchRec.HDir=INVALID_HANDLE_VALUE Then
|
---|
2816 | Begin
|
---|
2817 | FindFirst:=-GetLastError;
|
---|
2818 | Exit;
|
---|
2819 | End;
|
---|
2820 | While SearchRec.SearchRecIntern.dwFileAttributes And SearchRec.InternalAttr=0 Do
|
---|
2821 | Begin
|
---|
2822 | If FindNextFile(SearchRec.HDir,SearchRec.SearchRecIntern)=False Then
|
---|
2823 | Begin
|
---|
2824 | Result:=-GetLastError;
|
---|
2825 | WinBase.FindClose(SearchRec.HDir);
|
---|
2826 | Exit;
|
---|
2827 | End;
|
---|
2828 | End;
|
---|
2829 |
|
---|
2830 | FileTimeToLocalFileTime(SearchRec.SearchRecIntern.ftLastWriteTime,Actual);
|
---|
2831 | FileTimeToDosDateTime(Actual,date,time);
|
---|
2832 | SearchRec.Time:=(date Shl 16) Or Time;
|
---|
2833 | SearchRec.Size:=SearchRec.SearchRecIntern.nFileSizeLow;
|
---|
2834 | SearchRec.Attr:=SearchRec.SearchRecIntern.dwFileAttributes;
|
---|
2835 | SearchRec.Name:=cstring(SearchRec.SearchRecIntern.cFileName);
|
---|
2836 | Result := 0;
|
---|
2837 | {$ENDIF}
|
---|
2838 | End;
|
---|
2839 |
|
---|
2840 | Function FindNext(Var SearchRec: TSearchRec): LongInt;
|
---|
2841 | {$IFDEF OS2}
|
---|
2842 | Var
|
---|
2843 | OS2SearchRec: FILEFINDBUF3;
|
---|
2844 | Result: Integer;
|
---|
2845 | Count: LongWord;
|
---|
2846 | Const
|
---|
2847 | Size = SizeOf(OS2SearchRec);
|
---|
2848 | {$ENDIF}
|
---|
2849 | {$IFDEF WIN32}
|
---|
2850 | Var Actual:FILETIME;
|
---|
2851 | date,time:word;
|
---|
2852 | {$ENDIF}
|
---|
2853 | Begin
|
---|
2854 | {$IFDEF OS2}
|
---|
2855 | Count := 1;
|
---|
2856 | Result := DosFindNext (SearchRec.HDir, OS2SearchRec, Size, Count);
|
---|
2857 | If Result = NO_ERROR Then
|
---|
2858 | Begin
|
---|
2859 | With OS2SearchRec Do
|
---|
2860 | Begin
|
---|
2861 | SearchRec.Name := achName;
|
---|
2862 | SearchRec.Size := cbFile;
|
---|
2863 | SearchRec.Attr := attrFile;
|
---|
2864 | SearchRec.Time := fdateLastWrite;
|
---|
2865 | SearchRec.Time := SearchRec.Time Shl 16 + ftimeLastWrite;
|
---|
2866 | End;
|
---|
2867 | FindNext := 0;
|
---|
2868 | End
|
---|
2869 | Else FindNext := -Result;
|
---|
2870 | {$ENDIF}
|
---|
2871 | {$IFDEF Win95}
|
---|
2872 | If FindNextFile(SearchRec.HDir,SearchRec.SearchRecIntern)=False Then
|
---|
2873 | Begin
|
---|
2874 | Result:=-GetLastError;
|
---|
2875 | WinBase.FindClose(SearchRec.HDir);
|
---|
2876 | Exit;
|
---|
2877 | End;
|
---|
2878 | While SearchRec.SearchRecIntern.dwFileAttributes And SearchRec.InternalAttr=0 Do
|
---|
2879 | Begin
|
---|
2880 | If FindNextFile(SearchRec.HDir,SearchRec.SearchRecIntern)=False Then
|
---|
2881 | Begin
|
---|
2882 | Result:=-GetLastError;
|
---|
2883 | WinBase.FindClose(SearchRec.HDir);
|
---|
2884 | Exit;
|
---|
2885 | End;
|
---|
2886 | End;
|
---|
2887 |
|
---|
2888 | FileTimeToLocalFileTime(SearchRec.SearchRecIntern.ftLastWriteTime,Actual);
|
---|
2889 | FileTimeToDosDateTime(Actual,date,time);
|
---|
2890 | SearchRec.Time:=(date Shl 16) Or Time;
|
---|
2891 | SearchRec.Size:=SearchRec.SearchRecIntern.nFileSizeLow;
|
---|
2892 | SearchRec.Attr:=SearchRec.SearchRecIntern.dwFileAttributes;
|
---|
2893 | SearchRec.Name:=cstring(SearchRec.SearchRecIntern.cFileName);
|
---|
2894 | Result := 0;
|
---|
2895 | {$ENDIF}
|
---|
2896 | End;
|
---|
2897 |
|
---|
2898 | Procedure FindClose(Var SearchRec: TSearchRec);
|
---|
2899 | Begin
|
---|
2900 | {$IFDEF OS2}
|
---|
2901 | DosFindClose(SearchRec.HDir);
|
---|
2902 | {$ENDIF}
|
---|
2903 | {$IFDEF Win95}
|
---|
2904 | WinBase.FindClose(SearchRec.HDir);
|
---|
2905 | {$ENDIF}
|
---|
2906 | End;
|
---|
2907 |
|
---|
2908 | Function FileGetDate(Handle: LongInt): LongInt;
|
---|
2909 | {$IFDEF OS2}
|
---|
2910 | Var
|
---|
2911 | Buffer: FILESTATUS3;
|
---|
2912 | {$ENDIF}
|
---|
2913 | {$IFDEF Win95}
|
---|
2914 | Var
|
---|
2915 | LastAccess,creation,LastWrite,actual:FILETIME;
|
---|
2916 | date,Time:Word;
|
---|
2917 | {$ENDIF}
|
---|
2918 | Begin
|
---|
2919 | {$IFDEF OS2}
|
---|
2920 | If DosQueryFileInfo(Handle, FIL_STANDARD, Buffer, SizeOf(Buffer)) = NO_ERROR Then
|
---|
2921 | FileGetDate := (Buffer.fdateLastWrite Shl 16) Or Buffer.ftimeLastWrite
|
---|
2922 | Else FileGetDate := -1;
|
---|
2923 | {$ENDIF}
|
---|
2924 | {$IFDEF Win95}
|
---|
2925 | If Not GetFileTime(Handle,creation,LastAccess,LastWrite) Then
|
---|
2926 | Begin
|
---|
2927 | CloseHandle(Handle);
|
---|
2928 | FileGetDate:=-1;
|
---|
2929 | Exit;
|
---|
2930 | End;
|
---|
2931 | CloseHandle(Handle);
|
---|
2932 | FileTimeToLocalFileTime(LastWrite,actual);
|
---|
2933 | FileTimeToDosDateTime(actual,date,Time);
|
---|
2934 | FileGetDate := (date Shl 16) Or Time;
|
---|
2935 | {$ENDIF}
|
---|
2936 | End;
|
---|
2937 |
|
---|
2938 | Procedure FileSetDate(Handle: Integer; Age: LongInt);
|
---|
2939 | {$IFDEF OS2}
|
---|
2940 | Var
|
---|
2941 | Buffer: FILESTATUS3;
|
---|
2942 | {$ENDIF}
|
---|
2943 | {$IFDEF Win95}
|
---|
2944 | Var
|
---|
2945 | date,Time:Word;
|
---|
2946 | LastWrite:FILETIME;
|
---|
2947 | {$ENDIF}
|
---|
2948 | Begin
|
---|
2949 | {$IFDEF OS2}
|
---|
2950 | FillChar(Buffer, SizeOf(Buffer), 0);
|
---|
2951 | Buffer.ftimeLastWrite := Age And $FFFF;
|
---|
2952 | Buffer.fdateLastWrite := Age Shr 16;
|
---|
2953 | DosSetFileInfo(Handle, FIL_STANDARD, Buffer, SizeOf(Buffer));
|
---|
2954 | {$ENDIF}
|
---|
2955 | {$IFDEF Win95}
|
---|
2956 | date:= Age Shr 16;
|
---|
2957 | Time:= Age And $FFFF;
|
---|
2958 | DosDateTimeToFileTime(date,Time,LastWrite);
|
---|
2959 |
|
---|
2960 | WinBase.SetFileTime(Handle,Nil,Nil,LastWrite);
|
---|
2961 | {$ENDIF}
|
---|
2962 | End;
|
---|
2963 |
|
---|
2964 | Function FileGetAttr(Const FileName: String): LongInt;
|
---|
2965 | {$IFDEF OS2}
|
---|
2966 | Var
|
---|
2967 | Buffer: FILESTATUS3;
|
---|
2968 | {$ENDIF}
|
---|
2969 | Var
|
---|
2970 | FileNameZ: cstring;
|
---|
2971 | Begin
|
---|
2972 | FileNameZ := FileName;
|
---|
2973 | {$IFDEF OS2}
|
---|
2974 | Result := - DosQueryPathInfo(FileNameZ, FIL_STANDARD, Buffer, SizeOf(Buffer));
|
---|
2975 | If Result = 0 Then Result := Buffer.attrFile;
|
---|
2976 | {$ENDIF}
|
---|
2977 | {$IFDEF Win95}
|
---|
2978 | Result := GetFileAttributes(FileNameZ);
|
---|
2979 | {$ENDIF}
|
---|
2980 | End;
|
---|
2981 |
|
---|
2982 | Function FileSetAttr(Const FileName: String; Attr: Integer): Integer;
|
---|
2983 | {$IFDEF OS2}
|
---|
2984 | Var
|
---|
2985 | Buffer: FILESTATUS3;
|
---|
2986 | {$ENDIF}
|
---|
2987 | Var
|
---|
2988 | FileNameZ: cstring;
|
---|
2989 | Begin
|
---|
2990 | FileNameZ := FileName;
|
---|
2991 | {$IFDEF OS2}
|
---|
2992 | FillChar(Buffer, SizeOf(Buffer), 0);
|
---|
2993 | Buffer.attrFile := Attr;
|
---|
2994 | Result := - DosSetPathInfo(FileNameZ, FIL_STANDARD, Buffer, SizeOf(Buffer), 0);
|
---|
2995 | {$ENDIF}
|
---|
2996 | {$IFDEF Win95}
|
---|
2997 | If SetFileAttributes(FileNameZ,Attr) Then Result:=0
|
---|
2998 | Else Result := -GetLastError;
|
---|
2999 | {$ENDIF}
|
---|
3000 | End;
|
---|
3001 |
|
---|
3002 | Function CopyFile(Const SourceName, DestName: String): Boolean;
|
---|
3003 | Var
|
---|
3004 | SourceZ, DestZ: cstring;
|
---|
3005 | Begin
|
---|
3006 | SourceZ := SourceName;
|
---|
3007 | DestZ := DestName;
|
---|
3008 | {$IFDEF OS2}
|
---|
3009 | Result := (DosCopy(SourceZ, DestZ, DCPY_EXISTING) = NO_ERROR);
|
---|
3010 | {$ENDIF}
|
---|
3011 | {$IFDEF Win95}
|
---|
3012 | Result := WinBase.CopyFile(SourceZ, DestZ, True);
|
---|
3013 | {$ENDIF}
|
---|
3014 | End;
|
---|
3015 |
|
---|
3016 | Function DeleteFile(Const FileName: String): Boolean;
|
---|
3017 | Var
|
---|
3018 | FileNameZ: cstring;
|
---|
3019 | Begin
|
---|
3020 | FileNameZ := FileName;
|
---|
3021 | {$IFDEF OS2}
|
---|
3022 | Result := (DosDelete(FileNameZ) = NO_ERROR);
|
---|
3023 | {$ENDIF}
|
---|
3024 | {$IFDEF Win95}
|
---|
3025 | Result := WinBase.DeleteFile(FileNameZ);
|
---|
3026 | {$ENDIF}
|
---|
3027 | End;
|
---|
3028 |
|
---|
3029 | Function RenameFile(Const OldName, NewName: String): Boolean;
|
---|
3030 | Var
|
---|
3031 | OldNameZ, NewNameZ: cstring;
|
---|
3032 | Begin
|
---|
3033 | OldNameZ := OldName;
|
---|
3034 | NewNameZ := NewName;
|
---|
3035 | {$IFDEF OS2}
|
---|
3036 | Result := (DosMove(OldNameZ, NewNameZ) = NO_ERROR);
|
---|
3037 | {$ENDIF}
|
---|
3038 | {$IFDEF Win95}
|
---|
3039 | Result := MoveFile(OldNameZ, NewNameZ);
|
---|
3040 | {$ENDIF}
|
---|
3041 | End;
|
---|
3042 |
|
---|
3043 | Function ChangeFileExt(Const FileName, extension: String): String;
|
---|
3044 | Var
|
---|
3045 | P: Integer;
|
---|
3046 | Begin
|
---|
3047 | P := Length(FileName);
|
---|
3048 | While (P > 0) And (FileName[P] <> '.') Do Dec(P);
|
---|
3049 | If P = 0 Then Result := FileName + extension
|
---|
3050 | Else Result := Copy(FileName, 1, P - 1) + extension;
|
---|
3051 | End;
|
---|
3052 |
|
---|
3053 | Function ExtractFilePath(Const FileName: String): String;
|
---|
3054 | Var
|
---|
3055 | P: Integer;
|
---|
3056 | Begin
|
---|
3057 | P := Length(FileName);
|
---|
3058 | While (P > 0) And (FileName[P] <> ':') And (FileName[P] <> '\') Do Dec(P);
|
---|
3059 | Result := Copy(FileName, 1, P);
|
---|
3060 | End;
|
---|
3061 |
|
---|
3062 | Function ExtractFileName(Const FileName: String): String;
|
---|
3063 | Var
|
---|
3064 | P: Integer;
|
---|
3065 | Begin
|
---|
3066 | P := Length(FileName);
|
---|
3067 | While (P > 0) And (FileName[P] <> ':') And (FileName[P] <> '\') Do Dec(P);
|
---|
3068 | Result := Copy(FileName, P + 1, 255);
|
---|
3069 | End;
|
---|
3070 |
|
---|
3071 | Function ExtractFileExt(Const FileName: String): String;
|
---|
3072 | Var
|
---|
3073 | P: Integer;
|
---|
3074 | Begin
|
---|
3075 | P := Length(FileName);
|
---|
3076 | While (P > 0) And (FileName[P] <> '.') Do Dec(P);
|
---|
3077 | If P = 0 Then Result := ''
|
---|
3078 | Else Result := Copy(FileName, P, 255);
|
---|
3079 | End;
|
---|
3080 |
|
---|
3081 | Function ConcatFileName(Const pathname, FileName: String): String;
|
---|
3082 | Begin
|
---|
3083 | If (pathname = '') Or (FileName = '') Or
|
---|
3084 | (pathname[Length(pathname)] In ['\', ':']) Then
|
---|
3085 | Result := pathname + FileName
|
---|
3086 | Else Result := pathname + '\' + FileName;
|
---|
3087 | End;
|
---|
3088 |
|
---|
3089 | Function ExpandFileName(FileName: String): String;
|
---|
3090 | {$IFDEF OS2}
|
---|
3091 | Const
|
---|
3092 | Level = FIL_QUERYFULLNAME;
|
---|
3093 | Var
|
---|
3094 | Buffer:CString;
|
---|
3095 | {$ENDIF}
|
---|
3096 | {$IFDEF Win95}
|
---|
3097 | Var
|
---|
3098 | TempName : PChar;
|
---|
3099 | {$ENDIF}
|
---|
3100 | Var
|
---|
3101 | FileNameZ: cstring;
|
---|
3102 | Begin
|
---|
3103 | FileNameZ := FileName;
|
---|
3104 | {$IFDEF OS2}
|
---|
3105 | If DosQueryPathInfo(FileNameZ, Level, Buffer, SizeOf(Buffer)) = NO_ERROR Then Result := Buffer
|
---|
3106 | Else
|
---|
3107 | Begin
|
---|
3108 | If ((length(FileName)=2)And(FileName[2]=':')) Then
|
---|
3109 | Begin
|
---|
3110 | {$I-}
|
---|
3111 | GetDir(ord(Upcase(FileName[1]))-64,Result);
|
---|
3112 | {$I+}
|
---|
3113 | If IoResult<>0 Then Result:='';
|
---|
3114 | End
|
---|
3115 | Else Result:='';
|
---|
3116 | End;
|
---|
3117 | {$ENDIF}
|
---|
3118 | {$IFDEF Win95}
|
---|
3119 | Result[0]:=Chr(GetFullPathName(FileNameZ,256,cstring(Result[1]),TempName));
|
---|
3120 | {$ENDIF}
|
---|
3121 | End;
|
---|
3122 |
|
---|
3123 | Function EditFileName(Const Name, edit: String): String;
|
---|
3124 | {$IFDEF OS2}
|
---|
3125 | Var
|
---|
3126 | Buffer: cstring;
|
---|
3127 | {$ENDIF}
|
---|
3128 | Var
|
---|
3129 | NameZ, EditZ: cstring;
|
---|
3130 | Begin
|
---|
3131 | NameZ := Name;
|
---|
3132 | EditZ := edit;
|
---|
3133 | {$IFDEF OS2}
|
---|
3134 | If DosEditName(1, NameZ, EditZ, Buffer, 256) = 0 Then Result := Buffer
|
---|
3135 | Else Result := '';
|
---|
3136 | {$ENDIF}
|
---|
3137 | {$IFDEF Win95}
|
---|
3138 | Result := ''; //Not supported
|
---|
3139 | {$ENDIF}
|
---|
3140 | End;
|
---|
3141 |
|
---|
3142 | Function FileSearch(Const Name, DirList: String): String;
|
---|
3143 | {$IFDEF OS2}
|
---|
3144 | Const
|
---|
3145 | Flags = SEARCH_IGNORENETERRS;
|
---|
3146 | {$ENDIF}
|
---|
3147 | {$IFDEF Win95}
|
---|
3148 | Var
|
---|
3149 | Temp : PChar;
|
---|
3150 | {$ENDIF}
|
---|
3151 | Var
|
---|
3152 | NameZ, DirListZ, Buffer: cstring;
|
---|
3153 | Begin
|
---|
3154 | NameZ := Name;
|
---|
3155 | DirListZ := DirList;
|
---|
3156 | {$IFDEF OS2}
|
---|
3157 | If DosSearchPath(Flags, DirListZ, NameZ, Buffer, SizeOf(Buffer)) = NO_ERROR Then
|
---|
3158 | Result := Buffer
|
---|
3159 | Else Result := '';
|
---|
3160 | {$ENDIF}
|
---|
3161 | {$IFDEF Win95}
|
---|
3162 | If SearchPath(DirListZ,Name,Nil,256,Buffer,Temp)=0 Then Result:=''
|
---|
3163 | Else Result:=Buffer;
|
---|
3164 | {$ENDIF}
|
---|
3165 | End;
|
---|
3166 |
|
---|
3167 | Function DiskFree(Drive: Byte): LongInt;
|
---|
3168 | {$IFDEF OS2}
|
---|
3169 | Var
|
---|
3170 | Buffer: FSALLOCATE;
|
---|
3171 | {$ENDIF}
|
---|
3172 | {$IFDEF Win95}
|
---|
3173 | Var
|
---|
3174 | C : cstring;
|
---|
3175 | S:LongWord;
|
---|
3176 | Sec,clust,freeclust:LongWord;
|
---|
3177 | {$ENDIF}
|
---|
3178 | Begin
|
---|
3179 | {$IFDEF OS2}
|
---|
3180 | If DosQueryFSInfo(Drive, FSIL_ALLOC, Buffer, SizeOf(Buffer)) = NO_ERROR Then
|
---|
3181 | With Buffer Do Result := cUnitAvail * cSectorUnit * cbSector
|
---|
3182 | Else Result := -1;
|
---|
3183 | {$ENDIF}
|
---|
3184 | {$IFDEF Win95}
|
---|
3185 | If Drive=0 Then
|
---|
3186 | Begin
|
---|
3187 | If Not GetDiskFreeSpace(Nil,S,Sec,freeclust,clust) Then
|
---|
3188 | Begin
|
---|
3189 | Result:=-1;
|
---|
3190 | Exit;
|
---|
3191 | End;
|
---|
3192 | End
|
---|
3193 | Else
|
---|
3194 | Begin
|
---|
3195 | C:=Chr(Ord('A')+(Drive-1))+':\';
|
---|
3196 | If Not GetDiskFreeSpace(C,S,Sec,freeclust,clust) Then
|
---|
3197 | Begin
|
---|
3198 | Result:=-1;
|
---|
3199 | Exit;
|
---|
3200 | End;
|
---|
3201 | End;
|
---|
3202 | Result:=S*Sec*freeclust;
|
---|
3203 | {$ENDIF}
|
---|
3204 | End;
|
---|
3205 |
|
---|
3206 | Function DiskSize(Drive: Byte): LongInt;
|
---|
3207 | {$IFDEF OS2}
|
---|
3208 | Var
|
---|
3209 | Buffer: FSALLOCATE;
|
---|
3210 | {$ENDIF}
|
---|
3211 | {$IFDEF Win95}
|
---|
3212 | Var
|
---|
3213 | C : cstring;
|
---|
3214 | S:LongWord;
|
---|
3215 | Sec,clust,freeclust:LongWord;
|
---|
3216 | {$ENDIF}
|
---|
3217 | Begin
|
---|
3218 | {$IFDEF OS2}
|
---|
3219 | If DosQueryFSInfo(Drive, FSIL_ALLOC, Buffer, SizeOf(Buffer)) = NO_ERROR Then
|
---|
3220 | With Buffer Do Result := cUnit * cSectorUnit * cbSector
|
---|
3221 | Else Result := -1;
|
---|
3222 | {$ENDIF}
|
---|
3223 | {$IFDEF Win95}
|
---|
3224 | If Drive=0 Then
|
---|
3225 | Begin
|
---|
3226 | If Not GetDiskFreeSpace(Nil,S,Sec,freeclust,clust) Then
|
---|
3227 | Begin
|
---|
3228 | Result:=-1;
|
---|
3229 | Exit;
|
---|
3230 | End;
|
---|
3231 | End
|
---|
3232 | Else
|
---|
3233 | Begin
|
---|
3234 | C:=Chr(Ord('A')+(Drive-1))+':\';
|
---|
3235 | If Not GetDiskFreeSpace(C,S,Sec,freeclust,clust) Then
|
---|
3236 | Begin
|
---|
3237 | Result:=-1;
|
---|
3238 | Exit;
|
---|
3239 | End;
|
---|
3240 | End;
|
---|
3241 | Result:=S*Sec*clust;
|
---|
3242 | {$ENDIF}
|
---|
3243 | End;
|
---|
3244 |
|
---|
3245 | Function FileDateToDateTime(FileDate: LongInt): TDateTime;
|
---|
3246 | Var
|
---|
3247 | Day, Month, Year, Hour, Min, Sec: Word;
|
---|
3248 | Begin
|
---|
3249 | Sec := (FileDate And 31) Shl 1;
|
---|
3250 | FileDate := FileDate Shr 5;
|
---|
3251 | Min := FileDate And 63;
|
---|
3252 | FileDate := FileDate Shr 6;
|
---|
3253 | Hour := FileDate And 31;
|
---|
3254 | FileDate := FileDate Shr 5;
|
---|
3255 |
|
---|
3256 | Day := FileDate And 31;
|
---|
3257 | FileDate := FileDate Shr 5;
|
---|
3258 | Month := FileDate And 15;
|
---|
3259 | FileDate := FileDate Shr 4;
|
---|
3260 | Year := 1980 + (FileDate And 127);
|
---|
3261 |
|
---|
3262 | Result := EncodeDate(Year, Month, Day) + EncodeTime(Hour, Min, Sec, 0);
|
---|
3263 | End;
|
---|
3264 |
|
---|
3265 | Function DateTimeToFileDate(DateTime: TDateTime): LongInt;
|
---|
3266 | Var
|
---|
3267 | Day, Month, Year, Hour, Min, Sec, MSec: Word;
|
---|
3268 | FileDate, FILETIME: LongInt;
|
---|
3269 | Begin
|
---|
3270 | DecodeDate(DateTime, Year, Month, Day);
|
---|
3271 | DecodeTime(DateTime, Hour, Min, Sec, MSec);
|
---|
3272 |
|
---|
3273 | FileDate := Year - 1980;
|
---|
3274 | FileDate := (FileDate Shl 4) Or Month;
|
---|
3275 | FileDate := (FileDate Shl 5) Or Day;
|
---|
3276 |
|
---|
3277 | FILETIME := Hour;
|
---|
3278 | FILETIME := (FILETIME Shl 6) Or Min;
|
---|
3279 | FILETIME := (FILETIME Shl 5) Or (Sec Div 2);
|
---|
3280 |
|
---|
3281 | Result := (FileDate Shl 16) Or FILETIME;
|
---|
3282 | End;
|
---|
3283 |
|
---|
3284 | /* Alte Implementierung, macht Probleme mit neuem Compiler
|
---|
3285 |
|
---|
3286 | Function DateTimeToFileDate(DateTime: TDateTime): LongInt;
|
---|
3287 | Var
|
---|
3288 | Day, Month, Year, Hour, Min, Sec, MSec: Word;
|
---|
3289 | FileDate: LongInt;
|
---|
3290 | Begin
|
---|
3291 | DecodeDate(DateTime, Year, Month, Day);
|
---|
3292 | DecodeTime(DateTime, Hour, Min, Sec, MSec);
|
---|
3293 |
|
---|
3294 | FileDate := Year - 1980;
|
---|
3295 | FileDate := (FileDate Shl 4) Or Month;
|
---|
3296 | FileDate := (FileDate Shl 5) Or Day;
|
---|
3297 | FileDate := Hour;
|
---|
3298 | FileDate := (FileDate Shl 6) Or Min;
|
---|
3299 | FileDate := (FileDate Shl 5) Or (Sec Div 2);
|
---|
3300 |
|
---|
3301 | Result := FileDate;
|
---|
3302 | End;
|
---|
3303 |
|
---|
3304 | */
|
---|
3305 |
|
---|
3306 | { --- PChar Handling --- }
|
---|
3307 |
|
---|
3308 | Function StrLen(Str:PChar): Cardinal;
|
---|
3309 | Begin
|
---|
3310 | Asm
|
---|
3311 | MOV EDI, Str
|
---|
3312 | CALLN32 !StringLength
|
---|
3313 | MOV Result, EAX
|
---|
3314 | End;
|
---|
3315 | End;
|
---|
3316 |
|
---|
3317 | Function StrEnd(Str:PChar):PChar;
|
---|
3318 | Begin
|
---|
3319 | Asm
|
---|
3320 | MOV EDI, Str
|
---|
3321 | CALLN32 !StringLength
|
---|
3322 | MOV Result, EDI
|
---|
3323 | End;
|
---|
3324 | End;
|
---|
3325 |
|
---|
3326 | Function StrMove(Dest, Source: PChar; Count: Cardinal): PChar;
|
---|
3327 | Begin
|
---|
3328 | If (Source = Nil) Or (Dest = Nil) Or (Count = 0) Then Result := Nil
|
---|
3329 | Else
|
---|
3330 | Begin
|
---|
3331 | Move(Source^, Dest^, Count);
|
---|
3332 | Result := Dest;
|
---|
3333 | End;
|
---|
3334 | End;
|
---|
3335 |
|
---|
3336 | Function StrCopy(Dest, Source:PChar):PChar;
|
---|
3337 | Begin
|
---|
3338 | Asm
|
---|
3339 | MOV ESI, Source
|
---|
3340 | MOV EDI, Dest
|
---|
3341 | MOV ECX, $FFFFFFFF
|
---|
3342 | CALLN32 !StringCopy
|
---|
3343 | MOV EAX, Dest
|
---|
3344 | MOV Result, EAX
|
---|
3345 | End;
|
---|
3346 | End;
|
---|
3347 |
|
---|
3348 | Function StrECopy(Dest, Source:PChar):PChar;
|
---|
3349 | Begin
|
---|
3350 | Asm
|
---|
3351 | MOV ESI, Source
|
---|
3352 | MOV EDI, Dest
|
---|
3353 | MOV ECX, $FFFFFFFF
|
---|
3354 | CALLN32 !StringCopy
|
---|
3355 | MOV Result, EDI
|
---|
3356 | End;
|
---|
3357 | End;
|
---|
3358 |
|
---|
3359 | Function StrLCopy(Dest, Source:PChar; MaxLen: Cardinal):PChar;
|
---|
3360 | Begin
|
---|
3361 | Asm
|
---|
3362 | MOV ESI, Source
|
---|
3363 | MOV EDI, Dest
|
---|
3364 | MOV ECX, MaxLen
|
---|
3365 | CALLN32 !StringCopy
|
---|
3366 | MOV EAX, Dest
|
---|
3367 | MOV Result, EAX
|
---|
3368 | End;
|
---|
3369 | End;
|
---|
3370 |
|
---|
3371 | Function StrPCopy(Dest: PChar; Const Source: String): PChar;
|
---|
3372 | Begin
|
---|
3373 | Asm
|
---|
3374 | MOV EDI, Dest
|
---|
3375 | MOV ESI, Source
|
---|
3376 | Xor ECX, ECX
|
---|
3377 | MOV CL, [ESI]
|
---|
3378 | Inc ESI
|
---|
3379 | CALLN32 !StringCopy
|
---|
3380 | MOV EAX, Dest
|
---|
3381 | MOV Result, EAX
|
---|
3382 | End;
|
---|
3383 | End;
|
---|
3384 |
|
---|
3385 | Function StrPLCopy(Dest: PChar; Const Source: String; MaxLen: Cardinal): PChar;
|
---|
3386 | Begin
|
---|
3387 | Asm
|
---|
3388 | MOV EDI, Dest
|
---|
3389 | MOV ESI, Source
|
---|
3390 | Xor ECX, ECX
|
---|
3391 | MOV CL, [ESI]
|
---|
3392 | Inc ESI
|
---|
3393 | CMP ECX, MaxLen
|
---|
3394 | JLE StrPLCopy_1
|
---|
3395 | MOV ECX, MaxLen
|
---|
3396 |
|
---|
3397 | StrPLCopy_1:
|
---|
3398 |
|
---|
3399 | CALLN32 !StringCopy
|
---|
3400 | MOV EAX, Dest
|
---|
3401 | MOV Result, EAX
|
---|
3402 | End;
|
---|
3403 | End;
|
---|
3404 |
|
---|
3405 | Function StrCat(Dest, Source: PChar): PChar;
|
---|
3406 | Begin
|
---|
3407 | Asm
|
---|
3408 | MOV EDI, Dest
|
---|
3409 | MOV ESI, Source
|
---|
3410 | CALLN32 !StringLength
|
---|
3411 | MOV ECX, $FFFFFFFF
|
---|
3412 | CALLN32 !StringCopy
|
---|
3413 | MOV EAX, Dest
|
---|
3414 | MOV Result, EAX
|
---|
3415 | End;
|
---|
3416 | End;
|
---|
3417 |
|
---|
3418 | Function StrLCat(Dest, Source: PChar; MaxLen: Cardinal): PChar;
|
---|
3419 | Begin
|
---|
3420 | Asm
|
---|
3421 | MOV EDI, Dest
|
---|
3422 | MOV ESI, Source
|
---|
3423 | CALLN32 !StringLength
|
---|
3424 | MOV ECX, MaxLen
|
---|
3425 | SUB ECX, EAX
|
---|
3426 | JLE StrLCat_1
|
---|
3427 | CALLN32 !StringCopy
|
---|
3428 |
|
---|
3429 | StrLCat_1:
|
---|
3430 |
|
---|
3431 | MOV EAX, Dest
|
---|
3432 | MOV Result, EAX
|
---|
3433 | End;
|
---|
3434 | End;
|
---|
3435 |
|
---|
3436 | Function StrComp(Str1, Str2: PChar): Integer;
|
---|
3437 | Begin
|
---|
3438 | Asm
|
---|
3439 | MOV EDI, Str1
|
---|
3440 | CALLN32 !StringLength
|
---|
3441 | MOV ECX, EAX
|
---|
3442 | MOV ESI, Str1
|
---|
3443 | MOV EDI, Str2
|
---|
3444 | CALLN32 !StringCompare
|
---|
3445 | MOV Result, EAX
|
---|
3446 | End;
|
---|
3447 | End;
|
---|
3448 |
|
---|
3449 | Function StrLComp(Str1, Str2: PChar; MaxLen: Cardinal): Integer;
|
---|
3450 | Begin
|
---|
3451 | Asm
|
---|
3452 | MOV EDI, Str1
|
---|
3453 | MOV ECX, MaxLen
|
---|
3454 | MOV EBX, ECX
|
---|
3455 | Xor EAX, EAX
|
---|
3456 | REPNZ SCASB
|
---|
3457 | SUB EBX, ECX
|
---|
3458 | MOV ECX, EBX
|
---|
3459 | MOV ESI, Str1
|
---|
3460 | MOV EDI, Str2
|
---|
3461 | CALLN32 !StringCompare
|
---|
3462 | MOV Result, EAX
|
---|
3463 | End;
|
---|
3464 | End;
|
---|
3465 |
|
---|
3466 | Function StrIComp(Str1, Str2: PChar): Integer;
|
---|
3467 | Begin
|
---|
3468 | Asm
|
---|
3469 | // Set MaxLen (ECX) to Maxint
|
---|
3470 | MOV ECX, $ffffffff
|
---|
3471 | MOV ESI, Str1 // Set ESI to Str1
|
---|
3472 | MOV EDI, Str2 // Set EDI to Str2
|
---|
3473 | CALLN32 !ZeroTerminatedStringICompare
|
---|
3474 | MOV Result, EAX // Set result
|
---|
3475 | End;
|
---|
3476 | End;
|
---|
3477 |
|
---|
3478 | Function StrLIComp(Str1, Str2: PChar; MaxLen: Cardinal): Integer;
|
---|
3479 | Begin
|
---|
3480 | Asm
|
---|
3481 | MOV ECX, MaxLen // put MaxLen into ECX
|
---|
3482 | MOV ESI, Str1
|
---|
3483 | MOV EDI, Str2
|
---|
3484 | CALLN32 !StringICompare
|
---|
3485 | MOV Result, EAX
|
---|
3486 | End;
|
---|
3487 | End;
|
---|
3488 |
|
---|
3489 | Function StrScan(Str: PChar; Chr: Char): PChar;
|
---|
3490 | Begin
|
---|
3491 | Asm
|
---|
3492 | MOV EDI, Str
|
---|
3493 | CALLN32 !StringLength
|
---|
3494 | Inc EAX
|
---|
3495 | MOV ECX, EAX
|
---|
3496 | Xor EBX, EBX
|
---|
3497 | MOV AL, Chr
|
---|
3498 | MOV EDI, Str
|
---|
3499 | REPNZ SCASB
|
---|
3500 | Dec EDI
|
---|
3501 | CMP AL, [EDI]
|
---|
3502 | JNE !StrScan_1
|
---|
3503 | MOV EBX, EDI
|
---|
3504 |
|
---|
3505 | !StrScan_1:
|
---|
3506 |
|
---|
3507 | MOV Result, EBX
|
---|
3508 | End;
|
---|
3509 | End;
|
---|
3510 |
|
---|
3511 | Function StrRScan(Str: PChar; Chr: Char): PChar;
|
---|
3512 | Begin
|
---|
3513 | Asm
|
---|
3514 | MOV EDI, Str
|
---|
3515 | CALLN32 !StringLength
|
---|
3516 | Inc EAX
|
---|
3517 | MOV ECX, EAX
|
---|
3518 | Xor EBX, EBX
|
---|
3519 | MOV AL, Chr
|
---|
3520 | STD
|
---|
3521 | REPNZ SCASB
|
---|
3522 | Inc EDI
|
---|
3523 | CMP AL, [EDI]
|
---|
3524 | JNE !StrRScan_1
|
---|
3525 | MOV EBX, EDI
|
---|
3526 |
|
---|
3527 | !StrRScan_1:
|
---|
3528 |
|
---|
3529 | CLD
|
---|
3530 | MOV Result, EBX
|
---|
3531 | End;
|
---|
3532 | End;
|
---|
3533 |
|
---|
3534 | Function StrPos(Str, SubStr: PChar): PChar;
|
---|
3535 | Begin
|
---|
3536 | Asm
|
---|
3537 | MOV EDI, SubStr
|
---|
3538 | CALLN32 !StringLength
|
---|
3539 | CMP EAX, 0
|
---|
3540 | JE !ErrOutStrPos
|
---|
3541 |
|
---|
3542 | MOV EDX, EAX
|
---|
3543 | MOV EDI, Str
|
---|
3544 | CALLN32 !StringLength
|
---|
3545 | CMP EAX, 0
|
---|
3546 | JE !ErrOutStrPos
|
---|
3547 | SUB EAX, EDX
|
---|
3548 | JB !ErrOutStrPos
|
---|
3549 | MOV EDI, Str
|
---|
3550 |
|
---|
3551 | !1:
|
---|
3552 |
|
---|
3553 | MOV ESI, SubStr
|
---|
3554 | LODSB
|
---|
3555 | REPNE SCASB
|
---|
3556 | JNE !ErrOutStrPos;
|
---|
3557 | MOV EAX, ECX
|
---|
3558 | PUSH EDI
|
---|
3559 | MOV ECX, EDX
|
---|
3560 | Dec ECX
|
---|
3561 | REPE CMPSB
|
---|
3562 | MOV ECX, EAX
|
---|
3563 | POP EDI
|
---|
3564 | JNE !1
|
---|
3565 | MOV EAX, EDI
|
---|
3566 | Dec EAX
|
---|
3567 | JMP !out
|
---|
3568 |
|
---|
3569 | !ErrOutStrPos:
|
---|
3570 |
|
---|
3571 | Xor EAX,EAX
|
---|
3572 |
|
---|
3573 | !out:
|
---|
3574 |
|
---|
3575 | MOV Result, EAX
|
---|
3576 | End;
|
---|
3577 | End;
|
---|
3578 |
|
---|
3579 | Function StrLower(Str: PChar): PChar;
|
---|
3580 | Begin
|
---|
3581 | Asm
|
---|
3582 | CLD
|
---|
3583 | MOV ESI, Str
|
---|
3584 |
|
---|
3585 | !StringLower1:
|
---|
3586 |
|
---|
3587 | LODSB
|
---|
3588 | Or AL, AL
|
---|
3589 | JE !OutStrLower
|
---|
3590 |
|
---|
3591 | CMP AL, 'A'
|
---|
3592 | JB !StringLower1
|
---|
3593 | CMP AL, 'Z'
|
---|
3594 | JA !StringLower1
|
---|
3595 | Or AL, 32
|
---|
3596 | MOV [ESI-1], AL
|
---|
3597 | JMP !StringLower1
|
---|
3598 |
|
---|
3599 | !OutStrLower:
|
---|
3600 |
|
---|
3601 | MOV EAX, Str
|
---|
3602 | MOV Result, EAX
|
---|
3603 | End;
|
---|
3604 | End;
|
---|
3605 |
|
---|
3606 | Function StrUpper(Str: PChar): PChar;
|
---|
3607 | Begin
|
---|
3608 | Asm
|
---|
3609 | CLD
|
---|
3610 | MOV ESI, Str
|
---|
3611 |
|
---|
3612 | !StringUpper_Loop:
|
---|
3613 |
|
---|
3614 | LODSB
|
---|
3615 | Or AL, AL
|
---|
3616 | JE !OutStrUpper
|
---|
3617 |
|
---|
3618 | CMP AL, 'a'
|
---|
3619 | JB !StringUpper_Loop
|
---|
3620 | CMP AL, 'z'
|
---|
3621 | JA !StringUpper_Loop
|
---|
3622 | And AL, $DF
|
---|
3623 | MOV [ESI-1], AL
|
---|
3624 | JMP !StringUpper_Loop
|
---|
3625 |
|
---|
3626 | !OutStrUpper:
|
---|
3627 |
|
---|
3628 | MOV EAX, Str
|
---|
3629 | MOV Result, EAX
|
---|
3630 | End;
|
---|
3631 | End;
|
---|
3632 |
|
---|
3633 | Function StrPas(Str: PChar): String;
|
---|
3634 | Begin
|
---|
3635 | Result := Str^;
|
---|
3636 | End;
|
---|
3637 |
|
---|
3638 | Function StrAlloc(Size: Cardinal): PChar;
|
---|
3639 | Type
|
---|
3640 | PLong = ^LongInt;
|
---|
3641 | Var
|
---|
3642 | P: PChar;
|
---|
3643 | Begin
|
---|
3644 | GetMem(P, Size + 4);
|
---|
3645 | PLong(P)^ := Size + 4;
|
---|
3646 | Inc(P, 4);
|
---|
3647 | StrAlloc := P;
|
---|
3648 | End;
|
---|
3649 |
|
---|
3650 | Function StrBufSize(Str: PChar): Cardinal;
|
---|
3651 | Type
|
---|
3652 | PLong = ^LongInt;
|
---|
3653 | Begin
|
---|
3654 | Dec(Str, 4);
|
---|
3655 | StrBufSize := PLong(Str)^ - 4;
|
---|
3656 | End;
|
---|
3657 |
|
---|
3658 | Function StrNew(Str: PChar): PChar;
|
---|
3659 | Var
|
---|
3660 | Size: LongInt;
|
---|
3661 | Begin
|
---|
3662 | If Str = Nil Then StrNew := Nil
|
---|
3663 | Else
|
---|
3664 | Begin
|
---|
3665 | Size := StrLen(Str) + 1;
|
---|
3666 | StrNew := StrMove(StrAlloc(Size), Str, Size);
|
---|
3667 | End;
|
---|
3668 | End;
|
---|
3669 |
|
---|
3670 | Procedure StrDispose(Str: PChar);
|
---|
3671 | Type
|
---|
3672 | PLong = ^LongInt;
|
---|
3673 | Begin
|
---|
3674 | If Str <> Nil Then
|
---|
3675 | If Str <> NullStr Then
|
---|
3676 | Begin
|
---|
3677 | Dec(Str, 4);
|
---|
3678 | FreeMem(Str, PLong(Str)^);
|
---|
3679 | End;
|
---|
3680 | End;
|
---|
3681 |
|
---|
3682 | { --- String formatting --- }
|
---|
3683 |
|
---|
3684 | {$HINTS OFF}
|
---|
3685 | Function FormatBuf(Var Buffer; BufLen: Cardinal; Const format; FmtLen: Cardinal; Const Args: Array Of Const): Cardinal;
|
---|
3686 | Var
|
---|
3687 | { format And Result buffers }
|
---|
3688 |
|
---|
3689 | FmtPos, OldFmtPos, BufPos, ArgPos: LongInt;
|
---|
3690 | Buf: cstring Absolute Buffer;
|
---|
3691 | Fmt: cstring Absolute format;
|
---|
3692 |
|
---|
3693 | { argument Buffer }
|
---|
3694 |
|
---|
3695 | VArgs: Array[0..1023] Of TVarRec Absolute Args;
|
---|
3696 |
|
---|
3697 | { Workaround For High() problem }
|
---|
3698 |
|
---|
3699 | High_Args: LongInt;
|
---|
3700 |
|
---|
3701 | { format Details }
|
---|
3702 |
|
---|
3703 | Index, Width, Precision: LongInt;
|
---|
3704 | LeftAlign: Boolean;
|
---|
3705 | ArgType: Char;
|
---|
3706 |
|
---|
3707 | { temporary variables }
|
---|
3708 |
|
---|
3709 | C: Char;
|
---|
3710 | P: Pointer;
|
---|
3711 | E: Extended;
|
---|
3712 | Pnt,M:LongInt;
|
---|
3713 | L: LongInt;
|
---|
3714 | S: String[80];
|
---|
3715 |
|
---|
3716 | { Raise Exception: format And argument don't match }
|
---|
3717 |
|
---|
3718 | Procedure IllegalArg;
|
---|
3719 | Begin
|
---|
3720 | FmtLoadConvertError(SInvalidFormat, [ArgType]);
|
---|
3721 | End;
|
---|
3722 |
|
---|
3723 | { Raise Exception: out Of arguments }
|
---|
3724 |
|
---|
3725 | Procedure OutOfArgs;
|
---|
3726 | Begin
|
---|
3727 | FmtLoadConvertError(SArgumentMissing, [ArgType]);
|
---|
3728 | End;
|
---|
3729 |
|
---|
3730 | { Get an argument from the Open Array. If the
|
---|
3731 | Type Is unexpected, Raise an Exception. }
|
---|
3732 |
|
---|
3733 | Function GetIntegerArg: LongInt;
|
---|
3734 | Begin
|
---|
3735 | If ArgPos > High_Args Then OutOfArgs;
|
---|
3736 | If VArgs[ArgPos].VType <> vtInteger Then IllegalArg;
|
---|
3737 | Result := VArgs[ArgPos].VInteger;
|
---|
3738 | Inc(ArgPos);
|
---|
3739 | End;
|
---|
3740 |
|
---|
3741 | Function GetExtendedArg: Extended;
|
---|
3742 | Begin
|
---|
3743 | If ArgPos > High_Args Then OutOfArgs;
|
---|
3744 | If VArgs[ArgPos].VType <> vtExtended Then IllegalArg;
|
---|
3745 | Result := VArgs[ArgPos].VExtended^;
|
---|
3746 | Inc(ArgPos);
|
---|
3747 | End;
|
---|
3748 |
|
---|
3749 | Function GetPointerArg: Pointer;
|
---|
3750 | Begin
|
---|
3751 | If ArgPos > High_Args Then OutOfArgs;
|
---|
3752 | If VArgs[ArgPos].VType <> vtPointer Then IllegalArg;
|
---|
3753 | Result := VArgs[ArgPos].VPointer;
|
---|
3754 | Inc(ArgPos);
|
---|
3755 | End;
|
---|
3756 |
|
---|
3757 | Procedure GetStringArg(Var FirstChar: Pointer; Var len: LongInt);
|
---|
3758 | Begin
|
---|
3759 | If ArgPos > High_Args Then OutOfArgs;
|
---|
3760 | Case VArgs[ArgPos].VType Of
|
---|
3761 | vtChar:
|
---|
3762 | Begin
|
---|
3763 | FirstChar := @VArgs[ArgPos].VChar;
|
---|
3764 | len := 1;
|
---|
3765 | End;
|
---|
3766 |
|
---|
3767 | vtString:
|
---|
3768 | Begin
|
---|
3769 | FirstChar := VArgs[ArgPos].VString;
|
---|
3770 | len := Byte(FirstChar^);
|
---|
3771 | Inc(FirstChar);
|
---|
3772 | End;
|
---|
3773 |
|
---|
3774 | vtPointer,
|
---|
3775 | vtPChar:
|
---|
3776 | Begin
|
---|
3777 | FirstChar := VArgs[ArgPos].VPChar;
|
---|
3778 | len := StrLen(FirstChar);
|
---|
3779 | End;
|
---|
3780 |
|
---|
3781 | vtAnsiString:
|
---|
3782 | Begin
|
---|
3783 | FirstChar := VArgs[ArgPos].VPChar;
|
---|
3784 | len := Length(AnsiString(VArgs[ArgPos].VAnsiString));
|
---|
3785 | End;
|
---|
3786 | Else
|
---|
3787 | IllegalArg;
|
---|
3788 | End;
|
---|
3789 | Inc(ArgPos);
|
---|
3790 | End;
|
---|
3791 |
|
---|
3792 | { Parse A Number from the format String. A '*' means:
|
---|
3793 | Get the Next Integer argument from the Open Array. }
|
---|
3794 |
|
---|
3795 | Function ParseNum: LongInt;
|
---|
3796 | Begin
|
---|
3797 | If Fmt[FmtPos] = '*' Then Result := GetIntegerArg
|
---|
3798 | Else
|
---|
3799 | Begin
|
---|
3800 | Result := 0;
|
---|
3801 | While (Fmt[FmtPos] In ['0'..'9']) And (FmtPos < FmtLen) Do
|
---|
3802 | Begin
|
---|
3803 | Result := Result * 10 + Ord(Fmt[FmtPos]) - 48;
|
---|
3804 | Inc(FmtPos);
|
---|
3805 | End;
|
---|
3806 | End;
|
---|
3807 | End;
|
---|
3808 |
|
---|
3809 | { Parse A whole format specifier. }
|
---|
3810 |
|
---|
3811 | Function ParseFmtSpec: Char;
|
---|
3812 | Label
|
---|
3813 | LIndex, LColon, LMinus, LWidth, LPoint, LType;
|
---|
3814 | Begin
|
---|
3815 | Width := -1;
|
---|
3816 | Index := -1;
|
---|
3817 | Precision := -1;
|
---|
3818 | LeftAlign := False;
|
---|
3819 | ArgType := #0;
|
---|
3820 | C := Fmt[FmtPos];
|
---|
3821 |
|
---|
3822 | LIndex:
|
---|
3823 |
|
---|
3824 | If Not (C In ['0'..'9']) Then Goto LMinus;
|
---|
3825 | Width := ParseNum;
|
---|
3826 | If FmtPos >= FmtLen Then Exit;
|
---|
3827 | C := Fmt[FmtPos];
|
---|
3828 |
|
---|
3829 | LColon:
|
---|
3830 |
|
---|
3831 | If C <> ':' Then Goto LPoint;
|
---|
3832 | Index := Width;
|
---|
3833 | Width := -1;
|
---|
3834 | Inc(FmtPos);
|
---|
3835 | If FmtPos >= FmtLen Then Exit;
|
---|
3836 | C := Fmt[FmtPos];
|
---|
3837 |
|
---|
3838 | LMinus:
|
---|
3839 |
|
---|
3840 | If C <> '-' Then Goto LWidth;
|
---|
3841 | LeftAlign := True;
|
---|
3842 | Inc(FmtPos);
|
---|
3843 | If FmtPos >= FmtLen Then Exit;
|
---|
3844 | C := Fmt[FmtPos];
|
---|
3845 |
|
---|
3846 | LWidth:
|
---|
3847 |
|
---|
3848 | If Not (C In ['0'..'9']) Then Goto LPoint;
|
---|
3849 | Width := ParseNum;
|
---|
3850 | If FmtPos >= FmtLen Then Exit;
|
---|
3851 | C := Fmt[FmtPos];
|
---|
3852 |
|
---|
3853 | LPoint:
|
---|
3854 |
|
---|
3855 | If C <> '.' Then Goto LType;
|
---|
3856 | Inc(FmtPos);
|
---|
3857 | Precision := ParseNum;
|
---|
3858 | If FmtPos >= FmtLen Then Exit;
|
---|
3859 | C := Fmt[FmtPos];
|
---|
3860 |
|
---|
3861 | LType:
|
---|
3862 |
|
---|
3863 | Result := UpCase(C);
|
---|
3864 | ArgType := Result;
|
---|
3865 |
|
---|
3866 | {WriteLn;
|
---|
3867 | WriteLn('Index:', Index, ' Align:', LeftAlign, ' Width:', Width, ' Prec: ', Precision, ' Type:', Result);
|
---|
3868 | WriteLn;}
|
---|
3869 |
|
---|
3870 | Inc(FmtPos);
|
---|
3871 | End;
|
---|
3872 |
|
---|
3873 | { Append something To the Result Buffer }
|
---|
3874 |
|
---|
3875 | Procedure AppendStr(P: Pointer; Count: LongInt);
|
---|
3876 | Begin
|
---|
3877 | If BufLen - BufPos < Count Then Count := BufLen - BufPos;
|
---|
3878 | Move(P^, Buf[BufPos], Count);
|
---|
3879 | Inc(BufPos, Count);
|
---|
3880 | End;
|
---|
3881 |
|
---|
3882 | Procedure AppendChar(C: Char; Count: LongInt);
|
---|
3883 | Begin
|
---|
3884 | If BufLen - BufPos < Count Then Count := BufLen - BufPos;
|
---|
3885 | FillChar(Buf[BufPos], Count, C);
|
---|
3886 | Inc(BufPos, Count);
|
---|
3887 | End;
|
---|
3888 |
|
---|
3889 | Begin
|
---|
3890 | FmtPos := 0;
|
---|
3891 | OldFmtPos := 0;
|
---|
3892 | BufPos := 0;
|
---|
3893 | ArgPos := 0;
|
---|
3894 |
|
---|
3895 | High_Args := High(Args);
|
---|
3896 |
|
---|
3897 | While (FmtPos < FmtLen) And (BufPos < BufLen) Do
|
---|
3898 | Begin
|
---|
3899 | C := Fmt[FmtPos];
|
---|
3900 | Inc(FmtPos);
|
---|
3901 | If C = '%' Then
|
---|
3902 | Begin
|
---|
3903 | C := ParseFmtSpec;
|
---|
3904 | If C = 'S' Then
|
---|
3905 | Begin
|
---|
3906 | GetStringArg(P, L);
|
---|
3907 | If (Precision > -1) And (Precision < L) Then L := Precision;
|
---|
3908 | End
|
---|
3909 | Else
|
---|
3910 | Begin
|
---|
3911 | Case C Of
|
---|
3912 | 'D': Begin
|
---|
3913 | Str(GetIntegerArg, S);
|
---|
3914 | L := Length(S);
|
---|
3915 | If (Precision <> -1) And (L < Precision) Then
|
---|
3916 | Begin
|
---|
3917 | SetLength(S, Precision);
|
---|
3918 | Move(S[1], S[1 + Precision - L], L);
|
---|
3919 | FillChar(S[1], Precision - L, '0');
|
---|
3920 | End;
|
---|
3921 | End;
|
---|
3922 | 'E': S := FloatToStrF(GetExtendedArg, ffExponent, Precision, 3);
|
---|
3923 | 'F': S := FloatToStrF(GetExtendedArg, ffFixed, 9999, Precision);
|
---|
3924 | 'G': S := FloatToStrF(GetExtendedArg, ffGeneral, Precision, 3);
|
---|
3925 | 'N': S := FloatToStrF(GetExtendedArg, ffFixed, 9999, Precision);
|
---|
3926 | 'M': S := FloatToStrF(GetExtendedArg, ffCurrency, 9999, Precision);
|
---|
3927 | 'P': Begin
|
---|
3928 | L := LongInt(GetPointerArg);
|
---|
3929 | S := IntToHex(L Shr 16, 4) + ':' + IntToHex(L And $FFFF, 4);
|
---|
3930 | End;
|
---|
3931 | 'X': Begin
|
---|
3932 | If Precision <> -1 Then S := IntToHex(GetIntegerArg, Precision)
|
---|
3933 | Else S := IntToHex(GetIntegerArg, 0);
|
---|
3934 | End;
|
---|
3935 | Else FmtLoadConvertError(SInvalidFormat, [C]);
|
---|
3936 | End;
|
---|
3937 | P := @S[1];
|
---|
3938 | L := Length(S);
|
---|
3939 | End;
|
---|
3940 |
|
---|
3941 | { now P Points To the First Char To Append To our Result, L holds the
|
---|
3942 | Length Of the Text To Insert. If Width > L Then we have To pad our
|
---|
3943 | Text With spaces. }
|
---|
3944 |
|
---|
3945 | If LeftAlign Then
|
---|
3946 | Begin
|
---|
3947 | AppendStr(P, L);
|
---|
3948 | If (Width > -1) And (L < Width) Then AppendChar(' ', Width - L );
|
---|
3949 | End
|
---|
3950 | Else
|
---|
3951 | Begin
|
---|
3952 | If (Width > -1) And (L < Width) Then AppendChar(' ', Width - L );
|
---|
3953 | AppendStr(P, L);
|
---|
3954 | End;
|
---|
3955 | End
|
---|
3956 | Else
|
---|
3957 | Begin
|
---|
3958 | { Ordinary character }
|
---|
3959 | Buf[BufPos] := C;
|
---|
3960 | Inc(BufPos);
|
---|
3961 | End;
|
---|
3962 | OldFmtPos := FmtPos;
|
---|
3963 | End;
|
---|
3964 | Result := BufPos;
|
---|
3965 | End;
|
---|
3966 | {$HINTS ON}
|
---|
3967 |
|
---|
3968 |
|
---|
3969 | Function format(Const format: String; Const Args: Array Of Const): String;
|
---|
3970 | Begin
|
---|
3971 | SetLength(Result, FormatBuf(Result[1], 255, format[1], Length(format), Args));
|
---|
3972 | End;
|
---|
3973 |
|
---|
3974 | Procedure FmtStr(Var Result: String; Const format: String; Const Args: Array Of Const);
|
---|
3975 | Begin
|
---|
3976 | SetLength(Result, FormatBuf(Result[1], 255, format[1], Length(format), Args));
|
---|
3977 | End;
|
---|
3978 |
|
---|
3979 | Function StrFmt(Buffer, format: PChar; Const Args: Array Of Const): PChar;
|
---|
3980 | Begin
|
---|
3981 | FormatBuf(Buffer, MaxLongInt, format, StrLen(format), Args);
|
---|
3982 | Result := Buffer;
|
---|
3983 | End;
|
---|
3984 |
|
---|
3985 | Function StrLFmt(Buffer: PChar; MaxLen: Cardinal; format: PChar; Const Args: Array Of Const): PChar;
|
---|
3986 | Begin
|
---|
3987 | FormatBuf(Buffer, MaxLen, format, StrLen(format), Args);
|
---|
3988 | Result := Buffer;
|
---|
3989 | End;
|
---|
3990 |
|
---|
3991 | { --- floating Point conversion --- }
|
---|
3992 |
|
---|
3993 | Function FloatToStr(Value: Extended): String;
|
---|
3994 | Begin
|
---|
3995 | Result := FloatToStrF(Value, ffGeneral, 15, 0);
|
---|
3996 | End;
|
---|
3997 |
|
---|
3998 | Function FloatToStrF(Value: Extended; format: TFloatFormat; Precision, Digits: Integer): String;
|
---|
3999 | Var
|
---|
4000 | P: Integer;
|
---|
4001 | Negative, TooSmall, TooLarge: Boolean;
|
---|
4002 | Begin
|
---|
4003 | Case format Of
|
---|
4004 |
|
---|
4005 | ffGeneral:
|
---|
4006 |
|
---|
4007 | Begin
|
---|
4008 | If (Precision = -1) Or (Precision > 15) Then Precision := 15;
|
---|
4009 | TooSmall := Abs(Value) < 0.00001;
|
---|
4010 | If Not TooSmall Then
|
---|
4011 | Begin
|
---|
4012 | Str(Value:0:999, Result);
|
---|
4013 | P := Pos('.', Result);
|
---|
4014 | Result[P] := DecimalSeparator;
|
---|
4015 | TooLarge := P > Precision + 1;
|
---|
4016 | End;
|
---|
4017 |
|
---|
4018 | If TooSmall Or TooLarge Then
|
---|
4019 | Result := FloatToStrF(Value, ffExponent, Precision, Digits);
|
---|
4020 |
|
---|
4021 | P := Length(Result);
|
---|
4022 | While Result[P] = '0' Do Dec(P);
|
---|
4023 | If Result[P] = DecimalSeparator Then Dec(P);
|
---|
4024 | SetLength(Result, P);
|
---|
4025 | End;
|
---|
4026 |
|
---|
4027 | ffExponent:
|
---|
4028 |
|
---|
4029 | Begin
|
---|
4030 | If (Precision = -1) Or (Precision > 15) Then Precision := 15;
|
---|
4031 | Str(Value:Precision + 8, Result);
|
---|
4032 | Result[3] := DecimalSeparator;
|
---|
4033 | If (Digits < 4) And (Result[Precision + 5] = '0') Then
|
---|
4034 | Begin
|
---|
4035 | Delete(Result, Precision + 5, 1);
|
---|
4036 | If (Digits < 3) And (Result[Precision + 5] = '0') Then
|
---|
4037 | Begin
|
---|
4038 | Delete(Result, Precision + 5, 1);
|
---|
4039 | If (Digits < 2) And (Result[Precision + 5] = '0') Then
|
---|
4040 | Begin
|
---|
4041 | Delete(Result, Precision + 5, 1);
|
---|
4042 | If (Digits < 1) And (Result[Precision + 5] = '0') Then Delete(Result, Precision + 3, 3);
|
---|
4043 | End;
|
---|
4044 | End;
|
---|
4045 | End;
|
---|
4046 | If Result[1] = ' ' Then Delete(Result, 1, 1);
|
---|
4047 | End;
|
---|
4048 |
|
---|
4049 | ffFixed:
|
---|
4050 |
|
---|
4051 | Begin
|
---|
4052 | If Digits = -1 Then Digits := 2
|
---|
4053 | Else If Digits > 15 Then Digits := 15;
|
---|
4054 | Str(Value:0:Digits, Result);
|
---|
4055 | If Result[1] = ' ' Then Delete(Result, 1, 1);
|
---|
4056 | P := Pos('.', Result);
|
---|
4057 | If P <> 0 Then Result[P] := DecimalSeparator;
|
---|
4058 | End;
|
---|
4059 |
|
---|
4060 | ffNumber:
|
---|
4061 |
|
---|
4062 | Begin
|
---|
4063 | If Digits = -1 Then Digits := 2
|
---|
4064 | Else If Digits > 15 Then Digits := 15;
|
---|
4065 | Str(Value:0:Digits, Result);
|
---|
4066 | If Result[1] = ' ' Then Delete(Result, 1, 1);
|
---|
4067 | P := Pos('.', Result);
|
---|
4068 | If P <> 0 Then Result[P] := DecimalSeparator;
|
---|
4069 | Dec(P, 3);
|
---|
4070 | While (P > 1) Do
|
---|
4071 | Begin
|
---|
4072 | If Result[P - 1] <> '-' Then Insert(ThousandSeparator, Result, P);
|
---|
4073 | Dec(P, 3);
|
---|
4074 | End;
|
---|
4075 | End;
|
---|
4076 |
|
---|
4077 | ffCurrency:
|
---|
4078 |
|
---|
4079 | Begin
|
---|
4080 | If Value < 0 Then
|
---|
4081 | Begin
|
---|
4082 | Negative := True;
|
---|
4083 | Value := -Value;
|
---|
4084 | End
|
---|
4085 | Else Negative := False;
|
---|
4086 |
|
---|
4087 | If Digits = -1 Then Digits := CurrencyDecimals
|
---|
4088 | Else If Digits > 15 Then Digits := 15;
|
---|
4089 | Str(Value:0:Digits, Result);
|
---|
4090 | If Result[1] = ' ' Then Delete(Result, 1, 1);
|
---|
4091 | P := Pos('.', Result);
|
---|
4092 | If P <> 0 Then Result[P] := DecimalSeparator;
|
---|
4093 | Dec(P, 3);
|
---|
4094 | While (P > 1) Do
|
---|
4095 | Begin
|
---|
4096 | Insert(ThousandSeparator, Result, P);
|
---|
4097 | Dec(P, 3);
|
---|
4098 | End;
|
---|
4099 |
|
---|
4100 | If Not Negative Then
|
---|
4101 | Begin
|
---|
4102 | Case CurrencyFormat Of
|
---|
4103 | 0: Result := CurrencyString + Result;
|
---|
4104 | 1: Result := Result + CurrencyString;
|
---|
4105 | 2: Result := CurrencyString + ' ' + Result;
|
---|
4106 | 3: Result := Result + ' ' + CurrencyString;
|
---|
4107 | End
|
---|
4108 | End
|
---|
4109 | Else
|
---|
4110 | Begin
|
---|
4111 | Case NegCurrFormat Of
|
---|
4112 | 0: Result := '(' + CurrencyString + Result + ')';
|
---|
4113 | 1: Result := '-' + CurrencyString + Result;
|
---|
4114 | 2: Result := CurrencyString + '-' + Result;
|
---|
4115 | 3: Result := CurrencyString + Result + '-';
|
---|
4116 | 4: Result := '(' + Result + CurrencyString + ')';
|
---|
4117 | 5: Result := '-' + Result + CurrencyString;
|
---|
4118 | 6: Result := Result + '-' + CurrencyString;
|
---|
4119 | 7: Result := Result + CurrencyString + '-';
|
---|
4120 | 8: Result := '-' + Result + ' ' + CurrencyString;
|
---|
4121 | 9: Result := '-' + CurrencyString + ' ' + Result;
|
---|
4122 | 10: Result := CurrencyString + ' ' + Result + '-';
|
---|
4123 | End;
|
---|
4124 | End;
|
---|
4125 | End;
|
---|
4126 | End;
|
---|
4127 | End;
|
---|
4128 |
|
---|
4129 | Function FloatToText(Buffer: PChar; Value: Extended; format: TFloatFormat; Precision, Digits: Integer): Integer;
|
---|
4130 | Var
|
---|
4131 | Tmp: String[40];
|
---|
4132 | Begin
|
---|
4133 | Tmp := FloatToStrF(Value, format, Precision, Digits);
|
---|
4134 | Result := Length(Tmp);
|
---|
4135 | Move(Tmp[1], Buffer[0], Result);
|
---|
4136 | End;
|
---|
4137 |
|
---|
4138 | Function StrToFloat(Const S: String): Extended;
|
---|
4139 | Var
|
---|
4140 | Error: Integer;
|
---|
4141 | Tmp: String;
|
---|
4142 | P: Integer;
|
---|
4143 | Begin
|
---|
4144 | Tmp := S;
|
---|
4145 | P := Pos(DecimalSeparator, Tmp);
|
---|
4146 | If P <> 0 Then Tmp[P] := '.';
|
---|
4147 | Val(Tmp, Result, Error);
|
---|
4148 | If Error <> 0 Then FmtLoadConvertError(SInvalidFloat, [S]);
|
---|
4149 | End;
|
---|
4150 |
|
---|
4151 | Function TextToFloat(Buffer: PChar; Var Value: Extended): Boolean;
|
---|
4152 | Var
|
---|
4153 | Error: Integer;
|
---|
4154 | Tmp: String;
|
---|
4155 | P: Integer;
|
---|
4156 | Begin
|
---|
4157 | Tmp := StrPas(Buffer);
|
---|
4158 | P := Pos(DecimalSeparator, Tmp);
|
---|
4159 | If P <> 0 Then Tmp[P] := '.';
|
---|
4160 | Val(Tmp, Value, Error);
|
---|
4161 | Result := (Error = 0);
|
---|
4162 | End;
|
---|
4163 |
|
---|
4164 | Function FloatToTextFmt(Buffer: PChar; Value: Extended; format: PChar): Integer;
|
---|
4165 | Var
|
---|
4166 | Digits: String[40]; { String Of Digits }
|
---|
4167 | Exponent: String[8]; { Exponent strin }
|
---|
4168 | FmtStart, FmtStop: PChar; { Start And End Of relevant part }
|
---|
4169 | { Of format String }
|
---|
4170 | ExpFmt, ExpSize: Integer; { Type And Length Of }
|
---|
4171 | { exponential format chosen }
|
---|
4172 | Placehold: Array[1..4] Of Integer; { Number Of placeholders In All }
|
---|
4173 | { four Sections }
|
---|
4174 | thousand: Boolean; { thousand separators? }
|
---|
4175 | UnexpectedDigits: Integer; { Number Of unexpected Digits that }
|
---|
4176 | { have To be inserted before the }
|
---|
4177 | { First placeholder. }
|
---|
4178 | DigitExponent: Integer; { Exponent Of First digit In }
|
---|
4179 | { Digits Array. }
|
---|
4180 |
|
---|
4181 | { Find end of format section starting at P. False, if empty }
|
---|
4182 |
|
---|
4183 | Function GetSectionEnd(Var P: PChar): Boolean;
|
---|
4184 | Var
|
---|
4185 | C: Char;
|
---|
4186 | SQ, DQ: Boolean;
|
---|
4187 | Begin
|
---|
4188 | Result := False;
|
---|
4189 | SQ := False;
|
---|
4190 | DQ := False;
|
---|
4191 | C := P[0];
|
---|
4192 | While (C <> #0) And ((C <> ';') Or SQ Or DQ) Do
|
---|
4193 | Begin
|
---|
4194 | Result := True;
|
---|
4195 | Case C Of
|
---|
4196 | #34: If Not SQ Then DQ := Not DQ;
|
---|
4197 | #39: If Not DQ Then SQ := Not SQ;
|
---|
4198 | End;
|
---|
4199 | Inc(P);
|
---|
4200 | C := P[0];
|
---|
4201 | End;
|
---|
4202 | End;
|
---|
4203 |
|
---|
4204 | { Find start and end of format section to apply. If section doesn't exist,
|
---|
4205 | use section 1. If section 2 is used, the sign of value is ignored. }
|
---|
4206 |
|
---|
4207 | Procedure GetSectionRange(section: Integer);
|
---|
4208 | Var
|
---|
4209 | Sec: Array[1..3] Of PChar;
|
---|
4210 | SecOk: Array[1..3] Of Boolean;
|
---|
4211 | Begin
|
---|
4212 | Sec[1] := format;
|
---|
4213 | SecOk[1] := GetSectionEnd(Sec[1]);
|
---|
4214 | If section > 1 Then
|
---|
4215 | Begin
|
---|
4216 | Sec[2] := Sec[1];
|
---|
4217 | If Sec[2][0] <> #0 Then Inc(Sec[2]);
|
---|
4218 | SecOk[2] := GetSectionEnd(Sec[2]);
|
---|
4219 | If section > 2 Then
|
---|
4220 | Begin
|
---|
4221 | Sec[3] := Sec[2];
|
---|
4222 | If Sec[3][0] <> #0 Then Inc(Sec[3]);
|
---|
4223 | SecOk[3] := GetSectionEnd(Sec[3]);
|
---|
4224 | End;
|
---|
4225 | End;
|
---|
4226 | If Not SecOk[1] Then FmtStart := Nil
|
---|
4227 | Else
|
---|
4228 | Begin
|
---|
4229 | If Not SecOk[section] Then section := 1
|
---|
4230 | Else If section = 2 Then Value := -Value; { Remove sign }
|
---|
4231 | If section = 1 Then FmtStart := format Else
|
---|
4232 | Begin
|
---|
4233 | FmtStart := Sec[section - 1];
|
---|
4234 | Inc(FmtStart);
|
---|
4235 | End;
|
---|
4236 | FmtStop := Sec[section];
|
---|
4237 | End;
|
---|
4238 | End;
|
---|
4239 |
|
---|
4240 | { Find format section ranging from FmtStart to FmtStop. }
|
---|
4241 |
|
---|
4242 | Procedure GetFormatOptions;
|
---|
4243 | Var
|
---|
4244 | Fmt: PChar;
|
---|
4245 | SQ, DQ: Boolean;
|
---|
4246 | area: Integer;
|
---|
4247 | Begin
|
---|
4248 | SQ := False;
|
---|
4249 | DQ := False;
|
---|
4250 | Fmt := FmtStart;
|
---|
4251 | ExpFmt := 0;
|
---|
4252 | area := 1;
|
---|
4253 | thousand := False;
|
---|
4254 | Placehold[1] := 0;
|
---|
4255 | Placehold[2] := 0;
|
---|
4256 | Placehold[3] := 0;
|
---|
4257 | Placehold[4] := 0;
|
---|
4258 |
|
---|
4259 | While Fmt < FmtStop Do
|
---|
4260 | Begin
|
---|
4261 | Case Fmt[0] Of
|
---|
4262 | #34:
|
---|
4263 | Begin
|
---|
4264 | If Not SQ Then DQ := Not DQ;
|
---|
4265 | Inc(Fmt);
|
---|
4266 | End;
|
---|
4267 |
|
---|
4268 | #39:
|
---|
4269 | Begin
|
---|
4270 | If Not DQ Then SQ := Not SQ;
|
---|
4271 | Inc(Fmt);
|
---|
4272 | End;
|
---|
4273 |
|
---|
4274 | Else
|
---|
4275 | { This was 'if not SQ or DQ'. Looked wrong... }
|
---|
4276 | If Not SQ Or DQ Then
|
---|
4277 | Begin
|
---|
4278 | Case Fmt[0] Of
|
---|
4279 | '0':
|
---|
4280 | Begin
|
---|
4281 | Case area Of
|
---|
4282 | 1:
|
---|
4283 | area := 2;
|
---|
4284 | 4:
|
---|
4285 | Begin
|
---|
4286 | area := 3;
|
---|
4287 | Inc(Placehold[3], Placehold[4]);
|
---|
4288 | Placehold[4] := 0;
|
---|
4289 | End;
|
---|
4290 | End;
|
---|
4291 | Inc(Placehold[area]);
|
---|
4292 | Inc(Fmt);
|
---|
4293 | End;
|
---|
4294 |
|
---|
4295 | '#':
|
---|
4296 | Begin
|
---|
4297 | If area = 3 Then area := 4;
|
---|
4298 | Inc(Placehold[area]);
|
---|
4299 | Inc(Fmt);
|
---|
4300 | End;
|
---|
4301 |
|
---|
4302 | '.':
|
---|
4303 | Begin
|
---|
4304 | If area < 3 Then area := 3;
|
---|
4305 | Inc(Fmt);
|
---|
4306 | End;
|
---|
4307 |
|
---|
4308 | ',':
|
---|
4309 | Begin
|
---|
4310 | thousand := True;
|
---|
4311 | Inc(Fmt);
|
---|
4312 | End;
|
---|
4313 |
|
---|
4314 | 'e', 'E':
|
---|
4315 | If ExpFmt = 0 Then
|
---|
4316 | Begin
|
---|
4317 | If Fmt[0] = 'E' Then ExpFmt := 1 Else ExpFmt := 3;
|
---|
4318 | Inc(Fmt);
|
---|
4319 | If Fmt < FmtStop Then
|
---|
4320 | Begin
|
---|
4321 | Case Fmt[0] Of
|
---|
4322 | '+':
|
---|
4323 | Begin
|
---|
4324 | End;
|
---|
4325 |
|
---|
4326 | '-':
|
---|
4327 | Inc(ExpFmt);
|
---|
4328 |
|
---|
4329 | Else
|
---|
4330 | ExpFmt := 0;
|
---|
4331 | End;
|
---|
4332 |
|
---|
4333 | If ExpFmt <> 0 Then
|
---|
4334 | Begin
|
---|
4335 | Inc(Fmt);
|
---|
4336 | ExpSize := 0;
|
---|
4337 | While (Fmt < FmtStop) And (ExpSize < 4) And (Fmt[0] In ['0'..'9']) Do
|
---|
4338 | Begin
|
---|
4339 | Inc(ExpSize);
|
---|
4340 | Inc(Fmt);
|
---|
4341 | End;
|
---|
4342 | End;
|
---|
4343 | End;
|
---|
4344 | End
|
---|
4345 | Else Inc(Fmt);
|
---|
4346 |
|
---|
4347 | Else { Case }
|
---|
4348 | Inc(Fmt);
|
---|
4349 | End; { Case }
|
---|
4350 | End; { Begin }
|
---|
4351 | End; { Case }
|
---|
4352 | End; { While .. Begin }
|
---|
4353 | End;
|
---|
4354 |
|
---|
4355 | Procedure FloatToStr;
|
---|
4356 | Var
|
---|
4357 | I, J, Exp, Width, Decimals, DecimalPoint, len: Integer;
|
---|
4358 | Begin
|
---|
4359 | If ExpFmt = 0 Then
|
---|
4360 | Begin
|
---|
4361 | { Fixpoint }
|
---|
4362 | Decimals := Placehold[3] + Placehold[4];
|
---|
4363 | Width := Placehold[1] + Placehold[2] + Decimals;
|
---|
4364 |
|
---|
4365 | If Decimals = 0 Then Str(Value: Width: 0, Digits)
|
---|
4366 | Else Str(Value: Width + 1: Decimals, Digits);
|
---|
4367 |
|
---|
4368 | len := Length(Digits);
|
---|
4369 |
|
---|
4370 | { Find the decimal point }
|
---|
4371 | If Decimals = 0 Then DecimalPoint := len + 1 Else DecimalPoint := len - Decimals;
|
---|
4372 |
|
---|
4373 | { If value is very small, and no decimal places
|
---|
4374 | are desired, remove the leading 0. }
|
---|
4375 | If (Abs(Value) < 1) And (Placehold[2] = 0) Then
|
---|
4376 | Begin
|
---|
4377 | If Placehold[1] = 0 Then Delete(Digits, DecimalPoint - 1, 1)
|
---|
4378 | Else Digits[DecimalPoint - 1] := ' ';
|
---|
4379 | End;
|
---|
4380 |
|
---|
4381 | { Convert optional zeroes to spaces. }
|
---|
4382 | I := len;
|
---|
4383 | J := DecimalPoint + Placehold[3];
|
---|
4384 | While (I > J) And (Digits[I] = '0') Do
|
---|
4385 | Begin
|
---|
4386 | Digits[I] := ' ';
|
---|
4387 | Dec(I);
|
---|
4388 | End;
|
---|
4389 |
|
---|
4390 | { If integer value and no obligatory decimal
|
---|
4391 | places, remove decimal point. }
|
---|
4392 |
|
---|
4393 | If (DecimalPoint < len) And (Digits[DecimalPoint + 1] = ' ') Then
|
---|
4394 | Digits[DecimalPoint] := ' ';
|
---|
4395 |
|
---|
4396 | { Convert spaces left from obligatory decimal point to zeroes. }
|
---|
4397 |
|
---|
4398 | I := DecimalPoint - Placehold[2];
|
---|
4399 | While (I < DecimalPoint) And (Digits[I] = ' ') Do
|
---|
4400 | Begin
|
---|
4401 | Digits[I] := '0';
|
---|
4402 | Inc(I);
|
---|
4403 | End;
|
---|
4404 |
|
---|
4405 | Exp := 0;
|
---|
4406 | End
|
---|
4407 | Else
|
---|
4408 | Begin
|
---|
4409 | { Scientific: exactly <Width> Digits With <Precision> Decimals
|
---|
4410 | And adjusted Exponent. }
|
---|
4411 | If Placehold[1] + Placehold[2] = 0 Then Placehold[1] := 1;
|
---|
4412 |
|
---|
4413 | Decimals := Placehold[3] + Placehold[4];
|
---|
4414 | Width := Placehold[1] + Placehold[2] + Decimals;
|
---|
4415 |
|
---|
4416 | Str(Value: Width + 8, Digits);
|
---|
4417 |
|
---|
4418 | //WriteLn('Digits: ', Digits);
|
---|
4419 |
|
---|
4420 | { Find and cut out exponent. Always the
|
---|
4421 | last 6 characters in the string.
|
---|
4422 | -> 0000E+0000 }
|
---|
4423 |
|
---|
4424 | I := Length(Digits) - 5;
|
---|
4425 |
|
---|
4426 | Val(Copy(Digits, I + 1, 5), Exp, J);
|
---|
4427 |
|
---|
4428 | //WriteLn('Exp: ', Exp);
|
---|
4429 |
|
---|
4430 | Exp := Exp + 1 - (Placehold[1] + Placehold[2]);
|
---|
4431 | Delete(Digits, I, 6);
|
---|
4432 |
|
---|
4433 | //WriteLn('Exp: ', Exp);
|
---|
4434 |
|
---|
4435 | { Str() always returns at least one digit after the decimal point.
|
---|
4436 | If we don't want it, we have to remove it. }
|
---|
4437 | If (Decimals = 0) And (Placehold[1] + Placehold[2] <= 1) Then
|
---|
4438 | Begin
|
---|
4439 | If Digits[4] >= '5' Then
|
---|
4440 | Begin
|
---|
4441 | Inc(Digits[2]);
|
---|
4442 | If Digits[2] > '9' Then
|
---|
4443 | Begin
|
---|
4444 | Digits[2] := '1';
|
---|
4445 | Inc(Exp);
|
---|
4446 | End;
|
---|
4447 | End;
|
---|
4448 | Delete(Digits, 3, 2);
|
---|
4449 | DecimalPoint := Length(Digits) + 1;
|
---|
4450 | End
|
---|
4451 | Else
|
---|
4452 | Begin
|
---|
4453 | //WriteLn(Digits);
|
---|
4454 |
|
---|
4455 | { Move decimal point at the desired position }
|
---|
4456 | Delete(Digits, 3, 1);
|
---|
4457 | DecimalPoint := 2 + Placehold[1] + Placehold[2];
|
---|
4458 | If Decimals <> 0 Then Insert('.', Digits, DecimalPoint);
|
---|
4459 | End;
|
---|
4460 |
|
---|
4461 | //WriteLn(Digits);
|
---|
4462 |
|
---|
4463 | { Convert optional zeroes to spaces. }
|
---|
4464 | I := Length(Digits);
|
---|
4465 | J := DecimalPoint + Placehold[3];
|
---|
4466 | While (I > J) And (Digits[I] = '0') Do
|
---|
4467 | Begin
|
---|
4468 | Digits[I] := ' ';
|
---|
4469 | Dec(I);
|
---|
4470 | End;
|
---|
4471 |
|
---|
4472 | { If integer number and no obligatory decimal paces, remove decimal point }
|
---|
4473 |
|
---|
4474 | If (DecimalPoint < Length(Digits)) And (Digits[DecimalPoint + 1] = ' ') Then
|
---|
4475 | Digits[DecimalPoint] := ' ';
|
---|
4476 |
|
---|
4477 | If Digits[1] = ' ' Then
|
---|
4478 | Begin
|
---|
4479 | Delete(Digits, 1, 1);
|
---|
4480 | Dec(DecimalPoint);
|
---|
4481 | End;
|
---|
4482 |
|
---|
4483 | { Calculate exponent string }
|
---|
4484 | Str(Abs(Exp), Exponent);
|
---|
4485 | While Length(Exponent) < ExpSize Do Insert('0', Exponent, 1);
|
---|
4486 | If Exp >= 0 Then
|
---|
4487 | Begin
|
---|
4488 | If ExpFmt In [1, 3] Then Insert('+', Exponent, 1);
|
---|
4489 | End
|
---|
4490 | Else Insert('-', Exponent, 1);
|
---|
4491 | If ExpFmt < 3 Then Insert('E', Exponent, 1) Else Insert('e', Exponent, 1);
|
---|
4492 | End;
|
---|
4493 |
|
---|
4494 | DigitExponent := DecimalPoint - 2;
|
---|
4495 | If Digits[1] = '-' Then Dec(DigitExponent);
|
---|
4496 |
|
---|
4497 | UnexpectedDigits := DecimalPoint - 1 - (Placehold[1] + Placehold[2]);
|
---|
4498 | End;
|
---|
4499 |
|
---|
4500 | Function PutResult: LongInt;
|
---|
4501 | Var
|
---|
4502 | SQ, DQ: Boolean;
|
---|
4503 | Fmt, Buf: PChar;
|
---|
4504 | Dig, N: Integer;
|
---|
4505 | Begin
|
---|
4506 | SQ := False;
|
---|
4507 | DQ := False;
|
---|
4508 | Fmt := FmtStart;
|
---|
4509 | Buf := Buffer;
|
---|
4510 | Dig := 1;
|
---|
4511 |
|
---|
4512 | //WriteLn('Putting result: ');
|
---|
4513 |
|
---|
4514 | While Fmt < FmtStop Do
|
---|
4515 | Begin
|
---|
4516 | //Write(Fmt[0]);
|
---|
4517 |
|
---|
4518 | Case Fmt[0] Of
|
---|
4519 | #34:
|
---|
4520 | Begin
|
---|
4521 | If Not SQ Then DQ := Not DQ;
|
---|
4522 | Inc(Fmt);
|
---|
4523 | End;
|
---|
4524 |
|
---|
4525 | #39:
|
---|
4526 | Begin
|
---|
4527 | If Not DQ Then SQ := Not SQ;
|
---|
4528 | Inc(Fmt);
|
---|
4529 | End;
|
---|
4530 |
|
---|
4531 | Else
|
---|
4532 |
|
---|
4533 | If Not (SQ Or DQ) Then
|
---|
4534 | Begin
|
---|
4535 | Case Fmt[0] Of
|
---|
4536 | '0', '#', '.':
|
---|
4537 | Begin
|
---|
4538 | If (Dig = 1) And (UnexpectedDigits > 0) Then
|
---|
4539 | Begin
|
---|
4540 | { Everything unexpected is written before the first digit }
|
---|
4541 | For N := 1 To UnexpectedDigits Do
|
---|
4542 | Begin
|
---|
4543 | Buf[0] := Digits[N];
|
---|
4544 | Inc(Buf);
|
---|
4545 | If thousand And (Digits[N] <> '-') Then
|
---|
4546 | Begin
|
---|
4547 | If (DigitExponent Mod 3 = 0) And (DigitExponent > 0) Then
|
---|
4548 | Begin
|
---|
4549 | Buf[0] := ThousandSeparator;
|
---|
4550 | Inc(Buf);
|
---|
4551 | End;
|
---|
4552 | Dec(DigitExponent);
|
---|
4553 | End;
|
---|
4554 | End;
|
---|
4555 | Inc(Dig, UnexpectedDigits);
|
---|
4556 | End;
|
---|
4557 |
|
---|
4558 | If Digits[Dig] <> ' ' Then
|
---|
4559 | Begin
|
---|
4560 | If Digits[Dig] = '.' Then Buf[0] := DecimalSeparator
|
---|
4561 | Else Buf[0] := Digits[Dig];
|
---|
4562 | Inc(Buf);
|
---|
4563 | If thousand And (DigitExponent Mod 3 = 0) And (DigitExponent > 0) Then
|
---|
4564 | Begin
|
---|
4565 | Buf[0] := ThousandSeparator;
|
---|
4566 | Inc(Buf);
|
---|
4567 | End;
|
---|
4568 | End;
|
---|
4569 | Inc(Dig);
|
---|
4570 | Dec(DigitExponent);
|
---|
4571 | Inc(Fmt);
|
---|
4572 | End;
|
---|
4573 |
|
---|
4574 | 'e', 'E':
|
---|
4575 | Begin
|
---|
4576 | If ExpFmt <> 0 Then
|
---|
4577 | Begin
|
---|
4578 | Inc(Fmt);
|
---|
4579 | If Fmt < FmtStop Then
|
---|
4580 | Begin
|
---|
4581 | If Fmt[0] In ['+', '-'] Then
|
---|
4582 | Begin
|
---|
4583 | Inc(Fmt, ExpSize);
|
---|
4584 |
|
---|
4585 | //WriteLn('Exponent: ', Exponent);
|
---|
4586 |
|
---|
4587 | For N := 1 To Length(Exponent) Do Buf[N - 1] := Exponent[N];
|
---|
4588 | Inc(Buf, Length(Exponent));
|
---|
4589 | ExpFmt := 0;
|
---|
4590 | End;
|
---|
4591 | Inc(Fmt);
|
---|
4592 | End;
|
---|
4593 | End
|
---|
4594 | Else
|
---|
4595 | Begin
|
---|
4596 | { No legal exponential format. Simply write
|
---|
4597 | the 'E' to the reult. }
|
---|
4598 | Buf[0] := Fmt[0];
|
---|
4599 | Inc(Buf);
|
---|
4600 | Inc(Fmt);
|
---|
4601 | End;
|
---|
4602 | End;
|
---|
4603 |
|
---|
4604 | Else
|
---|
4605 | { Usual character }
|
---|
4606 | If Fmt[0] <> ',' Then
|
---|
4607 | Begin
|
---|
4608 | Buf[0] := Fmt[0];
|
---|
4609 | Inc(Buf);
|
---|
4610 | End;
|
---|
4611 | Inc(Fmt);
|
---|
4612 | End; { Case }
|
---|
4613 | End
|
---|
4614 |
|
---|
4615 | Else { IF }
|
---|
4616 |
|
---|
4617 | Begin
|
---|
4618 | { Character inside single or double quotes }
|
---|
4619 | Buf[0] := Fmt[0];
|
---|
4620 | Inc(Buf);
|
---|
4621 | Inc(Fmt);
|
---|
4622 | End;
|
---|
4623 | End; { Case }
|
---|
4624 | End; { While .. Begin }
|
---|
4625 |
|
---|
4626 | //WriteLn;
|
---|
4627 |
|
---|
4628 | Result := LongInt(Buf) - LongInt(Buffer);
|
---|
4629 | End;
|
---|
4630 |
|
---|
4631 | Begin
|
---|
4632 | If Value > 0 Then GetSectionRange(1)
|
---|
4633 | Else If Value < 0 Then GetSectionRange(2)
|
---|
4634 | Else GetSectionRange(3);
|
---|
4635 |
|
---|
4636 | If FmtStart = Nil Then
|
---|
4637 | Begin
|
---|
4638 | //WriteLn('No format sections available.');
|
---|
4639 | Result := FloatToText(Buffer, Value, ffGeneral, 15, 4);
|
---|
4640 | End
|
---|
4641 | Else
|
---|
4642 | Begin
|
---|
4643 | GetFormatOptions;
|
---|
4644 | //WriteLn('Parsing complete');
|
---|
4645 | If (ExpFmt = 0) And (Abs(Value) >= 1E18) Then Result := FloatToText(Buffer, Value, ffGeneral, 15, 4)
|
---|
4646 | Else
|
---|
4647 | Begin
|
---|
4648 | FloatToStr;
|
---|
4649 | //WriteLn('FloatToStr() complete: "', Digits, '" / ', Exponent);
|
---|
4650 | //WriteLn('Unexpected digits: ', UnexpectedDigits);
|
---|
4651 | //WriteLn('DigitExponent: ', DigitExponent);
|
---|
4652 | Result := PutResult;
|
---|
4653 | //WriteLn('PutResult() complete');
|
---|
4654 | End;
|
---|
4655 | End;
|
---|
4656 | End;
|
---|
4657 |
|
---|
4658 |
|
---|
4659 | Function FormatFloat(Const format: String; Value: Extended): String;
|
---|
4660 | Var
|
---|
4661 | Temp: cstring[128];
|
---|
4662 | Begin
|
---|
4663 | Temp := format;
|
---|
4664 | SetLength(Result, FloatToTextFmt(@Result[1], Value, @Temp));
|
---|
4665 | End;
|
---|
4666 |
|
---|
4667 |
|
---|
4668 | Procedure FloatToDecimal(Var Result: TFloatRec; Value: Extended; Precision, Decimals: Integer);
|
---|
4669 | Var
|
---|
4670 | Buffer: String[24];
|
---|
4671 | Error, N: Integer;
|
---|
4672 | Begin
|
---|
4673 | { If Precision > 15 Then Precision := 15;
|
---|
4674 | If Decimals > 15 Then Decimals := 15; }
|
---|
4675 |
|
---|
4676 | Str(Value:23, Buffer);
|
---|
4677 | {WriteLn('Buffer is: ', Buffer);}
|
---|
4678 |
|
---|
4679 | Result.Negative := (Buffer[1] = '-');
|
---|
4680 | Val(Copy(Buffer, 19, 5), Result.Exponent, Error);
|
---|
4681 | Inc(Result. Exponent);
|
---|
4682 | {WriteLn('Exponent is: ', Result.Exponent);}
|
---|
4683 |
|
---|
4684 | Result.Digits[0] := Buffer[2];
|
---|
4685 | Move(Buffer[4], Result.Digits[1], 14);
|
---|
4686 |
|
---|
4687 | If Decimals + Result.Exponent < Precision Then N := Decimals + Result.Exponent
|
---|
4688 | Else N := Precision;
|
---|
4689 |
|
---|
4690 | {WriteLn('Cut point is ', N);}
|
---|
4691 |
|
---|
4692 | If N > 15 Then N := 15;
|
---|
4693 |
|
---|
4694 | {WriteLn('That makes ', N, ' with our precision.');}
|
---|
4695 |
|
---|
4696 | {WriteLn;}
|
---|
4697 |
|
---|
4698 | If N = 0 Then
|
---|
4699 | Begin
|
---|
4700 | If Result.Digits[0] >= '5' Then
|
---|
4701 | Begin
|
---|
4702 | Result.Digits[0] := '1';
|
---|
4703 | Result.Digits[1] := #0;
|
---|
4704 | Inc(Result.Exponent);
|
---|
4705 | End
|
---|
4706 | Else Result.Digits[0] := #0;
|
---|
4707 | End
|
---|
4708 | Else If N > 0 Then
|
---|
4709 | Begin
|
---|
4710 | If Result.Digits[N] >= '5' Then
|
---|
4711 | Begin
|
---|
4712 | { Round up }
|
---|
4713 | Repeat
|
---|
4714 | Result.Digits[N] := #0;
|
---|
4715 | Dec(N);
|
---|
4716 | Inc(Result.Digits[N]);
|
---|
4717 | Until (N = 0) Or (Result.Digits[N] < ':');
|
---|
4718 | If Result.Digits[0] = ':' Then
|
---|
4719 | Begin
|
---|
4720 | Result.Digits[0] := '1';
|
---|
4721 | Inc(Result.Exponent);
|
---|
4722 | End;
|
---|
4723 | End
|
---|
4724 | Else
|
---|
4725 | Begin
|
---|
4726 | { Cut zeros }
|
---|
4727 | Result.Digits[N] := '0';
|
---|
4728 | While (Result.Digits[N] = '0') And (N > -1) Do
|
---|
4729 | Begin
|
---|
4730 | Result.Digits[N] := #0;
|
---|
4731 | Dec(N);
|
---|
4732 | End;
|
---|
4733 | End;
|
---|
4734 | End
|
---|
4735 | Else Result.Digits[0] := #0;
|
---|
4736 |
|
---|
4737 | If Result.Digits[0] = #0 Then
|
---|
4738 | Begin
|
---|
4739 | { Zero has neither Exponent nor signum }
|
---|
4740 | Result.Exponent := 0;
|
---|
4741 | Result.Negative := False;
|
---|
4742 | End;
|
---|
4743 | End;
|
---|
4744 |
|
---|
4745 | { Time encoding And decoding }
|
---|
4746 |
|
---|
4747 | Procedure FastDiv(P, Q: LongWord; Var X, Y: LongInt); Assembler;
|
---|
4748 | Asm
|
---|
4749 | MOV EAX, P;
|
---|
4750 | Xor EDX, EDX;
|
---|
4751 | Div DWord Ptr Q;
|
---|
4752 | MOV EBX, X;
|
---|
4753 | MOV [EBX], EAX;
|
---|
4754 | MOV EBX, Y;
|
---|
4755 | MOV [EBX], EDX;
|
---|
4756 | End;
|
---|
4757 |
|
---|
4758 | Function _EncodeDate(Var date: TDateTime; Year, Month, Day: LongInt): Boolean;
|
---|
4759 | Begin
|
---|
4760 | If (Year <= 9999) And (Month In [1..12]) And (Day In [1..31]) Then
|
---|
4761 | Begin
|
---|
4762 | If Month > 2 Then Dec (Month, 3)
|
---|
4763 | Else
|
---|
4764 | Begin
|
---|
4765 | Inc (Month, 9);
|
---|
4766 | Dec (Year);
|
---|
4767 | End;
|
---|
4768 | date:= (146097 * (Year Div 100)) Shr 2
|
---|
4769 | + (1461 * (Year Mod 100)) Shr 2
|
---|
4770 | + (153 * Month + 2) Div 5 + Day - 306;
|
---|
4771 | Result := True;
|
---|
4772 | End
|
---|
4773 | Else Result := False;
|
---|
4774 | End;
|
---|
4775 |
|
---|
4776 | /*
|
---|
4777 | Function _EncodeDate(Var date: TDateTime; Year, Month, Day: LongWord): Boolean;
|
---|
4778 | Var
|
---|
4779 | LeapYear: Boolean;
|
---|
4780 | Begin
|
---|
4781 | If (Year <= 9999) And (Month In [1..12]) And (Day In [1..31]) Then
|
---|
4782 | Begin
|
---|
4783 | LeapYear := (Year Mod 4 = 0) And Not (Year Mod 100 = 0) Or (Year Mod 400 = 0);
|
---|
4784 | Dec(Year);
|
---|
4785 | date := Year * 365 + Year Div 4 - Year Div 100 + Year Div 400
|
---|
4786 | + 1 + DaysPassed[LeapYear, Month] + Day - 1;
|
---|
4787 | Result := True;
|
---|
4788 | End
|
---|
4789 | Else Result := False;
|
---|
4790 | End;
|
---|
4791 | */
|
---|
4792 |
|
---|
4793 | Function _EncodeTime(Var Time: TDateTime; Hour, Min, Sec, MSec: LongInt): Boolean;
|
---|
4794 | Begin
|
---|
4795 | If (Hour < 24) And (Min < 60) And (Sec < 60) And (MSec < 1000) Then
|
---|
4796 | Begin
|
---|
4797 | Time := (((Hour * 60 + Min) * 60 + Sec) * 1000 + MSec) / MSecsPerDay;
|
---|
4798 | Result := True
|
---|
4799 | End
|
---|
4800 | Else Result := False;
|
---|
4801 | End;
|
---|
4802 |
|
---|
4803 | Function EncodeDate(Year, Month, Day: Word): TDateTime;
|
---|
4804 | Begin
|
---|
4805 | If Not _EncodeDate(Result, Year, Month, Day) Then
|
---|
4806 | FmtLoadConvertError(SDateEncodeError, [Year, Month, Day]);
|
---|
4807 | End;
|
---|
4808 |
|
---|
4809 | Function EncodeTime(Hour, Min, Sec, MSec: Word): TDateTime;
|
---|
4810 | Begin
|
---|
4811 | If Not _EncodeTime(Result, Hour, Min, Sec, MSec) Then
|
---|
4812 | FmtLoadConvertError(STimeEncodeError, [Hour, Min, Sec, MSec]);
|
---|
4813 | End;
|
---|
4814 |
|
---|
4815 | Procedure DecodeDate(date: TDateTime; Var Year, Month, Day: Word);
|
---|
4816 | Const
|
---|
4817 | Days400 = 146097;
|
---|
4818 | Days4 = 1461;
|
---|
4819 | Var
|
---|
4820 | Y, M, D, Tmp1, Tmp2, Tmp3, Tmp4: LongInt;
|
---|
4821 | Begin
|
---|
4822 | Tmp1 := Trunc (date) + 306;
|
---|
4823 | Tmp2 := 4 * Tmp1 - 1;
|
---|
4824 |
|
---|
4825 | FastDiv(Tmp2, Days400, Tmp3, Tmp1);
|
---|
4826 |
|
---|
4827 | Tmp2 := Tmp1 Shr 2;
|
---|
4828 | Tmp4 := 4 * Tmp2 + 3;
|
---|
4829 |
|
---|
4830 | FastDiv(Tmp4, Days4, Tmp1, Tmp2);
|
---|
4831 |
|
---|
4832 | Tmp2 := (Tmp2 + 4) Shr 2;
|
---|
4833 |
|
---|
4834 | Y := 100 * Tmp3 + Tmp1;
|
---|
4835 | Tmp3 := 5 * Tmp2 - 3;
|
---|
4836 |
|
---|
4837 | FastDiv(Tmp3, 153, M, Tmp2);
|
---|
4838 |
|
---|
4839 | D := (Tmp2 + 5) Div 5;
|
---|
4840 | If M < 10 Then Inc (M, 3)
|
---|
4841 | Else
|
---|
4842 | Begin
|
---|
4843 | Dec (M, 9);
|
---|
4844 | Inc (Y);
|
---|
4845 | End;
|
---|
4846 |
|
---|
4847 | Year := Y;
|
---|
4848 | Month := M;
|
---|
4849 | Day := D;
|
---|
4850 | End;
|
---|
4851 |
|
---|
4852 | /*
|
---|
4853 | Procedure DecodeDate(date: TDateTime; Var Year, Month, Day: Word);
|
---|
4854 | Const
|
---|
4855 | Days400 = 146097;
|
---|
4856 | Days100 = 36524;
|
---|
4857 | Days4 = 1461;
|
---|
4858 | Var
|
---|
4859 | cnt, DayNum: LongInt;
|
---|
4860 | LeapYear: Boolean;
|
---|
4861 | Begin
|
---|
4862 | DayNum := Trunc(date);
|
---|
4863 |
|
---|
4864 | Year := 1;
|
---|
4865 |
|
---|
4866 | While DayNum > Days400 Do
|
---|
4867 | Begin
|
---|
4868 | Inc(Year, 400);
|
---|
4869 | Dec(DayNum, Days400);
|
---|
4870 | End;
|
---|
4871 |
|
---|
4872 | cnt := 0;
|
---|
4873 | While (DayNum > Days100) And (cnt < 3) Do
|
---|
4874 | Begin
|
---|
4875 | Inc(Year, 100);
|
---|
4876 | Dec(DayNum, Days100);
|
---|
4877 | Inc(cnt);
|
---|
4878 | End;
|
---|
4879 |
|
---|
4880 | While DayNum > Days4 Do
|
---|
4881 | Begin
|
---|
4882 | Inc(Year, 4);
|
---|
4883 | Dec(DayNum, Days4);
|
---|
4884 | End;
|
---|
4885 |
|
---|
4886 | cnt := 0;
|
---|
4887 | While (DayNum > 365) And (cnt < 3) Do
|
---|
4888 | Begin
|
---|
4889 | Inc(Year);
|
---|
4890 | Dec(DayNum, 365);
|
---|
4891 | Inc(cnt);
|
---|
4892 | End;
|
---|
4893 |
|
---|
4894 | LeapYear := (Year Mod 4 = 0) And Not (Year Mod 100 = 0) Or (Year Mod 400 = 0);
|
---|
4895 |
|
---|
4896 | Month := 0;
|
---|
4897 | While DaysPassed[LeapYear, Month + 1] < DayNum Do
|
---|
4898 | Inc(Month);
|
---|
4899 |
|
---|
4900 | Day := DayNum - DaysPassed[LeapYear, Month];
|
---|
4901 | End;
|
---|
4902 | */
|
---|
4903 |
|
---|
4904 | Procedure DecodeTime(Time: TDateTime; Var Hour, Min, Sec, MSec: Word);
|
---|
4905 | Begin
|
---|
4906 | Time := Frac(Time) * 24;
|
---|
4907 | Hour := Trunc(Time);
|
---|
4908 | Time := Frac(Time) * 60;
|
---|
4909 | Min := Trunc(Time);
|
---|
4910 | Time := Frac(Time) * 60;
|
---|
4911 | Sec := Trunc(Time);
|
---|
4912 | MSec := Trunc(Frac(Time) * 1000);
|
---|
4913 | End;
|
---|
4914 |
|
---|
4915 | Function DayOfWeek(date: TDateTime): Integer;
|
---|
4916 | Begin
|
---|
4917 | Result := (1 + Trunc(date)) Mod 7;
|
---|
4918 | If Result = 0 Then Result := 7;
|
---|
4919 | End;
|
---|
4920 |
|
---|
4921 | Function date: TDateTime;
|
---|
4922 | {$IFDEF OS2}
|
---|
4923 | Var
|
---|
4924 | dt: DateTime;
|
---|
4925 | {$ENDIF}
|
---|
4926 | {$IFDEF Win95}
|
---|
4927 | Var
|
---|
4928 | dt: SYSTEMTIME;
|
---|
4929 | {$ENDIF}
|
---|
4930 | Begin
|
---|
4931 | {$IFDEF OS2}
|
---|
4932 | DosGetDateTime (dt);
|
---|
4933 | date := EncodeDate(dt.Year, dt.Month, dt.Day);
|
---|
4934 | {$ENDIF}
|
---|
4935 | {$IFDEF Win95}
|
---|
4936 | GetLocalTime(dt);
|
---|
4937 | date := EncodeDate(dt.wYear, dt.wMonth, dt.wDay);
|
---|
4938 | {$ENDIF}
|
---|
4939 | End;
|
---|
4940 |
|
---|
4941 | Function Time: TDateTime;
|
---|
4942 | {$IFDEF OS2}
|
---|
4943 | Var
|
---|
4944 | dt: DateTime;
|
---|
4945 | {$ENDIF}
|
---|
4946 | {$IFDEF Win95}
|
---|
4947 | Var
|
---|
4948 | dt: SYSTEMTIME;
|
---|
4949 | {$ENDIF}
|
---|
4950 | Begin
|
---|
4951 | {$IFDEF OS2}
|
---|
4952 | DosGetDateTime (dt);
|
---|
4953 | Time := EncodeTime(dt.Hour, dt.Min, dt.Sec, dt.Hundredths * 10);
|
---|
4954 | {$ENDIF}
|
---|
4955 | {$IFDEF Win95}
|
---|
4956 | GetLocalTime(dt);
|
---|
4957 | Time := EncodeTime(dt.wHour, dt.wMinute, dt.wSecond, dt.wMilliSeconds * 10);
|
---|
4958 | {$ENDIF}
|
---|
4959 | End;
|
---|
4960 |
|
---|
4961 | Function now: TDateTime;
|
---|
4962 | {$IFDEF OS2}
|
---|
4963 | Var
|
---|
4964 | dt: DateTime;
|
---|
4965 | {$ENDIF}
|
---|
4966 | {$IFDEF Win95}
|
---|
4967 | Var
|
---|
4968 | dt: SYSTEMTIME;
|
---|
4969 | {$ENDIF}
|
---|
4970 | Begin
|
---|
4971 | {$IFDEF OS2}
|
---|
4972 | DosGetDateTime (dt);
|
---|
4973 | now := EncodeDate(dt.Year, dt.Month, dt.Day) + EncodeTime(dt.Hour, dt.Min, dt.Sec, dt.Hundredths * 10);
|
---|
4974 | {$ENDIF}
|
---|
4975 | {$IFDEF Win95}
|
---|
4976 | GetLocalTime(dt);
|
---|
4977 | now := EncodeDate(dt.wYear, dt.wMonth, dt.wDay) + EncodeTime(dt.wHour, dt.wMinute, dt.wSecond, dt.wMilliSeconds * 10);
|
---|
4978 | {$ENDIF}
|
---|
4979 | End;
|
---|
4980 |
|
---|
4981 | { --- date/Time To String conversion --- }
|
---|
4982 |
|
---|
4983 | Procedure DateTimeToString(Var Result: String; Const format: String; DateTime: TDateTime);
|
---|
4984 | Var
|
---|
4985 | Year, Month, Day, Hour, Min, Sec, MSec, Hour12: Word;
|
---|
4986 | BeforeNoon: Boolean;
|
---|
4987 |
|
---|
4988 | Procedure _DateTimeToString(Var Result: String; Const format: String; recursive: Boolean);
|
---|
4989 | { internal Function To Control recursion In format specifiers. Avoids
|
---|
4990 | stack overflow when format Strings contain Macros For other format
|
---|
4991 | Strings. }
|
---|
4992 |
|
---|
4993 | Var
|
---|
4994 | Start, Count, Pos, len, LastHourPos, LastHourSize, Tmp: Integer;
|
---|
4995 | Token: Char;
|
---|
4996 | UseMinutes: Boolean;
|
---|
4997 |
|
---|
4998 | Procedure AppendInt(I, Digits: Integer);
|
---|
4999 | Var
|
---|
5000 | S: String[5];
|
---|
5001 | P: Integer;
|
---|
5002 | Begin
|
---|
5003 | Str(I:Digits, S);
|
---|
5004 | P := 1;
|
---|
5005 | While S[P] = ' ' Do
|
---|
5006 | Begin
|
---|
5007 | S[P] := '0';
|
---|
5008 | Inc(P);
|
---|
5009 | End;
|
---|
5010 | AppendStr(Result, S);
|
---|
5011 | End;
|
---|
5012 |
|
---|
5013 | Procedure AppendStr(Const S: String);
|
---|
5014 | Begin
|
---|
5015 | Insert(S, Result, Length(Result) + 1);
|
---|
5016 | End;
|
---|
5017 |
|
---|
5018 | Function CountChar(C: Char; Max: Integer): Integer;
|
---|
5019 | Var
|
---|
5020 | Result: Integer;
|
---|
5021 | Begin
|
---|
5022 | Result := 1;
|
---|
5023 | While (Pos <= len) And (UpCase(format[Pos]) = C) And (Result < Max) Do
|
---|
5024 | Begin
|
---|
5025 | Inc(Pos);
|
---|
5026 | Inc(Result);
|
---|
5027 | End;
|
---|
5028 | CountChar := Result;
|
---|
5029 | End;
|
---|
5030 |
|
---|
5031 | Function IsSubStr(Const S: String): Boolean;
|
---|
5032 | Begin
|
---|
5033 | IsSubStr := (uppercase(Copy(format, Pos, Length(S))) = S);
|
---|
5034 | End;
|
---|
5035 |
|
---|
5036 | Procedure GetNextToken(BeforeNoon: Boolean);
|
---|
5037 | Begin
|
---|
5038 | Start := Pos;
|
---|
5039 | Token := UpCase(format[Pos]);
|
---|
5040 | Inc(Pos);
|
---|
5041 | Case Token Of
|
---|
5042 | #34,
|
---|
5043 | #39: Begin
|
---|
5044 | Inc(Start);
|
---|
5045 | While (Pos <= len) And (format[Pos] <> Token) Do Inc(Pos);
|
---|
5046 | Count := Pos - Start;
|
---|
5047 | If Pos < len Then Inc(Pos);
|
---|
5048 | Token := '$';
|
---|
5049 | End;
|
---|
5050 | 'D': Count := CountChar('D', 6);
|
---|
5051 | 'M': Count := CountChar('M', 4);
|
---|
5052 | 'Y': Count := CountChar('Y', 4);
|
---|
5053 | 'H',
|
---|
5054 | 'N',
|
---|
5055 | 'S',
|
---|
5056 | 'T': Count := CountChar(Token, 2);
|
---|
5057 | 'A': Begin
|
---|
5058 | If IsSubStr('MPM') Then
|
---|
5059 | Begin
|
---|
5060 | Inc(Pos, 3);
|
---|
5061 | Count := 0;
|
---|
5062 | End
|
---|
5063 | Else If IsSubStr('/P') Then
|
---|
5064 | Begin
|
---|
5065 | Inc(Pos, 2);
|
---|
5066 | If Not BeforeNoon Then Inc(Start, 2);
|
---|
5067 | Count := 1;
|
---|
5068 | End
|
---|
5069 | Else If IsSubStr('M/PM') Then
|
---|
5070 | Begin
|
---|
5071 | Inc(Pos, 4);
|
---|
5072 | If Not BeforeNoon Then Inc(Start, 3);
|
---|
5073 | Count := 2;
|
---|
5074 | End
|
---|
5075 | Else
|
---|
5076 | Begin
|
---|
5077 | Token := '$';
|
---|
5078 | Count := 1;
|
---|
5079 | End;
|
---|
5080 | End;
|
---|
5081 | 'C',
|
---|
5082 | '/',
|
---|
5083 | ':': Begin
|
---|
5084 | { Nope }
|
---|
5085 | End;
|
---|
5086 | Else Begin
|
---|
5087 | Token := '$';
|
---|
5088 | Count := 1;
|
---|
5089 | While (Pos <= len) And Not (UpCase(format[Pos]) In
|
---|
5090 | [#34, #39, 'A', 'C', 'D', 'H', 'M', 'N', 'S', 'T', 'Y', ':', '/']) Do
|
---|
5091 | Begin
|
---|
5092 | Inc(Pos);
|
---|
5093 | Inc(Count);
|
---|
5094 | End;
|
---|
5095 | End;
|
---|
5096 | End;
|
---|
5097 |
|
---|
5098 | If (Token = 'M') And UseMinutes Then Token := 'N';
|
---|
5099 |
|
---|
5100 | Case Token Of
|
---|
5101 | 'H': UseMinutes := True;
|
---|
5102 | 'A', 'C', 'D', 'M', 'N', 'S', 'T', 'Y': UseMinutes := False;
|
---|
5103 | End;
|
---|
5104 | End;
|
---|
5105 |
|
---|
5106 | Begin
|
---|
5107 | Pos := 1;
|
---|
5108 | len := Length(format);
|
---|
5109 | LastHourPos := 0;
|
---|
5110 | UseMinutes := False;
|
---|
5111 |
|
---|
5112 | If len = 0 Then _DateTimeToString(Result, 'C', True)
|
---|
5113 | Else While (Pos <= len) Do
|
---|
5114 | Begin
|
---|
5115 | GetNextToken(BeforeNoon);
|
---|
5116 | // WriteLn('Token=', Token, ' Start=', Start, ' Count=', Count);
|
---|
5117 | Case Token Of
|
---|
5118 | 'C': If recursive Then
|
---|
5119 | Begin
|
---|
5120 | _DateTimeToString(Result, ShortDateFormat, False);
|
---|
5121 | If (Hour + Min + Sec) > 0 Then
|
---|
5122 | Begin
|
---|
5123 | AppendStr(' ');
|
---|
5124 | _DateTimeToString(Result, LongTimeFormat, False);
|
---|
5125 | End;
|
---|
5126 | End
|
---|
5127 | Else AppendStr('C');
|
---|
5128 | 'D': Case Count Of
|
---|
5129 | 1: AppendInt(Day, 1);
|
---|
5130 | 2: AppendInt(Day, 2);
|
---|
5131 | 3: AppendStr(ShortDayNames[DayOfWeek(DateTime)]);
|
---|
5132 | 4: AppendStr(LongDayNames[DayOfWeek(DateTime)]);
|
---|
5133 | 5: If recursive Then _DateTimeToString(Result, ShortDateFormat, False)
|
---|
5134 | Else AppendStr('DDDDD');
|
---|
5135 | 6: If recursive Then _DateTimeToString(Result, LongDateFormat, False)
|
---|
5136 | Else AppendStr('DDDDDD');
|
---|
5137 | End;
|
---|
5138 | 'M': Case Count Of
|
---|
5139 | 1: AppendInt(Month, 1);
|
---|
5140 | 2: AppendInt(Month, 2);
|
---|
5141 | 3: AppendStr(ShortMonthNames[Month]);
|
---|
5142 | 4: AppendStr(LongMonthNames[Month]);
|
---|
5143 | End;
|
---|
5144 | 'Y': Case Count Of
|
---|
5145 | 1, 2: AppendInt(Year Mod 100, 2);
|
---|
5146 | 3, 4: AppendInt(Year, 4);
|
---|
5147 | End;
|
---|
5148 | 'H': Begin
|
---|
5149 | LastHourPos := Length(Result) + 1;
|
---|
5150 | LastHourSize := Count;
|
---|
5151 | AppendInt(Hour, Count);
|
---|
5152 | End;
|
---|
5153 | 'N': AppendInt(Min, Count);
|
---|
5154 | 'S': AppendInt(Sec, Count);
|
---|
5155 | 'T': Case Count Of
|
---|
5156 | 1: If recursive Then _DateTimeToString(Result, ShortTimeFormat, False)
|
---|
5157 | Else AppendStr('T');
|
---|
5158 | 2: If recursive Then _DateTimeToString(Result, LongTimeFormat, False)
|
---|
5159 | Else AppendStr('TT');
|
---|
5160 | End;
|
---|
5161 | 'A': Begin
|
---|
5162 | If LastHourPos <> 0 Then
|
---|
5163 | Begin
|
---|
5164 | If (LastHourSize = 1) And (Hour < 10) Then Tmp := 1
|
---|
5165 | Else Tmp := 2;
|
---|
5166 | Delete(Result, LastHourPos, Tmp);
|
---|
5167 | If (LastHourSize = 2) And (Hour12 < 10) Then
|
---|
5168 | Insert('0' + IntToStr(Hour12), Result, LastHourPos)
|
---|
5169 | Else Insert(IntToStr(Hour12), Result, LastHourPos);
|
---|
5170 | LastHourPos := 0;
|
---|
5171 | End;
|
---|
5172 | Case Count Of
|
---|
5173 | 0: If BeforeNoon Then AppendStr(TimeAMString)
|
---|
5174 | Else AppendStr(TimePMString);
|
---|
5175 | 1: AppendStr(format[Start]);
|
---|
5176 | 2: AppendStr(format[Start] + format[Start + 1]);
|
---|
5177 | End
|
---|
5178 | End;
|
---|
5179 | '/': AppendStr(DateSeparator);
|
---|
5180 | ':': AppendStr(TimeSeparator);
|
---|
5181 | '$': AppendStr(Copy(format, Start, Count));
|
---|
5182 | End;
|
---|
5183 | End;
|
---|
5184 | End;
|
---|
5185 |
|
---|
5186 | Begin
|
---|
5187 | DateTime := DateTime + 5.79e-6; // avoid rounding problems
|
---|
5188 |
|
---|
5189 | DecodeDate(DateTime, Year, Month, Day);
|
---|
5190 | DecodeTime(DateTime, Hour, Min, Sec, MSec);
|
---|
5191 |
|
---|
5192 | If (Hour = 0) Or (Hour > 12) Then
|
---|
5193 | Begin
|
---|
5194 | If Hour = 0 Then Hour12 := 12
|
---|
5195 | Else Hour12 := Hour - 12;
|
---|
5196 | BeforeNoon := False;
|
---|
5197 | End
|
---|
5198 | Else
|
---|
5199 | Begin
|
---|
5200 | BeforeNoon := True;
|
---|
5201 | Hour12 := Hour;
|
---|
5202 | End;
|
---|
5203 | Result := '';
|
---|
5204 |
|
---|
5205 | If Length(format) <> 0 Then _DateTimeToString(Result, format, True)
|
---|
5206 | Else _DateTimeToString(Result, 'C', True)
|
---|
5207 | End;
|
---|
5208 |
|
---|
5209 | Function DateToStr(date: TDateTime): String;
|
---|
5210 | Begin
|
---|
5211 | DateTimeToString(Result, ShortDateFormat, date);
|
---|
5212 | End;
|
---|
5213 |
|
---|
5214 | Function TimeToStr(Time: TDateTime): String;
|
---|
5215 | Begin
|
---|
5216 | DateTimeToString(Result, LongTimeFormat, Time);
|
---|
5217 | End;
|
---|
5218 |
|
---|
5219 | Function DateTimeToStr(DateTime: TDateTime): String;
|
---|
5220 | Begin
|
---|
5221 | DateTimeToString(Result, ShortDateFormat + ' ' + LongTimeFormat, DateTime);
|
---|
5222 | End;
|
---|
5223 |
|
---|
5224 | Function FormatDateTime(Const format: String; DateTime: TDateTime): String;
|
---|
5225 | Begin
|
---|
5226 | DateTimeToString(Result, format, DateTime);
|
---|
5227 | End;
|
---|
5228 |
|
---|
5229 | { --- String To date/Time conversions --- }
|
---|
5230 |
|
---|
5231 | Procedure IgnoreSpaces(Const S: String; Var Pos: Integer; len: Integer);
|
---|
5232 | Begin
|
---|
5233 | While (Pos <= len) And (S[Pos] = ' ') Do Inc(Pos);
|
---|
5234 | End;
|
---|
5235 |
|
---|
5236 | Function GetNumber(Var Num: Integer; Const S: String; Var Pos: Integer; len: Integer): Boolean;
|
---|
5237 | Begin
|
---|
5238 | Result := False;
|
---|
5239 | Num := 0;
|
---|
5240 | IgnoreSpaces(S, Pos, len);
|
---|
5241 | While (Pos <= len) And (S[Pos] In ['0'..'9']) Do
|
---|
5242 | Begin
|
---|
5243 | Result := True;
|
---|
5244 | Num := Num * 10 + Ord(S[Pos]) - 48;
|
---|
5245 | Inc(Pos);
|
---|
5246 | End;
|
---|
5247 | End;
|
---|
5248 |
|
---|
5249 | {$HINTS OFF}
|
---|
5250 | Function CompareString(Const SubStr, S: String; Var Pos: Integer; len: Integer): Boolean;
|
---|
5251 | Begin
|
---|
5252 | If CompareText(SubStr, Copy(S, 1, Length(SubStr))) = 0 Then
|
---|
5253 | Begin
|
---|
5254 | Result := True;
|
---|
5255 | Inc(Pos, Length(SubStr));
|
---|
5256 | End
|
---|
5257 | Else Result := False;
|
---|
5258 | End;
|
---|
5259 | {$HINTS ON}
|
---|
5260 |
|
---|
5261 | Function CompareChar(C: Char; S: String; Var Pos: Integer; len: Integer): Boolean;
|
---|
5262 | Begin
|
---|
5263 | If (Pos <= len) And (UpCase(C) = UpCase(S[Pos])) Then
|
---|
5264 | Begin
|
---|
5265 | Result := True;
|
---|
5266 | Inc(Pos);
|
---|
5267 | End
|
---|
5268 | Else Result := False;
|
---|
5269 | End;
|
---|
5270 |
|
---|
5271 | Function CutString(Var S: String; separator: Char): String;
|
---|
5272 | Var
|
---|
5273 | P: Integer;
|
---|
5274 | Begin
|
---|
5275 | P := Pos(separator, S);
|
---|
5276 | If P = 0 Then P := Length(S) + 1;
|
---|
5277 | Result := Copy(S, 1, P - 1);
|
---|
5278 | Delete(S, 1, P);
|
---|
5279 | End;
|
---|
5280 |
|
---|
5281 | Function ParseDate(Var date: TDateTime; Const S: String; Var Pos: Integer; len: Integer): Boolean;
|
---|
5282 | Var
|
---|
5283 | Head, Temp: String[15];
|
---|
5284 | N, Year, Month, Day: Integer;
|
---|
5285 | Number: Array[1..3] Of Integer;
|
---|
5286 | order: String[3];
|
---|
5287 |
|
---|
5288 | Function GetCurrentYear: Integer;
|
---|
5289 | Var
|
---|
5290 | Y, M, D: Word;
|
---|
5291 | Begin
|
---|
5292 | DecodeDate(now, Y, M, D);
|
---|
5293 | Result := Y;
|
---|
5294 | End;
|
---|
5295 |
|
---|
5296 | Begin
|
---|
5297 | order := 'XXX';
|
---|
5298 |
|
---|
5299 | Result := False;
|
---|
5300 |
|
---|
5301 | If Not GetNumber(Number[1], S, Pos, len) Then Exit;
|
---|
5302 | If Not CompareChar(DateSeparator, S, Pos, len) Then Exit;
|
---|
5303 | If Not GetNumber(Number[2], S, Pos, len) Then Exit;
|
---|
5304 | If Not CompareChar(DateSeparator, S, Pos, len) Then Exit;
|
---|
5305 | If Not GetNumber(Number[3], S, Pos, len) Then Number[3] := -1;
|
---|
5306 |
|
---|
5307 | { For N := 1 To 3 Do WriteLn(Number[N]); }
|
---|
5308 |
|
---|
5309 | Temp := ShortDateFormat;
|
---|
5310 |
|
---|
5311 | For N := 1 To 3 Do
|
---|
5312 | Begin
|
---|
5313 | Head := CutString(Temp, '/');
|
---|
5314 | If Length(Head) <> 0 Then order[N] := UpCase(Head[1]);
|
---|
5315 | End;
|
---|
5316 |
|
---|
5317 | If order = 'MDY' Then
|
---|
5318 | Begin
|
---|
5319 | Month := Number[1];
|
---|
5320 | Day := Number[2];
|
---|
5321 | Year := Number[3];
|
---|
5322 | End
|
---|
5323 | Else If order = 'DMY' Then
|
---|
5324 | Begin
|
---|
5325 | { WriteLn('DMY'); }
|
---|
5326 | Day := Number[1];
|
---|
5327 | Month := Number[2];
|
---|
5328 | Year := Number[3];
|
---|
5329 | End
|
---|
5330 | Else If order = 'YMD' Then
|
---|
5331 | Begin
|
---|
5332 | If Number[3] = -1 Then
|
---|
5333 | Begin
|
---|
5334 | Year := -1;
|
---|
5335 | Month := Number[1];
|
---|
5336 | Day := Number[2];
|
---|
5337 | End
|
---|
5338 | Else
|
---|
5339 | Begin
|
---|
5340 | Year := Number[1];
|
---|
5341 | Month := Number[2];
|
---|
5342 | Day := Number[3];
|
---|
5343 | End;
|
---|
5344 | End;
|
---|
5345 |
|
---|
5346 | If Year = -1 Then Year := GetCurrentYear
|
---|
5347 | Else If Year < 100 Then Inc(Year, 1900);
|
---|
5348 |
|
---|
5349 | Result := True;
|
---|
5350 | Result := _EncodeDate(date, Year, Month, Day);
|
---|
5351 | End;
|
---|
5352 |
|
---|
5353 | Function ParseTime(Var Time: TDateTime; Const S: String; Var Pos: Integer; len: Integer): Boolean;
|
---|
5354 | Var
|
---|
5355 | Hour, Min, Sec: Integer;
|
---|
5356 | Begin
|
---|
5357 | Result := False;
|
---|
5358 |
|
---|
5359 | If Not GetNumber(Hour, S, Pos, len) Then Exit;
|
---|
5360 | If Not CompareChar(TimeSeparator, S, Pos, len) Then Exit;
|
---|
5361 | If Not GetNumber(Min, S, Pos, len) Then Exit;
|
---|
5362 | If CompareChar(TimeSeparator, S, Pos, len) And Not GetNumber(Sec, S, Pos, len) Then Exit;
|
---|
5363 |
|
---|
5364 | IgnoreSpaces(S, Pos, len);
|
---|
5365 | If CompareChar('A', S, Pos, len) Then
|
---|
5366 | Begin
|
---|
5367 | CompareChar('M', S, Pos, len);
|
---|
5368 | If Hour = 12 Then Hour := 0;
|
---|
5369 | End
|
---|
5370 | Else If CompareChar('P', S, Pos, len) Then
|
---|
5371 | Begin
|
---|
5372 | CompareChar('M', S, Pos, len);
|
---|
5373 | If (Hour >= 1) And (Hour <= 11) Then Inc(Hour, 12);
|
---|
5374 | End;
|
---|
5375 |
|
---|
5376 | Result := _EncodeTime(Time, Hour, Min, Sec, 0);
|
---|
5377 | End;
|
---|
5378 |
|
---|
5379 | Function StrToDate(Const S: String): TDateTime;
|
---|
5380 | Var
|
---|
5381 | Pos, len: Integer;
|
---|
5382 | Begin
|
---|
5383 | Pos := 1;
|
---|
5384 | len := Length(S);
|
---|
5385 | If Not ParseDate(Result, S, Pos, len) Then FmtLoadConvertError(SInvalidDate, [S]);
|
---|
5386 | End;
|
---|
5387 |
|
---|
5388 | Function StrToTime(Const S: String): TDateTime;
|
---|
5389 | Var
|
---|
5390 | Pos, len: Integer;
|
---|
5391 | Begin
|
---|
5392 | Pos := 1;
|
---|
5393 | len := Length(S);
|
---|
5394 | If Not ParseTime(Result, S, Pos, len) Then FmtLoadConvertError(SInvalidTime, [S]);
|
---|
5395 | End;
|
---|
5396 |
|
---|
5397 | Function StrToDateTime(Const S: String): TDateTime;
|
---|
5398 | Var
|
---|
5399 | Time: TDateTime;
|
---|
5400 | Pos, len: Integer;
|
---|
5401 | Begin
|
---|
5402 | Pos := 1;
|
---|
5403 | len := Length(S);
|
---|
5404 | If Not ParseDate(Result, S, Pos, len) Then FmtLoadConvertError(SInvalidDateTime, [S]);
|
---|
5405 | If ParseTime(Time, S, Pos, len) Then Result := Result + Time;
|
---|
5406 | End;
|
---|
5407 |
|
---|
5408 | { --- Initialization File support --- }
|
---|
5409 |
|
---|
5410 | {$IFDEF GUI}
|
---|
5411 |
|
---|
5412 | Function GetProfileStr(Const Section, Entry, Default: String): String;
|
---|
5413 | Var
|
---|
5414 | CDefault,OutBuf: cstring;
|
---|
5415 | Begin
|
---|
5416 | CDefault := Default;
|
---|
5417 | {$IFDEF OS2}
|
---|
5418 | Fillchar(OutBuf, 255, 0); {sometimes the #0 character is not copied (cdp.ini)}
|
---|
5419 | PrfQueryProfileString(HINI_UserProfile, Section, Entry, Default, OutBuf, 255);
|
---|
5420 | Result := OutBuf;
|
---|
5421 | {$ENDIF}
|
---|
5422 | {$IFDEF Win95}
|
---|
5423 | If entry='' Then GetProfileString('USER',section,Default,CDefault,255)
|
---|
5424 | Else GetProfileString('USER',section,entry,CDefault,255);
|
---|
5425 | result:=CDefault;
|
---|
5426 | {$ENDIF}
|
---|
5427 | End;
|
---|
5428 |
|
---|
5429 | {$HINTS OFF}
|
---|
5430 | Function GetProfileChar(Const Section, Entry: String; Default: Char): Char;
|
---|
5431 | Var
|
---|
5432 | InBuf, OutBuf: cstring[2];
|
---|
5433 | Begin
|
---|
5434 | InBuf[0] := Default;
|
---|
5435 | InBuf[1] := #0;
|
---|
5436 | {$IFDEF OS2}
|
---|
5437 | PrfQueryProfileString(HINI_UserProfile,
|
---|
5438 | Section, Entry,
|
---|
5439 | InBuf, OutBuf, 2);
|
---|
5440 | Result := OutBuf[0];
|
---|
5441 | {$ENDIF}
|
---|
5442 | {$IFDEF Win95}
|
---|
5443 | GetProfileString('USER',section,InBuf,OutBuf,255);
|
---|
5444 | Result:= OutBuf[0];
|
---|
5445 | {$ENDIF}
|
---|
5446 | End;
|
---|
5447 | {$HINTS ON}
|
---|
5448 |
|
---|
5449 | Function GetProfileInt(Const Section, Entry: string; Default: Integer): Integer;
|
---|
5450 | {$IFDEF Win95}
|
---|
5451 | Var
|
---|
5452 | S: String;
|
---|
5453 | C: Integer;
|
---|
5454 | {$ENDIF}
|
---|
5455 | Begin
|
---|
5456 | {$IFDEF OS2}
|
---|
5457 | Result := PrfQueryProfileInt(HINI_UserProfile,Section, Entry,Default);
|
---|
5458 | {$ENDIF}
|
---|
5459 | {$IFDEF Win95}
|
---|
5460 | S:=GetProfileStr(section,entry,'');
|
---|
5461 | Val(S,Result,C);
|
---|
5462 | If C<>0 Then Result:=Default;
|
---|
5463 | {$ENDIF}
|
---|
5464 | End;
|
---|
5465 |
|
---|
5466 | Procedure GetFormatSettings;
|
---|
5467 | Const
|
---|
5468 | key = 'PM_National';
|
---|
5469 | Var
|
---|
5470 | N: Integer;
|
---|
5471 | Begin
|
---|
5472 | TimeAMString := GetProfileStr(key, 's1159', 'am');
|
---|
5473 | TimePMString := GetProfileStr(key, 's2359', 'pm');
|
---|
5474 | CurrencyString := GetProfileStr(key, 'sCurrency', '$');
|
---|
5475 | ThousandSeparator := GetProfileChar(key, 'sThousand', ',');
|
---|
5476 | DecimalSeparator := GetProfileChar(key, 'sDecimal', '.');
|
---|
5477 | DateSeparator := GetProfileChar(key, 'sDate', '/');
|
---|
5478 | TimeSeparator := GetProfileChar(key, 'sTime', ':');
|
---|
5479 | ListSeparator := GetProfileChar(key, 'sList', ';');
|
---|
5480 |
|
---|
5481 | DateOrder := GetProfileInt(key, 'iDate', 0);
|
---|
5482 | Case DateOrder Of
|
---|
5483 | 0: Begin
|
---|
5484 | ShortDateFormat := 'mm/dd/yyyy';
|
---|
5485 | LongDateFormat := 'dddd, mmmm d. yyyy';
|
---|
5486 | End;
|
---|
5487 | 1: Begin
|
---|
5488 | ShortDateFormat := 'dd/mm/yyyy';
|
---|
5489 | LongDateFormat := 'dddd, d. mmmm yyyy';
|
---|
5490 | End;
|
---|
5491 | 2: Begin
|
---|
5492 | ShortDateFormat := 'yyyy/mm/dd';
|
---|
5493 | LongDateFormat := 'dddd, yyyy mmmm d.';
|
---|
5494 | End;
|
---|
5495 | End;
|
---|
5496 |
|
---|
5497 | CurrencyFormat := GetProfileInt(key, 'iCurrency', 0);
|
---|
5498 |
|
---|
5499 | Case CurrencyFormat Of
|
---|
5500 | 0: NegCurrFormat := 1;
|
---|
5501 | 1: NegCurrFormat := 5;
|
---|
5502 | 2: NegCurrFormat := 9;
|
---|
5503 | 3: NegCurrFormat := 8;
|
---|
5504 | End;
|
---|
5505 |
|
---|
5506 | CurrencyDecimals := GetProfileInt(key, 'iDigits', 2);
|
---|
5507 |
|
---|
5508 | Case GetProfileInt(key, 'iLzero', 0) Of
|
---|
5509 | 0: Begin
|
---|
5510 | ShortTimeFormat := 'h:mm';
|
---|
5511 | LongTimeFormat := 'h:mm:ss';
|
---|
5512 | End;
|
---|
5513 | 1: Begin
|
---|
5514 | ShortTimeFormat := 'hh:mm';
|
---|
5515 | LongTimeFormat := 'hh:mm:ss';
|
---|
5516 | End;
|
---|
5517 | End;
|
---|
5518 |
|
---|
5519 | If GetProfileInt(key, 'iTime', 0) = 0 Then
|
---|
5520 | Begin
|
---|
5521 | ShortTimeFormat := ShortTimeFormat + ' ampm';
|
---|
5522 | LongTimeFormat := LongTimeFormat + ' ampm';
|
---|
5523 | TwelveHours := True;
|
---|
5524 | End
|
---|
5525 | Else TwelveHours := False;
|
---|
5526 |
|
---|
5527 | For N := 1 To 12 Do
|
---|
5528 | Begin
|
---|
5529 | ShortMonthNames[N] := LoadNLSStr(SShortMonthNames + N - 1);
|
---|
5530 | LongMonthNames[N] := LoadNLSStr(SLongMonthNames + N - 1);
|
---|
5531 | End;
|
---|
5532 |
|
---|
5533 | For N := 1 To 7 Do
|
---|
5534 | Begin
|
---|
5535 | ShortDayNames[N] := LoadNLSStr(SShortDayNames + N - 1);
|
---|
5536 | LongDayNames[N] := LoadNLSStr(SLongDayNames + N - 1);
|
---|
5537 | End;
|
---|
5538 | End;
|
---|
5539 |
|
---|
5540 | {$ELSE}
|
---|
5541 |
|
---|
5542 | Procedure GetFormatSettings; { VIO-only! }
|
---|
5543 | Var
|
---|
5544 | cc: COUNTRYCODE;
|
---|
5545 | CI: COUNTRYINFO;
|
---|
5546 | L: LongInt;
|
---|
5547 | Begin
|
---|
5548 | cc.country := 0;
|
---|
5549 | cc.codepage := 0;
|
---|
5550 | If DosQueryCtryInfo(SizeOf(CI), cc, CI, L) <> NO_ERROR Then Halt(255);
|
---|
5551 |
|
---|
5552 | CurrencyString := CI.szCurrency;
|
---|
5553 | CurrencyFormat := CI.fsCurrencyFmt;
|
---|
5554 |
|
---|
5555 | ThousandSeparator := CI.szThousandsSeparator[0];
|
---|
5556 | DecimalSeparator := CI.szDecimal[0];
|
---|
5557 | DateSeparator := CI.szDateSeparator[0];
|
---|
5558 | TimeSeparator := CI.szTimeSeparator[0];
|
---|
5559 | ListSeparator := CI.szDataSeparator[0];
|
---|
5560 | CurrencyDecimals := CI.cDecimalPlace;
|
---|
5561 |
|
---|
5562 | Case CurrencyFormat Of
|
---|
5563 | 0: NegCurrFormat := 1;
|
---|
5564 | 1: NegCurrFormat := 5;
|
---|
5565 | 2: NegCurrFormat := 9;
|
---|
5566 | 3: NegCurrFormat := 8;
|
---|
5567 | End;
|
---|
5568 |
|
---|
5569 | DateOrder := CI.fsDateFmt;
|
---|
5570 | Case DateOrder Of
|
---|
5571 | 0: Begin
|
---|
5572 | ShortDateFormat := 'mm/dd/yyyy';
|
---|
5573 | LongDateFormat := 'dddd, mmmm d. yyyy';
|
---|
5574 | End;
|
---|
5575 | 1: Begin
|
---|
5576 | ShortDateFormat := 'dd/mm/yyyy';
|
---|
5577 | LongDateFormat := 'dddd, d. mmmm yyyy';
|
---|
5578 | End;
|
---|
5579 | 2: Begin
|
---|
5580 | ShortDateFormat := 'yyyy/mm/dd';
|
---|
5581 | LongDateFormat := 'dddd, yyyy mmmm d.';
|
---|
5582 | End;
|
---|
5583 | End;
|
---|
5584 |
|
---|
5585 | Case CI.fsTimeFmt Of
|
---|
5586 | 0: Begin
|
---|
5587 | ShortTimeFormat := 'hh:mm ampm';
|
---|
5588 | LongTimeFormat := 'hh:mm:ss ampm';
|
---|
5589 | TwelveHours := True;
|
---|
5590 | End;
|
---|
5591 | 1: Begin
|
---|
5592 | ShortTimeFormat := 'hh:mm';
|
---|
5593 | LongTimeFormat := 'hh:mm:ss';
|
---|
5594 | TwelveHours := False;
|
---|
5595 | End;
|
---|
5596 | End;
|
---|
5597 |
|
---|
5598 | DosQueryCollate(256, cc, CollatingSequence, L);
|
---|
5599 | End;
|
---|
5600 |
|
---|
5601 | {$ENDIF}
|
---|
5602 |
|
---|
5603 | Function StringOfChars(CH: Char; Count: Integer): String;
|
---|
5604 | Begin
|
---|
5605 | SetLength(Result, Count);
|
---|
5606 | FillChar(Result[1], Count, CH);
|
---|
5607 | End;
|
---|
5608 |
|
---|
5609 | {Exception management}
|
---|
5610 | Constructor Exception.CreateFmt(Const Msg:String;Const Args:Array Of Const);
|
---|
5611 | Begin
|
---|
5612 | Inherited Create(format(Msg,Args));
|
---|
5613 | End;
|
---|
5614 |
|
---|
5615 | Constructor Exception.CreateRes(Ident:Word);
|
---|
5616 | Begin
|
---|
5617 | Inherited Create(LoadStr(Ident));
|
---|
5618 | End;
|
---|
5619 |
|
---|
5620 | Constructor Exception.CreateResFmt(Ident:Word;Const Args:Array Of Const);
|
---|
5621 | Begin
|
---|
5622 | Inherited Create(format(LoadStr(Ident),Args));
|
---|
5623 | End;
|
---|
5624 |
|
---|
5625 | Constructor Exception.CreateResNLS(Ident:Word);
|
---|
5626 | Begin
|
---|
5627 | Inherited Create(LoadNLSStr(Ident));
|
---|
5628 | End;
|
---|
5629 |
|
---|
5630 | Constructor Exception.CreateResNLSFmt(Ident:Word;Const Args:Array Of Const);
|
---|
5631 | Begin
|
---|
5632 | Inherited Create(format(LoadNLSStr(Ident),Args));
|
---|
5633 | End;
|
---|
5634 |
|
---|
5635 | Constructor Exception.CreateHelp(Const Msg:String;AHelpContext:LongInt);
|
---|
5636 | Begin
|
---|
5637 | Inherited Create(Msg);
|
---|
5638 | HelpContext:=AHelpContext;
|
---|
5639 | End;
|
---|
5640 |
|
---|
5641 | Constructor Exception.CreateFmtHelp(Const Msg:String;Const Args:Array Of Const;AHelpContext:LongInt);
|
---|
5642 | Begin
|
---|
5643 | Inherited Create(format(Msg,Args));
|
---|
5644 | HelpContext:=AHelpContext;
|
---|
5645 | End;
|
---|
5646 |
|
---|
5647 | Constructor Exception.CreateResHelp(Ident:Word;AHelpContext:LongInt);
|
---|
5648 | Begin
|
---|
5649 | Inherited Create(LoadStr(Ident));
|
---|
5650 | HelpContext:=AHelpContext;
|
---|
5651 | End;
|
---|
5652 |
|
---|
5653 | Constructor Exception.CreateResFmtHelp(Ident:Word;Const Args:Array Of Const;AHelpContext:LongInt);
|
---|
5654 | Begin
|
---|
5655 | Inherited Create(format(LoadStr(Ident),Args));
|
---|
5656 | HelpContext:=AHelpContext;
|
---|
5657 | End;
|
---|
5658 |
|
---|
5659 | Constructor Exception.CreateResNLSHelp(Ident:Word;AHelpContext:LongInt);
|
---|
5660 | Begin
|
---|
5661 | Inherited Create(LoadNLSStr(Ident));
|
---|
5662 | HelpContext:=AHelpContext;
|
---|
5663 | End;
|
---|
5664 |
|
---|
5665 | Constructor Exception.CreateResNLSFmtHelp(Ident:Word;Const Args:Array Of Const;AHelpContext:LongInt);
|
---|
5666 | Begin
|
---|
5667 | Inherited Create(format(LoadNLSStr(Ident),Args));
|
---|
5668 | HelpContext:=AHelpContext;
|
---|
5669 | End;
|
---|
5670 |
|
---|
5671 | Var AH,AQ:LongWord;
|
---|
5672 |
|
---|
5673 | Begin
|
---|
5674 | {$IFDEF OS2}
|
---|
5675 | InitPM;
|
---|
5676 | {$ENDIF}
|
---|
5677 | SetCurrentLanguageTable('SIBYL_NLS_Default');
|
---|
5678 | GetFormatSettings;
|
---|
5679 | End.
|
---|
5680 |
|
---|
5681 | { -- date -- -- changes ----------------------------------------------
|
---|
5682 |
|
---|
5683 | 28-Feb-96 assume fmShareDenyNone, If no sharing Mode Is specified.
|
---|
5684 | added support For File locking.
|
---|
5685 | 08-Mar-96 added lots Of comments. added resources And loading Of
|
---|
5686 | Error Messages And Month / Day Names.
|
---|
5687 | FIXED A bug In FormatStr.
|
---|
5688 | 14-Apr-96 removed Some forgotten debugging Code.
|
---|
5689 | 18-Apr-96 added windows-only AnsiLowerCase And AnsiCompareStr.
|
---|
5690 | FIXED A bug In DayOfWeek.
|
---|
5691 | Faster EncodeDate / DecodeDate.
|
---|
5692 | 12-may-96 Error codes returned by File Open FUNCTIONs were always -1.
|
---|
5693 | 24-may-96 added Trim, TrimLeft, TrimRight, And QuotedStr FUNCTIONs As
|
---|
5694 | In Delphi 2.0.
|
---|
5695 | 11-Jun-96 bug In FloatToStrF, ffGeneral With values < 0.001 always used
|
---|
5696 | FIXED Point.
|
---|
5697 | 27-Jul-96 removed SetLength, already declared In System Unit.
|
---|
5698 | 27-Aug-96 added SysErrorMessage.
|
---|
5699 | 26-Dec-96 FIXED Error In date encoding. changed numerous Parameters In
|
---|
5700 | API calls from LongInt To LongWord where ULONG was expected.
|
---|
5701 | 27-Dec-96 added support For AnsiStrings As Open Array Parameters In
|
---|
5702 | String formatting FUNCTIONs.
|
---|
5703 | 02-Feb-97 FIXED Some bugs:
|
---|
5704 | - FileWrite returned -1 ON Success instead Of ON failure.
|
---|
5705 | - DateTimeToFileDate didn't work With New Compiler.
|
---|
5706 | changed File access Mode For FileCreate To RD/WR/exclusive.
|
---|
5707 |
|
---|
5708 |
|
---|
5709 | ---------------------------
|
---|
5710 | Bemerkungen fr Jrg: (nur der Form halber)
|
---|
5711 | -
|
---|
5712 | Function FileCreate
|
---|
5713 | fmOpenReadWrite Or fmShareExclusive
|
---|
5714 | -
|
---|
5715 | Function DateTimeToFileDate
|
---|
5716 | Result := (FileDate Shl 16) Or FILETIME;
|
---|
5717 |
|
---|