PageRenderTime 47ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/delphifiles.inc

http://github.com/rofl0r/KOL
Pascal | 1163 lines | 1058 code | 31 blank | 74 comment | 19 complexity | 2866f898664e5a5fac6daa92a4805610 MD5 | raw file
  1. {
  2. This part of the unit modified by Tim Slusher and Vladimir Kladov.
  3. }
  4. {* Set of utility methods to work with files
  5. and reqistry.
  6. When programming KOL, which is Windows API-oriented, You should
  7. avoid alien (for Windows) embedded Pascal files handling, and
  8. use API-calls which implemented very well. This set of functions
  9. is intended to make this easier.
  10. Also TDirList object implementation present here and some registry
  11. access functions, which allow to make code more elegant.
  12. }
  13. {$UNDEF ASM_LOCAL}
  14. {$IFDEF ASM_VERSION}
  15. {$DEFINE ASM_LOCAL}
  16. {$ENDIF ASM_VERSION}
  17. {$IFDEF ASM_VERSION}
  18. function FileCreate(const FileName: string; OpenFlags: DWord): THandle;
  19. asm
  20. XOR ECX, ECX
  21. PUSH ECX
  22. MOV ECX, EDX
  23. SHR ECX, 16
  24. AND CX, $1FFF
  25. JNZ @@1
  26. MOV CL, FILE_ATTRIBUTE_NORMAL
  27. @@1: PUSH ECX
  28. MOV CL, DH
  29. PUSH ECX // CreationMode
  30. PUSH 0
  31. MOV CL, DL
  32. PUSH ECX // ShareMode
  33. MOV DX, 0
  34. PUSH EDX // AccessMode
  35. //CALL System.@LStrToPChar // FileName must not be ''
  36. PUSH EAX
  37. CALL CreateFile
  38. end;
  39. {$ELSE ASM_VERSION} //Pascal
  40. function FileCreate(const FileName: string; OpenFlags: DWord): THandle;
  41. var Attr: DWORD;
  42. begin
  43. Attr := (OpenFlags shr 16) and $1FFF;
  44. if Attr = 0 then Attr := FILE_ATTRIBUTE_NORMAL;
  45. Result := CreateFile( PChar(FileName), OpenFlags and $F0000000,
  46. OpenFlags and $F, nil, (OpenFlags shr 8) and $F,
  47. Attr, 0 );
  48. end;
  49. {$ENDIF ASM_VERSION}
  50. {$IFDEF ASM_VERSION}
  51. function FileClose(Handle: THandle): Boolean;
  52. asm
  53. PUSH EAX
  54. CALL CloseHandle
  55. TEST EAX, EAX
  56. SETNZ AL
  57. end;
  58. {$ELSE ASM_VERSION} //Pascal
  59. function FileClose(Handle: THandle): boolean;
  60. begin
  61. Result := CloseHandle(Handle);
  62. end;
  63. {$ENDIF ASM_VERSION}
  64. {$IFDEF ASM_VERSION}
  65. function FileExists( const FileName : String ) : Boolean;
  66. const size_TWin32FindData = sizeof( TWin32FindData );
  67. asm
  68. CALL EAX2PChar
  69. PUSH EAX
  70. CALL GetFileAttributes
  71. INC EAX
  72. JZ @@exit
  73. DEC EAX
  74. {$IFDEF PARANOIA}
  75. DB $24, FILE_ATTRIBUTE_DIRECTORY
  76. {$ELSE}
  77. AND AL, FILE_ATTRIBUTE_DIRECTORY
  78. {$ENDIF}
  79. SETZ AL
  80. @@exit:
  81. end;
  82. {$ELSE ASM_VERSION} //Pascal
  83. function FileExists( const FileName : String ) : Boolean;
  84. var
  85. Code: Integer;
  86. begin
  87. Code := GetFileAttributes(PChar(FileName));
  88. Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code = 0);
  89. end;
  90. {$ENDIF ASM_VERSION}
  91. {$IFDEF ASM_VERSION}
  92. function FileSeek(Handle: THandle; MoveTo: integer; MoveMethod: TMoveMethod): DWord;
  93. asm
  94. MOVZX ECX, CL
  95. PUSH ECX
  96. PUSH 0
  97. PUSH EDX
  98. PUSH EAX
  99. CALL SetFilePointer
  100. end;
  101. {$ELSE ASM_VERSION} //Pascal
  102. function FileSeek(Handle: THandle; MoveTo: integer; MoveMethod: TMoveMethod): DWord;
  103. begin
  104. Result := SetFilePointer(Handle, MoveTo, nil, Ord( MoveMethod ) );
  105. end;
  106. {$ENDIF ASM_VERSION}
  107. {$IFDEF ASM_VERSION}
  108. function FileRead(Handle: THandle; var Buffer; Count: DWord): DWord;
  109. asm
  110. PUSH EBP
  111. PUSH 0
  112. MOV EBP, ESP
  113. PUSH 0
  114. PUSH EBP
  115. PUSH ECX
  116. PUSH EDX
  117. PUSH EAX
  118. CALL ReadFile
  119. TEST EAX, EAX
  120. POP EAX
  121. JNZ @@exit
  122. XOR EAX, EAX
  123. @@exit:
  124. POP EBP
  125. end;
  126. {$ELSE ASM_VERSION} //Pascal
  127. function FileRead(Handle: THandle; var Buffer; Count: DWord): DWord;
  128. begin
  129. if not ReadFile(Handle, Buffer, Count, Result, nil) then
  130. Result := 0;
  131. end;
  132. {$ENDIF ASM_VERSION}
  133. {$IFDEF ASM_VERSION}
  134. function File2Str(Handle: THandle): String;
  135. asm
  136. PUSH EDX
  137. TEST EAX, EAX
  138. JZ @@exit // return ''
  139. PUSH EBX
  140. MOV EBX, EAX // EBX = Handle
  141. XOR EDX, EDX
  142. XOR ECX, ECX
  143. INC ECX
  144. CALL FileSeek
  145. PUSH EAX // Pos
  146. PUSH 0
  147. PUSH EBX
  148. CALL GetFileSize
  149. POP EDX
  150. SUB EAX, EDX // EAX = Size - Pos
  151. JZ @@exitEBX
  152. PUSH EAX
  153. CALL System.@GetMem
  154. XCHG EAX, EBX
  155. MOV EDX, EBX
  156. POP ECX
  157. PUSH ECX
  158. CALL FileRead
  159. POP ECX
  160. MOV EDX, EBX
  161. POP EBX
  162. POP EAX
  163. PUSH EDX
  164. {$IFDEF _D2}
  165. CALL _LStrFromPCharLen
  166. {$ELSE}
  167. CALL System.@LStrFromPCharLen
  168. {$ENDIF}
  169. JMP @@freebuf
  170. @@exitEBX:
  171. POP EBX
  172. @@exit:
  173. XCHG EDX, EAX
  174. POP EAX // @Result
  175. PUSH EDX
  176. CALL System.@LStrFromPChar
  177. @@freebuf:
  178. POP EAX
  179. TEST EAX, EAX
  180. JZ @@fin
  181. CALL System.@FreeMem
  182. @@fin:
  183. end;
  184. {$ELSE ASM_VERSION} //Pascal
  185. function File2Str(Handle: THandle): String;
  186. var Pos, Size: DWORD;
  187. begin
  188. Result := '';
  189. if Handle = 0 then Exit;
  190. Pos := FileSeek( Handle, 0, spCurrent );
  191. Size := GetFileSize( Handle, nil );
  192. SetString( Result, nil, Size - Pos + 1 );
  193. FileRead( Handle, Result[ 1 ], Size - Pos );
  194. Result[ Size - Pos + 1 ] := #0;
  195. end;
  196. {$ENDIF ASM_VERSION}
  197. {$IFDEF ASM_VERSION}
  198. function FileWrite(Handle: THandle; const Buffer; Count: DWord): DWord;
  199. asm
  200. PUSH EBP
  201. PUSH EBP
  202. MOV EBP, ESP
  203. PUSH 0
  204. PUSH EBP
  205. PUSH ECX
  206. PUSH EDX
  207. PUSH EAX
  208. CALL WriteFile
  209. TEST EAX, EAX
  210. POP EAX
  211. JNZ @@exit
  212. XOR EAX, EAX
  213. @@exit:
  214. POP EBP
  215. end;
  216. {$ELSE ASM_VERSION} //Pascal
  217. function FileWrite(Handle: THandle; const Buffer; Count: DWord): DWord;
  218. begin
  219. if not WriteFile(Handle, Buffer, Count, Result, nil) then
  220. Result := 0;
  221. end;
  222. {$ENDIF ASM_VERSION}
  223. {$IFDEF ASM_VERSION}
  224. function FileEOF( Handle: THandle ) : Boolean;
  225. asm
  226. PUSH EAX
  227. PUSH 0
  228. PUSH EAX
  229. CALL GetFileSize
  230. XCHG EAX, [ESP]
  231. MOV CL, spCurrent
  232. XOR EDX, EDX
  233. CALL FileSeek
  234. POP EDX
  235. CMP EAX, EDX
  236. SETGE AL
  237. end;
  238. {$ELSE ASM_VERSION} //Pascal
  239. function FileEOF( Handle: THandle ) : Boolean;
  240. var Siz, Pos : DWord;
  241. begin
  242. Siz := GetFileSize( Handle, nil );
  243. Pos := FileSeek( Handle, 0, spCurrent );
  244. Result := Pos >= Siz;
  245. end;
  246. {$ENDIF ASM_VERSION}
  247. {$IFDEF ASM_noVERSION}
  248. function FileFullPath( const FileName: String ) : String;
  249. const
  250. BkSlash: String = '\';
  251. szTShFileInfo = sizeof( TShFileInfo );
  252. asm
  253. PUSH EBX
  254. PUSH ESI
  255. MOV EBX, EDX
  256. PUSH EAX
  257. XCHG EAX, EDX
  258. CALL System.@LStrClr
  259. POP EDX
  260. PUSH 0
  261. MOV EAX, ESP
  262. CALL System.@LStrAsg
  263. MOV ESI, ESP
  264. @@loo: CMP dword ptr [ESI], 0
  265. JZ @@fin
  266. MOV EAX, ESI
  267. MOV EDX, [BkSlash]
  268. PUSH 0
  269. MOV ECX, ESP
  270. CALL Parse
  271. CMP dword ptr [EBX], 0
  272. JE @@1
  273. MOV EAX, EBX
  274. MOV EDX, [BkSlash]
  275. CALL System.@LStrCat
  276. JMP @@2
  277. @@1:
  278. POP EAX
  279. PUSH EAX
  280. CALL System.@LStrLen
  281. CMP EAX, 2
  282. JNE @@2
  283. POP EAX
  284. PUSH EAX
  285. CMP byte ptr [EAX+1], ':'
  286. JNE @@2
  287. MOV EAX, EBX
  288. POP EDX
  289. PUSH EDX
  290. CALL System.@LStrAsg
  291. JMP @@3
  292. @@2:
  293. PUSH 0
  294. MOV EAX, ESP
  295. MOV EDX, [EBX]
  296. CALL System.@LStrAsg
  297. MOV EAX, ESP
  298. MOV EDX, [ESP+4]
  299. CALL System.@LStrCat
  300. POP EAX
  301. PUSH EAX
  302. SUB ESP, szTShFileInfo
  303. MOV EDX, ESP
  304. PUSH SHGFI_DISPLAYNAME
  305. PUSH szTShFileInfo
  306. PUSH EDX
  307. PUSH 0
  308. PUSH EAX
  309. CALL ShGetFileInfo
  310. LEA EDX, [ESP].TShFileInfo.szDisplayName
  311. CMP byte ptr [EDX], 0
  312. JE @@clr_stk
  313. LEA EAX, [ESP+szTShFileInfo+4]
  314. CALL System.@LStrFromPChar
  315. @@clr_stk:
  316. ADD ESP, szTShFileInfo
  317. CALL RemoveStr
  318. POP EDX
  319. PUSH EDX
  320. MOV EAX, EBX
  321. CALL System.@LStrCat
  322. @@3: CALL RemoveStr
  323. JMP @@loo
  324. @@fin: CALL RemoveStr
  325. POP ESI
  326. POP EBX
  327. end;
  328. {$ELSE ASM_VERSION} //Pascal
  329. function FileFullPath( const FileName: String ) : String;
  330. var SFI: TShFileInfo;
  331. Src, S: String;
  332. begin
  333. Result := '';
  334. Src := FileName;
  335. while Src <> '' do
  336. begin
  337. S := Parse( Src, '\' );
  338. if Result <> '' then
  339. Result := Result + '\';
  340. if (Result = '') and (Length( S ) = 2) and (S[ 2 ] = ':') then
  341. Result := S
  342. else
  343. begin
  344. ShGetFileInfo( PChar( Result + S ), 0, SFI, Sizeof( SFI ),
  345. SHGFI_DISPLAYNAME );
  346. if SFI.szDisplayName[ 0 ] <> #0 then
  347. S := SFI.szDisplayName;
  348. Result := Result + S;
  349. end;
  350. end;
  351. if ExtractFileExt( Result ) = '' then
  352. // case when flag 'Hide extensions for registered file types' is set on
  353. // in the Explorer:
  354. Result := Result + ExtractFileExt( FileName );
  355. end;
  356. {$ENDIF ASM_VERSION}
  357. function FileShortPath( const FileName: String ): String;
  358. var Buf: array[ 0..MAX_PATH ] of Char;
  359. begin
  360. GetShortPathName( PChar( FileName ), Buf, Sizeof( Buf ) );
  361. Result := Buf;
  362. end;
  363. function FileIconSystemIdx( const Path: String ): Integer;
  364. var SFI: TShFileInfo;
  365. begin
  366. SFI.iIcon := 0; // Bartov
  367. ShGetFileInfo( PChar( Path ), 0, SFI, sizeof( SFI ),
  368. //-- Babenko Alexey: -----------------//
  369. // SHGFI_ICON or //
  370. //----------------------------------//
  371. SHGFI_SMALLICON or SHGFI_SYSICONINDEX );
  372. Result := SFI.iIcon;
  373. end;
  374. function FileIconSysIdxOffline( const Path: String ): Integer;
  375. var SFI: TShFileInfo;
  376. begin
  377. SFI.iIcon := 0; // Bartov
  378. ShGetFileInfo( PChar( Path ), FILE_ATTRIBUTE_NORMAL, SFI, sizeof( SFI ),
  379. //-- Babenko Alexey: -----------------//
  380. // SHGFI_ATTRIBUTES or SHGFI_ICON or //
  381. //----------------------------------//
  382. SHGFI_SMALLICON or SHGFI_SYSICONINDEX or SHGFI_USEFILEATTRIBUTES );
  383. Result := SFI.iIcon;
  384. end;
  385. procedure LogFileOutput( const filepath, str: String );
  386. var F: HFile;
  387. begin
  388. F := FileCreate( filepath, ofOpenWrite or ofOpenAlways );
  389. if F = INVALID_HANDLE_VALUE then Exit;
  390. FileSeek( F, 0, spEnd );
  391. FileWrite( F, {$IFNDEF _D2} String {$ENDIF}
  392. ( str + #13#10 )[ 1 ], Length( str ) + 2 );
  393. FileClose( F );
  394. end;
  395. function StrSaveToFile( const Filename, Str: String ): Boolean;
  396. var F: HFile;
  397. begin
  398. Result := FALSE;
  399. F := FileCreate( Filename, ofOpenWrite or ofOpenAlways );
  400. if F = INVALID_HANDLE_VALUE then Exit;
  401. FileWrite( F, Str[ 1 ], Length( Str ) );
  402. FileClose( F );
  403. Result := TRUE;
  404. end;
  405. function StrLoadFromFile( const Filename: String ): String;
  406. var F: HFile;
  407. begin
  408. Result := '';
  409. F := FileCreate( Filename, ofOpenRead or ofOpenExisting or ofShareDenyWrite );
  410. if F = INVALID_HANDLE_VALUE then Exit;
  411. Result := File2Str( F );
  412. FileClose( F ); {??ee(zhog); Dark Knight}
  413. end;
  414. {$IFDEF ASM_VERSION}
  415. function DirectoryExists(const Name: string): Boolean;
  416. asm
  417. //CALL System.@LStrToPChar // Name must not be ''
  418. PUSH EAX
  419. CALL GetFileAttributes
  420. INC EAX
  421. JZ @@exit
  422. DEC EAX
  423. {$IFDEF PARANOIA}
  424. DB $24, FILE_ATTRIBUTE_DIRECTORY
  425. {$ELSE}
  426. AND AL, FILE_ATTRIBUTE_DIRECTORY
  427. {$ENDIF}
  428. SETNZ AL
  429. @@exit:
  430. end;
  431. {$ELSE ASM_VERSION} //Pascal
  432. function DirectoryExists(const Name: string): Boolean;
  433. var
  434. Code: Integer;
  435. begin
  436. Code := GetFileAttributes(PChar(Name));
  437. Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
  438. end;
  439. {$ENDIF ASM_VERSION}
  440. function CheckDirectoryContent( const Name: String; SubDirsOnly: Boolean; const Mask: String ): Boolean;
  441. var FD: TWin32FindData;
  442. FH: THandle;
  443. begin
  444. if not DirectoryExists( Name ) then
  445. Result := TRUE
  446. else
  447. begin
  448. FH := Windows.FindFirstFile( PChar( IncludeTrailingPathDelimiter( Name )
  449. + Mask ), FD );
  450. if FH = INVALID_HANDLE_VALUE then
  451. Result := TRUE
  452. else
  453. begin
  454. Result := TRUE;
  455. repeat
  456. if not StrIn( FD.cFileName, ['.','..'] ) then
  457. begin
  458. if SubDirsOnly and LongBool(FD.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY)
  459. or not SubDirsOnly then
  460. begin
  461. Result := FALSE;
  462. break;
  463. end;
  464. end;
  465. until not Windows.FindNextFile( FH, FD );
  466. Windows.FindClose( FH );
  467. end;
  468. end;
  469. end;
  470. function DirectoryEmpty(const Name: String): Boolean;
  471. begin
  472. Result := CheckDirectoryContent( Name, FALSE, '*.*' );
  473. end;
  474. {-}
  475. function DirectorySize( const Path: String ): I64;
  476. var DirList: PDirList;
  477. I: Integer;
  478. begin
  479. Result := MakeInt64( 0, 0 );
  480. DirList := NewDirList( Path, '*.*', 0 );
  481. for I := 0 to DirList.Count-1 do
  482. begin
  483. if LongBool( DirList.Items[ I ].dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY ) then
  484. Result := Add64( Result, DirectorySize( DirList.Path + DirList.Names[ I ] ) )
  485. else
  486. Result := Add64( Result, MakeInt64( DirList.Items[ I ].nFileSizeLow,
  487. DirList.Items[ I ].nFileSizeHigh ) );
  488. end;
  489. DirList.Free;
  490. end;
  491. {+}
  492. function DirectoryHasSubdirs( const Path: String ): Boolean;
  493. begin
  494. Result := not CheckDirectoryContent( Path, TRUE, '*.*' );
  495. end;
  496. function GetFileList(const dir: string): PStrList;
  497. var
  498. Srch: TWin32FindData;
  499. flag: Integer;
  500. succ: boolean;
  501. begin
  502. result := nil;
  503. flag := FindFirstFile(PChar(dir), Srch);
  504. succ := flag <> 0;
  505. while succ do begin
  506. if (not (Srch.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY > 0))then begin
  507. if Result = nil then begin
  508. Result := NewStrList;
  509. end;
  510. Result.Add(Srch.cFileName);
  511. end;
  512. succ := FindNextFile(Flag, Srch);
  513. end;
  514. FindClose(Flag);
  515. end;
  516. function ExcludeTrailingChar( const S: String; C: Char ): String;
  517. begin
  518. Result := S;
  519. if Result <> '' then
  520. if Result[ Length( Result ) ] = C then
  521. Delete( Result, Length( Result ), 1 );
  522. end;
  523. function IncludeTrailingChar( const S: String; C: Char ): String;
  524. begin
  525. Result := S;
  526. if (Result = '') or (Result[ Length( Result ) ] <> C) then
  527. Result := Result + C;
  528. end;
  529. //---------------------------------------------------------
  530. // Following functions/procedures are created by Edward Aretino:
  531. // IncludeTrailingPathDelimiter, ExcludeTrailingPathDelimiter,
  532. // ForceDirectories, CreateDir, ChangeFileExt
  533. //---------------------------------------------------------
  534. function IncludeTrailingPathDelimiter(const S: string): string;
  535. begin
  536. {if CopyTail(S, 1) <> '\' then
  537. Result := S + '\'
  538. else
  539. Result := S;}
  540. Result := IncludeTrailingChar( S, '\' );
  541. end;
  542. function ExcludeTrailingPathDelimiter(const S: string): string;
  543. begin
  544. {Result := S;
  545. if Length(Result) = 0 then Exit;
  546. if (CopyTail(Result, 1) = '\') then
  547. DeleteTail(Result, 1);}
  548. Result := ExcludeTrailingChar( S, '\' );
  549. end;
  550. function ForceDirectories(Dir: string): Boolean;
  551. begin
  552. Result := Length(Dir) > 0; {Centronix}
  553. If not Result then Exit;
  554. Dir := ExcludeTrailingPathDelimiter(Dir);
  555. If (Length(Dir) < 3) or DirectoryExists(Dir) or
  556. (ExtractFilePath(Dir) = Dir) then Exit; // avoid 'xyz:\' problem.
  557. Result := ForceDirectories(ExtractFilePath(Dir)) and CreateDir(Dir);
  558. end;
  559. function CreateDir(const Dir: string): Boolean;
  560. begin
  561. Result := Windows.CreateDirectory(PChar(Dir), nil);
  562. end;
  563. function ChangeFileExt(FileName: String; const Extension: string): string;
  564. var
  565. FileExt: String;
  566. begin
  567. FileExt := ExtractFileExt(FileName);
  568. DeleteTail(FileName, Length(FileExt));
  569. Result := FileName+ Extension;
  570. end;
  571. {$IFDEF ASM_VERSION}
  572. {$IFNDEF _D2}
  573. {$DEFINE ASM_LStrFromPCharLen}
  574. {$ENDIF}
  575. {$ENDIF ASM_VERSION}
  576. {$IFDEF ASM_LStrFromPCharLen}
  577. {$DEFINE ASM_DIRDelimiters}
  578. {$ENDIF}
  579. {$IFDEF ASM_VERSION}
  580. {$DEFINE ASM_DIRDelimiters}
  581. {$ENDIF ASM_VERSION}
  582. {$IFDEF ASM_DIRDelimiters}
  583. const
  584. DirDelimiters: PChar = ':\';
  585. {$ENDIF}
  586. {$IFDEF ASM_VERSION}
  587. function ExtractFileName( const Path : String ) : String;
  588. asm
  589. PUSH EDX
  590. PUSH EAX
  591. MOV EDX, [DirDelimiters]
  592. CALL __DelimiterLast
  593. POP EDX
  594. CMP byte ptr [EAX], 0
  595. JZ @@1
  596. XCHG EDX, EAX
  597. INC EDX
  598. @@1: POP EAX
  599. CALL System.@LStrFromPChar
  600. end;
  601. {$ELSE ASM_VERSION} //Pascal
  602. function ExtractFileName( const Path : String ) : String;
  603. var P: PChar;
  604. begin
  605. P := __DelimiterLast( PChar( Path ), ':\' );
  606. if P^ = #0 then
  607. Result := Path
  608. else
  609. Result := P + 1;
  610. end;
  611. {$ENDIF ASM_VERSION}
  612. {$IFDEF ASM_LStrFromPCharLen} // LStrFromPCharLen - there are no in D2
  613. function ExtractFilePath( const Path : String ) : String;
  614. asm
  615. PUSH EDX
  616. MOV EDX, [DirDelimiters]
  617. CALL EAX2PChar
  618. PUSH EAX
  619. CALL __DelimiterLast
  620. XCHG EDX, EAX
  621. XOR ECX, ECX
  622. POP EAX
  623. CMP byte ptr [EDX], CL
  624. JZ @@ret_0
  625. SUB EDX, EAX
  626. INC EDX
  627. XCHG EDX, EAX
  628. XCHG ECX, EAX
  629. @@ret_0:
  630. POP EAX
  631. CALL System.@LStrFromPCharLen
  632. end;
  633. {$ELSE} //Pascal
  634. function ExtractFilePath( const Path : String ) : String;
  635. //var I : Integer;
  636. var P, P0: PChar;
  637. begin
  638. P0 := PChar( Path );
  639. P := __DelimiterLast( P0, ':\' );
  640. if P^ = #0 then
  641. Result := ''
  642. else
  643. Result := Copy( Path, 1, P - P0 + 1 );
  644. end;
  645. {$ENDIF}
  646. function ExtractFileNameWOext( const Path : String ) : String;
  647. begin
  648. Result := ExtractFileName( Path );
  649. Result := Copy( Result, 1, Length( Result ) - Length( ExtractFileExt( Result ) ) );
  650. end;
  651. {$IFDEF ASM_VERSION}
  652. const
  653. ExtDelimeters: PChar = '.';
  654. function ExtractFileExt( const Path : String ) : String;
  655. asm
  656. PUSH EDX
  657. MOV EDX, [ExtDelimeters]
  658. CALL EAX2PChar
  659. CALL __DelimiterLast
  660. @@1: XCHG EDX, EAX
  661. POP EAX
  662. CALL System.@LStrFromPChar
  663. end;
  664. {$ELSE ASM_VERSION} //Pascal
  665. function ExtractFileExt( const Path : String ) : String;
  666. var P: PChar;
  667. begin
  668. P := __DelimiterLast( PChar( Path ), '.' );
  669. Result := P;
  670. end;
  671. {$ENDIF ASM_VERSION}
  672. function ReplaceFileExt( const Path, NewExt: String ): String;
  673. begin
  674. Result := ExtractFilePath( Path ) +
  675. ExtractFileNameWOext( ExtractFileName( Path ) ) +
  676. NewExt;
  677. end;
  678. function ExtractShortPathName( const Path: String ): String;
  679. var
  680. Buffer: array[0..MAX_PATH - 1] of Char;
  681. begin
  682. SetString(Result, Buffer,
  683. GetShortPathName(PChar(Path), Buffer, SizeOf(Buffer)));
  684. end;
  685. function FilePathShortened( const Path: String; MaxLen: Integer ): String;
  686. begin
  687. Result := FilePathShortenPixels( Path, 0, MaxLen );
  688. end;
  689. function PixelsLength( DC: HDC; const Text: String ): Integer;
  690. var Sz: TSize;
  691. begin
  692. if DC = 0 then
  693. Result := Length( Text )
  694. else
  695. begin
  696. Windows.GetTextExtentPoint32( DC, PChar( Text ), Length( Text ), Sz );
  697. Result := Sz.cx;
  698. end;
  699. end;
  700. function FilePathShortenPixels( const Path: String; DC: HDC; MaxPixels: Integer ): String;
  701. var L0, L1: Integer;
  702. Prev: String;
  703. begin
  704. Result := Path;
  705. L0 := PixelsLength( DC, Result );
  706. while L0 > MaxPixels do
  707. begin
  708. Prev := Result;
  709. L1 := pos( '\...\', Result );
  710. if L1 <= 0 then
  711. Result := ExcludeTrailingPathDelimiter( ExtractFilePath( Result ) )
  712. else
  713. Result := Copy( Result, 1, L1 - 1 );
  714. if Result <> '' then
  715. Result := IncludeTrailingPathDelimiter( ExtractFilePath( Result ) ) + '...\' + ExtractFileName( Path );
  716. if (Result = '') or (Result = Prev) then
  717. begin
  718. L1 := Length( ExtractFilePath( Result ) );
  719. while (PixelsLength( DC, Result ) > MaxPixels) and (L1 > 1) do
  720. begin
  721. Dec( L1 );
  722. Result := Copy( Result, 1, L1 ) + '...\' + ExtractFileName( Result );
  723. end;
  724. if PixelsLength( DC, Result ) > MaxPixels then
  725. begin
  726. L1 := MaxPixels + 1;
  727. while ((MaxPixels > 0) and (L1 > 1) or (MaxPixels = 0) and (L1 > 0)) and
  728. (PixelsLength( DC, Result ) > MaxPixels) do
  729. begin
  730. Dec( L1 );
  731. Result := Copy( ExtractFileName( Path ), 1, L1 ) + '...';
  732. end;
  733. end;
  734. break;
  735. end;
  736. L0 := PixelsLength( DC, Result );
  737. end;
  738. end;
  739. procedure CutFirstDirectory(var S: String);
  740. var
  741. Root: Boolean;
  742. P: Integer;
  743. begin
  744. if S = '\' then
  745. S := ''
  746. else
  747. begin
  748. if S[1] = '\' then
  749. begin
  750. Root := True;
  751. Delete(S, 1, 1);
  752. end
  753. else
  754. Root := False;
  755. if S[1] = '.' then
  756. Delete(S, 1, 4);
  757. P := pos('\',S);
  758. if P <> 0 then
  759. begin
  760. Delete(S, 1, P);
  761. S := '...\' + S;
  762. end
  763. else
  764. S := '';
  765. if Root then
  766. S := '\' + S;
  767. end;
  768. end;
  769. function MinimizeName( const Path: String; DC: HDC; MaxPixels: Integer ): String;
  770. var
  771. Drive, Dir, Name: String;
  772. begin
  773. Result := Path;
  774. Dir := ExtractFilePath(Result);
  775. Name := ExtractFileName(Result);
  776. if (Length(Dir) >= 2) and (Dir[2] = ':') then
  777. begin
  778. Drive := Copy(Dir, 1, 2);
  779. Delete(Dir, 1, 2);
  780. end
  781. else
  782. Drive := '';
  783. while ((Dir <> '') or (Drive <> '')) and (PixelsLength(DC, Result) > MaxPixels) do
  784. begin
  785. if Dir = '\...\' then
  786. begin
  787. Drive := '';
  788. Dir := '...\';
  789. end
  790. else if Dir = '' then
  791. Drive := ''
  792. else
  793. CutFirstDirectory(Dir);
  794. Result := Drive + Dir + Name;
  795. end;
  796. end;
  797. {$IFDEF ASM_VERSION}
  798. function FileSize( const Path : String ) : Integer;
  799. const size_TWin32FindData = sizeof( TWin32FindData );
  800. asm
  801. ADD ESP, - size_TWin32FindData
  802. PUSH ESP
  803. //CALL System.@LStrToPChar // Path must not be ''
  804. PUSH EAX
  805. CALL FindFirstFile
  806. INC EAX
  807. JZ @@exit
  808. DEC EAX
  809. PUSH EAX
  810. CALL FindClose
  811. MOV EAX, [ESP].TWin32FindData.nFileSizeLow
  812. @@exit:
  813. ADD ESP, size_TWin32FindData
  814. end;
  815. {$ELSE ASM_VERSION} //Pascal
  816. function FileSize( const Path : String ) : Integer;
  817. var FD : TWin32FindData;
  818. FH : THandle;
  819. begin
  820. FH := FindFirstFile( PChar( Path ), FD );
  821. Result := 0;
  822. if FH = INVALID_HANDLE_VALUE then exit;
  823. Result := FD.nFileSizeLow;
  824. if ((FD.nFileSizeLow and $80000000) <> 0) or
  825. (FD.nFileSizeHigh <> 0) then Result := -1;
  826. FindClose( FH );
  827. end;
  828. {$ENDIF ASM_VERSION}
  829. //*
  830. function FileTimeCompare( const FT1, FT2 : TFileTime ) : Integer;
  831. var ST1, ST2 : TSystemTime;
  832. begin
  833. FileTimeToSystemTime( FT1, ST1 );
  834. FileTimeToSystemTime( FT2, ST2 );
  835. Result := CompareSystemTime( ST1, ST2 );
  836. end;
  837. function GetSystemDir: String;
  838. var Buf: array[ 0..MAX_PATH ] of Char;
  839. begin
  840. GetSystemDirectory( @ Buf[ 0 ], MAX_PATH + 1 );
  841. Result := IncludeTrailingPathDelimiter( PChar( @ Buf[ 0 ] ) );
  842. end;
  843. //*
  844. function GetWindowsDir : string;
  845. var Buf : array[ 0..MAX_PATH ] of Char;
  846. begin
  847. GetWindowsDirectory( @Buf[ 0 ], MAX_PATH + 1 );
  848. Result := IncludeTrailingPathDelimiter( PChar( @ Buf[ 0 ] ) );
  849. end;
  850. function GetWorkDir : string;
  851. var Buf: array[ 0..MAX_PATH ] of Char;
  852. begin
  853. GetCurrentDirectory( MAX_PATH + 1, @ Buf[ 0 ] );
  854. Result := IncludeTrailingPathDelimiter( PChar( @ Buf[ 0 ] ) );
  855. end;
  856. //*
  857. function GetTempDir : string;
  858. var Buf : array[ 0..MAX_PATH ] of Char;
  859. begin
  860. Windows.GetTempPath( MAX_PATH + 1, @Buf[ 0 ] );
  861. Result := IncludeTrailingPathDelimiter( PChar( @ Buf[ 0 ] ) );
  862. end;
  863. function CreateTempFile( const DirPath, Prefix: String ): String;
  864. var Buf: array[ 0..MAX_PATH ] of Char;
  865. begin
  866. GetTempFileName( PChar( DirPath ), PChar( Prefix ), 0, Buf );
  867. Result := Buf;
  868. end;
  869. function GetFileListStr(FPath{e.g.'c:\tmp\'}, FMask{e.g.'*.*'}: string): string;
  870. {* List of files in string, separating each path from others with semicolon (';').
  871. E.g.: 'c:\tmp\unit1.dcu;c:\tmp\unit1.~pa' (for use with DeleteFile2Recycle())}
  872. var
  873. Srch: TWin32FindData;
  874. flag: Integer;
  875. succ: boolean;
  876. dir:string;
  877. begin
  878. result := '';
  879. if (FPath<>'') and (FPath[length(FPath)]<>'\') then FPath:=FPath+'\';
  880. if (FMask<>'') and (FMask[1]='\') then FMask:=CopyEnd(FMask,2);
  881. dir:=FPath+FMask;
  882. flag := FindFirstFile(PChar(dir), Srch);
  883. succ := flag <> 0;
  884. while succ do begin
  885. if (not (Srch.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY > 0))then begin
  886. if Result<>''then Result:=Result+';';
  887. Result:=Result+FPath+Srch.cFileName;
  888. end;
  889. succ := FindNextFile(Flag, Srch);
  890. end;
  891. FindClose(Flag);
  892. end;
  893. function DeleteFiles( const DirPath: String ): Boolean;
  894. var Files, Name: String;
  895. begin
  896. Files := GetFileListStr( ExtractFilePath( DirPath ), ExtractFileName( DirPath ) );
  897. Result := TRUE;
  898. while Files <> '' do
  899. begin
  900. Name := Parse( Files, ';' );
  901. Result := Result and DeleteFile( PChar( Name ) );
  902. end;
  903. end;
  904. //*
  905. function DeleteFile2Recycle( const Filename : String ) : Boolean;
  906. var FOS : TSHFileOpStruct;
  907. Buf : PChar;
  908. L : Integer;
  909. begin
  910. L := Length( Filename );
  911. GetMem( Buf, L + 2 );
  912. StrCopy( Buf, PChar( Filename ) );
  913. Buf[ L + 1 ] := #0;
  914. for L := L downto 0 do
  915. if Buf[ L ] = ';' then Buf[ L ] := #0;
  916. FillChar( FOS, Sizeof( FOS ), 0 );
  917. if Applet <> nil then
  918. FOS.Wnd := Applet.Handle;
  919. FOS.wFunc := FO_DELETE;
  920. FOS.pFrom := Buf;
  921. FOS.fFlags := FOF_ALLOWUNDO or FOF_NOCONFIRMATION;
  922. FOS.fAnyOperationsAborted := True;
  923. FOS.lpszProgressTitle := PChar( 'Delete ' + Filename + ' to Recycle bin' );
  924. Result := SHFileOperation( FOS ) = 0;
  925. if Result then
  926. Result := not FOS.fAnyOperationsAborted;
  927. FreeMem( Buf );
  928. end;
  929. function CopyMoveFiles( const FromList, ToList: String; Move: Boolean ): Boolean;
  930. var FOS : TSHFileOpStruct;
  931. Buf : PChar;
  932. L : Integer;
  933. begin
  934. L := Length( FromList );
  935. GetMem( Buf, L + 2 );
  936. StrCopy( Buf, PChar( FromList ) );
  937. Buf[ L + 1 ] := #0;
  938. for L := L downto 0 do
  939. if Buf[ L ] = ';' then Buf[ L ] := #0;
  940. FillChar( FOS, Sizeof( FOS ), 0 );
  941. if Applet <> nil then
  942. FOS.Wnd := Applet.Handle;
  943. if Move then
  944. begin
  945. FOS.wFunc := FO_MOVE;
  946. FOS.lpszProgressTitle := PChar( 'Move files' );
  947. end
  948. else
  949. begin
  950. FOS.wFunc := FO_COPY;
  951. FOS.lpszProgressTitle := PChar( 'Copy files' );
  952. end;
  953. FOS.pFrom := Buf;
  954. FOS.pTo := PChar( ToList + #0 );
  955. FOS.fFlags := FOF_ALLOWUNDO;
  956. FOS.fAnyOperationsAborted := True;
  957. Result := SHFileOperation( FOS ) = 0;
  958. if Result then
  959. Result := not FOS.fAnyOperationsAborted;
  960. FreeMem( Buf );
  961. end;
  962. {-}
  963. function DiskFreeSpace( const Path: String ): I64;
  964. type TGetDFSEx = function( Path: PChar; CallerFreeBytes, TotalBytes, FreeBytes: Pointer )
  965. : Bool; stdcall;
  966. var GetDFSEx: TGetDFSEx;
  967. Kern32: THandle;
  968. V: TOSVersionInfo;
  969. Ex: Boolean;
  970. SpC, BpS, NFC, TNC: DWORD;
  971. FBA, TNB: I64;
  972. begin
  973. GetDFSEx := nil;
  974. V.dwOSVersionInfoSize := Sizeof( V );
  975. GetVersionEx( V );
  976. Ex := FALSE;
  977. if V.dwPlatformId = VER_PLATFORM_WIN32_NT then
  978. begin
  979. Ex := V.dwMajorVersion >= 4;
  980. end
  981. else
  982. if V.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS then
  983. begin
  984. Ex := V.dwMajorVersion > 4;
  985. if not Ex then
  986. if V.dwMajorVersion = 4 then
  987. begin
  988. Ex := V.dwMinorVersion > 0;
  989. if not Ex then
  990. Ex := LoWord( V.dwBuildNumber ) >= $1111;
  991. end;
  992. end;
  993. if Ex then
  994. begin
  995. Kern32 := GetModuleHandle( 'kernel32.dll' );
  996. GetDFSEx := GetProcAddress( Kern32, 'GetDiskFreeSpaceExA' );
  997. end;
  998. if Assigned( GetDFSEx ) then
  999. GetDFSEx( PChar( Path ), @ FBA, @ TNB, @Result )
  1000. else
  1001. begin
  1002. GetDiskFreeSpace( PChar( Path ), SpC, BpS, NFC, TNC );
  1003. Result := Mul64i( MakeInt64( SpC * BpS, 0 ), NFC );
  1004. end;
  1005. end;
  1006. {+}
  1007. //*
  1008. function GetUniqueFilename( PathName: string ) : String;
  1009. var Path, Nam, Ext : String;
  1010. I, J, K : Integer;
  1011. begin
  1012. Result := PathName;
  1013. Path := ExtractFilePath( PathName );
  1014. if not DirectoryExists( Path ) then Exit;
  1015. Nam := ExtractFileNameWOext( PathName );
  1016. if Nam = '' then
  1017. begin
  1018. if Path[ Length( Path ) ] = '\' then
  1019. Path := Copy( Path, 1, Length( Path ) - 1 );
  1020. PathName := Path;
  1021. Result := Path;
  1022. end;
  1023. Nam := ExtractFileNameWOext( PathName );
  1024. Ext := ExtractFileExt( PathName );
  1025. I := Length( Nam );
  1026. for J := I downto 1 do
  1027. if not (Nam[ J ] in [ '0'..'9' ]) then
  1028. begin
  1029. I := J;
  1030. break;
  1031. end;
  1032. K := Str2Int( CopyEnd( Nam, I + 1 ) );
  1033. while FileExists( Result ) do
  1034. begin
  1035. Inc( K );
  1036. Result := Path + Copy( Nam, 1, I ) + Int2Str( K ) + Ext;
  1037. end;
  1038. end;
  1039. {$IFDEF ASM_VERSION}
  1040. function GetStartDir : String;
  1041. asm
  1042. PUSH EBX
  1043. MOV EBX, EAX
  1044. XOR EAX, EAX
  1045. MOV AH, 2
  1046. SUB ESP, EAX
  1047. MOV EDX, ESP
  1048. PUSH EAX
  1049. PUSH EDX
  1050. PUSH 0
  1051. CALL GetModuleFileName
  1052. LEA EDX, [ESP + EAX]
  1053. @@1: DEC EDX
  1054. CMP byte ptr [EDX], '\'
  1055. JNZ @@1
  1056. INC EDX
  1057. MOV byte ptr [EDX], 0
  1058. MOV EAX, EBX
  1059. MOV EDX, ESP
  1060. CALL System.@LStrFromPChar
  1061. ADD ESP, 200h
  1062. POP EBX
  1063. end;
  1064. {$ELSE ASM_VERSION} //Pascal
  1065. function GetStartDir : String;
  1066. var Buffer:array[0..260] of Char;
  1067. I : Integer;
  1068. begin
  1069. I := GetModuleFileName( 0, Buffer, Sizeof( Buffer ) );
  1070. for I := I downto 0 do
  1071. if Buffer[ I ] = '\' then
  1072. begin
  1073. Buffer[ I + 1 ] := #0;
  1074. break;
  1075. end;
  1076. Result := Buffer;
  1077. end;
  1078. {$ENDIF ASM_VERSION}
  1079. //{$ENDIF LINUX/WIN32}