home *** CD-ROM | disk | FTP | other *** search
/ Kompuutteri K-CD 2002 #1 / K-CD_2002-01.iso / Delphi / INSTALL / program files / Borland / Delphi6 / Doc / SysUtils.int < prev    next >
Encoding:
Text File  |  2001-05-22  |  121.2 KB  |  2,911 lines

  1. { *********************************************************************** }
  2. {                                                                         }
  3. { Delphi / Kylix Cross-Platform Runtime Library                           }
  4. { System Utilities Unit                                                   }
  5. {                                                                         }
  6. { Copyright (c) 1995-2001 Borland Softwrare Corporation                   }
  7. {                                                                         }
  8. { *********************************************************************** }
  9.  
  10. unit SysUtils;
  11.  
  12. {$H+}
  13. {$WARN SYMBOL_PLATFORM OFF}
  14.  
  15. interface
  16.  
  17. uses
  18. {$IFDEF MSWINDOWS}
  19. Windows,
  20. {$ENDIF}
  21. {$IFDEF LINUX}
  22. Types,
  23. Libc,
  24. {$ENDIF}
  25. SysConst;
  26.  
  27. const
  28. { File open modes }
  29.  
  30. {$IFDEF LINUX}
  31.   fmOpenRead       = O_RDONLY;
  32.   fmOpenWrite      = O_WRONLY;
  33.   fmOpenReadWrite  = O_RDWR;
  34. //  fmShareCompat not supported
  35.   fmShareExclusive = $0010;
  36.   fmShareDenyWrite = $0020;
  37. //  fmShareDenyRead  not supported
  38.   fmShareDenyNone  = $0030;
  39. {$ENDIF}
  40. {$IFDEF MSWINDOWS}
  41.   fmOpenRead       = $0000;
  42.   fmOpenWrite      = $0001;
  43.   fmOpenReadWrite  = $0002;
  44.  
  45.   fmShareCompat    = $0000 platform; // DOS compatibility mode is not portable
  46.   fmShareExclusive = $0010;
  47.   fmShareDenyWrite = $0020;
  48.   fmShareDenyRead  = $0030 platform; // write-only not supported on all platforms
  49.   fmShareDenyNone  = $0040;
  50. {$ENDIF}
  51.  
  52. { File attribute constants }
  53.  
  54.   faReadOnly  = $00000001 platform;
  55.   faHidden    = $00000002 platform;
  56.   faSysFile   = $00000004 platform;
  57.   faVolumeID  = $00000008 platform;
  58.   faDirectory = $00000010;
  59.   faArchive   = $00000020 platform;
  60.   faAnyFile   = $0000003F;
  61.  
  62. { Units of time }
  63.  
  64.   HoursPerDay   = 24;
  65.   MinsPerDay    = HoursPerDay * 60;
  66.   SecsPerDay    = MinsPerDay * 60;
  67.   MSecsPerDay   = SecsPerDay * 1000;
  68.  
  69. { Days between 1/1/0001 and 12/31/1899 }
  70.  
  71.   DateDelta = 693594;
  72.  
  73. { Days between TDateTime basis (12/31/1899) and Unix time_t basis (1/1/1970) }
  74.  
  75.   UnixDateDelta = 25569;
  76.  
  77. type
  78.  
  79. { Standard Character set type }
  80.  
  81.   TSysCharSet = set of Char;
  82.  
  83. { Set access to an integer }
  84.  
  85.   TIntegerSet = set of 0..SizeOf(Integer) * 8 - 1;
  86.  
  87. { Type conversion records }
  88.  
  89.   WordRec = packed record
  90.     case Integer of
  91.       0: (Lo, Hi: Byte);
  92.       1: (Bytes: array [0..1] of Byte);
  93.   end;
  94.  
  95.   LongRec = packed record
  96.     case Integer of
  97.       0: (Lo, Hi: Word);
  98.       1: (Words: array [0..1] of Word);
  99.       2: (Bytes: array [0..3] of Byte);
  100.   end;
  101.  
  102.   Int64Rec = packed record
  103.     case Integer of
  104.       0: (Lo, Hi: Cardinal);
  105.       1: (Cardinals: array [0..1] of Cardinal);
  106.       2: (Words: array [0..3] of Word);
  107.       3: (Bytes: array [0..7] of Byte);
  108.   end;
  109.  
  110. { General arrays }
  111.  
  112.   PByteArray = ^TByteArray;
  113.   TByteArray = array[0..32767] of Byte;
  114.  
  115.   PWordArray = ^TWordArray;
  116.   TWordArray = array[0..16383] of Word;
  117.  
  118. { Generic procedure pointer }
  119.  
  120.   TProcedure = procedure;
  121.  
  122. { Generic filename type }
  123.  
  124.   TFileName = type string;
  125.  
  126. { Search record used by FindFirst, FindNext, and FindClose }
  127.  
  128.   TSearchRec = record
  129.     Time: Integer;
  130.     Size: Integer;
  131.     Attr: Integer;
  132.     Name: TFileName;
  133.     ExcludeAttr: Integer;
  134. {$IFDEF MSWINDOWS}
  135.     FindHandle: THandle  platform;
  136.     FindData: TWin32FindData  platform;
  137. {$ENDIF}
  138. {$IFDEF LINUX}
  139.     Mode: mode_t  platform;
  140.     FindHandle: Pointer  platform;
  141.     PathOnly: String  platform;
  142.     Pattern: String  platform;
  143. {$ENDIF}
  144.   end;
  145.  
  146. { FloatToText, FloatToTextFmt, TextToFloat, and FloatToDecimal type codes }
  147.  
  148.   TFloatValue = (fvExtended, fvCurrency);
  149.  
  150. { FloatToText format codes }
  151.  
  152.   TFloatFormat = (ffGeneral, ffExponent, ffFixed, ffNumber, ffCurrency);
  153.  
  154. { FloatToDecimal result record }
  155.  
  156.   TFloatRec = packed record
  157.     Exponent: Smallint;
  158.     Negative: Boolean;
  159.     Digits: array[0..20] of Char;
  160.   end;
  161.  
  162. { Date and time record }
  163.  
  164.   TTimeStamp = record
  165.     Time: Integer;      { Number of milliseconds since midnight }
  166.     Date: Integer;      { One plus number of days since 1/1/0001 }
  167.   end;
  168.  
  169. { MultiByte Character Set (MBCS) byte type }
  170.   TMbcsByteType = (mbSingleByte, mbLeadByte, mbTrailByte);
  171.  
  172. { System Locale information record }
  173.   TSysLocale = packed record
  174.     DefaultLCID: Integer;
  175.     PriLangID: Integer;
  176.     SubLangID: Integer;
  177.     FarEast: Boolean;
  178.     MiddleEast: Boolean;
  179.   end;
  180.  
  181. {$IFDEF MSWINDOWS}
  182. { This is used by TLanguages }
  183.   TLangRec = packed record
  184.     FName: string;
  185.     FLCID: LCID;
  186.     FExt: string;
  187.   end;
  188.  
  189. { This stores the languages that the system supports }
  190.   TLanguages = class
  191.   public
  192.     constructor Create;
  193.     function IndexOf(ID: LCID): Integer;
  194.     property Count: Integer;
  195.     property Name[Index: Integer]: string;
  196.     property NameFromLocaleID[ID: LCID]: string;
  197.     property NameFromLCID[const ID: string]: string;
  198.     property ID[Index: Integer]: string;
  199.     property LocaleID[Index: Integer]: LCID;
  200.     property Ext[Index: Integer]: string;
  201.   end platform;
  202. {$ENDIF}
  203.  
  204. {$IFDEF LINUX}
  205.   TEraRange = record
  206.     StartDate : Integer;         // whole days since 12/31/1899 (TDateTime basis)
  207.     EndDate   : Integer;         // whole days since 12/31/1899 (TDateTime basis)
  208. //    Direction : Char;
  209.   end;
  210. {$ENDIF}
  211.  
  212. { Exceptions }
  213.  
  214.   Exception = class(TObject)
  215.   public
  216.     constructor Create(const Msg: string);
  217.     constructor CreateFmt(const Msg: string; const Args: array of const);
  218.     constructor CreateRes(Ident: Integer); overload;
  219.     constructor CreateRes(ResStringRec: PResStringRec); overload;
  220.     constructor CreateResFmt(Ident: Integer; const Args: array of const); overload;
  221.     constructor CreateResFmt(ResStringRec: PResStringRec; const Args: array of const); overload;
  222.     constructor CreateHelp(const Msg: string; AHelpContext: Integer);
  223.     constructor CreateFmtHelp(const Msg: string; const Args: array of const;
  224.       AHelpContext: Integer);
  225.     constructor CreateResHelp(Ident: Integer; AHelpContext: Integer); overload;
  226.     constructor CreateResHelp(ResStringRec: PResStringRec; AHelpContext: Integer); overload;
  227.     constructor CreateResFmtHelp(ResStringRec: PResStringRec; const Args: array of const;
  228.       AHelpContext: Integer); overload;
  229.     constructor CreateResFmtHelp(Ident: Integer; const Args: array of const;
  230.       AHelpContext: Integer); overload;
  231.     property HelpContext: Integer;
  232.     property Message: string;
  233.   end;
  234.  
  235.   ExceptClass = class of Exception;
  236.  
  237.   EAbort = class(Exception);
  238.  
  239.   EHeapException = class(Exception)
  240.   public
  241.     procedure FreeInstance; override;
  242.   end;
  243.  
  244.   EOutOfMemory = class(EHeapException);
  245.  
  246.   EInOutError = class(Exception)
  247.   public
  248.     ErrorCode: Integer;
  249.   end;
  250.  
  251. {$IFDEF MSWINDOWS}
  252.   PExceptionRecord = ^TExceptionRecord;
  253.   TExceptionRecord = record
  254.     ExceptionCode: Cardinal;
  255.     ExceptionFlags: Cardinal;
  256.     ExceptionRecord: PExceptionRecord;
  257.     ExceptionAddress: Pointer;
  258.     NumberParameters: Cardinal;
  259.     ExceptionInformation: array[0..14] of Cardinal;
  260.   end;
  261. {$ENDIF}
  262.  
  263.   EExternal = class(Exception)
  264.   public
  265. {$IFDEF MSWINDOWS}
  266.     ExceptionRecord: PExceptionRecord platform;
  267. {$ENDIF}
  268. {$IFDEF LINUX}
  269.     ExceptionAddress: LongWord platform;
  270.     AccessAddress: LongWord platform;
  271.     SignalNumber: Integer platform;
  272. {$ENDIF}
  273.   end;
  274.  
  275.   EExternalException = class(EExternal);
  276.  
  277.   EIntError = class(EExternal);
  278.   EDivByZero = class(EIntError);
  279.   ERangeError = class(EIntError);
  280.   EIntOverflow = class(EIntError);
  281.  
  282.   EMathError = class(EExternal);
  283.   EInvalidOp = class(EMathError);
  284.   EZeroDivide = class(EMathError);
  285.   EOverflow = class(EMathError);
  286.   EUnderflow = class(EMathError);
  287.  
  288.   EInvalidPointer = class(EHeapException);
  289.  
  290.   EInvalidCast = class(Exception);
  291.  
  292.   EConvertError = class(Exception);
  293.  
  294.   EAccessViolation = class(EExternal);
  295.   EPrivilege = class(EExternal);
  296.   EStackOverflow = class(EExternal)
  297.     end deprecated;
  298.   EControlC = class(EExternal);
  299. {$IFDEF LINUX}
  300.   EQuit = class(EExternal) end platform;
  301. {$ENDIF}
  302.  
  303.   EVariantError = class(Exception);
  304.  
  305.   EPropReadOnly = class(Exception);
  306.   EPropWriteOnly = class(Exception);
  307.  
  308.   EAssertionFailed = class(Exception);
  309.  
  310. {$IFNDEF PC_MAPPED_EXCEPTIONS}
  311.   EAbstractError = class(Exception) end platform;
  312. {$ENDIF}
  313.  
  314.   EIntfCastError = class(Exception);
  315.  
  316.   EInvalidContainer = class(Exception);
  317.   EInvalidInsert = class(Exception);
  318.  
  319.   EPackageError = class(Exception);
  320.  
  321.   EOSError = class(Exception)
  322.   public
  323.     ErrorCode: DWORD;
  324.   end;
  325. {$IFDEF MSWINDOWS}
  326.   EWin32Error = class(EOSError)
  327.   end deprecated;
  328. {$ENDIF}
  329.  
  330.   ESafecallException = class(Exception);
  331.  
  332. {$IFDEF LINUX}
  333.  
  334. {
  335.         Signals
  336.  
  337.     External exceptions, or signals, are, by default, converted to language
  338.     exceptions by the Delphi RTL.  Under Linux, a Delphi application installs
  339.     signal handlers to trap the raw signals, and convert them.  Delphi libraries
  340.     do not install handlers by default.  So if you are implementing a standalone
  341.     library, such as an Apache DSO, and you want to have signals converted to
  342.     language exceptions that you can catch, you must install signal hooks
  343.     manually, using the interfaces that the Delphi RTL provides.
  344.  
  345.     For most libraries, installing signal handlers is pretty
  346.     straightforward.  Call HookSignal(RTL_SIGDEFAULT) at initialization time,
  347.     and UnhookSignal(RTL_SIGNALDEFAULT) at shutdown.  This will install handlers
  348.     for a set of signals that the RTL normally hooks for Delphi applications.
  349.  
  350.     There are some cases where the above initialization will not work properly:
  351.     The proper behaviour for setting up signal handlers is to set
  352.     a signal handler, and then later restore the signal handler to its previous
  353.     state when you clean up.  If you have two libraries lib1 and lib2, and lib1
  354.     installs a signal handler, and then lib2 installs a signal handler, those
  355.     libraries have to uninstall in the proper order if they restore signal
  356.     handlers, or the signal handlers can be left in an inconsistent and
  357.     potentially fatal state.  Not all libraries behave well with respect to
  358.     installing signal handlers.  To hedge against this possibility, and allow
  359.     you to manage signal handlers better in the face of whatever behaviour
  360.     you may find in external libraries, we provide a set of four interfaces to
  361.     allow you to tailor the Delphi signal handler hooking/unhooking in the
  362.     event of an emergency.  These are:
  363.         InquireSignal
  364.         AbandonSignalHandler
  365.         HookSignal
  366.         UnhookSignal
  367.  
  368.     InquireSignal allows you to look at the state of a signal handler, so
  369.     that you can find out if someone grabbed it out from under you.
  370.  
  371.     AbandonSignalHandler tells the RTL never to unhook a particular
  372.     signal handler.  This can be used if you find a case where it would
  373.     be unsafe to return to the previous state of signal handling.  For
  374.     example, if the previous signal handler was installed by a library
  375.     which has since been unloaded.
  376.  
  377.     HookSignal/UnhookSignal setup signal handlers that map certain signals
  378.     into language exceptions.
  379.  
  380.     See additional notes at InquireSignal, et al, below.
  381. }
  382.  
  383. const
  384.     RTL_SIGINT          = 0;    // User interrupt (SIGINT)
  385.     RTL_SIGFPE          = 1;    // Floating point exception (SIGFPE)
  386.     RTL_SIGSEGV         = 2;    // Segmentation violation (SIGSEGV)
  387.     RTL_SIGILL          = 3;    // Illegal instruction (SIGILL)
  388.     RTL_SIGBUS          = 4;    // Bus error (SIGBUS)
  389.     RTL_SIGQUIT         = 5;    // User interrupt (SIGQUIT)
  390.     RTL_SIGLAST         = RTL_SIGQUIT; // Used internally.  Don't use this.
  391.     RTL_SIGDEFAULT      = -1;   // Means all of a set of signals that the we capture
  392.                                 // normally.  This is currently all of the preceding
  393.                                 // signals.  You cannot pass this to InquireSignal.
  394.  
  395. type
  396.     { TSignalState is the state of a given signal handler, as returned by
  397.       InquireSignal.  See InquireSignal, below.
  398.     }
  399.     TSignalState = (ssNotHooked, ssHooked, ssOverridden);
  400.  
  401. var
  402.  
  403.   {
  404.     If DeferUserInterrupts is set, we do not raise either SIGINT or SIGQUIT as
  405.     an exception, instead, we set SIGINTIssued or SIGQUITIssued when the
  406.     signal arrives, and swallow the signal where the OS issued it.  This gives
  407.     GUI applications the chance to defer the actual handling of the signal
  408.     until a time when it is safe to do so.
  409.   }
  410.  
  411.   DeferUserInterrupts: Boolean;
  412.   SIGINTIssued: Boolean;
  413.   SIGQUITIssued: Boolean;
  414. {$ENDIF}
  415.  
  416. {$IFDEF LINUX}
  417. const
  418.   MAX_PATH = 4095;  //from /usr/include/linux/limits.h PATH_MAX
  419. {$ENDIF}
  420.  
  421. var
  422.  
  423. { Empty string and null string pointer. These constants are provided for
  424.   backwards compatibility only.  }
  425.  
  426.   EmptyStr: string = '';
  427.   NullStr: PString = @EmptyStr;
  428.  
  429.   EmptyWideStr: WideString = '';
  430.   NullWideStr: PWideString = @EmptyWideStr;
  431.  
  432. {$IFDEF MSWINDOWS}
  433. { Win32 platform identifier.  This will be one of the following values:
  434.  
  435.     VER_PLATFORM_WIN32s
  436.     VER_PLATFORM_WIN32_WINDOWS
  437.     VER_PLATFORM_WIN32_NT
  438.  
  439.   See WINDOWS.PAS for the numerical values. }
  440.  
  441.   Win32Platform: Integer = 0;
  442.  
  443. { Win32 OS version information -
  444.  
  445.   see TOSVersionInfo.dwMajorVersion/dwMinorVersion/dwBuildNumber }
  446.  
  447.   Win32MajorVersion: Integer = 0;
  448.   Win32MinorVersion: Integer = 0;
  449.   Win32BuildNumber: Integer = 0;
  450.  
  451. { Win32 OS extra version info string -
  452.  
  453.   see TOSVersionInfo.szCSDVersion }
  454.  
  455.   Win32CSDVersion: string = '';
  456. {$ENDIF}
  457.  
  458. { Currency and date/time formatting options
  459.  
  460.   The initial values of these variables are fetched from the system registry
  461.   using the GetLocaleInfo function in the Win32 API. The description of each
  462.   variable specifies the LOCALE_XXXX constant used to fetch the initial
  463.   value.
  464.  
  465.   CurrencyString - Defines the currency symbol used in floating-point to
  466.   decimal conversions. The initial value is fetched from LOCALE_SCURRENCY.
  467.  
  468.   CurrencyFormat - Defines the currency symbol placement and separation
  469.   used in floating-point to decimal conversions. Possible values are:
  470.  
  471.     0 = '$1'
  472.     1 = '1$'
  473.     2 = '$ 1'
  474.     3 = '1 $'
  475.  
  476.   The initial value is fetched from LOCALE_ICURRENCY.
  477.  
  478.   NegCurrFormat - Defines the currency format for used in floating-point to
  479.   decimal conversions of negative numbers. Possible values are:
  480.  
  481.     0 = '($1)'      4 = '(1$)'      8 = '-1 $'      12 = '$ -1'
  482.     1 = '-$1'       5 = '-1$'       9 = '-$ 1'      13 = '1- $'
  483.     2 = '$-1'       6 = '1-$'      10 = '1 $-'      14 = '($ 1)'
  484.     3 = '$1-'       7 = '1$-'      11 = '$ 1-'      15 = '(1 $)'
  485.  
  486.   The initial value is fetched from LOCALE_INEGCURR.
  487.  
  488.   ThousandSeparator - The character used to separate thousands in numbers
  489.   with more than three digits to the left of the decimal separator. The
  490.   initial value is fetched from LOCALE_STHOUSAND.  A value of #0 indicates
  491.   no thousand separator character should be output even if the format string
  492.   specifies thousand separators.
  493.  
  494.   DecimalSeparator - The character used to separate the integer part from
  495.   the fractional part of a number. The initial value is fetched from
  496.   LOCALE_SDECIMAL.  DecimalSeparator must be a non-zero value.
  497.  
  498.   CurrencyDecimals - The number of digits to the right of the decimal point
  499.   in a currency amount. The initial value is fetched from LOCALE_ICURRDIGITS.
  500.  
  501.   DateSeparator - The character used to separate the year, month, and day
  502.   parts of a date value. The initial value is fetched from LOCATE_SDATE.
  503.  
  504.   ShortDateFormat - The format string used to convert a date value to a
  505.   short string suitable for editing. For a complete description of date and
  506.   time format strings, refer to the documentation for the FormatDate
  507.   function. The short date format should only use the date separator
  508.   character and the  m, mm, d, dd, yy, and yyyy format specifiers. The
  509.   initial value is fetched from LOCALE_SSHORTDATE.
  510.  
  511.   LongDateFormat - The format string used to convert a date value to a long
  512.   string suitable for display but not for editing. For a complete description
  513.   of date and time format strings, refer to the documentation for the
  514.   FormatDate function. The initial value is fetched from LOCALE_SLONGDATE.
  515.  
  516.   TimeSeparator - The character used to separate the hour, minute, and
  517.   second parts of a time value. The initial value is fetched from
  518.   LOCALE_STIME.
  519.  
  520.   TimeAMString - The suffix string used for time values between 00:00 and
  521.   11:59 in 12-hour clock format. The initial value is fetched from
  522.   LOCALE_S1159.
  523.  
  524.   TimePMString - The suffix string used for time values between 12:00 and
  525.   23:59 in 12-hour clock format. The initial value is fetched from
  526.   LOCALE_S2359.
  527.  
  528.   ShortTimeFormat - The format string used to convert a time value to a
  529.   short string with only hours and minutes. The default value is computed
  530.   from LOCALE_ITIME and LOCALE_ITLZERO.
  531.  
  532.   LongTimeFormat - The format string used to convert a time value to a long
  533.   string with hours, minutes, and seconds. The default value is computed
  534.   from LOCALE_ITIME and LOCALE_ITLZERO.
  535.  
  536.   ShortMonthNames - Array of strings containing short month names. The mmm
  537.   format specifier in a format string passed to FormatDate causes a short
  538.   month name to be substituted. The default values are fecthed from the
  539.   LOCALE_SABBREVMONTHNAME system locale entries.
  540.  
  541.   LongMonthNames - Array of strings containing long month names. The mmmm
  542.   format specifier in a format string passed to FormatDate causes a long
  543.   month name to be substituted. The default values are fecthed from the
  544.   LOCALE_SMONTHNAME system locale entries.
  545.  
  546.   ShortDayNames - Array of strings containing short day names. The ddd
  547.   format specifier in a format string passed to FormatDate causes a short
  548.   day name to be substituted. The default values are fecthed from the
  549.   LOCALE_SABBREVDAYNAME system locale entries.
  550.  
  551.   LongDayNames - Array of strings containing long day names. The dddd
  552.   format specifier in a format string passed to FormatDate causes a long
  553.   day name to be substituted. The default values are fecthed from the
  554.   LOCALE_SDAYNAME system locale entries.
  555.  
  556.   ListSeparator - The character used to separate items in a list.  The
  557.   initial value is fetched from LOCALE_SLIST.
  558.  
  559.   TwoDigitYearCenturyWindow - Determines what century is added to two
  560.   digit years when converting string dates to numeric dates.  This value
  561.   is subtracted from the current year before extracting the century.
  562.   This can be used to extend the lifetime of existing applications that
  563.   are inextricably tied to 2 digit year data entry.  The best solution
  564.   to Year 2000 (Y2k) issues is not to accept 2 digit years at all - require
  565.   4 digit years in data entry to eliminate century ambiguities.
  566.  
  567.   Examples:
  568.  
  569.   Current TwoDigitCenturyWindow  Century  StrToDate() of:
  570.   Year    Value                  Pivot    '01/01/03' '01/01/68' '01/01/50'
  571.   -------------------------------------------------------------------------
  572.   1998    0                      1900     1903       1968       1950
  573.   2002    0                      2000     2003       2068       2050
  574.   1998    50 (default)           1948     2003       1968       1950
  575.   2002    50 (default)           1952     2003       1968       2050
  576.   2020    50 (default)           1970     2003       2068       2050
  577.  }
  578.  
  579. var
  580.   CurrencyString: string;
  581.   CurrencyFormat: Byte;
  582.   NegCurrFormat: Byte;
  583.   ThousandSeparator: Char;
  584.   DecimalSeparator: Char;
  585.   CurrencyDecimals: Byte;
  586.   DateSeparator: Char;
  587.   ShortDateFormat: string;
  588.   LongDateFormat: string;
  589.   TimeSeparator: Char;
  590.   TimeAMString: string;
  591.   TimePMString: string;
  592.   ShortTimeFormat: string;
  593.   LongTimeFormat: string;
  594.   ShortMonthNames: array[1..12] of string;
  595.   LongMonthNames: array[1..12] of string;
  596.   ShortDayNames: array[1..7] of string;
  597.   LongDayNames: array[1..7] of string;
  598.   SysLocale: TSysLocale;
  599.   TwoDigitYearCenturyWindow: Word = 50;
  600.   ListSeparator: Char;
  601.  
  602. const
  603.   MaxEraCount = 7;
  604.  
  605. var
  606.   EraNames: array [1..MaxEraCount] of string;
  607.   EraYearOffsets: array [1..MaxEraCount] of Integer;
  608. {$IFDEF LINUX}
  609.   EraRanges : array [1..MaxEraCount] of TEraRange platform;
  610.   EraYearFormats: array [1..MaxEraCount] of string platform;
  611.   EraCount: Byte platform;
  612. {$ENDIF}
  613.  
  614. const
  615.   PathDelim  = {$IFDEF MSWINDOWS} '\'; {$ELSE} '/'; {$ENDIF}
  616.   DriveDelim = {$IFDEF MSWINDOWS} ':'; {$ELSE} '';  {$ENDIF}
  617.   PathSep    = {$IFDEF MSWINDOWS} ';'; {$ELSE} ':'; {$ENDIF}
  618.  
  619. {$IFDEF MSWINDOWS}
  620. function Languages: TLanguages;
  621. {$ENDIF}
  622.  
  623. { Memory management routines }
  624.  
  625. { AllocMem allocates a block of the given size on the heap. Each byte in
  626.   the allocated buffer is set to zero. To dispose the buffer, use the
  627.   FreeMem standard procedure. }
  628.  
  629. function AllocMem(Size: Cardinal): Pointer;
  630.  
  631. { Exit procedure handling }
  632.  
  633. { AddExitProc adds the given procedure to the run-time library's exit
  634.   procedure list. When an application terminates, its exit procedures are
  635.   executed in reverse order of definition, i.e. the last procedure passed
  636.   to AddExitProc is the first one to get executed upon termination. }
  637.  
  638. procedure AddExitProc(Proc: TProcedure);
  639.  
  640. { String handling routines }
  641.  
  642. { NewStr allocates a string on the heap. NewStr is provided for backwards
  643.   compatibility only. }
  644.  
  645. function NewStr(const S: string): PString; deprecated;
  646.  
  647. { DisposeStr disposes a string pointer that was previously allocated using
  648.   NewStr. DisposeStr is provided for backwards compatibility only. }
  649.  
  650. procedure DisposeStr(P: PString); deprecated;
  651.  
  652. { AssignStr assigns a new dynamically allocated string to the given string
  653.   pointer. AssignStr is provided for backwards compatibility only. }
  654.  
  655. procedure AssignStr(var P: PString; const S: string); deprecated;
  656.  
  657. { AppendStr appends S to the end of Dest. AppendStr is provided for
  658.   backwards compatibility only. Use "Dest := Dest + S" instead. }
  659.  
  660. procedure AppendStr(var Dest: string; const S: string); deprecated;
  661.  
  662. { UpperCase converts all ASCII characters in the given string to upper case.
  663.   The conversion affects only 7-bit ASCII characters between 'a' and 'z'. To
  664.   convert 8-bit international characters, use AnsiUpperCase. }
  665.  
  666. function UpperCase(const S: string): string;
  667.  
  668. { LowerCase converts all ASCII characters in the given string to lower case.
  669.   The conversion affects only 7-bit ASCII characters between 'A' and 'Z'. To
  670.   convert 8-bit international characters, use AnsiLowerCase. }
  671.  
  672. function LowerCase(const S: string): string;
  673.  
  674. { CompareStr compares S1 to S2, with case-sensitivity. The return value is
  675.   less than 0 if S1 < S2, 0 if S1 = S2, or greater than 0 if S1 > S2. The
  676.   compare operation is based on the 8-bit ordinal value of each character
  677.   and is not affected by the current user locale. }
  678.  
  679. function CompareStr(const S1, S2: string): Integer;
  680.  
  681. { CompareMem performs a binary compare of Length bytes of memory referenced
  682.   by P1 to that of P2.  CompareMem returns True if the memory referenced by
  683.   P1 is identical to that of P2. }
  684.  
  685. function CompareMem(P1, P2: Pointer; Length: Integer): Boolean; assembler;
  686.  
  687. { CompareText compares S1 to S2, without case-sensitivity. The return value
  688.   is the same as for CompareStr. The compare operation is based on the 8-bit
  689.   ordinal value of each character, after converting 'a'..'z' to 'A'..'Z',
  690.   and is not affected by the current user locale. }
  691.  
  692. function CompareText(const S1, S2: string): Integer;
  693.  
  694. { SameText compares S1 to S2, without case-sensitivity. Returns true if
  695.   S1 and S2 are the equal, that is, if CompareText would return 0. SameText
  696.   has the same 8-bit limitations as CompareText }
  697.  
  698. function SameText(const S1, S2: string): Boolean;
  699.  
  700. { AnsiUpperCase converts all characters in the given string to upper case.
  701.   The conversion uses the current user locale. }
  702.  
  703. function AnsiUpperCase(const S: string): string;
  704.  
  705. { AnsiLowerCase converts all characters in the given string to lower case.
  706.   The conversion uses the current user locale. }
  707.  
  708. function AnsiLowerCase(const S: string): string;
  709.  
  710. { AnsiCompareStr compares S1 to S2, with case-sensitivity. The compare
  711.   operation is controlled by the current user locale. The return value
  712.   is the same as for CompareStr. }
  713.  
  714. function AnsiCompareStr(const S1, S2: string): Integer;
  715.  
  716. { AnsiSameStr compares S1 to S2, with case-sensitivity. The compare
  717.   operation is controlled by the current user locale. The return value
  718.   is True if AnsiCompareStr would have returned 0. }
  719.  
  720. function AnsiSameStr(const S1, S2: string): Boolean;
  721.  
  722. { AnsiCompareText compares S1 to S2, without case-sensitivity. The compare
  723.   operation is controlled by the current user locale. The return value
  724.   is the same as for CompareStr. }
  725.  
  726. function AnsiCompareText(const S1, S2: string): Integer;
  727.  
  728. { AnsiSameText compares S1 to S2, without case-sensitivity. The compare
  729.   operation is controlled by the current user locale. The return value
  730.   is True if AnsiCompareText would have returned 0. }
  731.  
  732. function AnsiSameText(const S1, S2: string): Boolean;
  733.  
  734. { AnsiStrComp compares S1 to S2, with case-sensitivity. The compare
  735.   operation is controlled by the current user locale. The return value
  736.   is the same as for CompareStr. }
  737.  
  738. function AnsiStrComp(S1, S2: PChar): Integer;
  739.  
  740. { AnsiStrIComp compares S1 to S2, without case-sensitivity. The compare
  741.   operation is controlled by the current user locale. The return value
  742.   is the same as for CompareStr. }
  743.  
  744. function AnsiStrIComp(S1, S2: PChar): Integer;
  745.  
  746. { AnsiStrLComp compares S1 to S2, with case-sensitivity, up to a maximum
  747.   length of MaxLen bytes. The compare operation is controlled by the
  748.   current user locale. The return value is the same as for CompareStr. }
  749.  
  750. function AnsiStrLComp(S1, S2: PChar; MaxLen: Cardinal): Integer;
  751.  
  752. { AnsiStrLIComp compares S1 to S2, without case-sensitivity, up to a maximum
  753.   length of MaxLen bytes. The compare operation is controlled by the
  754.   current user locale. The return value is the same as for CompareStr. }
  755.  
  756. function AnsiStrLIComp(S1, S2: PChar; MaxLen: Cardinal): Integer;
  757.  
  758. { AnsiStrLower converts all characters in the given string to lower case.
  759.   The conversion uses the current user locale. }
  760.  
  761. function AnsiStrLower(Str: PChar): PChar;
  762.  
  763. { AnsiStrUpper converts all characters in the given string to upper case.
  764.   The conversion uses the current user locale. }
  765.  
  766. function AnsiStrUpper(Str: PChar): PChar;
  767.  
  768. { AnsiLastChar returns a pointer to the last full character in the string.
  769.   This function supports multibyte characters  }
  770.  
  771. function AnsiLastChar(const S: string): PChar;
  772.  
  773. { AnsiStrLastChar returns a pointer to the last full character in the string.
  774.   This function supports multibyte characters.  }
  775.  
  776. function AnsiStrLastChar(P: PChar): PChar;
  777.  
  778. { WideUpperCase converts all characters in the given string to upper case. }
  779.  
  780. function WideUpperCase(const S: WideString): WideString;
  781.  
  782. { WideLowerCase converts all characters in the given string to lower case. }
  783.  
  784. function WideLowerCase(const S: WideString): WideString;
  785.  
  786. { WideCompareStr compares S1 to S2, with case-sensitivity. The return value
  787.   is the same as for CompareStr. }
  788.  
  789. function WideCompareStr(const S1, S2: WideString): Integer;
  790.  
  791. { WideSameStr compares S1 to S2, with case-sensitivity. The return value
  792.   is True if WideCompareStr would have returned 0. }
  793.  
  794. function WideSameStr(const S1, S2: WideString): Boolean;
  795.  
  796. { WideCompareText compares S1 to S2, without case-sensitivity. The return value
  797.   is the same as for CompareStr. }
  798.  
  799. function WideCompareText(const S1, S2: WideString): Integer;
  800.  
  801. { WideSameText compares S1 to S2, without case-sensitivity. The return value
  802.   is True if WideCompareText would have returned 0. }
  803.  
  804. function WideSameText(const S1, S2: WideString): Boolean;
  805.  
  806. { Trim trims leading and trailing spaces and control characters from the
  807.   given string. }
  808.  
  809. function Trim(const S: string): string; overload;
  810. function Trim(const S: WideString): WideString; overload;
  811.  
  812. { TrimLeft trims leading spaces and control characters from the given
  813.   string. }
  814.  
  815. function TrimLeft(const S: string): string; overload;
  816. function TrimLeft(const S: WideString): WideString; overload;
  817.  
  818. { TrimRight trims trailing spaces and control characters from the given
  819.   string. }
  820.  
  821. function TrimRight(const S: string): string; overload;
  822. function TrimRight(const S: WideString): WideString; overload;
  823.  
  824. { QuotedStr returns the given string as a quoted string. A single quote
  825.   character is inserted at the beginning and the end of the string, and
  826.   for each single quote character in the string, another one is added. }
  827.  
  828. function QuotedStr(const S: string): string;
  829.  
  830. { AnsiQuotedStr returns the given string as a quoted string, using the
  831.   provided Quote character.  A Quote character is inserted at the beginning
  832.   and end of the string, and each Quote character in the string is doubled.
  833.   This function supports multibyte character strings (MBCS). }
  834.  
  835. function AnsiQuotedStr(const S: string; Quote: Char): string;
  836.  
  837. { AnsiExtractQuotedStr removes the Quote characters from the beginning and end
  838.   of a quoted string, and reduces pairs of Quote characters within the quoted
  839.   string to a single character. If the first character in Src is not the Quote
  840.   character, the function returns an empty string.  The function copies
  841.   characters from the Src to the result string until the second solitary
  842.   Quote character or the first null character in Src. The Src parameter is
  843.   updated to point to the first character following the quoted string.  If
  844.   the Src string does not contain a matching end Quote character, the Src
  845.   parameter is updated to point to the terminating null character in Src.
  846.   This function supports multibyte character strings (MBCS).  }
  847.  
  848. function AnsiExtractQuotedStr(var Src: PChar; Quote: Char): string;
  849.  
  850. { AnsiDequotedStr is a simplified version of AnsiExtractQuotedStr }
  851.  
  852. function AnsiDequotedStr(const S: string; AQuote: Char): string;
  853.  
  854. { AdjustLineBreaks adjusts all line breaks in the given string to the
  855.   indicated style.
  856.   When Style is tlbsCRLF, the function changes all
  857.   CR characters not followed by LF and all LF characters not preceded
  858.   by a CR into CR/LF pairs.
  859.   When Style is tlbsLF, the function changes all CR/LF pairs and CR characters
  860.   not followed by LF to LF characters. }
  861.  
  862. function AdjustLineBreaks(const S: string; Style: TTextLineBreakStyle =
  863.         {$IFDEF LINUX} tlbsLF {$ENDIF}
  864.         {$IFDEF MSWINDOWS} tlbsCRLF {$ENDIF}): string;
  865.  
  866. { IsValidIdent returns true if the given string is a valid identifier. An
  867.   identifier is defined as a character from the set ['A'..'Z', 'a'..'z', '_']
  868.   followed by zero or more characters from the set ['A'..'Z', 'a'..'z',
  869.   '0..'9', '_']. }
  870.  
  871. function IsValidIdent(const Ident: string): Boolean;
  872.  
  873. { IntToStr converts the given value to its decimal string representation. }
  874.  
  875. function IntToStr(Value: Integer): string; overload;
  876. function IntToStr(Value: Int64): string; overload;
  877.  
  878. { IntToHex converts the given value to a hexadecimal string representation
  879.   with the minimum number of digits specified. }
  880.  
  881. function IntToHex(Value: Integer; Digits: Integer): string; overload;
  882. function IntToHex(Value: Int64; Digits: Integer): string; overload;
  883.  
  884. { StrToInt converts the given string to an integer value. If the string
  885.   doesn't contain a valid value, an EConvertError exception is raised. }
  886.  
  887. function StrToInt(const S: string): Integer;
  888. function StrToIntDef(const S: string; Default: Integer): Integer;
  889. function TryStrToInt(const S: string; out Value: Integer): Boolean;
  890.  
  891. { Similar to the above functions but for Int64 instead }
  892.  
  893. function StrToInt64(const S: string): Int64;
  894. function StrToInt64Def(const S: string; const Default: Int64): Int64;
  895. function TryStrToInt64(const S: string; out Value: Int64): Boolean;
  896.  
  897. { StrToBool converts the given string to a boolean value.  If the string
  898.   doesn't contain a valid value, an EConvertError exception is raised.
  899.   BoolToStr converts boolean to a string value that in turn can be converted
  900.   back into a boolean.  BoolToStr will always pick the first element of
  901.   the TrueStrs/FalseStrs arrays. }
  902.  
  903. var
  904.   TrueBoolStrs: array of String;
  905.   FalseBoolStrs: array of String;
  906.  
  907. const
  908.   DefaultTrueBoolStr = 'True';   // DO NOT LOCALIZE
  909.   DefaultFalseBoolStr = 'False'; // DO NOT LOCALIZE
  910.  
  911. function StrToBool(const S: string): Boolean;
  912. function StrToBoolDef(const S: string; const Default: Boolean): Boolean;
  913. function TryStrToBool(const S: string; out Value: Boolean): Boolean;
  914.  
  915. function BoolToStr(B: Boolean; UseBoolStrs: Boolean = False): string;
  916.  
  917. { LoadStr loads the string resource given by Ident from the application's
  918.   executable file or associated resource module. If the string resource
  919.   does not exist, LoadStr returns an empty string. }
  920.  
  921. function LoadStr(Ident: Integer): string;
  922.  
  923. { FmtLoadStr loads the string resource given by Ident from the application's
  924.   executable file or associated resource module, and uses it as the format
  925.   string in a call to the Format function with the given arguments. }
  926.  
  927. function FmtLoadStr(Ident: Integer; const Args: array of const): string;
  928.  
  929. { File management routines }
  930.  
  931. { FileOpen opens the specified file using the specified access mode. The
  932.   access mode value is constructed by OR-ing one of the fmOpenXXXX constants
  933.   with one of the fmShareXXXX constants. If the return value is positive,
  934.   the function was successful and the value is the file handle of the opened
  935.   file. A return value of -1 indicates that an error occurred. }
  936.  
  937. function FileOpen(const FileName: string; Mode: LongWord): Integer;
  938.  
  939. { FileCreate creates a new file by the specified name. If the return value
  940.   is positive, the function was successful and the value is the file handle
  941.   of the new file. A return value of -1 indicates that an error occurred.
  942.   On Linux, this calls FileCreate(FileName, DEFFILEMODE) to create
  943.   the file with read and write access for the current user only.  }
  944.  
  945. function FileCreate(const FileName: string): Integer; overload;
  946.  
  947. { This second version of FileCreate lets you specify the access rights to put on the newly
  948.   created file.  The access rights parameter is ignored on Win32 }
  949.  
  950. function FileCreate(const FileName: string; Rights: Integer): Integer; overload;
  951.  
  952. { FileRead reads Count bytes from the file given by Handle into the buffer
  953.   specified by Buffer. The return value is the number of bytes actually
  954.   read; it is less than Count if the end of the file was reached. The return
  955.   value is -1 if an error occurred. }
  956.  
  957. function FileRead(Handle: Integer; var Buffer; Count: LongWord): Integer;
  958.  
  959. { FileWrite writes Count bytes to the file given by Handle from the buffer
  960.   specified by Buffer. The return value is the number of bytes actually
  961.   written, or -1 if an error occurred. }
  962.  
  963. function FileWrite(Handle: Integer; const Buffer; Count: LongWord): Integer;
  964.  
  965. { FileSeek changes the current position of the file given by Handle to be
  966.   Offset bytes relative to the point given by Origin. Origin = 0 means that
  967.   Offset is relative to the beginning of the file, Origin = 1 means that
  968.   Offset is relative to the current position, and Origin = 2 means that
  969.   Offset is relative to the end of the file. The return value is the new
  970.   current position, relative to the beginning of the file, or -1 if an error
  971.   occurred. }
  972.  
  973. function FileSeek(Handle, Offset, Origin: Integer): Integer; overload;
  974. function FileSeek(Handle: Integer; const Offset: Int64; Origin: Integer): Int64; overload;
  975.  
  976. { FileClose closes the specified file. }
  977.  
  978. procedure FileClose(Handle: Integer);
  979.  
  980. { FileAge returns the date-and-time stamp of the specified file. The return
  981.   value can be converted to a TDateTime value using the FileDateToDateTime
  982.   function. The return value is -1 if the file does not exist. }
  983.  
  984. function FileAge(const FileName: string): Integer;
  985.  
  986. { FileExists returns a boolean value that indicates whether the specified
  987.   file exists. }
  988.  
  989. function FileExists(const FileName: string): Boolean;
  990.  
  991. { DirectoryExists returns a boolean value that indicates whether the
  992.   specified directory exists (and is actually a directory) }
  993.  
  994. function DirectoryExists(const Directory: string): Boolean;
  995.  
  996. { ForceDirectories ensures that all the directories in a specific path exist.
  997.   Any portion that does not already exist will be created.  Function result
  998.   indicates success of the operation.  The function can fail if the current
  999.   user does not have sufficient file access rights to create directories in
  1000.   the given path.  }
  1001.  
  1002. function ForceDirectories(Dir: string): Boolean;
  1003.  
  1004. { FindFirst searches the directory given by Path for the first entry that
  1005.   matches the filename given by Path and the attributes given by Attr. The
  1006.   result is returned in the search record given by SearchRec. The return
  1007.   value is zero if the function was successful. Otherwise the return value
  1008.   is a system error code. After calling FindFirst, always call FindClose.
  1009.   FindFirst is typically used with FindNext and FindClose as follows:
  1010.  
  1011.     Result := FindFirst(Path, Attr, SearchRec);
  1012.     while Result = 0 do
  1013.     begin
  1014.       ProcessSearchRec(SearchRec);
  1015.       Result := FindNext(SearchRec);
  1016.     end;
  1017.     FindClose(SearchRec);
  1018.  
  1019.   where ProcessSearchRec represents user-defined code that processes the
  1020.   information in a search record. }
  1021.  
  1022. function FindFirst(const Path: string; Attr: Integer;
  1023.   var F: TSearchRec): Integer;
  1024.  
  1025. { FindNext returs the next entry that matches the name and attributes
  1026.   specified in a previous call to FindFirst. The search record must be one
  1027.   that was passed to FindFirst. The return value is zero if the function was
  1028.   successful. Otherwise the return value is a system error code. }
  1029.  
  1030. function FindNext(var F: TSearchRec): Integer;
  1031.  
  1032. { FindClose terminates a FindFirst/FindNext sequence and frees memory and system
  1033.   resources allocated by FindFirst.
  1034.   Every FindFirst/FindNext must end with a call to FindClose. }
  1035.  
  1036. procedure FindClose(var F: TSearchRec);
  1037.  
  1038. { FileGetDate returns the DOS date-and-time stamp of the file given by
  1039.   Handle. The return value is -1 if the handle is invalid. The
  1040.   FileDateToDateTime function can be used to convert the returned value to
  1041.   a TDateTime value. }
  1042.  
  1043. function FileGetDate(Handle: Integer): Integer;
  1044.  
  1045. { FileSetDate sets the DOS date-and-time stamp of the file given by FileName
  1046.   to the value given by Age. The DateTimeToFileDate function can be used to
  1047.   convert a TDateTime value to a DOS date-and-time stamp. The return value
  1048.   is zero if the function was successful. Otherwise the return value is a
  1049.   system error code.        }
  1050.  
  1051. function FileSetDate(const FileName: string; Age: Integer): Integer; overload;
  1052.  
  1053. {$IFDEF MSWINDOWS}
  1054. {  FileSetDate by handle is not available on Unix platforms because there
  1055.   is no standard way to set a file's modification time using only a file
  1056.   handle, and no standard way to obtain the file name of an open
  1057.   file handle.  }
  1058.  
  1059. function FileSetDate(Handle: Integer; Age: Integer): Integer; overload; platform;
  1060.  
  1061. { FileGetAttr returns the file attributes of the file given by FileName. The
  1062.   attributes can be examined by AND-ing with the faXXXX constants defined
  1063.   above. A return value of -1 indicates that an error occurred. }
  1064.  
  1065. function FileGetAttr(const FileName: string): Integer; platform;
  1066.  
  1067. { FileSetAttr sets the file attributes of the file given by FileName to the
  1068.   value given by Attr. The attribute value is formed by OR-ing the
  1069.   appropriate faXXXX constants. The return value is zero if the function was
  1070.   successful. Otherwise the return value is a system error code. }
  1071.  
  1072. function FileSetAttr(const FileName: string; Attr: Integer): Integer; platform;
  1073. {$ENDIF}
  1074.  
  1075. { FileIsReadOnly tests whether a given file is read-only for the current
  1076.   process and effective user id.  If the file does not exist, the
  1077.   function returns False.  (Check FileExists before calling FileIsReadOnly)
  1078.   This function is platform portable. }
  1079.  
  1080. function FileIsReadOnly(const FileName: string): Boolean;
  1081.  
  1082. { FileSetReadOnly sets the read only state of a file.  The file must
  1083.   exist and the current effective user id must be the owner of the file.
  1084.   On Unix systems, FileSetReadOnly attempts to set or remove
  1085.   all three (user, group, and other) write permissions on the file.
  1086.   If you want to grant partial permissions (writeable for owner but not
  1087.   for others), use platform specific functions such as chmod.
  1088.   The function returns True if the file was successfully modified,
  1089.   False if there was an error.  This function is platform portable.  }
  1090.  
  1091. function FileSetReadOnly(const FileName: string; ReadOnly: Boolean): Boolean;
  1092.  
  1093. { DeleteFile deletes the file given by FileName. The return value is True if
  1094.   the file was successfully deleted, or False if an error occurred. }
  1095.  
  1096. function DeleteFile(const FileName: string): Boolean;
  1097.  
  1098. { RenameFile renames the file given by OldName to the name given by NewName.
  1099.   The return value is True if the file was successfully renamed, or False if
  1100.   an error occurred. }
  1101.  
  1102. function RenameFile(const OldName, NewName: string): Boolean;
  1103.  
  1104. { ChangeFileExt changes the extension of a filename. FileName specifies a
  1105.   filename with or without an extension, and Extension specifies the new
  1106.   extension for the filename. The new extension can be a an empty string or
  1107.   a period followed by up to three characters. }
  1108.  
  1109. function ChangeFileExt(const FileName, Extension: string): string;
  1110.  
  1111. { ExtractFilePath extracts the drive and directory parts of the given
  1112.   filename. The resulting string is the leftmost characters of FileName,
  1113.   up to and including the colon or backslash that separates the path
  1114.   information from the name and extension. The resulting string is empty
  1115.   if FileName contains no drive and directory parts. }
  1116.  
  1117. function ExtractFilePath(const FileName: string): string;
  1118.  
  1119. { ExtractFileDir extracts the drive and directory parts of the given
  1120.   filename. The resulting string is a directory name suitable for passing
  1121.   to SetCurrentDir, CreateDir, etc. The resulting string is empty if
  1122.   FileName contains no drive and directory parts. }
  1123.  
  1124. function ExtractFileDir(const FileName: string): string;
  1125.  
  1126. { ExtractFileDrive extracts the drive part of the given filename.  For
  1127.   filenames with drive letters, the resulting string is '<drive>:'.
  1128.   For filenames with a UNC path, the resulting string is in the form
  1129.   '\\<servername>\<sharename>'.  If the given path contains neither
  1130.   style of filename, the result is an empty string. }
  1131.  
  1132. function ExtractFileDrive(const FileName: string): string;
  1133.  
  1134. { ExtractFileName extracts the name and extension parts of the given
  1135.   filename. The resulting string is the leftmost characters of FileName,
  1136.   starting with the first character after the colon or backslash that
  1137.   separates the path information from the name and extension. The resulting
  1138.   string is equal to FileName if FileName contains no drive and directory
  1139.   parts. }
  1140.  
  1141. function ExtractFileName(const FileName: string): string;
  1142.  
  1143. { ExtractFileExt extracts the extension part of the given filename. The
  1144.   resulting string includes the period character that separates the name
  1145.   and extension parts. The resulting string is empty if the given filename
  1146.   has no extension. }
  1147.  
  1148. function ExtractFileExt(const FileName: string): string;
  1149.  
  1150. { ExpandFileName expands the given filename to a fully qualified filename.
  1151.   The resulting string consists of a drive letter, a colon, a root relative
  1152.   directory path, and a filename. Embedded '.' and '..' directory references
  1153.   are removed. }
  1154.  
  1155. function ExpandFileName(const FileName: string): string;
  1156.  
  1157. { ExpandFilenameCase returns a fully qualified filename like ExpandFilename,
  1158.   but performs a case-insensitive filename search looking for a close match
  1159.   in the actual file system, differing only in uppercase versus lowercase of
  1160.   the letters.  This is useful to convert lazy user input into useable file
  1161.   names, or to convert filename data created on a case-insensitive file
  1162.   system (Win32) to something useable on a case-sensitive file system (Linux).
  1163.  
  1164.   The MatchFound out parameter indicates what kind of match was found in the
  1165.   file system, and what the function result is based upon:
  1166.  
  1167.   ( in order of increasing difficulty or complexity )
  1168.   mkExactMatch:  Case-sensitive match.  Result := ExpandFileName(FileName).
  1169.   mkSingleMatch: Exactly one file in the given directory path matches the
  1170.         given filename on a case-insensitive basis.
  1171.         Result := ExpandFileName(FileName as found in file system).
  1172.   mkAmbiguous: More than one file in the given directory path matches the
  1173.         given filename case-insensitively.
  1174.         In many cases, this should be considered an error.
  1175.         Result := ExpandFileName(First matching filename found).
  1176.   mkNone:  File not found at all.  Result := ExpandFileName(FileName).
  1177.  
  1178.   Note that because this function has to search the file system it may be
  1179.   much slower than ExpandFileName, particularly when the given filename is
  1180.   ambiguous or does not exist.  Use ExpandFilenameCase only when you have
  1181.   a filename of dubious orgin - such as from user input - and you want
  1182.   to make a best guess before failing.  }
  1183.  
  1184. type
  1185.   TFilenameCaseMatch = (mkNone, mkExactMatch, mkSingleMatch, mkAmbiguous);
  1186.  
  1187. function ExpandFileNameCase(const FileName: string;
  1188.   out MatchFound: TFilenameCaseMatch): string;
  1189.  
  1190. { ExpandUNCFileName expands the given filename to a fully qualified filename.
  1191.   This function is the same as ExpandFileName except that it will return the
  1192.   drive portion of the filename in the format '\\<servername>\<sharename> if
  1193.   that drive is actually a network resource instead of a local resource.
  1194.   Like ExpandFileName, embedded '.' and '..' directory references are
  1195.   removed. }
  1196.  
  1197. function ExpandUNCFileName(const FileName: string): string;
  1198.  
  1199. { ExtractRelativePath will return a file path name relative to the given
  1200.   BaseName.  It strips the common path dirs and adds '..\' for each level
  1201.   up from the BaseName path. }
  1202.  
  1203. function ExtractRelativePath(const BaseName, DestName: string): string;
  1204.  
  1205. {$IFDEF MSWINDOWS}
  1206. { ExtractShortPathName will convert the given filename to the short form
  1207.   by calling the GetShortPathName API.  Will return an empty string if
  1208.   the file or directory specified does not exist }
  1209.  
  1210. function ExtractShortPathName(const FileName: string): string;
  1211. {$ENDIF}
  1212.  
  1213. { FileSearch searches for the file given by Name in the list of directories
  1214.   given by DirList. The directory paths in DirList must be separated by
  1215.   semicolons. The search always starts with the current directory of the
  1216.   current drive. The returned value is a concatenation of one of the
  1217.   directory paths and the filename, or an empty string if the file could not
  1218.   be located. }
  1219.  
  1220. function FileSearch(const Name, DirList: string): string;
  1221.  
  1222. {$IFDEF MSWINDOWS}
  1223. { DiskFree returns the number of free bytes on the specified drive number,
  1224.   where 0 = Current, 1 = A, 2 = B, etc. DiskFree returns -1 if the drive
  1225.   number is invalid. }
  1226.  
  1227. function DiskFree(Drive: Byte): Int64;
  1228.  
  1229. { DiskSize returns the size in bytes of the specified drive number, where
  1230.   0 = Current, 1 = A, 2 = B, etc. DiskSize returns -1 if the drive number
  1231.   is invalid. }
  1232.  
  1233. function DiskSize(Drive: Byte): Int64;
  1234. {$ENDIF}
  1235.  
  1236. { FileDateToDateTime converts a DOS date-and-time value to a TDateTime
  1237.   value. The FileAge, FileGetDate, and FileSetDate routines operate on DOS
  1238.   date-and-time values, and the Time field of a TSearchRec used by the
  1239.   FindFirst and FindNext functions contains a DOS date-and-time value. }
  1240.  
  1241. function FileDateToDateTime(FileDate: Integer): TDateTime;
  1242.  
  1243. { DateTimeToFileDate converts a TDateTime value to a DOS date-and-time
  1244.   value. The FileAge, FileGetDate, and FileSetDate routines operate on DOS
  1245.   date-and-time values, and the Time field of a TSearchRec used by the
  1246.   FindFirst and FindNext functions contains a DOS date-and-time value. }
  1247.  
  1248. function DateTimeToFileDate(DateTime: TDateTime): Integer;
  1249.  
  1250. { GetCurrentDir returns the current directory. }
  1251.  
  1252. function GetCurrentDir: string;
  1253.  
  1254. { SetCurrentDir sets the current directory. The return value is True if
  1255.   the current directory was successfully changed, or False if an error
  1256.   occurred. }
  1257.  
  1258. function SetCurrentDir(const Dir: string): Boolean;
  1259.  
  1260. { CreateDir creates a new directory. The return value is True if a new
  1261.   directory was successfully created, or False if an error occurred. }
  1262.  
  1263. function CreateDir(const Dir: string): Boolean;
  1264.  
  1265. { RemoveDir deletes an existing empty directory. The return value is
  1266.   True if the directory was successfully deleted, or False if an error
  1267.   occurred. }
  1268.  
  1269. function RemoveDir(const Dir: string): Boolean;
  1270.  
  1271. { PChar routines }
  1272. { const params help simplify C++ code.  No effect on pascal code }
  1273.  
  1274. { StrLen returns the number of characters in Str, not counting the null
  1275.   terminator. }
  1276.  
  1277. function StrLen(const Str: PChar): Cardinal;
  1278.  
  1279. { StrEnd returns a pointer to the null character that terminates Str. }
  1280.  
  1281. function StrEnd(const Str: PChar): PChar;
  1282.  
  1283. { StrMove copies exactly Count characters from Source to Dest and returns
  1284.   Dest. Source and Dest may overlap. }
  1285.  
  1286. function StrMove(Dest: PChar; const Source: PChar; Count: Cardinal): PChar;
  1287.  
  1288. { StrCopy copies Source to Dest and returns Dest. }
  1289.  
  1290. function StrCopy(Dest: PChar; const Source: PChar): PChar;
  1291.  
  1292. { StrECopy copies Source to Dest and returns StrEnd(Dest). }
  1293.  
  1294. function StrECopy(Dest:PChar; const Source: PChar): PChar;
  1295.  
  1296. { StrLCopy copies at most MaxLen characters from Source to Dest and
  1297.   returns Dest. }
  1298.  
  1299. function StrLCopy(Dest: PChar; const Source: PChar; MaxLen: Cardinal): PChar;
  1300.  
  1301. { StrPCopy copies the Pascal style string Source into Dest and
  1302.   returns Dest. }
  1303.  
  1304. function StrPCopy(Dest: PChar; const Source: string): PChar;
  1305.  
  1306. { StrPLCopy copies at most MaxLen characters from the Pascal style string
  1307.   Source into Dest and returns Dest. }
  1308.  
  1309. function StrPLCopy(Dest: PChar; const Source: string;
  1310.   MaxLen: Cardinal): PChar;
  1311.  
  1312. { StrCat appends a copy of Source to the end of Dest and returns Dest. }
  1313.  
  1314. function StrCat(Dest: PChar; const Source: PChar): PChar;
  1315.  
  1316. { StrLCat appends at most MaxLen - StrLen(Dest) characters from Source to
  1317.   the end of Dest, and returns Dest. }
  1318.  
  1319. function StrLCat(Dest: PChar; const Source: PChar; MaxLen: Cardinal): PChar;
  1320.  
  1321. { StrComp compares Str1 to Str2. The return value is less than 0 if
  1322.   Str1 < Str2, 0 if Str1 = Str2, or greater than 0 if Str1 > Str2. }
  1323.  
  1324. function StrComp(const Str1, Str2: PChar): Integer;
  1325.  
  1326. { StrIComp compares Str1 to Str2, without case sensitivity. The return
  1327.   value is the same as StrComp. }
  1328.  
  1329. function StrIComp(const Str1, Str2: PChar): Integer;
  1330.  
  1331. { StrLComp compares Str1 to Str2, for a maximum length of MaxLen
  1332.   characters. The return value is the same as StrComp. }
  1333.  
  1334. function StrLComp(const Str1, Str2: PChar; MaxLen: Cardinal): Integer;
  1335.  
  1336. { StrLIComp compares Str1 to Str2, for a maximum length of MaxLen
  1337.   characters, without case sensitivity. The return value is the same
  1338.   as StrComp. }
  1339.  
  1340. function StrLIComp(const Str1, Str2: PChar; MaxLen: Cardinal): Integer;
  1341.  
  1342. { StrScan returns a pointer to the first occurrence of Chr in Str. If Chr
  1343.   does not occur in Str, StrScan returns NIL. The null terminator is
  1344.   considered to be part of the string. }
  1345.  
  1346. function StrScan(const Str: PChar; Chr: Char): PChar;
  1347.  
  1348. { StrRScan returns a pointer to the last occurrence of Chr in Str. If Chr
  1349.   does not occur in Str, StrRScan returns NIL. The null terminator is
  1350.   considered to be part of the string. }
  1351.  
  1352. function StrRScan(const Str: PChar; Chr: Char): PChar;
  1353.  
  1354. { StrPos returns a pointer to the first occurrence of Str2 in Str1. If
  1355.   Str2 does not occur in Str1, StrPos returns NIL. }
  1356.  
  1357. function StrPos(const Str1, Str2: PChar): PChar;
  1358.  
  1359. { StrUpper converts Str to upper case and returns Str. }
  1360.  
  1361. function StrUpper(Str: PChar): PChar;
  1362.  
  1363. { StrLower converts Str to lower case and returns Str. }
  1364.  
  1365. function StrLower(Str: PChar): PChar;
  1366.  
  1367. { StrPas converts Str to a Pascal style string. This function is provided
  1368.   for backwards compatibility only. To convert a null terminated string to
  1369.   a Pascal style string, use a string type cast or an assignment. }
  1370.  
  1371. function StrPas(const Str: PChar): string;
  1372.  
  1373. { StrAlloc allocates a buffer of the given size on the heap. The size of
  1374.   the allocated buffer is encoded in a four byte header that immediately
  1375.   preceeds the buffer. To dispose the buffer, use StrDispose. }
  1376.  
  1377. function StrAlloc(Size: Cardinal): PChar;
  1378.  
  1379. { StrBufSize returns the allocated size of the given buffer, not including
  1380.   the two byte header. }
  1381.  
  1382. function StrBufSize(const Str: PChar): Cardinal;
  1383.  
  1384. { StrNew allocates a copy of Str on the heap. If Str is NIL, StrNew returns
  1385.   NIL and doesn't allocate any heap space. Otherwise, StrNew makes a
  1386.   duplicate of Str, obtaining space with a call to the StrAlloc function,
  1387.   and returns a pointer to the duplicated string. To dispose the string,
  1388.   use StrDispose. }
  1389.  
  1390. function StrNew(const Str: PChar): PChar;
  1391.  
  1392. { StrDispose disposes a string that was previously allocated with StrAlloc
  1393.   or StrNew. If Str is NIL, StrDispose does nothing. }
  1394.  
  1395. procedure StrDispose(Str: PChar);
  1396.  
  1397. { String formatting routines }
  1398.  
  1399. { The Format routine formats the argument list given by the Args parameter
  1400.   using the format string given by the Format parameter.
  1401.  
  1402.   Format strings contain two types of objects--plain characters and format
  1403.   specifiers. Plain characters are copied verbatim to the resulting string.
  1404.   Format specifiers fetch arguments from the argument list and apply
  1405.   formatting to them.
  1406.  
  1407.   Format specifiers have the following form:
  1408.  
  1409.     "%" [index ":"] ["-"] [width] ["." prec] type
  1410.  
  1411.   A format specifier begins with a % character. After the % come the
  1412.   following, in this order:
  1413.  
  1414.   -  an optional argument index specifier, [index ":"]
  1415.   -  an optional left-justification indicator, ["-"]
  1416.   -  an optional width specifier, [width]
  1417.   -  an optional precision specifier, ["." prec]
  1418.   -  the conversion type character, type
  1419.  
  1420.   The following conversion characters are supported:
  1421.  
  1422.   d  Decimal. The argument must be an integer value. The value is converted
  1423.      to a string of decimal digits. If the format string contains a precision
  1424.      specifier, it indicates that the resulting string must contain at least
  1425.      the specified number of digits; if the value has less digits, the
  1426.      resulting string is left-padded with zeros.
  1427.  
  1428.   u  Unsigned decimal.  Similar to 'd' but no sign is output.
  1429.  
  1430.   e  Scientific. The argument must be a floating-point value. The value is
  1431.      converted to a string of the form "-d.ddd...E+ddd". The resulting
  1432.      string starts with a minus sign if the number is negative, and one digit
  1433.      always precedes the decimal point. The total number of digits in the
  1434.      resulting string (including the one before the decimal point) is given
  1435.      by the precision specifer in the format string--a default precision of
  1436.      15 is assumed if no precision specifer is present. The "E" exponent
  1437.      character in the resulting string is always followed by a plus or minus
  1438.      sign and at least three digits.
  1439.  
  1440.   f  Fixed. The argument must be a floating-point value. The value is
  1441.      converted to a string of the form "-ddd.ddd...". The resulting string
  1442.      starts with a minus sign if the number is negative. The number of digits
  1443.      after the decimal point is given by the precision specifier in the
  1444.      format string--a default of 2 decimal digits is assumed if no precision
  1445.      specifier is present.
  1446.  
  1447.   g  General. The argument must be a floating-point value. The value is
  1448.      converted to the shortest possible decimal string using fixed or
  1449.      scientific format. The number of significant digits in the resulting
  1450.      string is given by the precision specifier in the format string--a
  1451.      default precision of 15 is assumed if no precision specifier is present.
  1452.      Trailing zeros are removed from the resulting string, and a decimal
  1453.      point appears only if necessary. The resulting string uses fixed point
  1454.      format if the number of digits to the left of the decimal point in the
  1455.      value is less than or equal to the specified precision, and if the
  1456.      value is greater than or equal to 0.00001. Otherwise the resulting
  1457.      string uses scientific format.
  1458.  
  1459.   n  Number. The argument must be a floating-point value. The value is
  1460.      converted to a string of the form "-d,ddd,ddd.ddd...". The "n" format
  1461.      corresponds to the "f" format, except that the resulting string
  1462.      contains thousand separators.
  1463.  
  1464.   m  Money. The argument must be a floating-point value. The value is
  1465.      converted to a string that represents a currency amount. The conversion
  1466.      is controlled by the CurrencyString, CurrencyFormat, NegCurrFormat,
  1467.      ThousandSeparator, DecimalSeparator, and CurrencyDecimals global
  1468.      variables, all of which are initialized from locale settings provided
  1469.      by the operating system.  For example, Currency Format preferences can be
  1470.      set in the International section of the Windows Control Panel. If the format
  1471.      string contains a precision specifier, it overrides the value given
  1472.      by the CurrencyDecimals global variable.
  1473.  
  1474.   p  Pointer. The argument must be a pointer value. The value is converted
  1475.      to a string of the form "XXXX:YYYY" where XXXX and YYYY are the
  1476.      segment and offset parts of the pointer expressed as four hexadecimal
  1477.      digits.
  1478.  
  1479.   s  String. The argument must be a character, a string, or a PChar value.
  1480.      The string or character is inserted in place of the format specifier.
  1481.      The precision specifier, if present in the format string, specifies the
  1482.      maximum length of the resulting string. If the argument is a string
  1483.      that is longer than this maximum, the string is truncated.
  1484.  
  1485.   x  Hexadecimal. The argument must be an integer value. The value is
  1486.      converted to a string of hexadecimal digits. If the format string
  1487.      contains a precision specifier, it indicates that the resulting string
  1488.      must contain at least the specified number of digits; if the value has
  1489.      less digits, the resulting string is left-padded with zeros.
  1490.  
  1491.   Conversion characters may be specified in upper case as well as in lower
  1492.   case--both produce the same results.
  1493.  
  1494.   For all floating-point formats, the actual characters used as decimal and
  1495.   thousand separators are obtained from the DecimalSeparator and
  1496.   ThousandSeparator global variables.
  1497.  
  1498.   Index, width, and precision specifiers can be specified directly using
  1499.   decimal digit string (for example "%10d"), or indirectly using an asterisk
  1500.   charcater (for example "%*.*f"). When using an asterisk, the next argument
  1501.   in the argument list (which must be an integer value) becomes the value
  1502.   that is actually used. For example "Format('%*.*f', [8, 2, 123.456])" is
  1503.   the same as "Format('%8.2f', [123.456])".
  1504.  
  1505.   A width specifier sets the minimum field width for a conversion. If the
  1506.   resulting string is shorter than the minimum field width, it is padded
  1507.   with blanks to increase the field width. The default is to right-justify
  1508.   the result by adding blanks in front of the value, but if the format
  1509.   specifier contains a left-justification indicator (a "-" character
  1510.   preceding the width specifier), the result is left-justified by adding
  1511.   blanks after the value.
  1512.  
  1513.   An index specifier sets the current argument list index to the specified
  1514.   value. The index of the first argument in the argument list is 0. Using
  1515.   index specifiers, it is possible to format the same argument multiple
  1516.   times. For example "Format('%d %d %0:d %d', [10, 20])" produces the string
  1517.   '10 20 10 20'.
  1518.  
  1519.   The Format function can be combined with other formatting functions. For
  1520.   example
  1521.  
  1522.     S := Format('Your total was %s on %s', [
  1523.       FormatFloat('$#,##0.00;;zero', Total),
  1524.       FormatDateTime('mm/dd/yy', Date)]);
  1525.  
  1526.   which uses the FormatFloat and FormatDateTime functions to customize the
  1527.   format beyond what is possible with Format. }
  1528.  
  1529. function Format(const Format: string; const Args: array of const): string;
  1530.  
  1531. { FmtStr formats the argument list given by Args using the format string
  1532.   given by Format into the string variable given by Result. For further
  1533.   details, see the description of the Format function. }
  1534.  
  1535. procedure FmtStr(var Result: string; const Format: string;
  1536.   const Args: array of const);
  1537.  
  1538. { StrFmt formats the argument list given by Args using the format string
  1539.   given by Format into the buffer given by Buffer. It is up to the caller to
  1540.   ensure that Buffer is large enough for the resulting string. The returned
  1541.   value is Buffer. For further details, see the description of the Format
  1542.   function. }
  1543.  
  1544. function StrFmt(Buffer, Format: PChar; const Args: array of const): PChar;
  1545.  
  1546. { StrFmt formats the argument list given by Args using the format string
  1547.   given by Format into the buffer given by Buffer. The resulting string will
  1548.   contain no more than MaxBufLen characters, not including the null terminator.
  1549.   The returned value is Buffer. For further details, see the description of
  1550.   the Format function. }
  1551.  
  1552. function StrLFmt(Buffer: PChar; MaxBufLen: Cardinal; Format: PChar;
  1553.   const Args: array of const): PChar;
  1554.  
  1555. { FormatBuf formats the argument list given by Args using the format string
  1556.   given by Format and FmtLen into the buffer given by Buffer and BufLen.
  1557.   The Format parameter is a reference to a buffer containing FmtLen
  1558.   characters, and the Buffer parameter is a reference to a buffer of BufLen
  1559.   characters. The returned value is the number of characters actually stored
  1560.   in Buffer. The returned value is always less than or equal to BufLen. For
  1561.   further details, see the description of the Format function. }
  1562.  
  1563. function FormatBuf(var Buffer; BufLen: Cardinal; const Format;
  1564.   FmtLen: Cardinal; const Args: array of const): Cardinal;
  1565.  
  1566. { The WideFormat routine formats the argument list given by the Args parameter
  1567.   using the format WideString given by the Format parameter. This routine is
  1568.   the WideString equivalent of Format. For further details, see the description
  1569.   of the Format function. }
  1570. function WideFormat(const Format: WideString;
  1571.   const Args: array of const): WideString;
  1572.  
  1573. { FmtStr formats the argument list given by Args using the format WideString
  1574.   given by Format into the WideString variable given by Result. For further
  1575.   details, see the description of the Format function. }
  1576. procedure WideFmtStr(var Result: WideString; const Format: WideString;
  1577.   const Args: array of const);
  1578.  
  1579. { WideFormatBuf formats the argument list given by Args using the format string
  1580.   given by Format and FmtLen into the buffer given by Buffer and BufLen.
  1581.   The Format parameter is a reference to a buffer containing FmtLen
  1582.   UNICODE characters (WideChar), and the Buffer parameter is a reference to a
  1583.   buffer of BufLen UNICODE characters (WideChar). The return value is the number
  1584.   of UNICODE characters actually stored in Buffer. The return value is always
  1585.   less than or equal to BufLen. For further details, see the description of the
  1586.   Format function.
  1587.  
  1588.   Important: BufLen, FmtLen and the return result are always the number of
  1589.   UNICODE characters, *not* the number of bytes. To calculate the number of bytes
  1590.   multiply them by SizeOf(WideChar). }
  1591. function WideFormatBuf(var Buffer; BufLen: Cardinal; const Format;
  1592.   FmtLen: Cardinal; const Args: array of const): Cardinal;
  1593.  
  1594. { Floating point conversion routines }
  1595.  
  1596. { FloatToStr converts the floating-point value given by Value to its string
  1597.   representation. The conversion uses general number format with 15
  1598.   significant digits. For further details, see the description of the
  1599.   FloatToStrF function. }
  1600.  
  1601. function FloatToStr(Value: Extended): string;
  1602.  
  1603. { CurrToStr converts the currency value given by Value to its string
  1604.   representation. The conversion uses general number format. For further
  1605.   details, see the description of the CurrToStrF function. }
  1606.  
  1607. function CurrToStr(Value: Currency): string;
  1608.  
  1609. { FloatToCurr will range validate a value to make sure it falls
  1610.   within the acceptable currency range }
  1611.  
  1612. const
  1613.   MinCurrency: Currency = -922337203685477.5807 {$IFDEF LINUX} + 1 {$ENDIF};  //!! overflow?
  1614.   MaxCurrency: Currency =  922337203685477.5807 {$IFDEF LINUX} - 1 {$ENDIF};  //!! overflow?
  1615.  
  1616. function FloatToCurr(const Value: Extended): Currency;
  1617.  
  1618. { FloatToStrF converts the floating-point value given by Value to its string
  1619.   representation. The Format parameter controls the format of the resulting
  1620.   string. The Precision parameter specifies the precision of the given value.
  1621.   It should be 7 or less for values of type Single, 15 or less for values of
  1622.   type Double, and 18 or less for values of type Extended. The meaning of the
  1623.   Digits parameter depends on the particular format selected.
  1624.  
  1625.   The possible values of the Format parameter, and the meaning of each, are
  1626.   described below.
  1627.  
  1628.   ffGeneral - General number format. The value is converted to the shortest
  1629.   possible decimal string using fixed or scientific format. Trailing zeros
  1630.   are removed from the resulting string, and a decimal point appears only
  1631.   if necessary. The resulting string uses fixed point format if the number
  1632.   of digits to the left of the decimal point in the value is less than or
  1633.   equal to the specified precision, and if the value is greater than or
  1634.   equal to 0.00001. Otherwise the resulting string uses scientific format,
  1635.   and the Digits parameter specifies the minimum number of digits in the
  1636.   exponent (between 0 and 4).
  1637.  
  1638.   ffExponent - Scientific format. The value is converted to a string of the
  1639.   form "-d.ddd...E+dddd". The resulting string starts with a minus sign if
  1640.   the number is negative, and one digit always precedes the decimal point.
  1641.   The total number of digits in the resulting string (including the one
  1642.   before the decimal point) is given by the Precision parameter. The "E"
  1643.   exponent character in the resulting string is always followed by a plus
  1644.   or minus sign and up to four digits. The Digits parameter specifies the
  1645.   minimum number of digits in the exponent (between 0 and 4).
  1646.  
  1647.   ffFixed - Fixed point format. The value is converted to a string of the
  1648.   form "-ddd.ddd...". The resulting string starts with a minus sign if the
  1649.   number is negative, and at least one digit always precedes the decimal
  1650.   point. The number of digits after the decimal point is given by the Digits
  1651.   parameter--it must be between 0 and 18. If the number of digits to the
  1652.   left of the decimal point is greater than the specified precision, the
  1653.   resulting value will use scientific format.
  1654.  
  1655.   ffNumber - Number format. The value is converted to a string of the form
  1656.   "-d,ddd,ddd.ddd...". The ffNumber format corresponds to the ffFixed format,
  1657.   except that the resulting string contains thousand separators.
  1658.  
  1659.   ffCurrency - Currency format. The value is converted to a string that
  1660.   represents a currency amount. The conversion is controlled by the
  1661.   CurrencyString, CurrencyFormat, NegCurrFormat, ThousandSeparator, and
  1662.   DecimalSeparator global variables, all of which are initialized from
  1663.   locale settings provided by the operating system.  For example,
  1664.   Currency Format preferences can be set in the International section
  1665.   of the Windows Control Panel.
  1666.   The number of digits after the decimal point is given by the Digits
  1667.   parameter--it must be between 0 and 18.
  1668.  
  1669.   For all formats, the actual characters used as decimal and thousand
  1670.   separators are obtained from the DecimalSeparator and ThousandSeparator
  1671.   global variables.
  1672.  
  1673.   If the given value is a NAN (not-a-number), the resulting string is 'NAN'.
  1674.   If the given value is positive infinity, the resulting string is 'INF'. If
  1675.   the given value is negative infinity, the resulting string is '-INF'. }
  1676.  
  1677. function FloatToStrF(Value: Extended; Format: TFloatFormat;
  1678.   Precision, Digits: Integer): string;
  1679.  
  1680. { CurrToStrF converts the currency value given by Value to its string
  1681.   representation. A call to CurrToStrF corresponds to a call to
  1682.   FloatToStrF with an implied precision of 19 digits. }
  1683.  
  1684. function CurrToStrF(Value: Currency; Format: TFloatFormat;
  1685.   Digits: Integer): string;
  1686.  
  1687. { FloatToText converts the given floating-point value to its decimal
  1688.   representation using the specified format, precision, and digits. The
  1689.   Value parameter must be a variable of type Extended or Currency, as
  1690.   indicated by the ValueType parameter. The resulting string of characters
  1691.   is stored in the given buffer, and the returned value is the number of
  1692.   characters stored. The resulting string is not null-terminated. For
  1693.   further details, see the description of the FloatToStrF function. }
  1694.  
  1695. function FloatToText(BufferArg: PChar; const Value; ValueType: TFloatValue;
  1696.   Format: TFloatFormat; Precision, Digits: Integer): Integer;
  1697.  
  1698. { FormatFloat formats the floating-point value given by Value using the
  1699.   format string given by Format. The following format specifiers are
  1700.   supported in the format string:
  1701.  
  1702.   0     Digit placeholder. If the value being formatted has a digit in the
  1703.         position where the '0' appears in the format string, then that digit
  1704.         is copied to the output string. Otherwise, a '0' is stored in that
  1705.         position in the output string.
  1706.  
  1707.   #     Digit placeholder. If the value being formatted has a digit in the
  1708.         position where the '#' appears in the format string, then that digit
  1709.         is copied to the output string. Otherwise, nothing is stored in that
  1710.         position in the output string.
  1711.  
  1712.   .     Decimal point. The first '.' character in the format string
  1713.         determines the location of the decimal separator in the formatted
  1714.         value; any additional '.' characters are ignored. The actual
  1715.         character used as a the decimal separator in the output string is
  1716.         determined by the DecimalSeparator global variable, which is initialized
  1717.         from locale settings obtained from the operating system.
  1718.  
  1719.   ,     Thousand separator. If the format string contains one or more ','
  1720.         characters, the output will have thousand separators inserted between
  1721.         each group of three digits to the left of the decimal point. The
  1722.         placement and number of ',' characters in the format string does not
  1723.         affect the output, except to indicate that thousand separators are
  1724.         wanted. The actual character used as a the thousand separator in the
  1725.         output is determined by the ThousandSeparator global variable, which
  1726.         is initialized from locale settings obtained from the operating system.
  1727.  
  1728.   E+    Scientific notation. If any of the strings 'E+', 'E-', 'e+', or 'e-'
  1729.   E-    are contained in the format string, the number is formatted using
  1730.   e+    scientific notation. A group of up to four '0' characters can
  1731.   e-    immediately follow the 'E+', 'E-', 'e+', or 'e-' to determine the
  1732.         minimum number of digits in the exponent. The 'E+' and 'e+' formats
  1733.         cause a plus sign to be output for positive exponents and a minus
  1734.         sign to be output for negative exponents. The 'E-' and 'e-' formats
  1735.         output a sign character only for negative exponents.
  1736.  
  1737.   'xx'  Characters enclosed in single or double quotes are output as-is, and
  1738.   "xx"  do not affect formatting.
  1739.  
  1740.   ;     Separates sections for positive, negative, and zero numbers in the
  1741.         format string.
  1742.  
  1743.   The locations of the leftmost '0' before the decimal point in the format
  1744.   string and the rightmost '0' after the decimal point in the format string
  1745.   determine the range of digits that are always present in the output string.
  1746.  
  1747.   The number being formatted is always rounded to as many decimal places as
  1748.   there are digit placeholders ('0' or '#') to the right of the decimal
  1749.   point. If the format string contains no decimal point, the value being
  1750.   formatted is rounded to the nearest whole number.
  1751.  
  1752.   If the number being formatted has more digits to the left of the decimal
  1753.   separator than there are digit placeholders to the left of the '.'
  1754.   character in the format string, the extra digits are output before the
  1755.   first digit placeholder.
  1756.  
  1757.   To allow different formats for positive, negative, and zero values, the
  1758.   format string can contain between one and three sections separated by
  1759.   semicolons.
  1760.  
  1761.   One section - The format string applies to all values.
  1762.  
  1763.   Two sections - The first section applies to positive values and zeros, and
  1764.   the second section applies to negative values.
  1765.  
  1766.   Three sections - The first section applies to positive values, the second
  1767.   applies to negative values, and the third applies to zeros.
  1768.  
  1769.   If the section for negative values or the section for zero values is empty,
  1770.   that is if there is nothing between the semicolons that delimit the
  1771.   section, the section for positive values is used instead.
  1772.  
  1773.   If the section for positive values is empty, or if the entire format string
  1774.   is empty, the value is formatted using general floating-point formatting
  1775.   with 15 significant digits, corresponding to a call to FloatToStrF with
  1776.   the ffGeneral format. General floating-point formatting is also used if
  1777.   the value has more than 18 digits to the left of the decimal point and
  1778.   the format string does not specify scientific notation.
  1779.  
  1780.   The table below shows some sample formats and the results produced when
  1781.   the formats are applied to different values:
  1782.  
  1783.   Format string          1234        -1234       0.5         0
  1784.   -----------------------------------------------------------------------
  1785.                          1234        -1234       0.5         0
  1786.   0                      1234        -1234       1           0
  1787.   0.00                   1234.00     -1234.00    0.50        0.00
  1788.   #.##                   1234        -1234       .5
  1789.   #,##0.00               1,234.00    -1,234.00   0.50        0.00
  1790.   #,##0.00;(#,##0.00)    1,234.00    (1,234.00)  0.50        0.00
  1791.   #,##0.00;;Zero         1,234.00    -1,234.00   0.50        Zero
  1792.   0.000E+00              1.234E+03   -1.234E+03  5.000E-01   0.000E+00
  1793.   #.###E-0               1.234E3     -1.234E3    5E-1        0E0
  1794.   ----------------------------------------------------------------------- }
  1795.  
  1796. function FormatFloat(const Format: string; Value: Extended): string;
  1797.  
  1798. { FormatCurr formats the currency value given by Value using the format
  1799.   string given by Format. For further details, see the description of the
  1800.   FormatFloat function. }
  1801.  
  1802. function FormatCurr(const Format: string; Value: Currency): string;
  1803.  
  1804. { FloatToTextFmt converts the given floating-point value to its decimal
  1805.   representation using the specified format. The Value parameter must be a
  1806.   variable of type Extended or Currency, as indicated by the ValueType
  1807.   parameter. The resulting string of characters is stored in the given
  1808.   buffer, and the returned value is the number of characters stored. The
  1809.   resulting string is not null-terminated. For further details, see the
  1810.   description of the FormatFloat function. }
  1811.  
  1812. function FloatToTextFmt(Buf: PChar; const Value; ValueType: TFloatValue;
  1813.   Format: PChar): Integer;
  1814.  
  1815. { StrToFloat converts the given string to a floating-point value. The string
  1816.   must consist of an optional sign (+ or -), a string of digits with an
  1817.   optional decimal point, and an optional 'E' or 'e' followed by a signed
  1818.   integer. Leading and trailing blanks in the string are ignored. The
  1819.   DecimalSeparator global variable defines the character that must be used
  1820.   as a decimal point. Thousand separators and currency symbols are not
  1821.   allowed in the string. If the string doesn't contain a valid value, an
  1822.   EConvertError exception is raised. }
  1823.  
  1824. function StrToFloat(const S: string): Extended;
  1825. function StrToFloatDef(const S: string; const Default: Extended): Extended;
  1826. function TryStrToFloat(const S: string; out Value: Extended): Boolean; overload;
  1827. function TryStrToFloat(const S: string; out Value: Double): Boolean; overload;
  1828. function TryStrToFloat(const S: string; out Value: Single): Boolean; overload;
  1829.  
  1830. { StrToCurr converts the given string to a currency value. For further
  1831.   details, see the description of the StrToFloat function. }
  1832.  
  1833. function StrToCurr(const S: string): Currency;
  1834. function StrToCurrDef(const S: string; const Default: Currency): Currency;
  1835. function TryStrToCurr(const S: string; out Value: Currency): Boolean;
  1836.  
  1837. { TextToFloat converts the null-terminated string given by Buffer to a
  1838.   floating-point value which is returned in the variable given by Value.
  1839.   The Value parameter must be a variable of type Extended or Currency, as
  1840.   indicated by the ValueType parameter. The return value is True if the
  1841.   conversion was successful, or False if the string is not a valid
  1842.   floating-point value. For further details, see the description of the
  1843.   StrToFloat function. }
  1844.  
  1845. function TextToFloat(Buffer: PChar; var Value;
  1846.   ValueType: TFloatValue): Boolean;
  1847.  
  1848. { FloatToDecimal converts a floating-point value to a decimal representation
  1849.   that is suited for further formatting. The Value parameter must be a
  1850.   variable of type Extended or Currency, as indicated by the ValueType
  1851.   parameter. For values of type Extended, the Precision parameter specifies
  1852.   the requested number of significant digits in the result--the allowed range
  1853.   is 1..18. For values of type Currency, the Precision parameter is ignored,
  1854.   and the implied precision of the conversion is 19 digits. The Decimals
  1855.   parameter specifies the requested maximum number of digits to the left of
  1856.   the decimal point in the result. Precision and Decimals together control
  1857.   how the result is rounded. To produce a result that always has a given
  1858.   number of significant digits regardless of the magnitude of the number,
  1859.   specify 9999 for the Decimals parameter. The result of the conversion is
  1860.   stored in the specified TFloatRec record as follows:
  1861.  
  1862.   Exponent - Contains the magnitude of the number, i.e. the number of
  1863.   significant digits to the right of the decimal point. The Exponent field
  1864.   is negative if the absolute value of the number is less than one. If the
  1865.   number is a NAN (not-a-number), Exponent is set to -32768. If the number
  1866.   is INF or -INF (positive or negative infinity), Exponent is set to 32767.
  1867.  
  1868.   Negative - True if the number is negative, False if the number is zero
  1869.   or positive.
  1870.  
  1871.   Digits - Contains up to 18 (for type Extended) or 19 (for type Currency)
  1872.   significant digits followed by a null terminator. The implied decimal
  1873.   point (if any) is not stored in Digits. Trailing zeros are removed, and
  1874.   if the resulting number is zero, NAN, or INF, Digits contains nothing but
  1875.   the null terminator. }
  1876.  
  1877. procedure FloatToDecimal(var Result: TFloatRec; const Value;
  1878.   ValueType: TFloatValue; Precision, Decimals: Integer);
  1879.  
  1880. { Date/time support routines }
  1881.  
  1882. function DateTimeToTimeStamp(DateTime: TDateTime): TTimeStamp;
  1883.  
  1884. function TimeStampToDateTime(const TimeStamp: TTimeStamp): TDateTime;
  1885. function MSecsToTimeStamp(MSecs: Comp): TTimeStamp;
  1886. function TimeStampToMSecs(const TimeStamp: TTimeStamp): Comp;
  1887.  
  1888. { EncodeDate encodes the given year, month, and day into a TDateTime value.
  1889.   The year must be between 1 and 9999, the month must be between 1 and 12,
  1890.   and the day must be between 1 and N, where N is the number of days in the
  1891.   specified month. If the specified values are not within range, an
  1892.   EConvertError exception is raised. The resulting value is the number of
  1893.   days between 12/30/1899 and the given date. }
  1894.  
  1895. function EncodeDate(Year, Month, Day: Word): TDateTime;
  1896.  
  1897. { EncodeTime encodes the given hour, minute, second, and millisecond into a
  1898.   TDateTime value. The hour must be between 0 and 23, the minute must be
  1899.   between 0 and 59, the second must be between 0 and 59, and the millisecond
  1900.   must be between 0 and 999. If the specified values are not within range, an
  1901.   EConvertError exception is raised. The resulting value is a number between
  1902.   0 (inclusive) and 1 (not inclusive) that indicates the fractional part of
  1903.   a day given by the specified time. The value 0 corresponds to midnight,
  1904.   0.5 corresponds to noon, 0.75 corresponds to 6:00 pm, etc. }
  1905.  
  1906. function EncodeTime(Hour, Min, Sec, MSec: Word): TDateTime;
  1907.  
  1908. { Instead of generating errors the following variations of EncodeDate and
  1909.   EncodeTime simply return False if the parameters given are not valid.
  1910.   Other than that, these functions are functionally the same as the above
  1911.   functions. }
  1912.  
  1913. function TryEncodeDate(Year, Month, Day: Word; out Date: TDateTime): Boolean;
  1914. function TryEncodeTime(Hour, Min, Sec, MSec: Word; out Time: TDateTime): Boolean;
  1915.  
  1916. { DecodeDate decodes the integral (date) part of the given TDateTime value
  1917.   into its corresponding year, month, and day. If the given TDateTime value
  1918.   is less than or equal to zero, the year, month, and day return parameters
  1919.   are all set to zero. }
  1920.  
  1921. procedure DecodeDate(const DateTime: TDateTime; var Year, Month, Day: Word);
  1922.  
  1923. { This variation of DecodeDate works similarly to the above function but
  1924.   returns more information.  The result value of this function indicates
  1925.   wither the year decoded is a leap year or not.  }
  1926.  
  1927. function DecodeDateFully(const DateTime: TDateTime; var Year, Month, Day,
  1928.   DOW: Word): Boolean;
  1929.  
  1930. {$IFDEF LINUX}
  1931. function InternalDecodeDate(const DateTime: TDateTime; var Year, Month, Day, DOW: Word): Boolean;
  1932. {$ENDIF}
  1933.  
  1934. { DecodeTime decodes the fractional (time) part of the given TDateTime value
  1935.   into its corresponding hour, minute, second, and millisecond. }
  1936.  
  1937. procedure DecodeTime(const DateTime: TDateTime; var Hour, Min, Sec, MSec: Word);
  1938.  
  1939. {$IFDEF MSWINDOWS}
  1940. { DateTimeToSystemTime converts a date and time from Delphi's TDateTime
  1941.   format into the Win32 API's TSystemTime format. }
  1942.  
  1943. procedure DateTimeToSystemTime(const DateTime: TDateTime; var SystemTime: TSystemTime);
  1944.  
  1945. { SystemTimeToDateTime converts a date and time from the Win32 API's
  1946.   TSystemTime format into Delphi's TDateTime format. }
  1947.  
  1948. function SystemTimeToDateTime(const SystemTime: TSystemTime): TDateTime;
  1949. {$ENDIF}
  1950.  
  1951. { DayOfWeek returns the day of the week of the given date. The result is an
  1952.   integer between 1 and 7, corresponding to Sunday through Saturday.
  1953.   This function is not ISO 8601 compliant, for that see the DateUtils unit. }
  1954.  
  1955. function DayOfWeek(const DateTime: TDateTime): Word;
  1956.  
  1957. { Date returns the current date. }
  1958.  
  1959. function Date: TDateTime;
  1960.  
  1961. { Time returns the current time. }
  1962.  
  1963. function Time: TDateTime;
  1964.  
  1965. { Now returns the current date and time, corresponding to Date + Time. }
  1966.  
  1967. function Now: TDateTime;
  1968.  
  1969. { Current year returns the year portion of the date returned by Now }
  1970.  
  1971. function CurrentYear: Word;
  1972.  
  1973. { IncMonth returns Date shifted by the specified number of months.
  1974.   NumberOfMonths parameter can be negative, to return a date N months ago.
  1975.   If the input day of month is greater than the last day of the resulting
  1976.   month, the day is set to the last day of the resulting month.
  1977.   Input time of day is copied to the DateTime result.  }
  1978.  
  1979. function IncMonth(const DateTime: TDateTime; NumberOfMonths: Integer = 1): TDateTime;
  1980.  
  1981. { Optimized version of IncMonth that works with years, months and days
  1982.   directly.  See above comments for more detail as to what happens to the day
  1983.   when incrementing months }
  1984.  
  1985. procedure IncAMonth(var Year, Month, Day: Word; NumberOfMonths: Integer = 1);
  1986.  
  1987. { ReplaceTime replaces the time portion of the DateTime parameter with the given
  1988.   time value, adjusting the signs as needed if the date is prior to 1900
  1989.   (Date value less than zero)  }
  1990.  
  1991. procedure ReplaceTime(var DateTime: TDateTime; const NewTime: TDateTime);
  1992.  
  1993. { ReplaceDate replaces the date portion of the DateTime parameter with the given
  1994.   date value, adjusting as needed for negative dates }
  1995.  
  1996. procedure ReplaceDate(var DateTime: TDateTime; const NewDate: TDateTime);
  1997.  
  1998. { IsLeapYear determines whether the given year is a leap year. }
  1999.  
  2000. function IsLeapYear(Year: Word): Boolean;
  2001.  
  2002. type
  2003.   PDayTable = ^TDayTable;
  2004.   TDayTable = array[1..12] of Word;
  2005.  
  2006. { The MonthDays array can be used to quickly find the number of
  2007.   days in a month:  MonthDays[IsLeapYear(Y), M]      }
  2008.  
  2009. const
  2010.   MonthDays: array [Boolean] of TDayTable =
  2011.     ((31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31),
  2012.      (31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31));
  2013.  
  2014. { DateToStr converts the date part of the given TDateTime value to a string.
  2015.   The conversion uses the format specified by the ShortDateFormat global
  2016.   variable. }
  2017.  
  2018. function DateToStr(const DateTime: TDateTime): string;
  2019.  
  2020. { TimeToStr converts the time part of the given TDateTime value to a string.
  2021.   The conversion uses the format specified by the LongTimeFormat global
  2022.   variable. }
  2023.  
  2024. function TimeToStr(const DateTime: TDateTime): string;
  2025.  
  2026. { DateTimeToStr converts the given date and time to a string. The resulting
  2027.   string consists of a date and time formatted using the ShortDateFormat and
  2028.   LongTimeFormat global variables. Time information is included in the
  2029.   resulting string only if the fractional part of the given date and time
  2030.   value is non-zero. }
  2031.  
  2032. function DateTimeToStr(const DateTime: TDateTime): string;
  2033.  
  2034. { StrToDate converts the given string to a date value. The string must
  2035.   consist of two or three numbers, separated by the character defined by
  2036.   the DateSeparator global variable. The order for month, day, and year is
  2037.   determined by the ShortDateFormat global variable--possible combinations
  2038.   are m/d/y, d/m/y, and y/m/d. If the string contains only two numbers, it
  2039.   is interpreted as a date (m/d or d/m) in the current year. Year values
  2040.   between 0 and 99 are assumed to be in the current century. If the given
  2041.   string does not contain a valid date, an EConvertError exception is
  2042.   raised. }
  2043.  
  2044. function StrToDate(const S: string): TDateTime;
  2045. function StrToDateDef(const S: string; const Default: TDateTime): TDateTime;
  2046. function TryStrToDate(const S: string; out Value: TDateTime): Boolean;
  2047.  
  2048. { StrToTime converts the given string to a time value. The string must
  2049.   consist of two or three numbers, separated by the character defined by
  2050.   the TimeSeparator global variable, optionally followed by an AM or PM
  2051.   indicator. The numbers represent hour, minute, and (optionally) second,
  2052.   in that order. If the time is followed by AM or PM, it is assumed to be
  2053.   in 12-hour clock format. If no AM or PM indicator is included, the time
  2054.   is assumed to be in 24-hour clock format. If the given string does not
  2055.   contain a valid time, an EConvertError exception is raised. }
  2056.  
  2057. function StrToTime(const S: string): TDateTime;
  2058. function StrToTimeDef(const S: string; const Default: TDateTime): TDateTime;
  2059. function TryStrToTime(const S: string; out Value: TDateTime): Boolean;
  2060.  
  2061. { StrToDateTime converts the given string to a date and time value. The
  2062.   string must contain a date optionally followed by a time. The date and
  2063.   time parts of the string must follow the formats described for the
  2064.   StrToDate and StrToTime functions. }
  2065.  
  2066. function StrToDateTime(const S: string): TDateTime;
  2067. function StrToDateTimeDef(const S: string; const Default: TDateTime): TDateTime;
  2068. function TryStrToDateTime(const S: string; out Value: TDateTime): Boolean;
  2069.  
  2070. { FormatDateTime formats the date-and-time value given by DateTime using the
  2071.   format given by Format. The following format specifiers are supported:
  2072.  
  2073.   c       Displays the date using the format given by the ShortDateFormat
  2074.           global variable, followed by the time using the format given by
  2075.           the LongTimeFormat global variable. The time is not displayed if
  2076.           the fractional part of the DateTime value is zero.
  2077.  
  2078.   d       Displays the day as a number without a leading zero (1-31).
  2079.  
  2080.   dd      Displays the day as a number with a leading zero (01-31).
  2081.  
  2082.   ddd     Displays the day as an abbreviation (Sun-Sat) using the strings
  2083.           given by the ShortDayNames global variable.
  2084.  
  2085.   dddd    Displays the day as a full name (Sunday-Saturday) using the strings
  2086.           given by the LongDayNames global variable.
  2087.  
  2088.   ddddd   Displays the date using the format given by the ShortDateFormat
  2089.           global variable.
  2090.  
  2091.   dddddd  Displays the date using the format given by the LongDateFormat
  2092.           global variable.
  2093.  
  2094.   g       Displays the period/era as an abbreviation (Japanese and
  2095.           Taiwanese locales only).
  2096.  
  2097.   gg      Displays the period/era as a full name.
  2098.  
  2099.   e       Displays the year in the current period/era as a number without
  2100.           a leading zero (Japanese, Korean and Taiwanese locales only).
  2101.  
  2102.   ee      Displays the year in the current period/era as a number with
  2103.           a leading zero (Japanese, Korean and Taiwanese locales only).
  2104.  
  2105.   m       Displays the month as a number without a leading zero (1-12). If
  2106.           the m specifier immediately follows an h or hh specifier, the
  2107.           minute rather than the month is displayed.
  2108.  
  2109.   mm      Displays the month as a number with a leading zero (01-12). If
  2110.           the mm specifier immediately follows an h or hh specifier, the
  2111.           minute rather than the month is displayed.
  2112.  
  2113.   mmm     Displays the month as an abbreviation (Jan-Dec) using the strings
  2114.           given by the ShortMonthNames global variable.
  2115.  
  2116.   mmmm    Displays the month as a full name (January-December) using the
  2117.           strings given by the LongMonthNames global variable.
  2118.  
  2119.   yy      Displays the year as a two-digit number (00-99).
  2120.  
  2121.   yyyy    Displays the year as a four-digit number (0000-9999).
  2122.  
  2123.   h       Displays the hour without a leading zero (0-23).
  2124.  
  2125.   hh      Displays the hour with a leading zero (00-23).
  2126.  
  2127.   n       Displays the minute without a leading zero (0-59).
  2128.  
  2129.   nn      Displays the minute with a leading zero (00-59).
  2130.  
  2131.   s       Displays the second without a leading zero (0-59).
  2132.  
  2133.   ss      Displays the second with a leading zero (00-59).
  2134.  
  2135.   z       Displays the millisecond without a leading zero (0-999).
  2136.  
  2137.   zzz     Displays the millisecond with a leading zero (000-999).
  2138.  
  2139.   t       Displays the time using the format given by the ShortTimeFormat
  2140.           global variable.
  2141.  
  2142.   tt      Displays the time using the format given by the LongTimeFormat
  2143.           global variable.
  2144.  
  2145.   am/pm   Uses the 12-hour clock for the preceding h or hh specifier, and
  2146.           displays 'am' for any hour before noon, and 'pm' for any hour
  2147.           after noon. The am/pm specifier can use lower, upper, or mixed
  2148.           case, and the result is displayed accordingly.
  2149.  
  2150.   a/p     Uses the 12-hour clock for the preceding h or hh specifier, and
  2151.           displays 'a' for any hour before noon, and 'p' for any hour after
  2152.           noon. The a/p specifier can use lower, upper, or mixed case, and
  2153.           the result is displayed accordingly.
  2154.  
  2155.   ampm    Uses the 12-hour clock for the preceding h or hh specifier, and
  2156.           displays the contents of the TimeAMString global variable for any
  2157.           hour before noon, and the contents of the TimePMString global
  2158.           variable for any hour after noon.
  2159.  
  2160.   /       Displays the date separator character given by the DateSeparator
  2161.           global variable.
  2162.  
  2163.   :       Displays the time separator character given by the TimeSeparator
  2164.           global variable.
  2165.  
  2166.   'xx'    Characters enclosed in single or double quotes are displayed as-is,
  2167.   "xx"    and do not affect formatting.
  2168.  
  2169.   Format specifiers may be written in upper case as well as in lower case
  2170.   letters--both produce the same result.
  2171.  
  2172.   If the string given by the Format parameter is empty, the date and time
  2173.   value is formatted as if a 'c' format specifier had been given.
  2174.  
  2175.   The following example:
  2176.  
  2177.     S := FormatDateTime('"The meeting is on" dddd, mmmm d, yyyy, ' +
  2178.       '"at" hh:mm AM/PM', StrToDateTime('2/15/95 10:30am'));
  2179.  
  2180.   assigns 'The meeting is on Wednesday, February 15, 1995 at 10:30 AM' to
  2181.   the string variable S. }
  2182.  
  2183. function FormatDateTime(const Format: string; DateTime: TDateTime): string;
  2184.  
  2185. { DateTimeToString converts the date and time value given by DateTime using
  2186.   the format string given by Format into the string variable given by Result.
  2187.   For further details, see the description of the FormatDateTime function. }
  2188.  
  2189. procedure DateTimeToString(var Result: string; const Format: string;
  2190.   DateTime: TDateTime);
  2191.  
  2192. { FloatToDateTime will range validate a value to make sure it falls
  2193.   within the acceptable date range }
  2194.  
  2195. const
  2196.   MinDateTime: TDateTime = -657434.0;      { 01/01/0100 12:00:00.000 AM }
  2197.   MaxDateTime: TDateTime =  2958465.99999; { 12/31/9999 11:59:59.999 PM }
  2198.  
  2199. function FloatToDateTime(const Value: Extended): TDateTime;
  2200.  
  2201. { System error messages }
  2202.  
  2203. function SysErrorMessage(ErrorCode: Integer): string;
  2204.  
  2205. { Initialization file support }
  2206.  
  2207. function GetLocaleStr(Locale, LocaleType: Integer; const Default: string): string; platform;
  2208. function GetLocaleChar(Locale, LocaleType: Integer; Default: Char): Char; platform;
  2209.  
  2210. { GetFormatSettings resets all date and number format variables to their
  2211.   default values. }
  2212.  
  2213. procedure GetFormatSettings;
  2214.  
  2215. { Exception handling routines }
  2216.  
  2217. {$IFDEF LINUX}
  2218. {   InquireSignal is used to determine the state of an OS signal handler.
  2219.     Pass it one of the RTL_SIG* constants, and it will return a TSignalState
  2220.     which will tell you if the signal has been hooked, not hooked, or overriden
  2221.     by some other module.  You can use this function to determine if some other
  2222.     module has hijacked your signal handlers, should you wish to reinstall your
  2223.     own. This is a risky proposition under Linux, and is only recommended as a
  2224.     last resort.  Do not pass RTL_SIGDEFAULT to this function.
  2225. }
  2226. function InquireSignal(RtlSigNum: Integer): TSignalState;
  2227. { AbandonSignalHandler tells the RTL to leave a signal handler
  2228.     in place, even if we believe that we hooked it at startup time.
  2229.  
  2230.     Once you have called AbandonSignalHandler with a specific signal number,
  2231.     neither UnhookSignal nor the RTL will restore any previous signal handler
  2232.     under any condition.
  2233. }
  2234. procedure AbandonSignalHandler(RtlSigNum: Integer);
  2235.  
  2236. { HookSignal is used to hook individual signals, or an RTL-defined default 
  2237.     set of signals.  It does not test whether a signal has already been
  2238.     hooked, so it should be used in conjunction with InquireSignal.  It is
  2239.     exposed to enable users to hook signals in standalone libraries, or in the
  2240.     event that an external module hijacks the RTL installed signal handlers.
  2241.     Pass RTL_SIGDEFAULT if you want to hook all the signals that the RTL
  2242.     normally hooks at startup time.
  2243. }
  2244. procedure HookSignal(RtlSigNum: Integer);
  2245.  
  2246. { UnhookSignal is used to remove signal handlers installed by HookSignal.
  2247.     It can remove individual signal handlers, or the RTL-defined default set
  2248.     of signals.  If OnlyIfHooked is True, then we will only unhook the signal
  2249.     if the signal handler has been hooked, and has not since been overriden by
  2250.     some foreign handler.
  2251. }
  2252. procedure UnhookSignal(RtlSigNum: Integer; OnlyIfHooked: Boolean = True);
  2253.  
  2254. { HookOSExceptions is used internally by thread support.  DON'T call this
  2255.   function yourself. }
  2256. procedure HookOSExceptions;
  2257.  
  2258. { MapSignal is used internally as well.  It maps a signal and associated
  2259.   context to an internal value that represents the type of Exception
  2260.   class to raise. }
  2261. function MapSignal(SigNum: Integer; Context: PSigContext): LongWord;
  2262.  
  2263. { SignalConverter is used internally to properly reinit the FPU and properly
  2264.   raise an external OS exception object.  DON'T call this function yourself. }
  2265. procedure SignalConverter(ExceptionEIP: LongWord; FaultAddr: LongWord; ErrorCode: LongWord);
  2266.  
  2267. {
  2268.     See the comment at the threadvar declarations for these below.  The access
  2269.     to these has been implemented through getter/setter functions because you
  2270.     cannot use threadvars across packages.
  2271. }
  2272. procedure SetSafeCallExceptionMsg(Msg: String);
  2273. procedure SetSafeCallExceptionAddr(Addr: Pointer);
  2274. function GetSafeCallExceptionMsg: String;
  2275. function GetSafeCallExceptionAddr: Pointer;
  2276.  
  2277. { HookOSExceptionsProc is used internally and cannot be used in a conventional
  2278.   manner.  DON'T ever set this variable. }
  2279. var
  2280.   HookOSExceptionsProc: procedure = nil platform deprecated;
  2281.  
  2282. { LoadLibrary / FreeLibrary are defined here only for convenience.  On Linux,
  2283.   they map directly to dlopen / dlclose.  Note that module loading semantics
  2284.   on Linux are not identical to Windows.  }
  2285.  
  2286. function LoadLibrary(ModuleName: PChar): HMODULE;
  2287.  
  2288. function FreeLibrary(Module: HMODULE): LongBool;
  2289.  
  2290. { GetProcAddress does what it implies.  It performs the same function as the like
  2291.   named function under Windows.  dlsym does not quite have the same sematics as
  2292.   GetProcAddress as it will return the address of a symbol in another module if
  2293.   it was not found in the given HMODULE.  This function will verify that the 'Proc'
  2294.   is actually found within the 'Module', and if not returns nil }
  2295. function GetProcAddress(Module: HMODULE; Proc: PChar): Pointer;
  2296.  
  2297. { Given a module name, this function will return the module handle.  There is no
  2298.   direct equivalent in Linux so this function provides that capability.  Also
  2299.   note, this function is specific to glibc. }
  2300. function GetModuleHandle(ModuleName: PChar): HMODULE;
  2301.  
  2302. { This function works just like GetModuleHandle, except it will look for a module
  2303.   that matches the given base package name.  For example, given the base package
  2304.   name 'package', the actual module name is, by default, 'bplpackage.so'.  This
  2305.   function will search for the string 'package' within the module name. }
  2306. function GetPackageModuleHandle(PackageName: PChar): HMODULE;
  2307.  
  2308. {$ENDIF}
  2309.  
  2310. { In Linux, the parameter to sleep() is in whole seconds.  In Windows, the
  2311.   parameter is in milliseconds.  To ease headaches, we implement a version
  2312.   of sleep here for Linux that takes milliseconds and calls a Linux system
  2313.   function with sub-second resolution.  This maps directly to the Windows
  2314.   API on Windows. }
  2315.  
  2316. procedure Sleep(milliseconds: Cardinal);{$IFDEF MSWINDOWS} stdcall; {$ENDIF}
  2317.  
  2318. function GetModuleName(Module: HMODULE): string;
  2319.  
  2320. function ExceptionErrorMessage(ExceptObject: TObject; ExceptAddr: Pointer;
  2321.   Buffer: PChar; Size: Integer): Integer;
  2322.  
  2323. procedure ShowException(ExceptObject: TObject; ExceptAddr: Pointer);
  2324.  
  2325. procedure Abort;
  2326.  
  2327. procedure OutOfMemoryError;
  2328.  
  2329. procedure Beep;
  2330.  
  2331. { MBCS functions }
  2332.  
  2333. { LeadBytes is a char set that indicates which char values are lead bytes
  2334.   in multibyte character sets (Japanese, Chinese, etc).
  2335.   This set is always empty for western locales. }
  2336. var
  2337.   LeadBytes: set of Char = [];
  2338. (*$EXTERNALSYM LeadBytes*)
  2339. (*$HPPEMIT 'namespace Sysutils {'*)
  2340. (*$HPPEMIT 'extern PACKAGE System::Set<Byte, 0, 255>  LeadBytes;'*)
  2341. (*$HPPEMIT '} // namespace Sysutils'*)
  2342.  
  2343. { ByteType indicates what kind of byte exists at the Index'th byte in S.
  2344.   Western locales always return mbSingleByte.  Far East multibyte locales
  2345.   may also return mbLeadByte, indicating the byte is the first in a multibyte
  2346.   character sequence, and mbTrailByte, indicating that the byte is one of
  2347.   a sequence of bytes following a lead byte.  One or more trail bytes can
  2348.   follow a lead byte, depending on locale charset encoding and OS platform.
  2349.   Parameters are assumed to be valid. }
  2350.  
  2351. function ByteType(const S: string; Index: Integer): TMbcsByteType;
  2352.  
  2353. { StrByteType works the same as ByteType, but on null-terminated PChar strings }
  2354.  
  2355. function StrByteType(Str: PChar; Index: Cardinal): TMbcsByteType;
  2356.  
  2357. { ByteToCharLen returns the character length of a MBCS string, scanning the
  2358.   string for up to MaxLen bytes.  In multibyte character sets, the number of
  2359.   characters in a string may be less than the number of bytes.  }
  2360.  
  2361. function ByteToCharLen(const S: string; MaxLen: Integer): Integer;
  2362.  
  2363. { CharToByteLen returns the byte length of a MBCS string, scanning the string
  2364.   for up to MaxLen characters. }
  2365.  
  2366. function CharToByteLen(const S: string; MaxLen: Integer): Integer;
  2367.  
  2368. { ByteToCharIndex returns the 1-based character index of the Index'th byte in
  2369.   a MBCS string.  Returns zero if Index is out of range:
  2370.   (Index <= 0) or (Index > Length(S)) }
  2371.  
  2372. function ByteToCharIndex(const S: string; Index: Integer): Integer;
  2373.  
  2374. { CharToByteIndex returns the 1-based byte index of the Index'th character
  2375.   in a MBCS string.  Returns zero if Index or Result are out of range:
  2376.   (Index <= 0) or (Index > Length(S)) or (Result would be > Length(S)) }
  2377.  
  2378. function CharToByteIndex(const S: string; Index: Integer): Integer;
  2379.  
  2380. { StrCharLength returns the number of bytes required by the first character
  2381.   in Str.  In Windows, multibyte characters can be up to two bytes in length.
  2382.   In Linux, multibyte characters can be up to six bytes in length (UTF-8). }
  2383.  
  2384. function StrCharLength(const Str: PChar): Integer;
  2385.  
  2386. { StrNextChar returns a pointer to the first byte of the character following
  2387.   the character pointed to by Str.  }
  2388.  
  2389. function StrNextChar(const Str: PChar): PChar;
  2390.  
  2391. { CharLength returns the number of bytes required by the character starting
  2392.   at bytes S[Index].  }
  2393.  
  2394. function CharLength(const S: String; Index: Integer): Integer;
  2395.  
  2396. { NextCharIndex returns the byte index of the first byte of the character
  2397.   following the character starting at S[Index].  }
  2398.  
  2399. function NextCharIndex(const S: String; Index: Integer): Integer;
  2400.  
  2401. { IsPathDelimiter returns True if the character at byte S[Index]
  2402.   is a PathDelimiter ('\' or '/'), and it is not a MBCS lead or trail byte. }
  2403.  
  2404. function IsPathDelimiter(const S: string; Index: Integer): Boolean;
  2405.  
  2406. { IsDelimiter returns True if the character at byte S[Index] matches any
  2407.   character in the Delimiters string, and the character is not a MBCS lead or
  2408.   trail byte.  S may contain multibyte characters; Delimiters must contain
  2409.   only single byte characters. }
  2410.  
  2411. function IsDelimiter(const Delimiters, S: string; Index: Integer): Boolean;
  2412.  
  2413. { IncludeTrailingPathDelimiter returns the path with a PathDelimiter
  2414.   ('/' or '\') at the end.  This function is MBCS enabled. }
  2415.  
  2416. function IncludeTrailingPathDelimiter(const S: string): string;
  2417.  
  2418. { IncludeTrailingBackslash is the old name for IncludeTrailingPathDelimiter. }
  2419.  
  2420. function IncludeTrailingBackslash(const S: string): string; platform;
  2421.  
  2422. { ExcludeTrailingPathDelimiter returns the path without a PathDelimiter
  2423.   ('\' or '/') at the end.  This function is MBCS enabled. }
  2424.  
  2425. function ExcludeTrailingPathDelimiter(const S: string): string;
  2426.  
  2427. { ExcludeTrailingBackslash is the old name for ExcludeTrailingPathDelimiter. }
  2428.  
  2429. function ExcludeTrailingBackslash(const S: string): string; platform;
  2430.  
  2431. { LastDelimiter returns the byte index in S of the rightmost whole
  2432.   character that matches any character in Delimiters (except null (#0)).
  2433.   S may contain multibyte characters; Delimiters must contain only single
  2434.   byte non-null characters.
  2435.   Example: LastDelimiter('\.:', 'c:\filename.ext') returns 12. }
  2436.  
  2437. function LastDelimiter(const Delimiters, S: string): Integer;
  2438.  
  2439. { AnsiCompareFileName supports DOS file name comparison idiosyncracies
  2440.   in Far East locales (Zenkaku) on Windows.
  2441.   In non-MBCS locales on Windows, AnsiCompareFileName is identical to
  2442.   AnsiCompareText (case insensitive).
  2443.   On Linux, AnsiCompareFileName is identical to AnsiCompareStr (case sensitive).
  2444.   For general purpose file name comparisions, you should use this function
  2445.   instead of AnsiCompareText. }
  2446.  
  2447. function AnsiCompareFileName(const S1, S2: string): Integer;
  2448.  
  2449. function SameFileName(const S1, S2: string): Boolean;
  2450.  
  2451. { AnsiLowerCaseFileName supports lowercase conversion idiosyncracies of
  2452.   DOS file names in Far East locales (Zenkaku).  In non-MBCS locales,
  2453.   AnsiLowerCaseFileName is identical to AnsiLowerCase. }
  2454.  
  2455. function AnsiLowerCaseFileName(const S: string): string;
  2456.  
  2457. { AnsiUpperCaseFileName supports uppercase conversion idiosyncracies of
  2458.   DOS file names in Far East locales (Zenkaku).  In non-MBCS locales,
  2459.   AnsiUpperCaseFileName is identical to AnsiUpperCase. }
  2460.  
  2461. function AnsiUpperCaseFileName(const S: string): string;
  2462.  
  2463. { AnsiPos:  Same as Pos but supports MBCS strings }
  2464.  
  2465. function AnsiPos(const Substr, S: string): Integer;
  2466.  
  2467. { AnsiStrPos: Same as StrPos but supports MBCS strings }
  2468.  
  2469. function AnsiStrPos(Str, SubStr: PChar): PChar;
  2470.  
  2471. { AnsiStrRScan: Same as StrRScan but supports MBCS strings }
  2472.  
  2473. function AnsiStrRScan(Str: PChar; Chr: Char): PChar;
  2474.  
  2475. { AnsiStrScan: Same as StrScan but supports MBCS strings }
  2476.  
  2477. function AnsiStrScan(Str: PChar; Chr: Char): PChar;
  2478.  
  2479. { StringReplace replaces occurances of <oldpattern> with <newpattern> in a
  2480.   given string.  Assumes the string may contain Multibyte characters }
  2481.  
  2482. type
  2483.   TReplaceFlags = set of (rfReplaceAll, rfIgnoreCase);
  2484.  
  2485. function StringReplace(const S, OldPattern, NewPattern: string;
  2486.   Flags: TReplaceFlags): string;
  2487.  
  2488. { WrapText will scan a string for BreakChars and insert the BreakStr at the
  2489.   last BreakChar position before MaxCol.  Will not insert a break into an
  2490.   embedded quoted string (both ''' and '"' supported) }
  2491.  
  2492. function WrapText(const Line, BreakStr: string; const BreakChars: TSysCharSet;
  2493.   MaxCol: Integer): string; overload;
  2494. function WrapText(const Line: string; MaxCol: Integer = 45): string; overload;
  2495.  
  2496. { FindCmdLineSwitch determines whether the string in the Switch parameter
  2497.   was passed as a command line argument to the application.  SwitchChars
  2498.   identifies valid argument-delimiter characters (i.e., "-" and "/" are
  2499.   common delimiters). The IgnoreCase paramter controls whether a
  2500.   case-sensistive or case-insensitive search is performed. }
  2501.  
  2502. const
  2503.   SwitchChars = {$IFDEF MSWINDOWS} ['/','-']; {$ENDIF}
  2504.                 {$IFDEF LINUX}  ['-'];  {$ENDIF}
  2505.  
  2506. function FindCmdLineSwitch(const Switch: string; const Chars: TSysCharSet;
  2507.   IgnoreCase: Boolean): Boolean; overload;
  2508.  
  2509. { These versions of FindCmdLineSwitch are convenient for writing portable
  2510.   code.  The characters that are valid to indicate command line switches vary
  2511.   on different platforms.  For example, '/' cannot be used as a switch char
  2512.   on Linux because '/' is the path delimiter. }
  2513.  
  2514. { This version uses SwitchChars defined above, and IgnoreCase False. }
  2515. function FindCmdLineSwitch(const Switch: string): Boolean; overload;
  2516.  
  2517. { This version uses SwitchChars defined above. }
  2518. function FindCmdLineSwitch(const Switch: string; IgnoreCase: Boolean): Boolean; overload;
  2519.  
  2520. { FreeAndNil frees the given TObject instance and sets the variable reference
  2521.   to nil.  Be careful to only pass TObjects to this routine. }
  2522.  
  2523. procedure FreeAndNil(var Obj);
  2524.  
  2525. { Interface support routines }
  2526.  
  2527. function Supports(const Instance: IInterface; const IID: TGUID; out Intf): Boolean; overload;
  2528. function Supports(const Instance: TObject; const IID: TGUID; out Intf): Boolean; overload;
  2529. function Supports(const Instance: IInterface; const IID: TGUID): Boolean; overload;
  2530. function Supports(const Instance: TObject; const IID: TGUID): Boolean; overload;
  2531. function Supports(const AClass: TClass; const IID: TGUID): Boolean; overload;
  2532.  
  2533. function CreateGUID(out Guid: TGUID): HResult;
  2534. {$IFDEF MSWINDOWS}
  2535.   stdcall;
  2536. {$ENDIF}
  2537. function StringToGUID(const S: string): TGUID;
  2538. function GUIDToString(const GUID: TGUID): string;
  2539. function IsEqualGUID(const guid1, guid2: TGUID): Boolean;
  2540. {$IFDEF MSWINDOWS}
  2541.   stdcall;  {$EXTERNALSYM IsEqualGUID}
  2542. {$ENDIF}
  2543.  
  2544. { Package support routines }
  2545.  
  2546. { Package Info flags }
  2547.  
  2548. const
  2549.   pfNeverBuild = $00000001;
  2550.   pfDesignOnly = $00000002;
  2551.   pfRunOnly = $00000004;
  2552.   pfIgnoreDupUnits = $00000008;
  2553.   pfModuleTypeMask = $C0000000;
  2554.   pfExeModule = $00000000;
  2555.   pfPackageModule = $40000000;
  2556.   pfProducerMask = $0C000000;
  2557.   pfV3Produced =  $00000000;
  2558.   pfProducerUndefined = $04000000;
  2559.   pfBCB4Produced = $08000000;
  2560.   pfDelphi4Produced = $0C000000;
  2561.   pfLibraryModule = $80000000;
  2562.  
  2563. { Unit info flags }
  2564.  
  2565. const
  2566.   ufMainUnit = $01;
  2567.   ufPackageUnit = $02;
  2568.   ufWeakUnit = $04;
  2569.   ufOrgWeakUnit = $08;
  2570.   ufImplicitUnit = $10;
  2571.  
  2572.   ufWeakPackageUnit = ufPackageUnit or ufWeakUnit;
  2573.  
  2574. {$IFDEF LINUX}
  2575. var
  2576.   PkgLoadingMode: Integer = RTLD_LAZY;
  2577. {$ENDIF}
  2578.  
  2579. { Procedure type of the callback given to GetPackageInfo.  Name is the actual
  2580.   name of the package element.  If IsUnit is True then Name is the name of
  2581.   a contained unit; a required package if False.  Param is the value passed
  2582.   to GetPackageInfo }
  2583.  
  2584. type
  2585.   TNameType = (ntContainsUnit, ntRequiresPackage, ntDcpBpiName);
  2586.  
  2587.   TPackageInfoProc = procedure (const Name: string; NameType: TNameType; Flags: Byte; Param: Pointer);
  2588.  
  2589. { LoadPackage loads a given package DLL, checks for duplicate units and
  2590.   calls the initialization blocks of all the contained units }
  2591.  
  2592. function LoadPackage(const Name: string): HMODULE;
  2593.  
  2594. { UnloadPackage does the opposite of LoadPackage by calling the finalization
  2595.   blocks of all contained units, then unloading the package DLL }
  2596.  
  2597. procedure UnloadPackage(Module: HMODULE);
  2598.  
  2599. { GetPackageInfo accesses the given package's info table and enumerates
  2600.   all the contained units and required packages }
  2601.  
  2602. procedure GetPackageInfo(Module: HMODULE; Param: Pointer; var Flags: Integer;
  2603.   InfoProc: TPackageInfoProc);
  2604.  
  2605. { GetPackageDescription loads the description resource from the package
  2606.   library. If the description resource does not exist,
  2607.   an empty string is returned. }
  2608. function GetPackageDescription(ModuleName: PChar): string;
  2609.  
  2610. { InitializePackage validates and initializes the given package DLL }
  2611.  
  2612. procedure InitializePackage(Module: HMODULE);
  2613.  
  2614. { FinalizePackage finalizes the given package DLL }
  2615.  
  2616. procedure FinalizePackage(Module: HMODULE);
  2617.  
  2618. { RaiseLastOSError calls GetLastError to retrieve the code for
  2619.   the last occuring error in a call to an OS or system library function.
  2620.   If GetLastError returns an error code,  RaiseLastOSError raises
  2621.   an EOSError exception with the error code and a system-provided
  2622.   message associated with with error. }
  2623.  
  2624. procedure RaiseLastOSError;
  2625.  
  2626. {$IFDEF MSWINDOWS}
  2627. procedure RaiseLastWin32Error; deprecated;  // use RaiseLastOSError
  2628.  
  2629. { Win32Check is used to check the return value of a Win32 API function     }
  2630. { which returns a BOOL to indicate success.  If the Win32 API function     }
  2631. { returns False (indicating failure), Win32Check calls RaiseLastOSError }
  2632. { to raise an exception.  If the Win32 API function returns True,          }
  2633. { Win32Check returns True. }
  2634.  
  2635. function Win32Check(RetVal: BOOL): BOOL; platform;
  2636. {$ENDIF}
  2637.  
  2638. { Termination procedure support }
  2639.  
  2640. type
  2641.   TTerminateProc = function: Boolean;
  2642.  
  2643. { Call AddTerminateProc to add a terminate procedure to the system list of }
  2644. { termination procedures.  Delphi will call all of the function in the     }
  2645. { termination procedure list before an application terminates.  The user-  }
  2646. { defined TermProc function should return True if the application can      }
  2647. { safely terminate or False if the application cannot safely terminate.    }
  2648. { If one of the functions in the termination procedure list returns False, }
  2649. { the application will not terminate. }
  2650.  
  2651. procedure AddTerminateProc(TermProc: TTerminateProc);
  2652.  
  2653. { CallTerminateProcs is called by VCL when an application is about to }
  2654. { terminate.  It returns True only if all of the functions in the     }
  2655. { system's terminate procedure list return True.  This function is    }
  2656. { intended only to be called by Delphi, and it should not be called   }
  2657. { directly. }
  2658.  
  2659. function CallTerminateProcs: Boolean;
  2660.  
  2661. function GDAL: LongWord;
  2662. procedure RCS;
  2663. procedure RPR;
  2664.  
  2665.  
  2666. { HexDisplayPrefix contains the prefix to display on hexadecimal
  2667.   values - '$' for Pascal syntax, '0x' for C++ syntax.  This is
  2668.   for display only - this does not affect the string-to-integer
  2669.   conversion routines. }
  2670. var
  2671.   HexDisplayPrefix: string = '$';
  2672.  
  2673. {$IFDEF MSWINDOWS}
  2674. { The GetDiskFreeSpace Win32 API does not support partitions larger than 2GB
  2675.   under Win95.  A new Win32 function, GetDiskFreeSpaceEx, supports partitions
  2676.   larger than 2GB but only exists on Win NT 4.0 and Win95 OSR2.
  2677.   The GetDiskFreeSpaceEx function pointer variable below will be initialized
  2678.   at startup to point to either the actual OS API function if it exists on
  2679.   the system, or to an internal Delphi function if it does not.  When running
  2680.   on Win95 pre-OSR2, the output of this function will still be limited to
  2681.   the 2GB range reported by Win95, but at least you don't have to worry
  2682.   about which API function to call in code you write.  }
  2683.  
  2684. var
  2685.   GetDiskFreeSpaceEx: function (Directory: PChar; var FreeAvailable,
  2686.     TotalSpace: TLargeInteger; TotalFree: PLargeInteger): Bool stdcall = nil;
  2687.  
  2688. { SafeLoadLibrary calls LoadLibrary, disabling normal Win32 error message
  2689.   popup dialogs if the requested file can't be loaded.  SafeLoadLibrary also
  2690.   preserves the current FPU control word (precision, exception masks) across
  2691.   the LoadLibrary call (in case the DLL you're loading hammers the FPU control
  2692.   word in its initialization, as many MS DLLs do)}
  2693.  
  2694. function SafeLoadLibrary(const Filename: string;
  2695.   ErrorMode: UINT = SEM_NOOPENFILEERRORBOX): HMODULE;
  2696.  
  2697. {$ENDIF}
  2698. { Thread synchronization }
  2699.  
  2700. { IReadWriteSync is an abstract interface for general read/write synchronization.
  2701.   Some implementations may allow simultaneous readers, but writers always have
  2702.   exclusive locks.
  2703.  
  2704.   Worst case is that this class behaves identical to a TRTLCriticalSection -
  2705.   that is, read and write locks block all other threads. }
  2706.  
  2707. type
  2708.   IReadWriteSync = interface
  2709.     procedure BeginRead;
  2710.     procedure EndRead;
  2711.     function BeginWrite: Boolean;
  2712.     procedure EndWrite;
  2713.   end;
  2714.  
  2715.   TSimpleRWSync = class(TInterfacedObject, IReadWriteSync)
  2716.   public
  2717.     constructor Create;
  2718.     destructor Destroy; override;
  2719.     procedure BeginRead;
  2720.     procedure EndRead;
  2721.     function BeginWrite: Boolean;
  2722.     procedure EndWrite;
  2723.   end;
  2724.  
  2725. { TThreadLocalCounter
  2726.  
  2727.   This class implements a lightweight non-blocking thread local storage
  2728.   mechanism specifically built for tracking per-thread recursion counts
  2729.   in TMultiReadExclusiveWriteSynchronizer.  This class is intended for
  2730.   Delphi RTL internal use only.  In the future it may be generalized
  2731.   and "hardened" for general application use, but until then leave it alone.
  2732.  
  2733.   Rules of Use:
  2734.   The tls object must be opened to gain access to the thread-specific data
  2735.   structure.  If a threadinfo block does not exist for the current thread,
  2736.   Open will allocate one.  Every call to Open must be matched with a call
  2737.   to Close.  The pointer returned by Open is invalid after the matching call
  2738.   to Close.
  2739.  
  2740.   The thread info structure is unique to each thread.  Once you have it, it's
  2741.   yours.  You don't need to guard against concurrent access to the thread
  2742.   data by multiple threads - your thread is the only thread that will ever
  2743.   have access to the structure that Open returns.  The thread info structure
  2744.   is allocated and owned by the tls object.  If you put allocated pointers
  2745.   in the thread info make sure you free them before you delete the threadinfo
  2746.   node.
  2747.  
  2748.   When thread data is no longer needed, call the Delete method on the pointer.
  2749.   This must be done between calls to Open and Close.  Delete schedules the
  2750.   pointer for destruction, but the pointer (and its data) will still be
  2751.   valid until Close is called.
  2752.  
  2753.   Important:  Do not keep the tls object open for long periods of time.  The
  2754.   tls object performs internal cleanup only when no threads have the
  2755.   tls object in the open state.  In particular, be careful not to wait on
  2756.   a thread synchronization event or critical section while you
  2757.   have the tls object open.  It's much better to open and close the tls
  2758.   object before and after the blocking event than to leave the tls object
  2759.   open while waiting.
  2760.  
  2761.   Implementation Notes:
  2762.   The main purpose of this storage class is to provide thread-local storage
  2763.   without using limited / problematic OS tls slots and without requiring
  2764.   expensive blocking thread synchronization.  This class performs no
  2765.   blocking waits or spin loops!  (except for memory allocation)
  2766.  
  2767.   Thread info is kept in linked lists to facilitate non-blocking threading
  2768.   techniques.  A hash table indexed by a hash of the current thread ID
  2769.   reduces linear search times.
  2770.  
  2771.   When a node is deleted, it is moved out of the hash table lists into
  2772.   the purgatory list.  The hash table no longer points to the deleted node,
  2773.   but the deleted node's next pointer still points into the hash table.  This
  2774.   is so that deleting a node will not interrupt other threads that are
  2775.   traversing the list concurrent with the deletion.  If another thread is
  2776.   visiting a node while it is being deleted, the thread will follow the
  2777.   node's next pointer and get back into the live list without interruption.
  2778.  
  2779.   The purgatory list is liked through the nodes' NextDead field.  Again, this
  2780.   is to preserve the exit path of other threads still visiting the deleted
  2781.   node.
  2782.  
  2783.   When the last concurrent use of the tls object is closed (when FOpenCount
  2784.   drops to zero), all nodes in the purgatory list are reviewed for destruction
  2785.   or recycling. It's safe to do this without a thread synchronization lock
  2786.   because we know there are no threads visiting any of the nodes.  Newly
  2787.   deleted nodes are cleared of their thread identity and assigned a clock tick
  2788.   expiration value.  If a deleted node has been in the purgatory for longer
  2789.   than the holding period, Close will free the node.  When Open needs to
  2790.   allocate a new node for a new thread, it first tries to recycle an old node
  2791.   from the purgatory.  If nothing is available for recycling, Open allocates
  2792.   new memory.  The default holding period is one minute.
  2793.  
  2794.   Note that nodes enter the holding pattern when the tls object is closed.
  2795.   They won't be reviewed for destruction until the *next* time the tls
  2796.   object transitions into the closed state.  This is intentional, to
  2797.   reduce memory allocation thrashing when multiple threads open, delete,
  2798.   and close tls frequently, as will be the case with non-recursive read
  2799.   locks in TMREWSync.
  2800.  
  2801.   Close grabs the purgatory list before checking the FOpenCount to avoid
  2802.   race conditions with other threads reopening the tls while Close is
  2803.   executing.  If FOpenCount is not yet zero, Close has to put the purgatory
  2804.   list back together (Reattach), including any items added to the
  2805.   purgatory list after Close swiped it.  Since the number of thread
  2806.   participants should be small (less than 32) and the frequency of deletions
  2807.   relative to thread data access should be low, the purgatory list should
  2808.   never grow large enough to make this non-blocking Close implementation a
  2809.   performance problem.
  2810.  
  2811.   The linked list management relies heavily on InterlockedExchange to perform
  2812.   atomic node pointer replacements.  There are brief windows of time where
  2813.   the linked list may be circular while a two-step insertion takes place.
  2814.   During that brief window, other threads traversing the lists may see
  2815.   the same node more than once more than once. (pun!) This is fine for what this
  2816.   implementation needs.  Don't do anything silly like try to count the
  2817.   nodes during a traversal.
  2818. }
  2819.  
  2820. type
  2821.   PThreadInfo = ^TThreadInfo;
  2822.   TThreadInfo = record
  2823.     Next: PThreadInfo;
  2824.     NextDead: PThreadInfo;
  2825.     ThreadID: Cardinal;
  2826.     RecursionCount: Cardinal;
  2827.   end;
  2828.  
  2829.   TThreadLocalCounter = class
  2830.   protected
  2831.     FHoldTime: Cardinal;
  2832.   public
  2833.     constructor Create;
  2834.     destructor Destroy; override;
  2835.     procedure Open(var Thread: PThreadInfo);
  2836.     procedure Delete(var Thread: PThreadInfo);
  2837.     procedure Close(var Thread: PThreadInfo);
  2838.   end;
  2839.  
  2840. {$IFDEF MSWINDOWS}
  2841.  
  2842. { TMultiReadExclusiveWriteSynchronizer minimizes thread serialization to gain
  2843.   read access to a resource shared among threads while still providing complete
  2844.   exclusivity to callers needing write access to the shared resource.
  2845.   (multithread shared reads, single thread exclusive write)
  2846.   Read locks are allowed while owning a write lock.
  2847.   Read locks can be promoted to write locks within the same thread.
  2848.   (BeginRead, BeginWrite, EndWrite, EndRead)
  2849.  
  2850.   Note: Other threads have an opportunity to modify the protected resource
  2851.   when you call BeginWrite before you are granted the write lock, even
  2852.   if you already have a read lock open.  Best policy is not to retain
  2853.   any info about the protected resource (such as count or size) across a
  2854.   write lock.  Always reacquire samples of the protected resource after
  2855.   acquiring or releasing a write lock.
  2856.  
  2857.   The function result of BeginWrite indicates whether another thread got
  2858.   the write lock while the current thread was waiting for the write lock.
  2859.   Return value of True means that the write lock was acquired without
  2860.   any intervening modifications by other threads.  Return value of False
  2861.   means another thread got the write lock while you were waiting, so the
  2862.   resource protected by the MREWS object should be considered modified.
  2863.   Any samples of the protected resource should be discarded.
  2864.  
  2865.   In general, it's better to just always reacquire samples of the protected
  2866.   resource after obtaining a write lock.  The boolean result of BeginWrite
  2867.   and the RevisionLevel property help cases where reacquiring the samples
  2868.   is computationally expensive or time consuming.
  2869.  
  2870.   RevisionLevel changes each time a write lock is granted.  You can test
  2871.   RevisionLevel for equality with a previously sampled value of the property
  2872.   to determine if a write lock has been granted, implying that the protected
  2873.   resource may be changed from its state when the original RevisionLevel
  2874.   value was sampled.  Do not rely on the sequentiality of the current
  2875.   RevisionLevel implementation (it will wrap around to zero when it tops out).
  2876.   Do not perform greater than / less than comparisons on RevisionLevel values.
  2877.   RevisionLevel indicates only the stability of the protected resource since
  2878.   your original sample.  It should not be used to calculate how many
  2879.   revisions have been made.
  2880. }
  2881.  
  2882. type
  2883.   TMultiReadExclusiveWriteSynchronizer = class(TInterfacedObject, IReadWriteSync)
  2884.   public
  2885.     constructor Create;
  2886.     destructor Destroy; override;
  2887.     procedure BeginRead;
  2888.     procedure EndRead;
  2889.     function BeginWrite: Boolean;
  2890.     procedure EndWrite;
  2891.     property RevisionLevel: Cardinal;
  2892.   end;
  2893. {$ELSE}
  2894. type
  2895.   TMultiReadExclusiveWriteSynchronizer = TSimpleRWSync;
  2896. {$ENDIF}
  2897.  
  2898. type
  2899.   TMREWSync = TMultiReadExclusiveWriteSynchronizer;  // short form
  2900.  
  2901. function GetEnvironmentVariable(const Name: string): string; overload;
  2902.  
  2903. {$IFDEF LINUX}
  2904. function InterlockedIncrement(var I: Integer): Integer;
  2905. function InterlockedDecrement(var I: Integer): Integer;
  2906. function InterlockedExchange(var A: Integer; B: Integer): Integer;
  2907. function InterlockedExchangeAdd(var A: Integer; B: Integer): Integer;
  2908. {$ENDIF}
  2909.  
  2910. implementation
  2911.