source: trunk/Packages/Common/Common.pas

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