source: Common/Common.pas

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