source: trunk/Packages/Common/Common.pas

Last change on this file was 107, checked in by chronos, 4 months ago
  • Fixed: Full screen mode switching on Windows.
  • Modified: Updated Common package.
File size: 19.3 KB
Line 
1unit Common;
2
3interface
4
5uses
6 {$IFDEF WINDOWS}Windows,{$ENDIF}
7 {$IFDEF UNIX}baseunix,{$ENDIF}
8 Classes, SysUtils, StrUtils, Dialogs, Process, LCLIntf, Graphics,
9 FileUtil, Generics.Collections; //, ShFolder, ShellAPI;
10
11type
12 TArrayOfByte = array of Byte;
13 TExceptionEvent = procedure(Sender: TObject; E: Exception) of object;
14
15 TUserNameFormat = (
16 unfNameUnknown = 0, // Unknown name type.
17 unfNameFullyQualifiedDN = 1, // Fully qualified distinguished name
18 unfNameSamCompatible = 2, // Windows NT® 4.0 account name
19 unfNameDisplay = 3, // A "friendly" display name
20 unfNameUniqueId = 6, // GUID string that the IIDFromString function returns
21 unfNameCanonical = 7, // Complete canonical name
22 unfNameUserPrincipal = 8, // User principal name
23 unfNameCanonicalEx = 9,
24 unfNameServicePrincipal = 10, // Generalized service principal name
25 unfDNSDomainName = 11);
26
27 TFilterMethod = function (FileName: string): Boolean of object;
28 TFileNameMethod = procedure (FileName: string) of object;
29
30var
31 ExceptionHandler: TExceptionEvent;
32 DLLHandle1: HModule;
33
34 {$IFDEF WINDOWS}
35 GetUserNameEx: procedure (NameFormat: DWORD;
36 lpNameBuffer: LPSTR; nSize: PULONG); stdcall;
37 {$ENDIF}
38
39const
40 clLightBlue = TColor($FF8080);
41 clLightGreen = TColor($80FF80);
42 clLightRed = TColor($8080FF);
43
44function AddLeadingZeroes(const aNumber, Length : integer) : string;
45function BinToInt(BinStr: string): Int64;
46function BinToHexString(Source: AnsiString): string;
47//function DelTree(DirName : string): Boolean;
48//function GetSpecialFolderPath(Folder: Integer): string;
49function BCDToInt(Value: Byte): Byte;
50function CompareByteArray(Data1, Data2: TArrayOfByte): Boolean;
51procedure CopyStringArray(Dest: TStringArray; Source: array of string);
52function CombinePaths(Path1, Path2: string): string;
53function ComputerName: string;
54procedure DeleteFiles(APath, AFileSpec: string);
55function EndsWith(Text, What: string): Boolean;
56function Explode(Separator: Char; Data: string): TStringArray;
57procedure ExecuteProgram(Executable: string; Parameters: array of string);
58procedure FileDialogUpdateFilterFileType(FileDialog: TOpenDialog);
59procedure FreeThenNil(var Obj);
60function GetDirCount(Dir: string): Integer;
61function GetUserName: string;
62function GetBitCount(Variable: QWord; MaxIndex: Integer): Integer;
63function GetBit(Variable: QWord; Index: Byte): Boolean;
64function GetStringPart(var Text: string; Separator: string): string;
65function GenerateNewName(OldName: string): string;
66function GetFileFilterItemExt(Filter: string; Index: Integer): string;
67function IntToBin(Data: Int64; Count: Byte): string;
68function Implode(Separator: string; List: TList<string>): string;
69function Implode(Separator: string; List: TStringList; Around: string = ''): string;
70function LastPos(const SubStr: String; const S: String): Integer;
71function LoadFileToStr(const FileName: TFileName): AnsiString;
72function LoggedOnUserNameEx(Format: TUserNameFormat): string;
73function MergeArray(A, B: array of string): TStringArray;
74function OccurenceOfChar(What: Char; Where: string): Integer;
75procedure OpenWebPage(URL: string);
76procedure OpenEmail(Email: string);
77procedure OpenFileInShell(FileName: string);
78function PosFromIndex(SubStr: string; Text: string;
79 StartIndex: Integer): Integer;
80function PosFromIndexReverse(SubStr: string; Text: string;
81 StartIndex: Integer): Integer;
82function RemoveQuotes(Text: string): string;
83procedure SaveStringToFile(S, FileName: string);
84procedure SetBit(var Variable: Int64; Index: Byte; State: Boolean); overload;
85procedure SetBit(var Variable: QWord; Index: Byte; State: Boolean); overload;
86procedure SetBit(var Variable: Cardinal; Index: Byte; State: Boolean); overload;
87procedure SetBit(var Variable: Word; Index: Byte; State: Boolean); overload;
88procedure SearchFiles(AList: TStrings; Dir: string;
89 FilterMethod: TFilterMethod = nil; FileNameMethod: TFileNameMethod = nil);
90procedure SortStrings(Strings: TStrings);
91function SplitString(var Text: string; Count: Word): string;
92function StripTags(const S: string): string;
93function StartsWith(Text, What: string): Boolean;
94function TryHexToInt(Data: string; out Value: Integer): Boolean;
95function TryBinToInt(Data: string; out Value: Integer): Boolean;
96
97
98implementation
99
100function StartsWith(Text, What: string): Boolean;
101begin
102 Result := Copy(Text, 1, Length(Text)) = What;
103end;
104
105function EndsWith(Text, What: string): Boolean;
106begin
107 Result := Copy(Text, Length(Text) - Length(What) + 1, MaxInt) = What;
108end;
109
110function BinToInt(BinStr : string) : Int64;
111var
112 i : byte;
113 RetVar : Int64;
114begin
115 BinStr := UpperCase(BinStr);
116 if BinStr[length(BinStr)] = 'B' then Delete(BinStr,length(BinStr),1);
117 RetVar := 0;
118 for i := 1 to length(BinStr) do begin
119 if not (BinStr[i] in ['0','1']) then begin
120 RetVar := 0;
121 Break;
122 end;
123 RetVar := (RetVar shl 1) + (byte(BinStr[i]) and 1) ;
124 end;
125
126 Result := RetVar;
127end;
128
129function BinToHexString(Source: AnsiString): string;
130var
131 I: Integer;
132begin
133 Result := '';
134 for I := 1 to Length(Source) do begin
135 Result := Result + LowerCase(IntToHex(Ord(Source[I]), 2));
136 end;
137end;
138
139
140procedure DeleteFiles(APath, AFileSpec: string);
141var
142 SearchRec: TSearchRec;
143 Find: Integer;
144 Path: string;
145begin
146 Path := IncludeTrailingPathDelimiter(APath);
147
148 Find := FindFirst(Path + AFileSpec, faAnyFile xor faDirectory, SearchRec);
149 while Find = 0 do begin
150 DeleteFile(Path + SearchRec.Name);
151
152 Find := SysUtils.FindNext(SearchRec);
153 end;
154 FindClose(SearchRec);
155end;
156
157
158function GetFileFilterItemExt(Filter: string; Index: Integer): string;
159var
160 List: TStringList;
161begin
162 try
163 List := TStringList.Create;
164 List.Text := StringReplace(Filter, '|', #10, [rfReplaceAll]);
165 Result := List[Index * 2 + 1];
166 finally
167 List.Free;
168 end;
169end;
170
171procedure FileDialogUpdateFilterFileType(FileDialog: TOpenDialog);
172var
173 FileExt: string;
174begin
175 FileExt := GetFileFilterItemExt(FileDialog.Filter, FileDialog.FilterIndex - 1);
176 Delete(FileExt, 1, 1); // Remove symbol '*'
177 if FileExt <> '.*' then
178 FileDialog.FileName := ChangeFileExt(FileDialog.FileName, FileExt)
179end;
180
181function GenerateNewName(OldName: string): string;
182var
183 I: Integer;
184 Number: Integer;
185begin
186 Number := 1;
187 // Find number on end
188 if Length(OldName) > 0 then begin
189 I := Length(OldName);
190 while (I > 1) and ((OldName[I] >= '0') and (OldName[I] <= '9')) do Dec(I);
191 TryStrToInt(Copy(OldName, I + 1, Length(OldName) - I), Number);
192 Inc(Number)
193 end;
194 Result := Copy(OldName, 1, I) + IntToStr(Number);
195end;
196
197(*function DelTree(DirName : string): Boolean;
198var
199 SHFileOpStruct : TSHFileOpStruct;
200 DirBuf : array [0..255] of char;
201begin
202 DirName := UTF8Decode(DirName);
203 try
204 Fillchar(SHFileOpStruct,Sizeof(SHFileOpStruct),0) ;
205 FillChar(DirBuf, Sizeof(DirBuf), 0 ) ;
206 StrPCopy(DirBuf, DirName) ;
207 with SHFileOpStruct do begin
208 Wnd := 0;
209 pFrom := @DirBuf;
210 wFunc := FO_DELETE;
211 fFlags := FOF_ALLOWUNDO;
212 fFlags := fFlags or FOF_NOCONFIRMATION;
213 fFlags := fFlags or FOF_SILENT;
214 end;
215 Result := (SHFileOperation(SHFileOpStruct) = 0) ;
216 except
217 Result := False;
218 end;
219end;*)
220
221function Implode(Separator: string; List: TStringList; Around: string = ''): string;
222var
223 I: Integer;
224begin
225 Result := '';
226 for I := 0 to List.Count - 1 do begin
227 Result := Result + Around + List[I] + Around;
228 if I < List.Count - 1 then Result := Result + Separator;
229 end;
230end;
231
232function LastPos(const SubStr: String; const S: String): Integer;
233begin
234 Result := Pos(ReverseString(SubStr), ReverseString(S));
235 if (Result <> 0) then
236 Result := ((Length(S) - Length(SubStr)) + 1) - Result + 1;
237end;
238
239function BCDToInt(Value: Byte): Byte;
240begin
241 Result := (Value shr 4) * 10 + (Value and 15);
242end;
243
244(*function GetSpecialFolderPath(Folder: Integer): string;
245const
246 SHGFP_TYPE_CURRENT = 0;
247var
248 Path: array[0..MAX_PATH] of Char;
249begin
250 Result := 'C:\Test';
251 if SUCCEEDED(SHGetFolderPath(0, Folder, 0, SHGFP_TYPE_CURRENT, @path[0])) then
252 Result := path
253 else
254 Result := '';
255end;*)
256
257function IntToBin(Data: Int64; Count: Byte): string;
258var
259 I: Integer;
260begin
261 Result := '';
262 for I := 0 to Count - 1 do
263 Result := IntToStr((Data shr I) and 1) + Result;
264end;
265
266function IntToHex(Data: Cardinal; Count: Byte): string;
267const
268 Chars: array[0..15] of Char = '0123456789ABCDEF';
269var
270 I: Integer;
271begin
272 Result := '';
273 for I := 0 to Count - 1 do
274 Result := Result + Chars[(Data shr (I * 4)) and 15];
275end;
276
277function TryHexToInt(Data: string; out Value: Integer): Boolean;
278var
279 I: Integer;
280begin
281 Data := UpperCase(Data);
282 Result := True;
283 Value := 0;
284 for I := 0 to Length(Data) - 1 do begin
285 if (Data[I + 1] >= '0') and (Data[I + 1] <= '9') then
286 Value := Value or (Ord(Data[I + 1]) - Ord('0')) shl ((Length(Data) - I - 1) * 4)
287 else if (Data[I + 1] >= 'A') and (Data[I + 1] <= 'F') then
288 Value := Value or (Ord(Data[I + 1]) - Ord('A') + 10) shl ((Length(Data) - I - 1) * 4)
289 else Result := False;
290 end;
291end;
292
293function TryBinToInt(Data: string; out Value: Integer): Boolean;
294var
295 I: Integer;
296begin
297 Result := True;
298 Value := 0;
299 for I := 0 to Length(Data) - 1 do begin
300 if (Data[I + 1] >= '0') and (Data[I + 1] <= '1') then
301 Value := Value or (Ord(Data[I + 1]) - Ord('0')) shl ((Length(Data) - I - 1))
302 else Result := False;
303 end;
304end;
305
306function CompareByteArray(Data1, Data2: TArrayOfByte): Boolean;
307var
308 I: Integer;
309begin
310 if Length(Data1) = Length(Data2) then begin
311 Result := True;
312 for I := 0 to Length(Data1) - 1 do begin
313 if Data1[I] <> Data2[I] then begin
314 Result := False;
315 Break;
316 end
317 end;
318 end else Result := False;
319end;
320
321function Explode(Separator: Char; Data: string): TStringArray;
322var
323 Index: Integer;
324begin
325 Result := Default(TStringArray);
326 repeat
327 Index := Pos(Separator, Data);
328 if Index > 0 then begin
329 SetLength(Result, Length(Result) + 1);
330 Result[High(Result)] := Copy(Data, 1, Index - 1);
331 Delete(Data, 1, Index);
332 end else Break;
333 until False;
334 if Data <> '' then begin
335 SetLength(Result, Length(Result) + 1);
336 Result[High(Result)] := Data;
337 end;
338end;
339
340function Implode(Separator: string; List: TList<string>): string;
341var
342 I: Integer;
343begin
344 Result := '';
345 for I := 0 to List.Count - 1 do begin
346 Result := Result + List[I];
347 if I < List.Count - 1 then Result := Result + Separator;
348 end;
349end;
350
351{$IFDEF WINDOWS}
352function GetUserName: string;
353const
354 MAX_USERNAME_LENGTH = 256;
355var
356 L: LongWord;
357begin
358 L := MAX_USERNAME_LENGTH + 2;
359 Result := Default(string);
360 SetLength(Result, L);
361 if Windows.GetUserName(PChar(Result), L) and (L > 0) then begin
362 SetLength(Result, StrLen(PChar(Result)));
363 Result := UTF8Encode(Result);
364 end else Result := '';
365end;
366
367function GetVersionInfo: TOSVersionInfo;
368begin
369 Result.dwOSVersionInfoSize := SizeOf(Result);
370 if GetVersionEx(Result) then begin
371 end;
372end;
373{$ENDIF}
374
375function ComputerName: string;
376{$IFDEF WINDOWS}
377const
378 INFO_BUFFER_SIZE = 32767;
379var
380 Buffer : array[0..INFO_BUFFER_SIZE] of WideChar;
381 Ret : DWORD;
382begin
383 Ret := INFO_BUFFER_SIZE;
384 If (GetComputerNameW(@Buffer[0],Ret)) then begin
385 Result := UTF8Encode(WideString(Buffer));
386 end
387 else begin
388 Result := 'ERROR_NO_COMPUTERNAME_RETURNED';
389 end;
390end;
391{$ENDIF}
392{$IFDEF UNIX}
393var
394 Name: UtsName;
395begin
396 Name := Default(UtsName);
397 fpuname(Name);
398 Result := Name.Nodename;
399end;
400{$ENDIF}
401
402{$IFDEF WINDOWS}
403function LoggedOnUserNameEx(Format: TUserNameFormat): string;
404const
405 MaxLength = 1000;
406var
407 UserName: array[0..MaxLength] of Char;
408 VersionInfo: TOSVersionInfo;
409 Size: DWORD;
410begin
411 VersionInfo := GetVersionInfo;
412 if VersionInfo.dwPlatformId = VER_PLATFORM_WIN32_NT then begin
413 Size := MaxLength;
414 GetUserNameEx(Integer(Format), @UserName, @Size);
415 //ShowMessage(SysErrorMessage(GetLastError));
416 if GetLastError = 0 then Result := UTF8Encode(UserName)
417 else Result := GetUserName;
418 end else Result := GetUserName;
419end;
420{$ELSE}
421function GetUserName: string;
422begin
423 Result := '';
424end;
425
426function LoggedOnUserNameEx(Format: TUserNameFormat): string;
427begin
428 Result := '';
429end;
430
431{$ENDIF}
432
433function SplitString(var Text: string; Count: Word): string;
434begin
435 Result := Copy(Text, 1, Count);
436 Delete(Text, 1, Count);
437end;
438
439function GetBitCount(Variable: QWord; MaxIndex: Integer): Integer;
440var
441 I: Integer;
442begin
443 Result := 0;
444 for I := 0 to MaxIndex - 1 do
445 if ((Variable shr I) and 1) = 1 then Inc(Result);
446end;
447
448function GetBit(Variable:QWord;Index:Byte):Boolean;
449begin
450 Result := ((Variable shr Index) and 1) = 1;
451end;
452
453procedure SetBit(var Variable: Int64; Index: Byte; State: Boolean);
454begin
455 Variable := (Variable and ((1 shl Index) xor High(QWord))) or (Int64(State) shl Index);
456end;
457
458procedure SetBit(var Variable:QWord;Index:Byte;State:Boolean); overload;
459begin
460 Variable := (Variable and ((1 shl Index) xor High(QWord))) or (QWord(State) shl Index);
461end;
462
463procedure SetBit(var Variable:Cardinal;Index:Byte;State:Boolean); overload;
464begin
465 Variable := (Variable and ((1 shl Index) xor High(Cardinal))) or (Cardinal(State) shl Index);
466end;
467
468procedure SetBit(var Variable:Word;Index:Byte;State:Boolean); overload;
469begin
470 Variable := (Variable and ((1 shl Index) xor High(Word))) or (Word(State) shl Index);
471end;
472
473function AddLeadingZeroes(const aNumber, Length : integer) : string;
474begin
475 Result := SysUtils.Format('%.*d', [Length, aNumber]) ;
476end;
477
478procedure LoadLibraries;
479begin
480 {$IFDEF WINDOWS}
481 DLLHandle1 := LoadLibrary('secur32.dll');
482 if DLLHandle1 <> 0 then
483 begin
484 @GetUserNameEx := GetProcAddress(DLLHandle1, 'GetUserNameExA');
485 end;
486 {$ENDIF}
487end;
488
489procedure FreeLibraries;
490begin
491 {$IFDEF WINDOWS}
492 if DLLHandle1 <> 0 then FreeLibrary(DLLHandle1);
493 {$ENDIF}
494end;
495
496procedure ExecuteProgram(Executable: string; Parameters: array of string);
497var
498 Process: TProcess;
499 I: Integer;
500begin
501 try
502 Process := TProcess.Create(nil);
503 Process.Executable := Executable;
504 for I := 0 to Length(Parameters) - 1 do
505 Process.Parameters.Add(Parameters[I]);
506 Process.Options := [poNoConsole];
507 Process.Execute;
508 finally
509 Process.Free;
510 end;
511end;
512
513procedure FreeThenNil(var Obj);
514begin
515 TObject(Obj).Free;
516 TObject(Obj) := nil;
517end;
518
519procedure OpenWebPage(URL: string);
520begin
521 OpenURL(URL);
522end;
523
524procedure OpenEmail(Email: string);
525begin
526 OpenURL('mailto:' + Email);
527end;
528
529procedure OpenFileInShell(FileName: string);
530begin
531 ExecuteProgram('cmd.exe', ['/c', 'start', FileName]);
532end;
533
534function RemoveQuotes(Text: string): string;
535begin
536 Result := Text;
537 if (Pos('"', Text) = 1) and (Text[Length(Text)] = '"') then
538 Result := Copy(Text, 2, Length(Text) - 2);
539end;
540
541function OccurenceOfChar(What: Char; Where: string): Integer;
542var
543 I: Integer;
544begin
545 Result := 0;
546 for I := 1 to Length(Where) do
547 if Where[I] = What then Inc(Result);
548end;
549
550function GetDirCount(Dir: string): Integer;
551begin
552 Result := OccurenceOfChar(DirectorySeparator, Dir);
553 if Copy(Dir, Length(Dir), 1) = DirectorySeparator then
554 Dec(Result);
555end;
556
557function MergeArray(A, B: array of string): TStringArray;
558var
559 I: Integer;
560begin
561 Result := Default(TStringArray);
562 SetLength(Result, Length(A) + Length(B));
563 for I := 0 to Length(A) - 1 do
564 Result[I] := A[I];
565 for I := 0 to Length(B) - 1 do
566 Result[Length(A) + I] := B[I];
567end;
568
569function LoadFileToStr(const FileName: TFileName): AnsiString;
570var
571 FileStream: TFileStream;
572 Read: Integer;
573begin
574 Result := '';
575 FileStream := TFileStream.Create(FileName, fmOpenRead);
576 try
577 if FileStream.Size > 0 then begin
578 SetLength(Result, FileStream.Size);
579 Read := FileStream.Read(Pointer(Result)^, FileStream.Size);
580 SetLength(Result, Read);
581 end;
582 finally
583 FileStream.Free;
584 end;
585end;
586
587function DefaultSearchFilter(const FileName: string): Boolean;
588begin
589 Result := True;
590end;
591
592procedure SaveStringToFile(S, FileName: string);
593var
594 F: TextFile;
595begin
596 AssignFile(F, FileName);
597 try
598 ReWrite(F);
599 Write(F, S);
600 finally
601 CloseFile(F);
602 end;
603end;
604
605procedure SearchFiles(AList: TStrings; Dir: string;
606 FilterMethod: TFilterMethod = nil; FileNameMethod: TFileNameMethod = nil);
607var
608 SR: TSearchRec;
609begin
610 Dir := IncludeTrailingPathDelimiter(Dir);
611 if FindFirst(Dir + '*', faAnyFile, SR) = 0 then
612 try
613 repeat
614 if (SR.Name = '.') or (SR.Name = '..') or (Assigned(FilterMethod) and (not FilterMethod(SR.Name) or
615 not FilterMethod(Copy(Dir, 3, Length(Dir)) + SR.Name))) then Continue;
616 if Assigned(FileNameMethod) then
617 FileNameMethod(Dir + SR.Name);
618 AList.Add(Dir + SR.Name);
619 if (SR.Attr and faDirectory) <> 0 then
620 SearchFiles(AList, Dir + SR.Name, FilterMethod);
621 until FindNext(SR) <> 0;
622 finally
623 FindClose(SR);
624 end;
625end;
626
627function GetStringPart(var Text: string; Separator: string): string;
628var
629 P: Integer;
630begin
631 P := Pos(Separator, Text);
632 if P > 0 then begin
633 Result := Copy(Text, 1, P - 1);
634 Delete(Text, 1, P - 1 + Length(Separator));
635 end else begin
636 Result := Text;
637 Text := '';
638 end;
639 Result := Trim(Result);
640 Text := Trim(Text);
641end;
642
643function StripTags(const S: string): string;
644var
645 Len: Integer;
646
647 function ReadUntil(const ReadFrom: Integer; const C: Char): Integer;
648 var
649 J: Integer;
650 begin
651 for J := ReadFrom to Len do
652 if (S[j] = C) then
653 begin
654 Result := J;
655 Exit;
656 end;
657 Result := Len + 1;
658 end;
659
660var
661 I, APos: Integer;
662begin
663 Len := Length(S);
664 I := 0;
665 Result := '';
666 while (I <= Len) do begin
667 Inc(I);
668 APos := ReadUntil(I, '<');
669 Result := Result + Copy(S, I, APos - i);
670 I := ReadUntil(APos + 1, '>');
671 end;
672end;
673
674function PosFromIndex(SubStr: string; Text: string;
675 StartIndex: Integer): Integer;
676var
677 I, MaxLen: SizeInt;
678 Ptr: PAnsiChar;
679begin
680 Result := 0;
681 if (StartIndex < 1) or (StartIndex > Length(Text) - Length(SubStr)) then Exit;
682 if Length(SubStr) > 0 then begin
683 MaxLen := Length(Text) - Length(SubStr) + 1;
684 I := StartIndex;
685 Ptr := @Text[StartIndex];
686 while (I <= MaxLen) do begin
687 if (SubStr[1] = Ptr^) and (CompareByte(Substr[1], Ptr^, Length(SubStr)) = 0) then begin
688 Result := I;
689 Exit;
690 end;
691 Inc(I);
692 Inc(Ptr);
693 end;
694 end;
695end;
696
697function PosFromIndexReverse(SubStr: string; Text: string;
698 StartIndex: Integer): Integer;
699var
700 I: SizeInt;
701 Ptr: PAnsiChar;
702begin
703 Result := 0;
704 if (StartIndex < 1) or (StartIndex > Length(Text)) then Exit;
705 if Length(SubStr) > 0 then begin
706 I := StartIndex;
707 Ptr := @Text[StartIndex];
708 while (I > 0) do begin
709 if (SubStr[1] = Ptr^) and (CompareByte(Substr[1], Ptr^, Length(SubStr)) = 0) then begin
710 Result := I;
711 Exit;
712 end;
713 Dec(I);
714 Dec(Ptr);
715 end;
716 end;
717end;
718
719procedure CopyStringArray(Dest: TStringArray; Source: array of string);
720var
721 I: Integer;
722begin
723 SetLength(Dest, Length(Source));
724 for I := 0 to Length(Dest) - 1 do
725 Dest[I] := Source[I];
726end;
727
728function CombinePaths(Path1, Path2: string): string;
729begin
730 Result := Path1;
731 if Result <> '' then Result := Result + DirectorySeparator + Path2
732 else Result := Path2;
733end;
734
735procedure SortStrings(Strings: TStrings);
736var
737 Tmp: TStringList;
738begin
739 Strings.BeginUpdate;
740 try
741 if Strings is TStringList then begin
742 TStringList(Strings).Sort;
743 end else begin
744 Tmp := TStringList.Create;
745 try
746 Tmp.Assign(Strings);
747 Tmp.Sort;
748 Strings.Assign(Tmp);
749 finally
750 Tmp.Free;
751 end;
752 end;
753 finally
754 Strings.EndUpdate;
755 end;
756end;
757
758
759initialization
760
761LoadLibraries;
762
763
764finalization
765
766FreeLibraries;
767
768end.
Note: See TracBrowser for help on using the repository browser.