| 1 | 
 | 
|---|
| 2 | {*****************************************************************************}
 | 
|---|
| 3 | {                                                                             }
 | 
|---|
| 4 | {    Tnt Delphi Unicode Controls                                              }
 | 
|---|
| 5 | {      http://www.tntware.com/delphicontrols/unicode/                         }
 | 
|---|
| 6 | {        Version: 2.3.0                                                       }
 | 
|---|
| 7 | {                                                                             }
 | 
|---|
| 8 | {    Copyright (c) 2002-2007, Troy Wolbrink (troy.wolbrink@tntware.com)       }
 | 
|---|
| 9 | {                                                                             }
 | 
|---|
| 10 | {*****************************************************************************}
 | 
|---|
| 11 | 
 | 
|---|
| 12 | unit TntSysUtils;
 | 
|---|
| 13 | 
 | 
|---|
| 14 | {$INCLUDE TntCompilers.inc}
 | 
|---|
| 15 | 
 | 
|---|
| 16 | interface
 | 
|---|
| 17 | 
 | 
|---|
| 18 | { TODO: Consider: more filename functions from SysUtils }
 | 
|---|
| 19 | { TODO: Consider: string functions from StrUtils. }
 | 
|---|
| 20 | 
 | 
|---|
| 21 | uses
 | 
|---|
| 22 |   Types, SysUtils, Windows;
 | 
|---|
| 23 | 
 | 
|---|
| 24 | //---------------------------------------------------------------------------------------------
 | 
|---|
| 25 | //                                 Tnt - Types
 | 
|---|
| 26 | //---------------------------------------------------------------------------------------------
 | 
|---|
| 27 | 
 | 
|---|
| 28 | // ......... introduced .........
 | 
|---|
| 29 | type
 | 
|---|
| 30 |   // The user of the application did something plainly wrong.
 | 
|---|
| 31 |   ETntUserError = class(Exception);
 | 
|---|
| 32 |   // A general error occured. (ie. file didn't exist, server didn't return data, etc.)
 | 
|---|
| 33 |   ETntGeneralError = class(Exception);
 | 
|---|
| 34 |   // Like Assert().  An error occured that should never have happened, send me a bug report now!
 | 
|---|
| 35 |   ETntInternalError = class(Exception);
 | 
|---|
| 36 | 
 | 
|---|
| 37 | //---------------------------------------------------------------------------------------------
 | 
|---|
| 38 | //                                 Tnt - SysUtils
 | 
|---|
| 39 | //---------------------------------------------------------------------------------------------
 | 
|---|
| 40 | 
 | 
|---|
| 41 | // ......... SBCS and MBCS functions with WideString replacements in SysUtils.pas .........
 | 
|---|
| 42 | 
 | 
|---|
| 43 | {TNT-WARN CompareStr}                   {TNT-WARN AnsiCompareStr}
 | 
|---|
| 44 | {TNT-WARN SameStr}                      {TNT-WARN AnsiSameStr}
 | 
|---|
| 45 | {TNT-WARN SameText}                     {TNT-WARN AnsiSameText}
 | 
|---|
| 46 | {TNT-WARN CompareText}                  {TNT-WARN AnsiCompareText}
 | 
|---|
| 47 | {TNT-WARN UpperCase}                    {TNT-WARN AnsiUpperCase}
 | 
|---|
| 48 | {TNT-WARN LowerCase}                    {TNT-WARN AnsiLowerCase}
 | 
|---|
| 49 | 
 | 
|---|
| 50 | {TNT-WARN AnsiPos}  { --> Pos() supports WideString. }
 | 
|---|
| 51 | {TNT-WARN FmtStr}
 | 
|---|
| 52 | {TNT-WARN Format}
 | 
|---|
| 53 | {TNT-WARN FormatBuf}
 | 
|---|
| 54 | 
 | 
|---|
| 55 | // ......... MBCS Byte Type Procs .........
 | 
|---|
| 56 | 
 | 
|---|
| 57 | {TNT-WARN ByteType}
 | 
|---|
| 58 | {TNT-WARN StrByteType}
 | 
|---|
| 59 | {TNT-WARN ByteToCharIndex}
 | 
|---|
| 60 | {TNT-WARN ByteToCharLen}
 | 
|---|
| 61 | {TNT-WARN CharToByteIndex}
 | 
|---|
| 62 | {TNT-WARN CharToByteLen}
 | 
|---|
| 63 | 
 | 
|---|
| 64 | // ........ null-terminated string functions .........
 | 
|---|
| 65 | 
 | 
|---|
| 66 | {TNT-WARN StrEnd}
 | 
|---|
| 67 | {TNT-WARN StrLen}
 | 
|---|
| 68 | {TNT-WARN StrLCopy}
 | 
|---|
| 69 | {TNT-WARN StrCopy}
 | 
|---|
| 70 | {TNT-WARN StrECopy}
 | 
|---|
| 71 | {TNT-WARN StrPLCopy}
 | 
|---|
| 72 | {TNT-WARN StrPCopy}
 | 
|---|
| 73 | {TNT-WARN StrLComp}
 | 
|---|
| 74 | {TNT-WARN AnsiStrLComp}
 | 
|---|
| 75 | {TNT-WARN StrComp}
 | 
|---|
| 76 | {TNT-WARN AnsiStrComp}
 | 
|---|
| 77 | {TNT-WARN StrLIComp}
 | 
|---|
| 78 | {TNT-WARN AnsiStrLIComp}
 | 
|---|
| 79 | {TNT-WARN StrIComp}
 | 
|---|
| 80 | {TNT-WARN AnsiStrIComp}
 | 
|---|
| 81 | {TNT-WARN StrLower}
 | 
|---|
| 82 | {TNT-WARN AnsiStrLower}
 | 
|---|
| 83 | {TNT-WARN StrUpper}
 | 
|---|
| 84 | {TNT-WARN AnsiStrUpper}
 | 
|---|
| 85 | {TNT-WARN StrPos}
 | 
|---|
| 86 | {TNT-WARN AnsiStrPos}
 | 
|---|
| 87 | {TNT-WARN StrScan}
 | 
|---|
| 88 | {TNT-WARN AnsiStrScan}
 | 
|---|
| 89 | {TNT-WARN StrRScan}
 | 
|---|
| 90 | {TNT-WARN AnsiStrRScan}
 | 
|---|
| 91 | {TNT-WARN StrLCat}
 | 
|---|
| 92 | {TNT-WARN StrCat}
 | 
|---|
| 93 | {TNT-WARN StrMove}
 | 
|---|
| 94 | {TNT-WARN StrPas}
 | 
|---|
| 95 | {TNT-WARN StrAlloc}
 | 
|---|
| 96 | {TNT-WARN StrBufSize}
 | 
|---|
| 97 | {TNT-WARN StrNew}
 | 
|---|
| 98 | {TNT-WARN StrDispose}
 | 
|---|
| 99 | 
 | 
|---|
| 100 | {TNT-WARN AnsiExtractQuotedStr}
 | 
|---|
| 101 | {TNT-WARN AnsiLastChar}
 | 
|---|
| 102 | {TNT-WARN AnsiStrLastChar}
 | 
|---|
| 103 | {TNT-WARN QuotedStr}
 | 
|---|
| 104 | {TNT-WARN AnsiQuotedStr}
 | 
|---|
| 105 | {TNT-WARN AnsiDequotedStr}
 | 
|---|
| 106 | 
 | 
|---|
| 107 | // ........ string functions .........
 | 
|---|
| 108 | 
 | 
|---|
| 109 | {$IFNDEF COMPILER_9_UP}
 | 
|---|
| 110 |   //
 | 
|---|
| 111 |   // pre-Delphi 9 issues w/ WideFormatBuf, WideFmtStr and WideFormat
 | 
|---|
| 112 |   //
 | 
|---|
| 113 | 
 | 
|---|
| 114 |   {$IFDEF COMPILER_7_UP}
 | 
|---|
| 115 |   type
 | 
|---|
| 116 |     PFormatSettings = ^TFormatSettings;
 | 
|---|
| 117 |   {$ENDIF}
 | 
|---|
| 118 | 
 | 
|---|
| 119 |   // SysUtils.WideFormatBuf doesn't correctly handle numeric specifiers.
 | 
|---|
| 120 |   function Tnt_WideFormatBuf(var Buffer; BufLen: Cardinal; const FormatStr;
 | 
|---|
| 121 |     FmtLen: Cardinal; const Args: array of const): Cardinal; {$IFDEF COMPILER_7_UP} overload; {$ENDIF}
 | 
|---|
| 122 | 
 | 
|---|
| 123 |   {$IFDEF COMPILER_7_UP}
 | 
|---|
| 124 |   function Tnt_WideFormatBuf(var Buffer; BufLen: Cardinal; const FormatStr;
 | 
|---|
| 125 |     FmtLen: Cardinal; const Args: array of const;
 | 
|---|
| 126 |       const FormatSettings: TFormatSettings): Cardinal; overload;
 | 
|---|
| 127 |   {$ENDIF}
 | 
|---|
| 128 | 
 | 
|---|
| 129 |   // SysUtils.WideFmtStr doesn't handle string lengths > 4096.
 | 
|---|
| 130 |   procedure Tnt_WideFmtStr(var Result: WideString; const FormatStr: WideString;
 | 
|---|
| 131 |     const Args: array of const); {$IFDEF COMPILER_7_UP} overload; {$ENDIF}
 | 
|---|
| 132 | 
 | 
|---|
| 133 |   {$IFDEF COMPILER_7_UP}
 | 
|---|
| 134 |   procedure Tnt_WideFmtStr(var Result: WideString; const FormatStr: WideString;
 | 
|---|
| 135 |     const Args: array of const; const FormatSettings: TFormatSettings); overload;
 | 
|---|
| 136 |   {$ENDIF}
 | 
|---|
| 137 | 
 | 
|---|
| 138 |   {----------------------------------------------------------------------------------------
 | 
|---|
| 139 |     Without the FormatSettings parameter, Tnt_WideFormat is *NOT* necessary...
 | 
|---|
| 140 |       TntSystem.InstallTntSystemUpdates([tsFixWideFormat]);
 | 
|---|
| 141 |         will fix WideFormat as well as WideFmtStr.
 | 
|---|
| 142 |   ----------------------------------------------------------------------------------------}
 | 
|---|
| 143 |   function Tnt_WideFormat(const FormatStr: WideString; const Args: array of const): WideString; {$IFDEF COMPILER_7_UP} overload; {$ENDIF}
 | 
|---|
| 144 | 
 | 
|---|
| 145 |   {$IFDEF COMPILER_7_UP}
 | 
|---|
| 146 |   function Tnt_WideFormat(const FormatStr: WideString; const Args: array of const;
 | 
|---|
| 147 |     const FormatSettings: TFormatSettings): WideString; overload;
 | 
|---|
| 148 |   {$ENDIF}
 | 
|---|
| 149 | 
 | 
|---|
| 150 | {$ENDIF}
 | 
|---|
| 151 | 
 | 
|---|
| 152 | {TNT-WARN WideUpperCase} // SysUtils.WideUpperCase is broken on Win9x for D6, D7, D9.
 | 
|---|
| 153 | function Tnt_WideUpperCase(const S: WideString): WideString;
 | 
|---|
| 154 | {TNT-WARN WideLowerCase} // SysUtils.WideLowerCase is broken on Win9x for D6, D7, D9.
 | 
|---|
| 155 | function Tnt_WideLowerCase(const S: WideString): WideString;
 | 
|---|
| 156 | 
 | 
|---|
| 157 | function TntWideLastChar(const S: WideString): WideChar;
 | 
|---|
| 158 | 
 | 
|---|
| 159 | {TNT-WARN StringReplace}
 | 
|---|
| 160 | {TNT-WARN WideStringReplace} // <-- WideStrUtils.WideStringReplace uses SysUtils.WideUpperCase which is broken on Win9x.
 | 
|---|
| 161 | function Tnt_WideStringReplace(const S, OldPattern, NewPattern: WideString;
 | 
|---|
| 162 |   Flags: TReplaceFlags; WholeWord: Boolean = False): WideString;
 | 
|---|
| 163 | 
 | 
|---|
| 164 | {TNT-WARN AdjustLineBreaks}
 | 
|---|
| 165 | type TTntTextLineBreakStyle = (tlbsLF, tlbsCRLF, tlbsCR);
 | 
|---|
| 166 | function TntAdjustLineBreaksLength(const S: WideString; Style: TTntTextLineBreakStyle = tlbsCRLF): Integer;
 | 
|---|
| 167 | function TntAdjustLineBreaks(const S: WideString; Style: TTntTextLineBreakStyle = tlbsCRLF): WideString;
 | 
|---|
| 168 | 
 | 
|---|
| 169 | {TNT-WARN WrapText}
 | 
|---|
| 170 | function WideWrapText(const Line, BreakStr: WideString; const BreakChars: TSysCharSet;
 | 
|---|
| 171 |   MaxCol: Integer): WideString; overload;
 | 
|---|
| 172 | function WideWrapText(const Line: WideString; MaxCol: Integer): WideString; overload;
 | 
|---|
| 173 | 
 | 
|---|
| 174 | // ........ filename manipulation .........
 | 
|---|
| 175 | 
 | 
|---|
| 176 | {TNT-WARN SameFileName}           // doesn't apply to Unicode filenames, use WideSameText
 | 
|---|
| 177 | {TNT-WARN AnsiCompareFileName}    // doesn't apply to Unicode filenames, use WideCompareText
 | 
|---|
| 178 | {TNT-WARN AnsiLowerCaseFileName}  // doesn't apply to Unicode filenames, use WideLowerCase
 | 
|---|
| 179 | {TNT-WARN AnsiUpperCaseFileName}  // doesn't apply to Unicode filenames, use WideUpperCase
 | 
|---|
| 180 | 
 | 
|---|
| 181 | {TNT-WARN IncludeTrailingBackslash}
 | 
|---|
| 182 | function WideIncludeTrailingBackslash(const S: WideString): WideString;
 | 
|---|
| 183 | {TNT-WARN IncludeTrailingPathDelimiter}
 | 
|---|
| 184 | function WideIncludeTrailingPathDelimiter(const S: WideString): WideString;
 | 
|---|
| 185 | {TNT-WARN ExcludeTrailingBackslash}
 | 
|---|
| 186 | function WideExcludeTrailingBackslash(const S: WideString): WideString;
 | 
|---|
| 187 | {TNT-WARN ExcludeTrailingPathDelimiter}
 | 
|---|
| 188 | function WideExcludeTrailingPathDelimiter(const S: WideString): WideString;
 | 
|---|
| 189 | {TNT-WARN IsDelimiter}
 | 
|---|
| 190 | function WideIsDelimiter(const Delimiters, S: WideString; Index: Integer): Boolean;
 | 
|---|
| 191 | {TNT-WARN IsPathDelimiter}
 | 
|---|
| 192 | function WideIsPathDelimiter(const S: WideString; Index: Integer): Boolean;
 | 
|---|
| 193 | {TNT-WARN LastDelimiter}
 | 
|---|
| 194 | function WideLastDelimiter(const Delimiters, S: WideString): Integer;
 | 
|---|
| 195 | {TNT-WARN ChangeFileExt}
 | 
|---|
| 196 | function WideChangeFileExt(const FileName, Extension: WideString): WideString;
 | 
|---|
| 197 | {TNT-WARN ExtractFilePath}
 | 
|---|
| 198 | function WideExtractFilePath(const FileName: WideString): WideString;
 | 
|---|
| 199 | {TNT-WARN ExtractFileDir}
 | 
|---|
| 200 | function WideExtractFileDir(const FileName: WideString): WideString;
 | 
|---|
| 201 | {TNT-WARN ExtractFileDrive}
 | 
|---|
| 202 | function WideExtractFileDrive(const FileName: WideString): WideString;
 | 
|---|
| 203 | {TNT-WARN ExtractFileName}
 | 
|---|
| 204 | function WideExtractFileName(const FileName: WideString): WideString;
 | 
|---|
| 205 | {TNT-WARN ExtractFileExt}
 | 
|---|
| 206 | function WideExtractFileExt(const FileName: WideString): WideString;
 | 
|---|
| 207 | {TNT-WARN ExtractRelativePath}
 | 
|---|
| 208 | function WideExtractRelativePath(const BaseName, DestName: WideString): WideString;
 | 
|---|
| 209 | 
 | 
|---|
| 210 | // ........ file management routines .........
 | 
|---|
| 211 | 
 | 
|---|
| 212 | {TNT-WARN ExpandFileName}
 | 
|---|
| 213 | function WideExpandFileName(const FileName: WideString): WideString;
 | 
|---|
| 214 | {TNT-WARN ExtractShortPathName}
 | 
|---|
| 215 | function WideExtractShortPathName(const FileName: WideString): WideString;
 | 
|---|
| 216 | {TNT-WARN FileCreate}
 | 
|---|
| 217 | function WideFileCreate(const FileName: WideString): Integer;
 | 
|---|
| 218 | {TNT-WARN FileOpen}
 | 
|---|
| 219 | function WideFileOpen(const FileName: WideString; Mode: LongWord): Integer;
 | 
|---|
| 220 | {TNT-WARN FileAge}
 | 
|---|
| 221 | function WideFileAge(const FileName: WideString): Integer; overload;
 | 
|---|
| 222 | function WideFileAge(const FileName: WideString; out FileDateTime: TDateTime): Boolean; overload;
 | 
|---|
| 223 | {TNT-WARN DirectoryExists}
 | 
|---|
| 224 | function WideDirectoryExists(const Name: WideString): Boolean;
 | 
|---|
| 225 | {TNT-WARN FileExists}
 | 
|---|
| 226 | function WideFileExists(const Name: WideString): Boolean;
 | 
|---|
| 227 | {TNT-WARN FileGetAttr}
 | 
|---|
| 228 | function WideFileGetAttr(const FileName: WideString): Cardinal;
 | 
|---|
| 229 | {TNT-WARN FileSetAttr}
 | 
|---|
| 230 | function WideFileSetAttr(const FileName: WideString; Attr: Integer): Boolean;
 | 
|---|
| 231 | {TNT-WARN FileIsReadOnly}
 | 
|---|
| 232 | function WideFileIsReadOnly(const FileName: WideString): Boolean;
 | 
|---|
| 233 | {TNT-WARN FileSetReadOnly}
 | 
|---|
| 234 | function WideFileSetReadOnly(const FileName: WideString; ReadOnly: Boolean): Boolean;
 | 
|---|
| 235 | {TNT-WARN ForceDirectories}
 | 
|---|
| 236 | function WideForceDirectories(Dir: WideString): Boolean;
 | 
|---|
| 237 | {TNT-WARN FileSearch}
 | 
|---|
| 238 | function WideFileSearch(const Name, DirList: WideString): WideString;
 | 
|---|
| 239 | {TNT-WARN RenameFile}
 | 
|---|
| 240 | function WideRenameFile(const OldName, NewName: WideString): Boolean;
 | 
|---|
| 241 | {TNT-WARN DeleteFile}
 | 
|---|
| 242 | function WideDeleteFile(const FileName: WideString): Boolean;
 | 
|---|
| 243 | {TNT-WARN CopyFile}
 | 
|---|
| 244 | function WideCopyFile(FromFile, ToFile: WideString; FailIfExists: Boolean): Boolean;
 | 
|---|
| 245 | 
 | 
|---|
| 246 | 
 | 
|---|
| 247 | {TNT-WARN TFileName}
 | 
|---|
| 248 | type
 | 
|---|
| 249 |   TWideFileName = type WideString;
 | 
|---|
| 250 | 
 | 
|---|
| 251 | {TNT-WARN TSearchRec} // <-- FindFile - warning on TSearchRec is all that is necessary
 | 
|---|
| 252 | type
 | 
|---|
| 253 |   TSearchRecW = record
 | 
|---|
| 254 |     Time: Integer;
 | 
|---|
| 255 |     Size: Int64;
 | 
|---|
| 256 |     Attr: Integer;
 | 
|---|
| 257 |     Name: TWideFileName;
 | 
|---|
| 258 |     ExcludeAttr: Integer;
 | 
|---|
| 259 |     FindHandle: THandle;
 | 
|---|
| 260 |     FindData: TWin32FindDataW;
 | 
|---|
| 261 |   end;
 | 
|---|
| 262 | function WideFindFirst(const Path: WideString; Attr: Integer; var F: TSearchRecW): Integer;
 | 
|---|
| 263 | function WideFindNext(var F: TSearchRecW): Integer;
 | 
|---|
| 264 | procedure WideFindClose(var F: TSearchRecW);
 | 
|---|
| 265 | 
 | 
|---|
| 266 | {TNT-WARN CreateDir}
 | 
|---|
| 267 | function WideCreateDir(const Dir: WideString): Boolean;
 | 
|---|
| 268 | {TNT-WARN RemoveDir}
 | 
|---|
| 269 | function WideRemoveDir(const Dir: WideString): Boolean;
 | 
|---|
| 270 | {TNT-WARN GetCurrentDir}
 | 
|---|
| 271 | function WideGetCurrentDir: WideString;
 | 
|---|
| 272 | {TNT-WARN SetCurrentDir}
 | 
|---|
| 273 | function WideSetCurrentDir(const Dir: WideString): Boolean;
 | 
|---|
| 274 | 
 | 
|---|
| 275 | 
 | 
|---|
| 276 | // ........ date/time functions .........
 | 
|---|
| 277 | 
 | 
|---|
| 278 | {TNT-WARN TryStrToDateTime}
 | 
|---|
| 279 | function TntTryStrToDateTime(Str: WideString; out DateTime: TDateTime): Boolean;
 | 
|---|
| 280 | {TNT-WARN TryStrToDate}
 | 
|---|
| 281 | function TntTryStrToDate(Str: WideString; out DateTime: TDateTime): Boolean;
 | 
|---|
| 282 | {TNT-WARN TryStrToTime}
 | 
|---|
| 283 | function TntTryStrToTime(Str: WideString; out DateTime: TDateTime): Boolean;
 | 
|---|
| 284 | 
 | 
|---|
| 285 | { introduced }
 | 
|---|
| 286 | function ValidDateTimeStr(Str: WideString): Boolean;
 | 
|---|
| 287 | function ValidDateStr(Str: WideString): Boolean;
 | 
|---|
| 288 | function ValidTimeStr(Str: WideString): Boolean;
 | 
|---|
| 289 | 
 | 
|---|
| 290 | {TNT-WARN StrToDateTime}
 | 
|---|
| 291 | function TntStrToDateTime(Str: WideString): TDateTime;
 | 
|---|
| 292 | {TNT-WARN StrToDate}
 | 
|---|
| 293 | function TntStrToDate(Str: WideString): TDateTime;
 | 
|---|
| 294 | {TNT-WARN StrToTime}
 | 
|---|
| 295 | function TntStrToTime(Str: WideString): TDateTime;
 | 
|---|
| 296 | {TNT-WARN StrToDateTimeDef}
 | 
|---|
| 297 | function TntStrToDateTimeDef(Str: WideString; Default: TDateTime): TDateTime;
 | 
|---|
| 298 | {TNT-WARN StrToDateDef}
 | 
|---|
| 299 | function TntStrToDateDef(Str: WideString; Default: TDateTime): TDateTime;
 | 
|---|
| 300 | {TNT-WARN StrToTimeDef}
 | 
|---|
| 301 | function TntStrToTimeDef(Str: WideString; Default: TDateTime): TDateTime;
 | 
|---|
| 302 | 
 | 
|---|
| 303 | {TNT-WARN CurrToStr}
 | 
|---|
| 304 | {TNT-WARN CurrToStrF}
 | 
|---|
| 305 | function TntCurrToStr(Value: Currency; lpFormat: PCurrencyFmtW = nil): WideString;
 | 
|---|
| 306 | {TNT-WARN StrToCurr}
 | 
|---|
| 307 | function TntStrToCurr(const S: WideString): Currency;
 | 
|---|
| 308 | {TNT-WARN StrToCurrDef}
 | 
|---|
| 309 | function ValidCurrencyStr(const S: WideString): Boolean;
 | 
|---|
| 310 | function TntStrToCurrDef(const S: WideString; const Default: Currency): Currency;
 | 
|---|
| 311 | function GetDefaultCurrencyFmt: TCurrencyFmtW;
 | 
|---|
| 312 | 
 | 
|---|
| 313 | // ........ misc functions .........
 | 
|---|
| 314 | 
 | 
|---|
| 315 | {TNT-WARN GetLocaleStr}
 | 
|---|
| 316 | function WideGetLocaleStr(LocaleID: LCID; LocaleType: Integer; const Default: WideString): WideString;
 | 
|---|
| 317 | {TNT-WARN SysErrorMessage}
 | 
|---|
| 318 | function WideSysErrorMessage(ErrorCode: Integer): WideString;
 | 
|---|
| 319 | 
 | 
|---|
| 320 | // ......... introduced .........
 | 
|---|
| 321 | 
 | 
|---|
| 322 | function WideLibraryErrorMessage(const LibName: WideString; Dll: THandle; ErrorCode: Integer): WideString;
 | 
|---|
| 323 | 
 | 
|---|
| 324 | const
 | 
|---|
| 325 |   CR = WideChar(#13);
 | 
|---|
| 326 |   LF = WideChar(#10);
 | 
|---|
| 327 |   CRLF = WideString(#13#10);
 | 
|---|
| 328 |   WideLineSeparator = WideChar($2028);
 | 
|---|
| 329 | 
 | 
|---|
| 330 | var
 | 
|---|
| 331 |   Win32PlatformIsUnicode: Boolean;
 | 
|---|
| 332 |   Win32PlatformIsXP: Boolean;
 | 
|---|
| 333 |   Win32PlatformIs2003: Boolean;
 | 
|---|
| 334 |   Win32PlatformIsVista: Boolean;
 | 
|---|
| 335 | 
 | 
|---|
| 336 | {$IFNDEF COMPILER_7_UP}
 | 
|---|
| 337 | function CheckWin32Version(AMajor: Integer; AMinor: Integer = 0): Boolean;
 | 
|---|
| 338 | {$ENDIF}
 | 
|---|
| 339 | function WinCheckH(RetVal: Cardinal): Cardinal;
 | 
|---|
| 340 | function WinCheckFileH(RetVal: Cardinal): Cardinal;
 | 
|---|
| 341 | function WinCheckP(RetVal: Pointer): Pointer;
 | 
|---|
| 342 | 
 | 
|---|
| 343 | function WideGetModuleFileName(Instance: HModule): WideString;
 | 
|---|
| 344 | function WideSafeLoadLibrary(const Filename: Widestring;
 | 
|---|
| 345 |   ErrorMode: UINT = SEM_NOOPENFILEERRORBOX): HMODULE;
 | 
|---|
| 346 | function WideLoadPackage(const Name: Widestring): HMODULE;
 | 
|---|
| 347 | 
 | 
|---|
| 348 | function IsWideCharUpper(WC: WideChar): Boolean;
 | 
|---|
| 349 | function IsWideCharLower(WC: WideChar): Boolean;
 | 
|---|
| 350 | function IsWideCharDigit(WC: WideChar): Boolean;
 | 
|---|
| 351 | function IsWideCharSpace(WC: WideChar): Boolean;
 | 
|---|
| 352 | function IsWideCharPunct(WC: WideChar): Boolean;
 | 
|---|
| 353 | function IsWideCharCntrl(WC: WideChar): Boolean;
 | 
|---|
| 354 | function IsWideCharBlank(WC: WideChar): Boolean;
 | 
|---|
| 355 | function IsWideCharXDigit(WC: WideChar): Boolean;
 | 
|---|
| 356 | function IsWideCharAlpha(WC: WideChar): Boolean;
 | 
|---|
| 357 | function IsWideCharAlphaNumeric(WC: WideChar): Boolean;
 | 
|---|
| 358 | 
 | 
|---|
| 359 | function WideTextPos(const SubStr, S: WideString): Integer;
 | 
|---|
| 360 | 
 | 
|---|
| 361 | function ExtractStringArrayStr(P: PWideChar): WideString;
 | 
|---|
| 362 | function ExtractStringFromStringArray(var P: PWideChar; Separator: WideChar = #0): WideString;
 | 
|---|
| 363 | function ExtractStringsFromStringArray(P: PWideChar; Separator: WideChar = #0): TWideStringDynArray;
 | 
|---|
| 364 | 
 | 
|---|
| 365 | function IsWideCharMappableToAnsi(const WC: WideChar): Boolean;
 | 
|---|
| 366 | function IsWideStringMappableToAnsi(const WS: WideString): Boolean;
 | 
|---|
| 367 | function IsRTF(const Value: WideString): Boolean;
 | 
|---|
| 368 | 
 | 
|---|
| 369 | function ENG_US_FloatToStr(Value: Extended): WideString;
 | 
|---|
| 370 | function ENG_US_StrToFloat(const S: WideString): Extended;
 | 
|---|
| 371 | 
 | 
|---|
| 372 | //---------------------------------------------------------------------------------------------
 | 
|---|
| 373 | //                                 Tnt - Variants
 | 
|---|
| 374 | //---------------------------------------------------------------------------------------------
 | 
|---|
| 375 | 
 | 
|---|
| 376 | // ........ Variants.pas has WideString versions of these functions .........
 | 
|---|
| 377 | {TNT-WARN VarToStr}
 | 
|---|
| 378 | {TNT-WARN VarToStrDef}
 | 
|---|
| 379 | 
 | 
|---|
| 380 | var
 | 
|---|
| 381 |   _SettingChangeTime: Cardinal;
 | 
|---|
| 382 | 
 | 
|---|
| 383 | implementation
 | 
|---|
| 384 | 
 | 
|---|
| 385 | uses
 | 
|---|
| 386 |   ActiveX, ComObj, SysConst,
 | 
|---|
| 387 |   {$IFDEF COMPILER_9_UP} WideStrUtils, {$ENDIF} TntWideStrUtils,
 | 
|---|
| 388 |   TntSystem, TntWindows, TntFormatStrUtils;
 | 
|---|
| 389 | 
 | 
|---|
| 390 | //---------------------------------------------------------------------------------------------
 | 
|---|
| 391 | //                                 Tnt - SysUtils
 | 
|---|
| 392 | //---------------------------------------------------------------------------------------------
 | 
|---|
| 393 | 
 | 
|---|
| 394 | {$IFNDEF COMPILER_9_UP}
 | 
|---|
| 395 | 
 | 
|---|
| 396 |   function _Tnt_WideFormatBuf(var Buffer; BufLen: Cardinal; const FormatStr;
 | 
|---|
| 397 |     FmtLen: Cardinal; const Args: array of const
 | 
|---|
| 398 |       {$IFDEF COMPILER_7_UP}; const FormatSettings: PFormatSettings {$ENDIF}): Cardinal;
 | 
|---|
| 399 |   var
 | 
|---|
| 400 |     OldFormat: WideString;
 | 
|---|
| 401 |     NewFormat: WideString;
 | 
|---|
| 402 |   begin
 | 
|---|
| 403 |     SetString(OldFormat, PWideChar(@FormatStr), FmtLen);
 | 
|---|
| 404 |     { The reason for this is that WideFormat doesn't correctly format floating point specifiers.
 | 
|---|
| 405 |       See QC#4254. }
 | 
|---|
| 406 |     NewFormat := ReplaceFloatingArgumentsInFormatString(OldFormat, Args{$IFDEF COMPILER_7_UP}, FormatSettings{$ENDIF});
 | 
|---|
| 407 |     {$IFDEF COMPILER_7_UP}
 | 
|---|
| 408 |     if FormatSettings <> nil then
 | 
|---|
| 409 |       Result := WideFormatBuf(Buffer, BufLen, Pointer(NewFormat)^,
 | 
|---|
| 410 |         Length(NewFormat), Args, FormatSettings^)
 | 
|---|
| 411 |     else
 | 
|---|
| 412 |     {$ENDIF}
 | 
|---|
| 413 |       Result := WideFormatBuf(Buffer, BufLen, Pointer(NewFormat)^,
 | 
|---|
| 414 |         Length(NewFormat), Args);
 | 
|---|
| 415 |   end;
 | 
|---|
| 416 | 
 | 
|---|
| 417 |   function Tnt_WideFormatBuf(var Buffer; BufLen: Cardinal; const FormatStr;
 | 
|---|
| 418 |     FmtLen: Cardinal; const Args: array of const): Cardinal;
 | 
|---|
| 419 |   begin
 | 
|---|
| 420 |     Result := _Tnt_WideFormatBuf(Buffer, BufLen, FormatStr, FmtLen, Args{$IFDEF COMPILER_7_UP}, nil{$ENDIF});
 | 
|---|
| 421 |   end;
 | 
|---|
| 422 | 
 | 
|---|
| 423 |   {$IFDEF COMPILER_7_UP}
 | 
|---|
| 424 |   function Tnt_WideFormatBuf(var Buffer; BufLen: Cardinal; const FormatStr;
 | 
|---|
| 425 |     FmtLen: Cardinal; const Args: array of const; const FormatSettings: TFormatSettings): Cardinal;
 | 
|---|
| 426 |   begin
 | 
|---|
| 427 |     Result := _Tnt_WideFormatBuf(Buffer, BufLen, FormatStr, FmtLen, Args, @FormatSettings);
 | 
|---|
| 428 |   end;
 | 
|---|
| 429 |   {$ENDIF}
 | 
|---|
| 430 | 
 | 
|---|
| 431 |   procedure _Tnt_WideFmtStr(var Result: WideString; const FormatStr: WideString;
 | 
|---|
| 432 |     const Args: array of const{$IFDEF COMPILER_7_UP}; const FormatSettings: PFormatSettings{$ENDIF});
 | 
|---|
| 433 |   var
 | 
|---|
| 434 |     Len, BufLen: Integer;
 | 
|---|
| 435 |     Buffer: array[0..4095] of WideChar;
 | 
|---|
| 436 |   begin
 | 
|---|
| 437 |     BufLen := Length(Buffer); // Fixes buffer overwrite issue. (See QC #4703, #4744)
 | 
|---|
| 438 |     if Length(FormatStr) < (Length(Buffer) - (Length(Buffer) div 4)) then
 | 
|---|
| 439 |       Len := _Tnt_WideFormatBuf(Buffer, Length(Buffer) - 1, Pointer(FormatStr)^,
 | 
|---|
| 440 |         Length(FormatStr), Args{$IFDEF COMPILER_7_UP}, FormatSettings{$ENDIF})
 | 
|---|
| 441 |     else
 | 
|---|
| 442 |     begin
 | 
|---|
| 443 |       BufLen := Length(FormatStr);
 | 
|---|
| 444 |       Len := BufLen;
 | 
|---|
| 445 |     end;
 | 
|---|
| 446 |     if Len >= BufLen - 1 then
 | 
|---|
| 447 |     begin
 | 
|---|
| 448 |       while Len >= BufLen - 1 do
 | 
|---|
| 449 |       begin
 | 
|---|
| 450 |         Inc(BufLen, BufLen);
 | 
|---|
| 451 |         Result := '';          // prevent copying of existing data, for speed
 | 
|---|
| 452 |         SetLength(Result, BufLen);
 | 
|---|
| 453 |         Len := _Tnt_WideFormatBuf(Pointer(Result)^, BufLen - 1, Pointer(FormatStr)^,
 | 
|---|
| 454 |           Length(FormatStr), Args{$IFDEF COMPILER_7_UP}, FormatSettings{$ENDIF});
 | 
|---|
| 455 |       end;
 | 
|---|
| 456 |       SetLength(Result, Len);
 | 
|---|
| 457 |     end
 | 
|---|
| 458 |     else
 | 
|---|
| 459 |       SetString(Result, Buffer, Len);
 | 
|---|
| 460 |   end;
 | 
|---|
| 461 | 
 | 
|---|
| 462 |   procedure Tnt_WideFmtStr(var Result: WideString; const FormatStr: WideString;
 | 
|---|
| 463 |     const Args: array of const);
 | 
|---|
| 464 |   begin
 | 
|---|
| 465 |     _Tnt_WideFmtStr(Result, FormatStr, Args{$IFDEF COMPILER_7_UP}, nil{$ENDIF});
 | 
|---|
| 466 |   end;
 | 
|---|
| 467 | 
 | 
|---|
| 468 |   {$IFDEF COMPILER_7_UP}
 | 
|---|
| 469 |   procedure Tnt_WideFmtStr(var Result: WideString; const FormatStr: WideString;
 | 
|---|
| 470 |     const Args: array of const; const FormatSettings: TFormatSettings);
 | 
|---|
| 471 |   begin
 | 
|---|
| 472 |     _Tnt_WideFmtStr(Result, FormatStr, Args, @FormatSettings);
 | 
|---|
| 473 |   end;
 | 
|---|
| 474 |   {$ENDIF}
 | 
|---|
| 475 | 
 | 
|---|
| 476 |   {----------------------------------------------------------------------------------------
 | 
|---|
| 477 |     Without the FormatSettings parameter, Tnt_WideFormat is *NOT* necessary...
 | 
|---|
| 478 |       TntSystem.InstallTntSystemUpdates([tsFixWideFormat]);
 | 
|---|
| 479 |         will fix WideFormat as well as WideFmtStr.
 | 
|---|
| 480 |   ----------------------------------------------------------------------------------------}
 | 
|---|
| 481 |   function Tnt_WideFormat(const FormatStr: WideString; const Args: array of const): WideString;
 | 
|---|
| 482 |   begin
 | 
|---|
| 483 |     Tnt_WideFmtStr(Result, FormatStr, Args);
 | 
|---|
| 484 |   end;
 | 
|---|
| 485 | 
 | 
|---|
| 486 |   {$IFDEF COMPILER_7_UP}
 | 
|---|
| 487 |   function Tnt_WideFormat(const FormatStr: WideString; const Args: array of const;
 | 
|---|
| 488 |     const FormatSettings: TFormatSettings): WideString;
 | 
|---|
| 489 |   begin
 | 
|---|
| 490 |     Tnt_WideFmtStr(Result, FormatStr, Args, FormatSettings);
 | 
|---|
| 491 |   end;
 | 
|---|
| 492 |   {$ENDIF}
 | 
|---|
| 493 | 
 | 
|---|
| 494 | {$ENDIF}
 | 
|---|
| 495 | 
 | 
|---|
| 496 | function Tnt_WideUpperCase(const S: WideString): WideString;
 | 
|---|
| 497 | begin
 | 
|---|
| 498 |   {$IFNDEF COMPILER_10_UP}
 | 
|---|
| 499 |   { SysUtils.WideUpperCase is broken for Win9x. }
 | 
|---|
| 500 |   Result := S;
 | 
|---|
| 501 |   if Length(Result) > 0 then
 | 
|---|
| 502 |     Tnt_CharUpperBuffW(PWideChar(Result), Length(Result));
 | 
|---|
| 503 |   {$ELSE}
 | 
|---|
| 504 |   Result := SysUtils.WideUpperCase{TNT-ALLOW WideUpperCase}(S);
 | 
|---|
| 505 |   {$ENDIF}
 | 
|---|
| 506 | end;
 | 
|---|
| 507 | 
 | 
|---|
| 508 | function Tnt_WideLowerCase(const S: WideString): WideString;
 | 
|---|
| 509 | begin
 | 
|---|
| 510 |   {$IFNDEF COMPILER_10_UP}
 | 
|---|
| 511 |   { SysUtils.WideLowerCase is broken for Win9x. }
 | 
|---|
| 512 |   Result := S;
 | 
|---|
| 513 |   if Length(Result) > 0 then
 | 
|---|
| 514 |     Tnt_CharLowerBuffW(PWideChar(Result), Length(Result));
 | 
|---|
| 515 |   {$ELSE}
 | 
|---|
| 516 |   Result := SysUtils.WideLowerCase{TNT-ALLOW WideLowerCase}(S);
 | 
|---|
| 517 |   {$ENDIF}
 | 
|---|
| 518 | end;
 | 
|---|
| 519 | 
 | 
|---|
| 520 | function TntWideLastChar(const S: WideString): WideChar;
 | 
|---|
| 521 | var
 | 
|---|
| 522 |   P: PWideChar;
 | 
|---|
| 523 | begin
 | 
|---|
| 524 |   P := WideLastChar(S);
 | 
|---|
| 525 |   if P = nil then
 | 
|---|
| 526 |     Result := #0
 | 
|---|
| 527 |   else
 | 
|---|
| 528 |     Result := P^;
 | 
|---|
| 529 | end;
 | 
|---|
| 530 | 
 | 
|---|
| 531 | function Tnt_WideStringReplace(const S, OldPattern, NewPattern: WideString;
 | 
|---|
| 532 |   Flags: TReplaceFlags; WholeWord: Boolean = False): WideString;
 | 
|---|
| 533 | 
 | 
|---|
| 534 |   function IsWordSeparator(WC: WideChar): Boolean;
 | 
|---|
| 535 |   begin
 | 
|---|
| 536 |     Result := (WC = WideChar(#0))
 | 
|---|
| 537 |            or IsWideCharSpace(WC)
 | 
|---|
| 538 |            or IsWideCharPunct(WC);
 | 
|---|
| 539 |   end;
 | 
|---|
| 540 | 
 | 
|---|
| 541 | var
 | 
|---|
| 542 |   SearchStr, Patt, NewStr: WideString;
 | 
|---|
| 543 |   Offset: Integer;
 | 
|---|
| 544 |   PrevChar, NextChar: WideChar;
 | 
|---|
| 545 | begin
 | 
|---|
| 546 |   if rfIgnoreCase in Flags then
 | 
|---|
| 547 |   begin
 | 
|---|
| 548 |     SearchStr := Tnt_WideUpperCase(S);
 | 
|---|
| 549 |     Patt := Tnt_WideUpperCase(OldPattern);
 | 
|---|
| 550 |   end else
 | 
|---|
| 551 |   begin
 | 
|---|
| 552 |     SearchStr := S;
 | 
|---|
| 553 |     Patt := OldPattern;
 | 
|---|
| 554 |   end;
 | 
|---|
| 555 |   NewStr := S;
 | 
|---|
| 556 |   Result := '';
 | 
|---|
| 557 |   while SearchStr <> '' do
 | 
|---|
| 558 |   begin
 | 
|---|
| 559 |     Offset := Pos(Patt, SearchStr);
 | 
|---|
| 560 |     if Offset = 0 then
 | 
|---|
| 561 |     begin
 | 
|---|
| 562 |       Result := Result + NewStr;
 | 
|---|
| 563 |       Break;
 | 
|---|
| 564 |     end; // done
 | 
|---|
| 565 | 
 | 
|---|
| 566 |     if (WholeWord) then
 | 
|---|
| 567 |     begin
 | 
|---|
| 568 |       if (Offset = 1) then
 | 
|---|
| 569 |         PrevChar := TntWideLastChar(Result)
 | 
|---|
| 570 |       else
 | 
|---|
| 571 |         PrevChar := NewStr[Offset - 1];
 | 
|---|
| 572 | 
 | 
|---|
| 573 |       if Offset + Length(OldPattern) <= Length(NewStr) then
 | 
|---|
| 574 |         NextChar := NewStr[Offset + Length(OldPattern)]
 | 
|---|
| 575 |       else
 | 
|---|
| 576 |         NextChar := WideChar(#0);
 | 
|---|
| 577 | 
 | 
|---|
| 578 |       if (not IsWordSeparator(PrevChar))
 | 
|---|
| 579 |       or (not IsWordSeparator(NextChar)) then
 | 
|---|
| 580 |       begin
 | 
|---|
| 581 |         Result := Result + Copy(NewStr, 1, Offset + Length(OldPattern) - 1);
 | 
|---|
| 582 |         NewStr := Copy(NewStr, Offset + Length(OldPattern), MaxInt);
 | 
|---|
| 583 |         SearchStr := Copy(SearchStr, Offset + Length(Patt), MaxInt);
 | 
|---|
| 584 |         continue;
 | 
|---|
| 585 |       end;
 | 
|---|
| 586 |     end;
 | 
|---|
| 587 | 
 | 
|---|
| 588 |     Result := Result + Copy(NewStr, 1, Offset - 1) + NewPattern;
 | 
|---|
| 589 |     NewStr := Copy(NewStr, Offset + Length(OldPattern), MaxInt);
 | 
|---|
| 590 |     if not (rfReplaceAll in Flags) then
 | 
|---|
| 591 |     begin
 | 
|---|
| 592 |       Result := Result + NewStr;
 | 
|---|
| 593 |       Break;
 | 
|---|
| 594 |     end;
 | 
|---|
| 595 |     SearchStr := Copy(SearchStr, Offset + Length(Patt), MaxInt);
 | 
|---|
| 596 |   end;
 | 
|---|
| 597 | end;
 | 
|---|
| 598 | 
 | 
|---|
| 599 | function TntAdjustLineBreaksLength(const S: WideString; Style: TTntTextLineBreakStyle = tlbsCRLF): Integer;
 | 
|---|
| 600 | var
 | 
|---|
| 601 |   Source, SourceEnd: PWideChar;
 | 
|---|
| 602 | begin
 | 
|---|
| 603 |   Source := Pointer(S);
 | 
|---|
| 604 |   SourceEnd := Source + Length(S);
 | 
|---|
| 605 |   Result := Length(S);
 | 
|---|
| 606 |   while Source < SourceEnd do
 | 
|---|
| 607 |   begin
 | 
|---|
| 608 |     case Source^ of
 | 
|---|
| 609 |       #10, WideLineSeparator:
 | 
|---|
| 610 |         if Style = tlbsCRLF then
 | 
|---|
| 611 |           Inc(Result);
 | 
|---|
| 612 |       #13:
 | 
|---|
| 613 |         if Style = tlbsCRLF then
 | 
|---|
| 614 |           if Source[1] = #10 then
 | 
|---|
| 615 |             Inc(Source)
 | 
|---|
| 616 |           else
 | 
|---|
| 617 |             Inc(Result)
 | 
|---|
| 618 |         else
 | 
|---|
| 619 |           if Source[1] = #10 then
 | 
|---|
| 620 |             Dec(Result);
 | 
|---|
| 621 |     end;
 | 
|---|
| 622 |     Inc(Source);
 | 
|---|
| 623 |   end;
 | 
|---|
| 624 | end;
 | 
|---|
| 625 | 
 | 
|---|
| 626 | function TntAdjustLineBreaks(const S: WideString; Style: TTntTextLineBreakStyle = tlbsCRLF): WideString;
 | 
|---|
| 627 | var
 | 
|---|
| 628 |   Source, SourceEnd, Dest: PWideChar;
 | 
|---|
| 629 |   DestLen: Integer;
 | 
|---|
| 630 | begin
 | 
|---|
| 631 |   Source := Pointer(S);
 | 
|---|
| 632 |   SourceEnd := Source + Length(S);
 | 
|---|
| 633 |   DestLen := TntAdjustLineBreaksLength(S, Style);
 | 
|---|
| 634 |   SetString(Result, nil, DestLen);
 | 
|---|
| 635 |   Dest := Pointer(Result);
 | 
|---|
| 636 |   while Source < SourceEnd do begin
 | 
|---|
| 637 |     case Source^ of
 | 
|---|
| 638 |       #10, WideLineSeparator:
 | 
|---|
| 639 |         begin
 | 
|---|
| 640 |           if Style in [tlbsCRLF, tlbsCR] then
 | 
|---|
| 641 |           begin
 | 
|---|
| 642 |             Dest^ := #13;
 | 
|---|
| 643 |             Inc(Dest);
 | 
|---|
| 644 |           end;
 | 
|---|
| 645 |           if Style in [tlbsCRLF, tlbsLF] then
 | 
|---|
| 646 |           begin
 | 
|---|
| 647 |             Dest^ := #10;
 | 
|---|
| 648 |             Inc(Dest);
 | 
|---|
| 649 |           end;
 | 
|---|
| 650 |           Inc(Source);
 | 
|---|
| 651 |         end;
 | 
|---|
| 652 |       #13:
 | 
|---|
| 653 |         begin
 | 
|---|
| 654 |           if Style in [tlbsCRLF, tlbsCR] then
 | 
|---|
| 655 |           begin
 | 
|---|
| 656 |             Dest^ := #13;
 | 
|---|
| 657 |             Inc(Dest);
 | 
|---|
| 658 |           end;
 | 
|---|
| 659 |           if Style in [tlbsCRLF, tlbsLF] then
 | 
|---|
| 660 |           begin
 | 
|---|
| 661 |             Dest^ := #10;
 | 
|---|
| 662 |             Inc(Dest);
 | 
|---|
| 663 |           end;
 | 
|---|
| 664 |           Inc(Source);
 | 
|---|
| 665 |           if Source^ = #10 then Inc(Source);
 | 
|---|
| 666 |         end;
 | 
|---|
| 667 |     else
 | 
|---|
| 668 |       Dest^ := Source^;
 | 
|---|
| 669 |       Inc(Dest);
 | 
|---|
| 670 |       Inc(Source);
 | 
|---|
| 671 |     end;
 | 
|---|
| 672 |   end;
 | 
|---|
| 673 | end;
 | 
|---|
| 674 | 
 | 
|---|
| 675 | function WideWrapText(const Line, BreakStr: WideString; const BreakChars: TSysCharSet;
 | 
|---|
| 676 |   MaxCol: Integer): WideString;
 | 
|---|
| 677 | 
 | 
|---|
| 678 |   function WideCharIn(C: WideChar; SysCharSet: TSysCharSet): Boolean;
 | 
|---|
| 679 |   begin
 | 
|---|
| 680 |     Result := (C <= High(AnsiChar)) and (AnsiChar(C) in SysCharSet);
 | 
|---|
| 681 |   end;
 | 
|---|
| 682 | 
 | 
|---|
| 683 | const
 | 
|---|
| 684 |   QuoteChars = ['''', '"'];
 | 
|---|
| 685 | var
 | 
|---|
| 686 |   Col, Pos: Integer;
 | 
|---|
| 687 |   LinePos, LineLen: Integer;
 | 
|---|
| 688 |   BreakLen, BreakPos: Integer;
 | 
|---|
| 689 |   QuoteChar, CurChar: WideChar;
 | 
|---|
| 690 |   ExistingBreak: Boolean;
 | 
|---|
| 691 | begin
 | 
|---|
| 692 |   Col := 1;
 | 
|---|
| 693 |   Pos := 1;
 | 
|---|
| 694 |   LinePos := 1;
 | 
|---|
| 695 |   BreakPos := 0;
 | 
|---|
| 696 |   QuoteChar := ' ';
 | 
|---|
| 697 |   ExistingBreak := False;
 | 
|---|
| 698 |   LineLen := Length(Line);
 | 
|---|
| 699 |   BreakLen := Length(BreakStr);
 | 
|---|
| 700 |   Result := '';
 | 
|---|
| 701 |   while Pos <= LineLen do
 | 
|---|
| 702 |   begin
 | 
|---|
| 703 |     CurChar := Line[Pos];
 | 
|---|
| 704 |     if CurChar = BreakStr[1] then
 | 
|---|
| 705 |     begin
 | 
|---|
| 706 |       if QuoteChar = ' ' then
 | 
|---|
| 707 |       begin
 | 
|---|
| 708 |         ExistingBreak := WideSameText(BreakStr, Copy(Line, Pos, BreakLen));
 | 
|---|
| 709 |         if ExistingBreak then
 | 
|---|
| 710 |         begin
 | 
|---|
| 711 |           Inc(Pos, BreakLen-1);
 | 
|---|
| 712 |           BreakPos := Pos;
 | 
|---|
| 713 |         end;
 | 
|---|
| 714 |       end
 | 
|---|
| 715 |     end
 | 
|---|
| 716 |     else if WideCharIn(CurChar, BreakChars) then
 | 
|---|
| 717 |     begin
 | 
|---|
| 718 |       if QuoteChar = ' ' then BreakPos := Pos
 | 
|---|
| 719 |     end
 | 
|---|
| 720 |     else if WideCharIn(CurChar, QuoteChars) then
 | 
|---|
| 721 |     begin
 | 
|---|
| 722 |       if CurChar = QuoteChar then
 | 
|---|
| 723 |         QuoteChar := ' '
 | 
|---|
| 724 |       else if QuoteChar = ' ' then
 | 
|---|
| 725 |         QuoteChar := CurChar;
 | 
|---|
| 726 |     end;
 | 
|---|
| 727 |     Inc(Pos);
 | 
|---|
| 728 |     Inc(Col);
 | 
|---|
| 729 |     if not (WideCharIn(QuoteChar, QuoteChars)) and (ExistingBreak or
 | 
|---|
| 730 |       ((Col > MaxCol) and (BreakPos > LinePos))) then
 | 
|---|
| 731 |     begin
 | 
|---|
| 732 |       Col := Pos - BreakPos;
 | 
|---|
| 733 |       Result := Result + Copy(Line, LinePos, BreakPos - LinePos + 1);
 | 
|---|
| 734 |       if not (WideCharIn(CurChar, QuoteChars)) then
 | 
|---|
| 735 |         while Pos <= LineLen do
 | 
|---|
| 736 |         begin
 | 
|---|
| 737 |           if WideCharIn(Line[Pos], BreakChars) then
 | 
|---|
| 738 |             Inc(Pos)
 | 
|---|
| 739 |           else if Copy(Line, Pos, Length(sLineBreak)) = sLineBreak then
 | 
|---|
| 740 |             Inc(Pos, Length(sLineBreak))
 | 
|---|
| 741 |           else
 | 
|---|
| 742 |             break;
 | 
|---|
| 743 |         end;
 | 
|---|
| 744 |       if not ExistingBreak and (Pos < LineLen) then
 | 
|---|
| 745 |         Result := Result + BreakStr;
 | 
|---|
| 746 |       Inc(BreakPos);
 | 
|---|
| 747 |       LinePos := BreakPos;
 | 
|---|
| 748 |       ExistingBreak := False;
 | 
|---|
| 749 |     end;
 | 
|---|
| 750 |   end;
 | 
|---|
| 751 |   Result := Result + Copy(Line, LinePos, MaxInt);
 | 
|---|
| 752 | end;
 | 
|---|
| 753 | 
 | 
|---|
| 754 | function WideWrapText(const Line: WideString; MaxCol: Integer): WideString;
 | 
|---|
| 755 | begin
 | 
|---|
| 756 |   Result := WideWrapText(Line, sLineBreak, [' ', '-', #9], MaxCol); { do not localize }
 | 
|---|
| 757 | end;
 | 
|---|
| 758 | 
 | 
|---|
| 759 | function WideIncludeTrailingBackslash(const S: WideString): WideString;
 | 
|---|
| 760 | begin
 | 
|---|
| 761 |   Result := WideIncludeTrailingPathDelimiter(S);
 | 
|---|
| 762 | end;
 | 
|---|
| 763 | 
 | 
|---|
| 764 | function WideIncludeTrailingPathDelimiter(const S: WideString): WideString;
 | 
|---|
| 765 | begin
 | 
|---|
| 766 |   Result := S;
 | 
|---|
| 767 |   if not WideIsPathDelimiter(Result, Length(Result)) then Result := Result + PathDelim;
 | 
|---|
| 768 | end;
 | 
|---|
| 769 | 
 | 
|---|
| 770 | function WideExcludeTrailingBackslash(const S: WideString): WideString;
 | 
|---|
| 771 | begin
 | 
|---|
| 772 |   Result := WideExcludeTrailingPathDelimiter(S);
 | 
|---|
| 773 | end;
 | 
|---|
| 774 | 
 | 
|---|
| 775 | function WideExcludeTrailingPathDelimiter(const S: WideString): WideString;
 | 
|---|
| 776 | begin
 | 
|---|
| 777 |   Result := S;
 | 
|---|
| 778 |   if WideIsPathDelimiter(Result, Length(Result)) then
 | 
|---|
| 779 |     SetLength(Result, Length(Result)-1);
 | 
|---|
| 780 | end;
 | 
|---|
| 781 | 
 | 
|---|
| 782 | function WideIsDelimiter(const Delimiters, S: WideString; Index: Integer): Boolean;
 | 
|---|
| 783 | begin
 | 
|---|
| 784 |   Result := False;
 | 
|---|
| 785 |   if (Index <= 0) or (Index > Length(S)) then exit;
 | 
|---|
| 786 |   Result := WStrScan(PWideChar(Delimiters), S[Index]) <> nil;
 | 
|---|
| 787 | end;
 | 
|---|
| 788 | 
 | 
|---|
| 789 | function WideIsPathDelimiter(const S: WideString; Index: Integer): Boolean;
 | 
|---|
| 790 | begin
 | 
|---|
| 791 |   Result := (Index > 0) and (Index <= Length(S)) and (S[Index] = PathDelim);
 | 
|---|
| 792 | end;
 | 
|---|
| 793 | 
 | 
|---|
| 794 | function WideLastDelimiter(const Delimiters, S: WideString): Integer;
 | 
|---|
| 795 | var
 | 
|---|
| 796 |   P: PWideChar;
 | 
|---|
| 797 | begin
 | 
|---|
| 798 |   Result := Length(S);
 | 
|---|
| 799 |   P := PWideChar(Delimiters);
 | 
|---|
| 800 |   while Result > 0 do
 | 
|---|
| 801 |   begin
 | 
|---|
| 802 |     if (S[Result] <> #0) and (WStrScan(P, S[Result]) <> nil) then
 | 
|---|
| 803 |       Exit;
 | 
|---|
| 804 |     Dec(Result);
 | 
|---|
| 805 |   end;
 | 
|---|
| 806 | end;
 | 
|---|
| 807 | 
 | 
|---|
| 808 | function WideChangeFileExt(const FileName, Extension: WideString): WideString;
 | 
|---|
| 809 | var
 | 
|---|
| 810 |   I: Integer;
 | 
|---|
| 811 | begin
 | 
|---|
| 812 |   I := WideLastDelimiter('.\:',Filename);
 | 
|---|
| 813 |   if (I = 0) or (FileName[I] <> '.') then I := MaxInt;
 | 
|---|
| 814 |   Result := Copy(FileName, 1, I - 1) + Extension;
 | 
|---|
| 815 | end;
 | 
|---|
| 816 | 
 | 
|---|
| 817 | function WideExtractFilePath(const FileName: WideString): WideString;
 | 
|---|
| 818 | var
 | 
|---|
| 819 |   I: Integer;
 | 
|---|
| 820 | begin
 | 
|---|
| 821 |   I := WideLastDelimiter('\:', FileName);
 | 
|---|
| 822 |   Result := Copy(FileName, 1, I);
 | 
|---|
| 823 | end;
 | 
|---|
| 824 | 
 | 
|---|
| 825 | function WideExtractFileDir(const FileName: WideString): WideString;
 | 
|---|
| 826 | var
 | 
|---|
| 827 |   I: Integer;
 | 
|---|
| 828 | begin
 | 
|---|
| 829 |   I := WideLastDelimiter(DriveDelim + PathDelim,Filename);
 | 
|---|
| 830 |   if (I > 1) and (FileName[I] = PathDelim) and
 | 
|---|
| 831 |     (not (FileName[I - 1] in [WideChar(PathDelim), WideChar(DriveDelim)])) then Dec(I);
 | 
|---|
| 832 |   Result := Copy(FileName, 1, I);
 | 
|---|
| 833 | end;
 | 
|---|
| 834 | 
 | 
|---|
| 835 | function WideExtractFileDrive(const FileName: WideString): WideString;
 | 
|---|
| 836 | var
 | 
|---|
| 837 |   I, J: Integer;
 | 
|---|
| 838 | begin
 | 
|---|
| 839 |   if (Length(FileName) >= 2) and (FileName[2] = DriveDelim) then
 | 
|---|
| 840 |     Result := Copy(FileName, 1, 2)
 | 
|---|
| 841 |   else if (Length(FileName) >= 2) and (FileName[1] = PathDelim) and
 | 
|---|
| 842 |     (FileName[2] = PathDelim) then
 | 
|---|
| 843 |   begin
 | 
|---|
| 844 |     J := 0;
 | 
|---|
| 845 |     I := 3;
 | 
|---|
| 846 |     While (I < Length(FileName)) and (J < 2) do
 | 
|---|
| 847 |     begin
 | 
|---|
| 848 |       if FileName[I] = PathDelim then Inc(J);
 | 
|---|
| 849 |       if J < 2 then Inc(I);
 | 
|---|
| 850 |     end;
 | 
|---|
| 851 |     if FileName[I] = PathDelim then Dec(I);
 | 
|---|
| 852 |     Result := Copy(FileName, 1, I);
 | 
|---|
| 853 |   end else Result := '';
 | 
|---|
| 854 | end;
 | 
|---|
| 855 | 
 | 
|---|
| 856 | function WideExtractFileName(const FileName: WideString): WideString;
 | 
|---|
| 857 | var
 | 
|---|
| 858 |   I: Integer;
 | 
|---|
| 859 | begin
 | 
|---|
| 860 |   I := WideLastDelimiter('\:', FileName);
 | 
|---|
| 861 |   Result := Copy(FileName, I + 1, MaxInt);
 | 
|---|
| 862 | end;
 | 
|---|
| 863 | 
 | 
|---|
| 864 | function WideExtractFileExt(const FileName: WideString): WideString;
 | 
|---|
| 865 | var
 | 
|---|
| 866 |   I: Integer;
 | 
|---|
| 867 | begin
 | 
|---|
| 868 |   I := WideLastDelimiter('.\:', FileName);
 | 
|---|
| 869 |   if (I > 0) and (FileName[I] = '.') then
 | 
|---|
| 870 |     Result := Copy(FileName, I, MaxInt) else
 | 
|---|
| 871 |     Result := '';
 | 
|---|
| 872 | end;
 | 
|---|
| 873 | 
 | 
|---|
| 874 | function WideExtractRelativePath(const BaseName, DestName: WideString): WideString;
 | 
|---|
| 875 | var
 | 
|---|
| 876 |   BasePath, DestPath: WideString;
 | 
|---|
| 877 |   BaseLead, DestLead: PWideChar;
 | 
|---|
| 878 |   BasePtr, DestPtr: PWideChar;
 | 
|---|
| 879 | 
 | 
|---|
| 880 |   function WideExtractFilePathNoDrive(const FileName: WideString): WideString;
 | 
|---|
| 881 |   begin
 | 
|---|
| 882 |     Result := WideExtractFilePath(FileName);
 | 
|---|
| 883 |     Delete(Result, 1, Length(WideExtractFileDrive(FileName)));
 | 
|---|
| 884 |   end;
 | 
|---|
| 885 | 
 | 
|---|
| 886 |   function Next(var Lead: PWideChar): PWideChar;
 | 
|---|
| 887 |   begin
 | 
|---|
| 888 |     Result := Lead;
 | 
|---|
| 889 |     if Result = nil then Exit;
 | 
|---|
| 890 |     Lead := WStrScan(Lead, PathDelim);
 | 
|---|
| 891 |     if Lead <> nil then
 | 
|---|
| 892 |     begin
 | 
|---|
| 893 |       Lead^ := #0;
 | 
|---|
| 894 |       Inc(Lead);
 | 
|---|
| 895 |     end;
 | 
|---|
| 896 |   end;
 | 
|---|
| 897 | 
 | 
|---|
| 898 | begin
 | 
|---|
| 899 |   if WideSameText(WideExtractFileDrive(BaseName), WideExtractFileDrive(DestName)) then
 | 
|---|
| 900 |   begin
 | 
|---|
| 901 |     BasePath := WideExtractFilePathNoDrive(BaseName);
 | 
|---|
| 902 |     DestPath := WideExtractFilePathNoDrive(DestName);
 | 
|---|
| 903 |     BaseLead := Pointer(BasePath);
 | 
|---|
| 904 |     BasePtr := Next(BaseLead);
 | 
|---|
| 905 |     DestLead := Pointer(DestPath);
 | 
|---|
| 906 |     DestPtr := Next(DestLead);
 | 
|---|
| 907 |     while (BasePtr <> nil) and (DestPtr <> nil) and WideSameText(BasePtr, DestPtr) do
 | 
|---|
| 908 |     begin
 | 
|---|
| 909 |       BasePtr := Next(BaseLead);
 | 
|---|
| 910 |       DestPtr := Next(DestLead);
 | 
|---|
| 911 |     end;
 | 
|---|
| 912 |     Result := '';
 | 
|---|
| 913 |     while BaseLead <> nil do
 | 
|---|
| 914 |     begin
 | 
|---|
| 915 |       Result := Result + '..' + PathDelim;             { Do not localize }
 | 
|---|
| 916 |       Next(BaseLead);
 | 
|---|
| 917 |     end;
 | 
|---|
| 918 |     if (DestPtr <> nil) and (DestPtr^ <> #0) then
 | 
|---|
| 919 |       Result := Result + DestPtr + PathDelim;
 | 
|---|
| 920 |     if DestLead <> nil then
 | 
|---|
| 921 |       Result := Result + DestLead;     // destlead already has a trailing backslash
 | 
|---|
| 922 |     Result := Result + WideExtractFileName(DestName);
 | 
|---|
| 923 |   end
 | 
|---|
| 924 |   else
 | 
|---|
| 925 |     Result := DestName;
 | 
|---|
| 926 | end;
 | 
|---|
| 927 | 
 | 
|---|
| 928 | function WideExpandFileName(const FileName: WideString): WideString;
 | 
|---|
| 929 | var
 | 
|---|
| 930 |   FName: PWideChar;
 | 
|---|
| 931 |   Buffer: array[0..MAX_PATH - 1] of WideChar;
 | 
|---|
| 932 | begin
 | 
|---|
| 933 |   SetString(Result, Buffer, Tnt_GetFullPathNameW(PWideChar(FileName), MAX_PATH, Buffer, FName));
 | 
|---|
| 934 | end;
 | 
|---|
| 935 | 
 | 
|---|
| 936 | function WideExtractShortPathName(const FileName: WideString): WideString;
 | 
|---|
| 937 | var
 | 
|---|
| 938 |   Buffer: array[0..MAX_PATH - 1] of WideChar;
 | 
|---|
| 939 | begin
 | 
|---|
| 940 |   SetString(Result, Buffer, Tnt_GetShortPathNameW(PWideChar(FileName), Buffer, MAX_PATH));
 | 
|---|
| 941 | end;
 | 
|---|
| 942 | 
 | 
|---|
| 943 | function WideFileCreate(const FileName: WideString): Integer;
 | 
|---|
| 944 | begin
 | 
|---|
| 945 |   Result := Integer(Tnt_CreateFileW(PWideChar(FileName), GENERIC_READ or GENERIC_WRITE,
 | 
|---|
| 946 |     0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0))
 | 
|---|
| 947 | end;
 | 
|---|
| 948 | 
 | 
|---|
| 949 | function WideFileOpen(const FileName: WideString; Mode: LongWord): Integer;
 | 
|---|
| 950 | const
 | 
|---|
| 951 |   AccessMode: array[0..2] of LongWord = (
 | 
|---|
| 952 |     GENERIC_READ,
 | 
|---|
| 953 |     GENERIC_WRITE,
 | 
|---|
| 954 |     GENERIC_READ or GENERIC_WRITE);
 | 
|---|
| 955 |   ShareMode: array[0..4] of LongWord = (
 | 
|---|
| 956 |     0,
 | 
|---|
| 957 |     0,
 | 
|---|
| 958 |     FILE_SHARE_READ,
 | 
|---|
| 959 |     FILE_SHARE_WRITE,
 | 
|---|
| 960 |     FILE_SHARE_READ or FILE_SHARE_WRITE);
 | 
|---|
| 961 | begin
 | 
|---|
| 962 |   Result := Integer(Tnt_CreateFileW(PWideChar(FileName), AccessMode[Mode and 3],
 | 
|---|
| 963 |     ShareMode[(Mode and $F0) shr 4], nil, OPEN_EXISTING,
 | 
|---|
| 964 |       FILE_ATTRIBUTE_NORMAL, 0));
 | 
|---|
| 965 | end;
 | 
|---|
| 966 | 
 | 
|---|
| 967 | function WideFileAge(const FileName: WideString): Integer;
 | 
|---|
| 968 | var
 | 
|---|
| 969 |   Handle: THandle;
 | 
|---|
| 970 |   FindData: TWin32FindDataW;
 | 
|---|
| 971 |   LocalFileTime: TFileTime;
 | 
|---|
| 972 | begin
 | 
|---|
| 973 |   Handle := Tnt_FindFirstFileW(PWideChar(FileName), FindData);
 | 
|---|
| 974 |   if Handle <> INVALID_HANDLE_VALUE then
 | 
|---|
| 975 |   begin
 | 
|---|
| 976 |     Windows.FindClose(Handle);
 | 
|---|
| 977 |     if (FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
 | 
|---|
| 978 |     begin
 | 
|---|
| 979 |       FileTimeToLocalFileTime(FindData.ftLastWriteTime, LocalFileTime);
 | 
|---|
| 980 |       if FileTimeToDosDateTime(LocalFileTime, LongRec(Result).Hi, LongRec(Result).Lo) then
 | 
|---|
| 981 |         Exit
 | 
|---|
| 982 |     end;
 | 
|---|
| 983 |   end;
 | 
|---|
| 984 |   Result := -1;
 | 
|---|
| 985 | end;
 | 
|---|
| 986 | 
 | 
|---|
| 987 | function WideFileAge(const FileName: WideString; out FileDateTime: TDateTime): Boolean;
 | 
|---|
| 988 | var
 | 
|---|
| 989 |   Handle: THandle;
 | 
|---|
| 990 |   FindData: TWin32FindDataW;
 | 
|---|
| 991 |   LSystemTime: TSystemTime;
 | 
|---|
| 992 |   LocalFileTime: TFileTime;
 | 
|---|
| 993 | begin
 | 
|---|
| 994 |   Result := False;
 | 
|---|
| 995 |   Handle := Tnt_FindFirstFileW(PWideChar(FileName), FindData);
 | 
|---|
| 996 |   if Handle <> INVALID_HANDLE_VALUE then
 | 
|---|
| 997 |   begin
 | 
|---|
| 998 |     Windows.FindClose(Handle);
 | 
|---|
| 999 |     if (FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
 | 
|---|
| 1000 |     begin
 | 
|---|
| 1001 |       Result := True;
 | 
|---|
| 1002 |       FileTimeToLocalFileTime(FindData.ftLastWriteTime, LocalFileTime);
 | 
|---|
| 1003 |       FileTimeToSystemTime(LocalFileTime, LSystemTime);
 | 
|---|
| 1004 |       with LSystemTime do
 | 
|---|
| 1005 |         FileDateTime := EncodeDate(wYear, wMonth, wDay) +
 | 
|---|
| 1006 |           EncodeTime(wHour, wMinute, wSecond, wMilliSeconds);
 | 
|---|
| 1007 |     end;
 | 
|---|
| 1008 |   end;
 | 
|---|
| 1009 | end;
 | 
|---|
| 1010 | 
 | 
|---|
| 1011 | function WideDirectoryExists(const Name: WideString): Boolean;
 | 
|---|
| 1012 | var
 | 
|---|
| 1013 |   Code: Cardinal;
 | 
|---|
| 1014 | begin
 | 
|---|
| 1015 |   Code := WideFileGetAttr(Name);
 | 
|---|
| 1016 |   Result := (Code <> INVALID_FILE_ATTRIBUTES) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
 | 
|---|
| 1017 | end;
 | 
|---|
| 1018 | 
 | 
|---|
| 1019 | function WideFileExists(const Name: WideString): Boolean;
 | 
|---|
| 1020 | var
 | 
|---|
| 1021 |   Handle: THandle;
 | 
|---|
| 1022 |   FindData: TWin32FindDataW;
 | 
|---|
| 1023 | begin
 | 
|---|
| 1024 |   Result := False;
 | 
|---|
| 1025 |   Handle := Tnt_FindFirstFileW(PWideChar(Name), FindData);
 | 
|---|
| 1026 |   if Handle <> INVALID_HANDLE_VALUE then
 | 
|---|
| 1027 |   begin
 | 
|---|
| 1028 |     Windows.FindClose(Handle);
 | 
|---|
| 1029 |     if (FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
 | 
|---|
| 1030 |       Result := True;
 | 
|---|
| 1031 |   end;
 | 
|---|
| 1032 | end;
 | 
|---|
| 1033 | 
 | 
|---|
| 1034 | function WideFileGetAttr(const FileName: WideString): Cardinal;
 | 
|---|
| 1035 | begin
 | 
|---|
| 1036 |   Result := Tnt_GetFileAttributesW(PWideChar(FileName));
 | 
|---|
| 1037 | end;
 | 
|---|
| 1038 | 
 | 
|---|
| 1039 | function WideFileSetAttr(const FileName: WideString; Attr: Integer): Boolean;
 | 
|---|
| 1040 | begin
 | 
|---|
| 1041 |   Result := Tnt_SetFileAttributesW(PWideChar(FileName), Attr)
 | 
|---|
| 1042 | end;
 | 
|---|
| 1043 | 
 | 
|---|
| 1044 | function WideFileIsReadOnly(const FileName: WideString): Boolean;
 | 
|---|
| 1045 | begin
 | 
|---|
| 1046 |   Result := (Tnt_GetFileAttributesW(PWideChar(FileName)) and faReadOnly) <> 0;
 | 
|---|
| 1047 | end;
 | 
|---|
| 1048 | 
 | 
|---|
| 1049 | function WideFileSetReadOnly(const FileName: WideString; ReadOnly: Boolean): Boolean;
 | 
|---|
| 1050 | var
 | 
|---|
| 1051 |   Flags: Integer;
 | 
|---|
| 1052 | begin
 | 
|---|
| 1053 |   Result := False;
 | 
|---|
| 1054 |   Flags := Tnt_GetFileAttributesW(PWideChar(FileName));
 | 
|---|
| 1055 |   if Flags = -1 then Exit;
 | 
|---|
| 1056 |   if ReadOnly then
 | 
|---|
| 1057 |     Flags := Flags or faReadOnly
 | 
|---|
| 1058 |   else
 | 
|---|
| 1059 |     Flags := Flags and not faReadOnly;
 | 
|---|
| 1060 |   Result := Tnt_SetFileAttributesW(PWideChar(FileName), Flags);
 | 
|---|
| 1061 | end;
 | 
|---|
| 1062 | 
 | 
|---|
| 1063 | function WideForceDirectories(Dir: WideString): Boolean;
 | 
|---|
| 1064 | begin
 | 
|---|
| 1065 |   Result := True;
 | 
|---|
| 1066 |   if Length(Dir) = 0 then
 | 
|---|
| 1067 |     raise ETntGeneralError.Create(SCannotCreateDir);
 | 
|---|
| 1068 |   Dir := WideExcludeTrailingBackslash(Dir);
 | 
|---|
| 1069 |   if (Length(Dir) < 3) or WideDirectoryExists(Dir)
 | 
|---|
| 1070 |     or (WideExtractFilePath(Dir) = Dir) then Exit; // avoid 'xyz:\' problem.
 | 
|---|
| 1071 |   Result := WideForceDirectories(WideExtractFilePath(Dir));
 | 
|---|
| 1072 |   if Result then
 | 
|---|
| 1073 |     Result := Tnt_CreateDirectoryW(PWideChar(Dir), nil)
 | 
|---|
| 1074 | end;
 | 
|---|
| 1075 | 
 | 
|---|
| 1076 | function WideFileSearch(const Name, DirList: WideString): WideString;
 | 
|---|
| 1077 | var
 | 
|---|
| 1078 |   I, P, L: Integer;
 | 
|---|
| 1079 |   C: WideChar;
 | 
|---|
| 1080 | begin
 | 
|---|
| 1081 |   Result := Name;
 | 
|---|
| 1082 |   P := 1;
 | 
|---|
| 1083 |   L := Length(DirList);
 | 
|---|
| 1084 |   while True do
 | 
|---|
| 1085 |   begin
 | 
|---|
| 1086 |     if WideFileExists(Result) then Exit;
 | 
|---|
| 1087 |     while (P <= L) and (DirList[P] = PathSep) do Inc(P);
 | 
|---|
| 1088 |     if P > L then Break;
 | 
|---|
| 1089 |     I := P;
 | 
|---|
| 1090 |     while (P <= L) and (DirList[P] <> PathSep) do
 | 
|---|
| 1091 |       Inc(P);
 | 
|---|
| 1092 |     Result := Copy(DirList, I, P - I);
 | 
|---|
| 1093 |     C := TntWideLastChar(Result);
 | 
|---|
| 1094 |     if (C <> DriveDelim) and (C <> PathDelim) then
 | 
|---|
| 1095 |       Result := Result + PathDelim;
 | 
|---|
| 1096 |     Result := Result + Name;
 | 
|---|
| 1097 |   end;
 | 
|---|
| 1098 |   Result := '';
 | 
|---|
| 1099 | end;
 | 
|---|
| 1100 | 
 | 
|---|
| 1101 | function WideRenameFile(const OldName, NewName: WideString): Boolean;
 | 
|---|
| 1102 | begin
 | 
|---|
| 1103 |   Result := Tnt_MoveFileW(PWideChar(OldName), PWideChar(NewName))
 | 
|---|
| 1104 | end;
 | 
|---|
| 1105 | 
 | 
|---|
| 1106 | function WideDeleteFile(const FileName: WideString): Boolean;
 | 
|---|
| 1107 | begin
 | 
|---|
| 1108 |   Result := Tnt_DeleteFileW(PWideChar(FileName))
 | 
|---|
| 1109 | end;
 | 
|---|
| 1110 | 
 | 
|---|
| 1111 | function WideCopyFile(FromFile, ToFile: WideString; FailIfExists: Boolean): Boolean;
 | 
|---|
| 1112 | begin
 | 
|---|
| 1113 |   Result := Tnt_CopyFileW(PWideChar(FromFile), PWideChar(ToFile), FailIfExists)
 | 
|---|
| 1114 | end;
 | 
|---|
| 1115 | 
 | 
|---|
| 1116 | function _WideFindMatchingFile(var F: TSearchRecW): Integer;
 | 
|---|
| 1117 | var
 | 
|---|
| 1118 |   LocalFileTime: TFileTime;
 | 
|---|
| 1119 | begin
 | 
|---|
| 1120 |   with F do
 | 
|---|
| 1121 |   begin
 | 
|---|
| 1122 |     while FindData.dwFileAttributes and ExcludeAttr <> 0 do
 | 
|---|
| 1123 |       if not Tnt_FindNextFileW(FindHandle, FindData) then
 | 
|---|
| 1124 |       begin
 | 
|---|
| 1125 |         Result := GetLastError;
 | 
|---|
| 1126 |         Exit;
 | 
|---|
| 1127 |       end;
 | 
|---|
| 1128 |     FileTimeToLocalFileTime(FindData.ftLastWriteTime, LocalFileTime);
 | 
|---|
| 1129 |     FileTimeToDosDateTime(LocalFileTime, LongRec(Time).Hi, LongRec(Time).Lo);
 | 
|---|
| 1130 |     Size := (Int64(FindData.nFileSizeHigh) shl 32) + FindData.nFileSizeLow;
 | 
|---|
| 1131 |     Attr := FindData.dwFileAttributes;
 | 
|---|
| 1132 |     Name := FindData.cFileName;
 | 
|---|
| 1133 |   end;
 | 
|---|
| 1134 |   Result := 0;
 | 
|---|
| 1135 | end;
 | 
|---|
| 1136 | 
 | 
|---|
| 1137 | function WideFindFirst(const Path: WideString; Attr: Integer; var F: TSearchRecW): Integer;
 | 
|---|
| 1138 | const
 | 
|---|
| 1139 |   faSpecial = faHidden or faSysFile {$IFNDEF COMPILER_9_UP} or faVolumeID {$ENDIF} or faDirectory;
 | 
|---|
| 1140 | begin
 | 
|---|
| 1141 |   F.ExcludeAttr := not Attr and faSpecial;
 | 
|---|
| 1142 |   F.FindHandle := Tnt_FindFirstFileW(PWideChar(Path), F.FindData);
 | 
|---|
| 1143 |   if F.FindHandle <> INVALID_HANDLE_VALUE then
 | 
|---|
| 1144 |   begin
 | 
|---|
| 1145 |     Result := _WideFindMatchingFile(F);
 | 
|---|
| 1146 |     if Result <> 0 then WideFindClose(F);
 | 
|---|
| 1147 |   end else
 | 
|---|
| 1148 |     Result := GetLastError;
 | 
|---|
| 1149 | end;
 | 
|---|
| 1150 | 
 | 
|---|
| 1151 | function WideFindNext(var F: TSearchRecW): Integer;
 | 
|---|
| 1152 | begin
 | 
|---|
| 1153 |   if Tnt_FindNextFileW(F.FindHandle, F.FindData) then
 | 
|---|
| 1154 |     Result := _WideFindMatchingFile(F) else
 | 
|---|
| 1155 |     Result := GetLastError;
 | 
|---|
| 1156 | end;
 | 
|---|
| 1157 | 
 | 
|---|
| 1158 | procedure WideFindClose(var F: TSearchRecW);
 | 
|---|
| 1159 | begin
 | 
|---|
| 1160 |   if F.FindHandle <> INVALID_HANDLE_VALUE then
 | 
|---|
| 1161 |   begin
 | 
|---|
| 1162 |     Windows.FindClose(F.FindHandle);
 | 
|---|
| 1163 |     F.FindHandle := INVALID_HANDLE_VALUE;
 | 
|---|
| 1164 |   end;
 | 
|---|
| 1165 | end;
 | 
|---|
| 1166 | 
 | 
|---|
| 1167 | function WideCreateDir(const Dir: WideString): Boolean;
 | 
|---|
| 1168 | begin
 | 
|---|
| 1169 |   Result := Tnt_CreateDirectoryW(PWideChar(Dir), nil);
 | 
|---|
| 1170 | end;
 | 
|---|
| 1171 | 
 | 
|---|
| 1172 | function WideRemoveDir(const Dir: WideString): Boolean;
 | 
|---|
| 1173 | begin
 | 
|---|
| 1174 |   Result := Tnt_RemoveDirectoryW(PWideChar(Dir));
 | 
|---|
| 1175 | end;
 | 
|---|
| 1176 | 
 | 
|---|
| 1177 | function WideGetCurrentDir: WideString;
 | 
|---|
| 1178 | begin
 | 
|---|
| 1179 |   SetLength(Result, MAX_PATH);
 | 
|---|
| 1180 |   Tnt_GetCurrentDirectoryW(MAX_PATH, PWideChar(Result));
 | 
|---|
| 1181 |   Result := PWideChar(Result);
 | 
|---|
| 1182 | end;
 | 
|---|
| 1183 | 
 | 
|---|
| 1184 | function WideSetCurrentDir(const Dir: WideString): Boolean;
 | 
|---|
| 1185 | begin
 | 
|---|
| 1186 |   Result := Tnt_SetCurrentDirectoryW(PWideChar(Dir));
 | 
|---|
| 1187 | end;
 | 
|---|
| 1188 | 
 | 
|---|
| 1189 | //=============================================================================================
 | 
|---|
| 1190 | //==  DATE/TIME STRING PARSING ================================================================
 | 
|---|
| 1191 | //=============================================================================================
 | 
|---|
| 1192 | 
 | 
|---|
| 1193 | function _IntTryStrToDateTime(Str: WideString; Flags: Integer; out DateTime: TDateTime): HResult;
 | 
|---|
| 1194 | begin
 | 
|---|
| 1195 |   Result := VarDateFromStr(Str, GetThreadLocale, Flags, Double(DateTime));
 | 
|---|
| 1196 |   if (not Succeeded(Result)) then begin
 | 
|---|
| 1197 |     if (Flags = VAR_TIMEVALUEONLY)
 | 
|---|
| 1198 |     and SysUtils.TryStrToTime{TNT-ALLOW TryStrToTime}(Str, DateTime) then
 | 
|---|
| 1199 |       Result := S_OK // SysUtils seems confident (works for date = "dd.MM.yy" and time = "H.mm.ss")
 | 
|---|
| 1200 |     else if (Flags = VAR_DATEVALUEONLY)
 | 
|---|
| 1201 |     and SysUtils.TryStrToDate{TNT-ALLOW TryStrToDate}(Str, DateTime) then
 | 
|---|
| 1202 |       Result := S_OK // SysUtils seems confident
 | 
|---|
| 1203 |     else if (Flags = 0)
 | 
|---|
| 1204 |     and SysUtils.TryStrToDateTime{TNT-ALLOW TryStrToDateTime}(Str, DateTime) then
 | 
|---|
| 1205 |       Result := S_OK // SysUtils seems confident
 | 
|---|
| 1206 |   end;
 | 
|---|
| 1207 | end;
 | 
|---|
| 1208 | 
 | 
|---|
| 1209 | function TntTryStrToDateTime(Str: WideString; out DateTime: TDateTime): Boolean;
 | 
|---|
| 1210 | begin
 | 
|---|
| 1211 |   Result := Succeeded(_IntTryStrToDateTime(Str, 0, DateTime));
 | 
|---|
| 1212 | end;
 | 
|---|
| 1213 | 
 | 
|---|
| 1214 | function TntTryStrToDate(Str: WideString; out DateTime: TDateTime): Boolean;
 | 
|---|
| 1215 | begin
 | 
|---|
| 1216 |   Result := Succeeded(_IntTryStrToDateTime(Str, VAR_DATEVALUEONLY, DateTime));
 | 
|---|
| 1217 | end;
 | 
|---|
| 1218 | 
 | 
|---|
| 1219 | function TntTryStrToTime(Str: WideString; out DateTime: TDateTime): Boolean;
 | 
|---|
| 1220 | begin
 | 
|---|
| 1221 |   Result := Succeeded(_IntTryStrToDateTime(Str, VAR_TIMEVALUEONLY, DateTime));
 | 
|---|
| 1222 | end;
 | 
|---|
| 1223 | 
 | 
|---|
| 1224 | function ValidDateTimeStr(Str: WideString): Boolean;
 | 
|---|
| 1225 | var
 | 
|---|
| 1226 |   Temp: TDateTime;
 | 
|---|
| 1227 | begin
 | 
|---|
| 1228 |   Result := Succeeded(_IntTryStrToDateTime(Str, 0, Temp));
 | 
|---|
| 1229 | end;
 | 
|---|
| 1230 | 
 | 
|---|
| 1231 | function ValidDateStr(Str: WideString): Boolean;
 | 
|---|
| 1232 | var
 | 
|---|
| 1233 |   Temp: TDateTime;
 | 
|---|
| 1234 | begin
 | 
|---|
| 1235 |   Result := Succeeded(_IntTryStrToDateTime(Str, VAR_DATEVALUEONLY, Temp));
 | 
|---|
| 1236 | end;
 | 
|---|
| 1237 | 
 | 
|---|
| 1238 | function ValidTimeStr(Str: WideString): Boolean;
 | 
|---|
| 1239 | var
 | 
|---|
| 1240 |   Temp: TDateTime;
 | 
|---|
| 1241 | begin
 | 
|---|
| 1242 |   Result := Succeeded(_IntTryStrToDateTime(Str, VAR_TIMEVALUEONLY, Temp));
 | 
|---|
| 1243 | end;
 | 
|---|
| 1244 | 
 | 
|---|
| 1245 | function TntStrToDateTimeDef(Str: WideString; Default: TDateTime): TDateTime;
 | 
|---|
| 1246 | begin
 | 
|---|
| 1247 |   if not TntTryStrToDateTime(Str, Result) then
 | 
|---|
| 1248 |     Result := Default;
 | 
|---|
| 1249 | end;
 | 
|---|
| 1250 | 
 | 
|---|
| 1251 | function TntStrToDateDef(Str: WideString; Default: TDateTime): TDateTime;
 | 
|---|
| 1252 | begin
 | 
|---|
| 1253 |   if not TntTryStrToDate(Str, Result) then
 | 
|---|
| 1254 |     Result := Default;
 | 
|---|
| 1255 | end;
 | 
|---|
| 1256 | 
 | 
|---|
| 1257 | function TntStrToTimeDef(Str: WideString; Default: TDateTime): TDateTime;
 | 
|---|
| 1258 | begin
 | 
|---|
| 1259 |   if not TntTryStrToTime(Str, Result) then
 | 
|---|
| 1260 |     Result := Default;
 | 
|---|
| 1261 | end;
 | 
|---|
| 1262 | 
 | 
|---|
| 1263 | function _IntStrToDateTime(Str: WideString; Flags: Integer; ErrorFormatStr: WideString): TDateTime;
 | 
|---|
| 1264 | begin
 | 
|---|
| 1265 |   try
 | 
|---|
| 1266 |     OleCheck(_IntTryStrToDateTime(Str, Flags, Result));
 | 
|---|
| 1267 |   except
 | 
|---|
| 1268 |     on E: Exception do begin
 | 
|---|
| 1269 |       E.Message := E.Message + CRLF + WideFormat(ErrorFormatStr, [Str]);
 | 
|---|
| 1270 |       raise EConvertError.Create(E.Message);
 | 
|---|
| 1271 |     end;
 | 
|---|
| 1272 |   end;
 | 
|---|
| 1273 | end;
 | 
|---|
| 1274 | 
 | 
|---|
| 1275 | function TntStrToDateTime(Str: WideString): TDateTime;
 | 
|---|
| 1276 | begin
 | 
|---|
| 1277 |   Result := _IntStrToDateTime(Str, 0, SInvalidDateTime);
 | 
|---|
| 1278 | end;
 | 
|---|
| 1279 | 
 | 
|---|
| 1280 | function TntStrToDate(Str: WideString): TDateTime;
 | 
|---|
| 1281 | begin
 | 
|---|
| 1282 |   Result := _IntStrToDateTime(Str, VAR_DATEVALUEONLY, SInvalidDate);
 | 
|---|
| 1283 | end;
 | 
|---|
| 1284 | 
 | 
|---|
| 1285 | function TntStrToTime(Str: WideString): TDateTime;
 | 
|---|
| 1286 | begin
 | 
|---|
| 1287 |   Result := _IntStrToDateTime(Str, VAR_TIMEVALUEONLY, SInvalidTime);
 | 
|---|
| 1288 | end;
 | 
|---|
| 1289 | 
 | 
|---|
| 1290 | //=============================================================================================
 | 
|---|
| 1291 | //==  CURRENCY STRING PARSING =================================================================
 | 
|---|
| 1292 | //=============================================================================================
 | 
|---|
| 1293 | 
 | 
|---|
| 1294 | function TntCurrToStr(Value: Currency; lpFormat: PCurrencyFmtW = nil): WideString;
 | 
|---|
| 1295 | const
 | 
|---|
| 1296 |   MAX_BUFF_SIZE = 64; // can a currency string actually be larger?
 | 
|---|
| 1297 | var
 | 
|---|
| 1298 |   ValueStr: WideString;
 | 
|---|
| 1299 | begin
 | 
|---|
| 1300 |   // format lpValue using ENG-US settings
 | 
|---|
| 1301 |   ValueStr := ENG_US_FloatToStr(Value);
 | 
|---|
| 1302 |   // get currency format
 | 
|---|
| 1303 |   SetLength(Result, MAX_BUFF_SIZE);
 | 
|---|
| 1304 |   if 0 = Tnt_GetCurrencyFormatW(GetThreadLocale, 0, PWideChar(ValueStr),
 | 
|---|
| 1305 |     lpFormat, PWideChar(Result), Length(Result))
 | 
|---|
| 1306 |   then begin
 | 
|---|
| 1307 |     RaiseLastOSError;
 | 
|---|
| 1308 |   end;
 | 
|---|
| 1309 |   Result := PWideChar(Result);
 | 
|---|
| 1310 | end;
 | 
|---|
| 1311 | 
 | 
|---|
| 1312 | function TntStrToCurr(const S: WideString): Currency;
 | 
|---|
| 1313 | begin
 | 
|---|
| 1314 |   try
 | 
|---|
| 1315 |     OleCheck(VarCyFromStr(S, GetThreadLocale, 0, Result));
 | 
|---|
| 1316 |   except
 | 
|---|
| 1317 |     on E: Exception do begin
 | 
|---|
| 1318 |       E.Message := E.Message + CRLF + WideFormat(SInvalidCurrency, [S]);
 | 
|---|
| 1319 |       raise EConvertError.Create(E.Message);
 | 
|---|
| 1320 |     end;
 | 
|---|
| 1321 |   end;
 | 
|---|
| 1322 | end;
 | 
|---|
| 1323 | 
 | 
|---|
| 1324 | function ValidCurrencyStr(const S: WideString): Boolean;
 | 
|---|
| 1325 | var
 | 
|---|
| 1326 |   Dummy: Currency;
 | 
|---|
| 1327 | begin
 | 
|---|
| 1328 |   Result := Succeeded(VarCyFromStr(S, GetThreadLocale, 0, Dummy));
 | 
|---|
| 1329 | end;
 | 
|---|
| 1330 | 
 | 
|---|
| 1331 | function TntStrToCurrDef(const S: WideString; const Default: Currency): Currency;
 | 
|---|
| 1332 | begin
 | 
|---|
| 1333 |   if not Succeeded(VarCyFromStr(S, GetThreadLocale, 0, Result)) then
 | 
|---|
| 1334 |     Result := Default;
 | 
|---|
| 1335 | end;
 | 
|---|
| 1336 | 
 | 
|---|
| 1337 | threadvar
 | 
|---|
| 1338 |   Currency_DecimalSep: WideString;
 | 
|---|
| 1339 |   Currency_ThousandSep: WideString;
 | 
|---|
| 1340 |   Currency_CurrencySymbol: WideString;
 | 
|---|
| 1341 | 
 | 
|---|
| 1342 | function GetDefaultCurrencyFmt: TCurrencyFmtW;
 | 
|---|
| 1343 | begin
 | 
|---|
| 1344 |   ZeroMemory(@Result, SizeOf(Result));
 | 
|---|
| 1345 |   Result.NumDigits := StrToIntDef(WideGetLocaleStr(GetThreadLocale, LOCALE_ICURRDIGITS, '2'), 2);
 | 
|---|
| 1346 |   Result.LeadingZero := StrToIntDef(WideGetLocaleStr(GetThreadLocale, LOCALE_ILZERO, '1'), 1);
 | 
|---|
| 1347 |   Result.Grouping := StrToIntDef(Copy(WideGetLocaleStr(GetThreadLocale, LOCALE_SMONGROUPING, '3;0'), 1, 1), 3);
 | 
|---|
| 1348 |   Currency_DecimalSep := WideGetLocaleStr(GetThreadLocale, LOCALE_SMONDECIMALSEP, '.');
 | 
|---|
| 1349 |   Result.lpDecimalSep := PWideChar(Currency_DecimalSep);
 | 
|---|
| 1350 |   Currency_ThousandSep := WideGetLocaleStr(GetThreadLocale, LOCALE_SMONTHOUSANDSEP, ',');
 | 
|---|
| 1351 |   Result.lpThousandSep := PWideChar(Currency_ThousandSep);
 | 
|---|
| 1352 |   Result.NegativeOrder := StrToIntDef(WideGetLocaleStr(GetThreadLocale, LOCALE_INEGCURR, '0'), 0);
 | 
|---|
| 1353 |   Result.PositiveOrder := StrToIntDef(WideGetLocaleStr(GetThreadLocale, LOCALE_ICURRENCY, '0'), 0);
 | 
|---|
| 1354 |   Currency_CurrencySymbol := WideGetLocaleStr(GetThreadLocale, LOCALE_SCURRENCY, '');
 | 
|---|
| 1355 |   Result.lpCurrencySymbol := PWideChar(Currency_CurrencySymbol);
 | 
|---|
| 1356 | end;
 | 
|---|
| 1357 | 
 | 
|---|
| 1358 | //=============================================================================================
 | 
|---|
| 1359 | 
 | 
|---|
| 1360 | function WideGetLocaleStr(LocaleID: LCID; LocaleType: Integer; const Default: WideString): WideString;
 | 
|---|
| 1361 | var
 | 
|---|
| 1362 |   L: Integer;
 | 
|---|
| 1363 | begin
 | 
|---|
| 1364 |   if (not Win32PlatformIsUnicode) then
 | 
|---|
| 1365 |     Result := GetLocaleStr{TNT-ALLOW GetLocaleStr}(LocaleID, LocaleType, Default)
 | 
|---|
| 1366 |   else begin
 | 
|---|
| 1367 |     SetLength(Result, 255);
 | 
|---|
| 1368 |     L := GetLocaleInfoW(LocaleID, LocaleType, PWideChar(Result), Length(Result));
 | 
|---|
| 1369 |     if L > 0 then
 | 
|---|
| 1370 |       SetLength(Result, L - 1)
 | 
|---|
| 1371 |     else
 | 
|---|
| 1372 |       Result := Default;
 | 
|---|
| 1373 |   end;
 | 
|---|
| 1374 | end;
 | 
|---|
| 1375 | 
 | 
|---|
| 1376 | function WideSysErrorMessage(ErrorCode: Integer): WideString;
 | 
|---|
| 1377 | begin
 | 
|---|
| 1378 |   Result := WideLibraryErrorMessage('system', 0, ErrorCode);
 | 
|---|
| 1379 | end;
 | 
|---|
| 1380 | 
 | 
|---|
| 1381 | function WideLibraryErrorMessage(const LibName: WideString; Dll: THandle; ErrorCode: Integer): WideString;
 | 
|---|
| 1382 | var
 | 
|---|
| 1383 |   Len: Integer;
 | 
|---|
| 1384 |   AnsiResult: AnsiString;
 | 
|---|
| 1385 |   Flags: Cardinal;
 | 
|---|
| 1386 | begin
 | 
|---|
| 1387 |   Flags := FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_IGNORE_INSERTS or FORMAT_MESSAGE_ARGUMENT_ARRAY;
 | 
|---|
| 1388 |   if Dll <> 0 then
 | 
|---|
| 1389 |     Flags := Flags or FORMAT_MESSAGE_FROM_HMODULE;
 | 
|---|
| 1390 |   if Win32PlatformIsUnicode then begin
 | 
|---|
| 1391 |     SetLength(Result, 256);
 | 
|---|
| 1392 |     Len := FormatMessageW(Flags, Pointer(Dll), ErrorCode, 0, PWideChar(Result), Length(Result), nil);
 | 
|---|
| 1393 |     SetLength(Result, Len);
 | 
|---|
| 1394 |   end else begin
 | 
|---|
| 1395 |     SetLength(AnsiResult, 256);
 | 
|---|
| 1396 |     Len := FormatMessageA(Flags, Pointer(Dll), ErrorCode, 0, PAnsiChar(AnsiResult), Length(AnsiResult), nil);
 | 
|---|
| 1397 |     SetLength(AnsiResult, Len);
 | 
|---|
| 1398 |     Result := AnsiResult;
 | 
|---|
| 1399 |   end;
 | 
|---|
| 1400 |   if Trim(Result) = '' then
 | 
|---|
| 1401 |     Result := WideFormat('Unspecified error (%d) from %s.', [ErrorCode, LibName]);
 | 
|---|
| 1402 | end;
 | 
|---|
| 1403 | 
 | 
|---|
| 1404 | {$IFNDEF COMPILER_7_UP}
 | 
|---|
| 1405 | function CheckWin32Version(AMajor: Integer; AMinor: Integer = 0): Boolean;
 | 
|---|
| 1406 | begin
 | 
|---|
| 1407 |   Result := (Win32MajorVersion > AMajor) or
 | 
|---|
| 1408 |             ((Win32MajorVersion = AMajor) and
 | 
|---|
| 1409 |              (Win32MinorVersion >= AMinor));
 | 
|---|
| 1410 | end;
 | 
|---|
| 1411 | {$ENDIF}
 | 
|---|
| 1412 | 
 | 
|---|
| 1413 | function WinCheckH(RetVal: Cardinal): Cardinal;
 | 
|---|
| 1414 | begin
 | 
|---|
| 1415 |   if RetVal = 0 then RaiseLastOSError;
 | 
|---|
| 1416 |   Result := RetVal;
 | 
|---|
| 1417 | end;
 | 
|---|
| 1418 | 
 | 
|---|
| 1419 | function WinCheckFileH(RetVal: Cardinal): Cardinal;
 | 
|---|
| 1420 | begin
 | 
|---|
| 1421 |   if RetVal = INVALID_HANDLE_VALUE then RaiseLastOSError;
 | 
|---|
| 1422 |   Result := RetVal;
 | 
|---|
| 1423 | end;
 | 
|---|
| 1424 | 
 | 
|---|
| 1425 | function WinCheckP(RetVal: Pointer): Pointer;
 | 
|---|
| 1426 | begin
 | 
|---|
| 1427 |   if RetVal = nil then RaiseLastOSError;
 | 
|---|
| 1428 |   Result := RetVal;
 | 
|---|
| 1429 | end;
 | 
|---|
| 1430 | 
 | 
|---|
| 1431 | function WideGetModuleFileName(Instance: HModule): WideString;
 | 
|---|
| 1432 | begin
 | 
|---|
| 1433 |   SetLength(Result, MAX_PATH);
 | 
|---|
| 1434 |   WinCheckH(Tnt_GetModuleFileNameW(Instance, PWideChar(Result), Length(Result)));
 | 
|---|
| 1435 |   Result := PWideChar(Result)
 | 
|---|
| 1436 | end;
 | 
|---|
| 1437 | 
 | 
|---|
| 1438 | function WideSafeLoadLibrary(const Filename: Widestring; ErrorMode: UINT): HMODULE;
 | 
|---|
| 1439 | var
 | 
|---|
| 1440 |   OldMode: UINT;
 | 
|---|
| 1441 |   FPUControlWord: Word;
 | 
|---|
| 1442 | begin
 | 
|---|
| 1443 |   OldMode := SetErrorMode(ErrorMode);
 | 
|---|
| 1444 |   try
 | 
|---|
| 1445 |     asm
 | 
|---|
| 1446 |       FNSTCW  FPUControlWord
 | 
|---|
| 1447 |     end;
 | 
|---|
| 1448 |     try
 | 
|---|
| 1449 |       Result := Tnt_LoadLibraryW(PWideChar(Filename));
 | 
|---|
| 1450 |     finally
 | 
|---|
| 1451 |       asm
 | 
|---|
| 1452 |         FNCLEX
 | 
|---|
| 1453 |         FLDCW FPUControlWord
 | 
|---|
| 1454 |       end;
 | 
|---|
| 1455 |     end;
 | 
|---|
| 1456 |   finally
 | 
|---|
| 1457 |     SetErrorMode(OldMode);
 | 
|---|
| 1458 |   end;
 | 
|---|
| 1459 | end;
 | 
|---|
| 1460 | 
 | 
|---|
| 1461 | function WideLoadPackage(const Name: Widestring): HMODULE;
 | 
|---|
| 1462 | begin
 | 
|---|
| 1463 |   Result := WideSafeLoadLibrary(Name);
 | 
|---|
| 1464 |   if Result = 0 then
 | 
|---|
| 1465 |   begin
 | 
|---|
| 1466 |     raise EPackageError.CreateFmt(sErrorLoadingPackage, [Name, WideSysErrorMessage(GetLastError)]);
 | 
|---|
| 1467 |   end;
 | 
|---|
| 1468 |   try
 | 
|---|
| 1469 |     InitializePackage(Result);
 | 
|---|
| 1470 |   except
 | 
|---|
| 1471 |     FreeLibrary(Result);
 | 
|---|
| 1472 |     raise;
 | 
|---|
| 1473 |   end;
 | 
|---|
| 1474 | end;
 | 
|---|
| 1475 | 
 | 
|---|
| 1476 | function _WideCharType(WC: WideChar; dwInfoType: Cardinal): Word;
 | 
|---|
| 1477 | begin
 | 
|---|
| 1478 |   Win32Check(Tnt_GetStringTypeExW(GetThreadLocale, dwInfoType, PWideChar(@WC), 1, Result))
 | 
|---|
| 1479 | end;
 | 
|---|
| 1480 | 
 | 
|---|
| 1481 | function IsWideCharUpper(WC: WideChar): Boolean;
 | 
|---|
| 1482 | begin
 | 
|---|
| 1483 |   Result := (_WideCharType(WC, CT_CTYPE1) and C1_UPPER) <> 0;
 | 
|---|
| 1484 | end;
 | 
|---|
| 1485 | 
 | 
|---|
| 1486 | function IsWideCharLower(WC: WideChar): Boolean;
 | 
|---|
| 1487 | begin
 | 
|---|
| 1488 |   Result := (_WideCharType(WC, CT_CTYPE1) and C1_LOWER) <> 0;
 | 
|---|
| 1489 | end;
 | 
|---|
| 1490 | 
 | 
|---|
| 1491 | function IsWideCharDigit(WC: WideChar): Boolean;
 | 
|---|
| 1492 | begin
 | 
|---|
| 1493 |   Result := (_WideCharType(WC, CT_CTYPE1) and C1_DIGIT) <> 0;
 | 
|---|
| 1494 | end;
 | 
|---|
| 1495 | 
 | 
|---|
| 1496 | function IsWideCharSpace(WC: WideChar): Boolean;
 | 
|---|
| 1497 | begin
 | 
|---|
| 1498 |   Result := (_WideCharType(WC, CT_CTYPE1) and C1_SPACE) <> 0;
 | 
|---|
| 1499 | end;
 | 
|---|
| 1500 | 
 | 
|---|
| 1501 | function IsWideCharPunct(WC: WideChar): Boolean;
 | 
|---|
| 1502 | begin
 | 
|---|
| 1503 |   Result := (_WideCharType(WC, CT_CTYPE1) and C1_PUNCT) <> 0;
 | 
|---|
| 1504 | end;
 | 
|---|
| 1505 | 
 | 
|---|
| 1506 | function IsWideCharCntrl(WC: WideChar): Boolean;
 | 
|---|
| 1507 | begin
 | 
|---|
| 1508 |   Result := (_WideCharType(WC, CT_CTYPE1) and C1_CNTRL) <> 0;
 | 
|---|
| 1509 | end;
 | 
|---|
| 1510 | 
 | 
|---|
| 1511 | function IsWideCharBlank(WC: WideChar): Boolean;
 | 
|---|
| 1512 | begin
 | 
|---|
| 1513 |   Result := (_WideCharType(WC, CT_CTYPE1) and C1_BLANK) <> 0;
 | 
|---|
| 1514 | end;
 | 
|---|
| 1515 | 
 | 
|---|
| 1516 | function IsWideCharXDigit(WC: WideChar): Boolean;
 | 
|---|
| 1517 | begin
 | 
|---|
| 1518 |   Result := (_WideCharType(WC, CT_CTYPE1) and C1_XDIGIT) <> 0;
 | 
|---|
| 1519 | end;
 | 
|---|
| 1520 | 
 | 
|---|
| 1521 | function IsWideCharAlpha(WC: WideChar): Boolean;
 | 
|---|
| 1522 | begin
 | 
|---|
| 1523 |   Result := (_WideCharType(WC, CT_CTYPE1) and C1_ALPHA) <> 0;
 | 
|---|
| 1524 | end;
 | 
|---|
| 1525 | 
 | 
|---|
| 1526 | function IsWideCharAlphaNumeric(WC: WideChar): Boolean;
 | 
|---|
| 1527 | begin
 | 
|---|
| 1528 |   Result := (_WideCharType(WC, CT_CTYPE1) and (C1_ALPHA + C1_DIGIT)) <> 0;
 | 
|---|
| 1529 | end;
 | 
|---|
| 1530 | 
 | 
|---|
| 1531 | function WideTextPos(const SubStr, S: WideString): Integer;
 | 
|---|
| 1532 | begin
 | 
|---|
| 1533 |   Result := Pos(Tnt_WideUpperCase(SubStr), Tnt_WideUpperCase(S));
 | 
|---|
| 1534 | end;
 | 
|---|
| 1535 | 
 | 
|---|
| 1536 | function FindDoubleTerminator(P: PWideChar): PWideChar;
 | 
|---|
| 1537 | begin
 | 
|---|
| 1538 |   Result := P;
 | 
|---|
| 1539 |   while True do begin
 | 
|---|
| 1540 |     Result := WStrScan(Result, #0);
 | 
|---|
| 1541 |     Inc(Result);
 | 
|---|
| 1542 |     if Result^ = #0 then begin
 | 
|---|
| 1543 |       Dec(Result);
 | 
|---|
| 1544 |       break;
 | 
|---|
| 1545 |     end;
 | 
|---|
| 1546 |   end;
 | 
|---|
| 1547 | end;
 | 
|---|
| 1548 | 
 | 
|---|
| 1549 | function ExtractStringArrayStr(P: PWideChar): WideString;
 | 
|---|
| 1550 | var
 | 
|---|
| 1551 |   PEnd: PWideChar;
 | 
|---|
| 1552 | begin
 | 
|---|
| 1553 |   PEnd := FindDoubleTerminator(P);
 | 
|---|
| 1554 |   Inc(PEnd, 2); // move past #0#0
 | 
|---|
| 1555 |   SetString(Result, P, PEnd - P);
 | 
|---|
| 1556 | end;
 | 
|---|
| 1557 | 
 | 
|---|
| 1558 | function ExtractStringFromStringArray(var P: PWideChar; Separator: WideChar = #0): WideString;
 | 
|---|
| 1559 | var
 | 
|---|
| 1560 |   Start: PWideChar;
 | 
|---|
| 1561 | begin
 | 
|---|
| 1562 |   Start := P;
 | 
|---|
| 1563 |   P := WStrScan(Start, Separator);
 | 
|---|
| 1564 |   if P = nil then begin
 | 
|---|
| 1565 |     Result := Start;
 | 
|---|
| 1566 |     P := WStrEnd(Start);
 | 
|---|
| 1567 |   end else begin
 | 
|---|
| 1568 |     SetString(Result, Start, P - Start);
 | 
|---|
| 1569 |     Inc(P);
 | 
|---|
| 1570 |   end;
 | 
|---|
| 1571 | end;
 | 
|---|
| 1572 | 
 | 
|---|
| 1573 | function ExtractStringsFromStringArray(P: PWideChar; Separator: WideChar = #0): TWideStringDynArray;
 | 
|---|
| 1574 | const
 | 
|---|
| 1575 |   GROW_COUNT = 256;
 | 
|---|
| 1576 | var
 | 
|---|
| 1577 |   Count: Integer;
 | 
|---|
| 1578 |   Item: WideString;
 | 
|---|
| 1579 | begin
 | 
|---|
| 1580 |   Count := 0;
 | 
|---|
| 1581 |   SetLength(Result, GROW_COUNT);
 | 
|---|
| 1582 |   Item := ExtractStringFromStringArray(P, Separator);
 | 
|---|
| 1583 |   While Item <> '' do begin
 | 
|---|
| 1584 |     if Count > High(Result) then
 | 
|---|
| 1585 |       SetLength(Result, Length(Result) + GROW_COUNT);
 | 
|---|
| 1586 |     Result[Count] := Item;
 | 
|---|
| 1587 |     Inc(Count);
 | 
|---|
| 1588 |     Item := ExtractStringFromStringArray(P, Separator);
 | 
|---|
| 1589 |   end;
 | 
|---|
| 1590 |   SetLength(Result, Count);
 | 
|---|
| 1591 | end;
 | 
|---|
| 1592 | 
 | 
|---|
| 1593 | function IsWideCharMappableToAnsi(const WC: WideChar): Boolean;
 | 
|---|
| 1594 | var
 | 
|---|
| 1595 |   UsedDefaultChar: BOOL;
 | 
|---|
| 1596 | begin
 | 
|---|
| 1597 |   WideCharToMultiByte(DefaultSystemCodePage, 0, PWideChar(@WC), 1, nil, 0, nil, @UsedDefaultChar);
 | 
|---|
| 1598 |   Result := not UsedDefaultChar;
 | 
|---|
| 1599 | end;
 | 
|---|
| 1600 | 
 | 
|---|
| 1601 | function IsWideStringMappableToAnsi(const WS: WideString): Boolean;
 | 
|---|
| 1602 | var
 | 
|---|
| 1603 |   UsedDefaultChar: BOOL;
 | 
|---|
| 1604 | begin
 | 
|---|
| 1605 |   WideCharToMultiByte(DefaultSystemCodePage, 0, PWideChar(WS), Length(WS), nil, 0, nil, @UsedDefaultChar);
 | 
|---|
| 1606 |   Result := not UsedDefaultChar;
 | 
|---|
| 1607 | end;
 | 
|---|
| 1608 | 
 | 
|---|
| 1609 | function IsRTF(const Value: WideString): Boolean;
 | 
|---|
| 1610 | const
 | 
|---|
| 1611 |   RTF_BEGIN_1  = WideString('{\RTF');
 | 
|---|
| 1612 |   RTF_BEGIN_2  = WideString('{URTF');
 | 
|---|
| 1613 | begin
 | 
|---|
| 1614 |   Result := (WideTextPos(RTF_BEGIN_1, Value) = 1)
 | 
|---|
| 1615 |          or (WideTextPos(RTF_BEGIN_2, Value) = 1);
 | 
|---|
| 1616 | end;
 | 
|---|
| 1617 | 
 | 
|---|
| 1618 | {$IFDEF COMPILER_7_UP}
 | 
|---|
| 1619 | var
 | 
|---|
| 1620 |   Cached_ENG_US_FormatSettings: TFormatSettings;
 | 
|---|
| 1621 |   Cached_ENG_US_FormatSettings_Time: Cardinal;
 | 
|---|
| 1622 | 
 | 
|---|
| 1623 | function ENG_US_FormatSettings: TFormatSettings;
 | 
|---|
| 1624 | begin
 | 
|---|
| 1625 |   if Cached_ENG_US_FormatSettings_Time = _SettingChangeTime then
 | 
|---|
| 1626 |     Result := Cached_ENG_US_FormatSettings
 | 
|---|
| 1627 |   else begin
 | 
|---|
| 1628 |     GetLocaleFormatSettings(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)), Result);
 | 
|---|
| 1629 |     Result.DecimalSeparator := '.'; // ignore overrides
 | 
|---|
| 1630 |     Cached_ENG_US_FormatSettings := Result;
 | 
|---|
| 1631 |     Cached_ENG_US_FormatSettings_Time := _SettingChangeTime;
 | 
|---|
| 1632 |   end;
 | 
|---|
| 1633 |  end;
 | 
|---|
| 1634 | 
 | 
|---|
| 1635 | function ENG_US_FloatToStr(Value: Extended): WideString;
 | 
|---|
| 1636 | begin
 | 
|---|
| 1637 |   Result := FloatToStr(Value, ENG_US_FormatSettings);
 | 
|---|
| 1638 | end;
 | 
|---|
| 1639 | 
 | 
|---|
| 1640 | function ENG_US_StrToFloat(const S: WideString): Extended;
 | 
|---|
| 1641 | begin
 | 
|---|
| 1642 |   if not TextToFloat(PAnsiChar(AnsiString(S)), Result, fvExtended, ENG_US_FormatSettings) then
 | 
|---|
| 1643 |     Result := StrToFloat(S); // try using native format
 | 
|---|
| 1644 | end;
 | 
|---|
| 1645 | 
 | 
|---|
| 1646 | {$ELSE}
 | 
|---|
| 1647 | 
 | 
|---|
| 1648 | function ENG_US_FloatToStr(Value: Extended): WideString;
 | 
|---|
| 1649 | var
 | 
|---|
| 1650 |   SaveDecimalSep: AnsiChar;
 | 
|---|
| 1651 | begin
 | 
|---|
| 1652 |   SaveDecimalSep := SysUtils.DecimalSeparator;
 | 
|---|
| 1653 |   try
 | 
|---|
| 1654 |     SysUtils.DecimalSeparator := '.';
 | 
|---|
| 1655 |     Result := FloatToStr(Value);
 | 
|---|
| 1656 |   finally
 | 
|---|
| 1657 |     SysUtils.DecimalSeparator := SaveDecimalSep;
 | 
|---|
| 1658 |   end;
 | 
|---|
| 1659 | end;
 | 
|---|
| 1660 | 
 | 
|---|
| 1661 | function ENG_US_StrToFloat(const S: WideString): Extended;
 | 
|---|
| 1662 | var
 | 
|---|
| 1663 |   SaveDecimalSep: AnsiChar;
 | 
|---|
| 1664 | begin
 | 
|---|
| 1665 |   try
 | 
|---|
| 1666 |     SaveDecimalSep := SysUtils.DecimalSeparator;
 | 
|---|
| 1667 |     try
 | 
|---|
| 1668 |       SysUtils.DecimalSeparator := '.';
 | 
|---|
| 1669 |       Result := StrToFloat(S);
 | 
|---|
| 1670 |     finally
 | 
|---|
| 1671 |       SysUtils.DecimalSeparator := SaveDecimalSep;
 | 
|---|
| 1672 |     end;
 | 
|---|
| 1673 |   except
 | 
|---|
| 1674 |     if SysUtils.DecimalSeparator <> '.' then
 | 
|---|
| 1675 |       Result := StrToFloat(S) // try using native format
 | 
|---|
| 1676 |     else
 | 
|---|
| 1677 |       raise;
 | 
|---|
| 1678 |   end;
 | 
|---|
| 1679 | end;
 | 
|---|
| 1680 | {$ENDIF}
 | 
|---|
| 1681 | 
 | 
|---|
| 1682 | //---------------------------------------------------------------------------------------------
 | 
|---|
| 1683 | //                                 Tnt - Variants
 | 
|---|
| 1684 | //---------------------------------------------------------------------------------------------
 | 
|---|
| 1685 | 
 | 
|---|
| 1686 | initialization
 | 
|---|
| 1687 |   Win32PlatformIsUnicode := (Win32Platform = VER_PLATFORM_WIN32_NT);
 | 
|---|
| 1688 |   Win32PlatformIsXP := ((Win32MajorVersion = 5) and (Win32MinorVersion >= 1))
 | 
|---|
| 1689 |                     or  (Win32MajorVersion > 5);
 | 
|---|
| 1690 |   Win32PlatformIs2003 := ((Win32MajorVersion = 5) and (Win32MinorVersion >= 2))
 | 
|---|
| 1691 |                     or  (Win32MajorVersion > 5);
 | 
|---|
| 1692 |   Win32PlatformIsVista := (Win32MajorVersion >= 6);
 | 
|---|
| 1693 | 
 | 
|---|
| 1694 | finalization
 | 
|---|
| 1695 |   Currency_DecimalSep := ''; {make memory sleuth happy}
 | 
|---|
| 1696 |   Currency_ThousandSep := ''; {make memory sleuth happy}
 | 
|---|
| 1697 |   Currency_CurrencySymbol := ''; {make memory sleuth happy}
 | 
|---|
| 1698 | 
 | 
|---|
| 1699 | end.
 | 
|---|