source: trunk/Packages/Common/UCommon.pas

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