Componentes.Terceros.jcl/official/1.100/devtools/JConvert/JConvertUtils.pas

238 lines
7.3 KiB
ObjectPascal

unit JConvertUtils;
interface
procedure Run;
implementation
uses
Windows, Classes, SysUtils, JvSearchFiles, JvJCLUtils, JvJVCLUtils, JTools;
procedure ShowHelp;
begin
writeln('Usage: ', ExtractFileName(ParamStr(0)),
' [-i] [-s] [-t | -b] <filespec(s) | @filelist>');
writeln(#9'-i', #9, 'Convert files in-place (output overwrites input)');
writeln(#9'-s', #9, 'Recurse subdirectories');
writeln(#9'-t', #9, 'Convert to text');
writeln(#9'-b', #9, 'Convert to binary');
writeln(#9'-c', #9, 'Check without converting');
writeln(#9'-v', #9, 'Verbose output');
writeln('');
writeln('');
writeln('This program differs from Borland''s Convert utility in two ways:');
writeln('');
writeln('1. Only if a file is changed, is it written back to disk.');
writeln(#9'This is essential when working with VCS systems.');
writeln('');
writeln('2. You can use the -c option to check how many files would be converted,');
writeln(#9, 'without actually making the conversion.');
end;
function InternalConvertDFM(InPlace, BinToTxt, Simulate, Verbose: boolean; const Filename: string): integer;
var
AFormat: TStreamOriginalFormat;
InFile, OutFile: TFileStream;
TmpStream: TMemoryStream;
ShortFilename: string;
function GetOutName(const AName: string; InPlace: boolean): string;
begin
if InPlace then
Result := AName
else
Result := ChangeFileExt(AName, '.txt');
end;
function IsTextResource(Stream: TStream): boolean;
var
Signature: integer;
begin
Stream.Read(Signature, sizeof(Signature));
Result := (Char(Signature) in [#9, #11, #13, ' ', 'o', 'O', 'i', 'I']);
Stream.Seek(-sizeof(Signature), soFromCurrent);
end;
begin
Result := 0;
ShortFilename := ExtractRelativePath(IncludeTrailingPathDelimiter(GetCurrentDir), Filename);
if (GetFileAttributes(PChar(Filename)) and FILE_ATTRIBUTE_READONLY <> 0) and not Simulate then
begin
writeln('WARNING: ', ShortFilename, ' is read-only (NOT converted).');
Exit;
end;
if Verbose then
writeln('Reading ', ShortFilename);
AFormat := sofUnknown;
try
InFile := TFileStream.Create(Filename, fmOpenRead or fmShareDenyNone);
TmpStream := TMemoryStream.Create;
try
if BinToTxt then
begin
if IsTextResource(InFile) then
Exit;
ObjectResourceToText(InFile, TmpStream, AFormat);
if AFormat = sofBinary then
begin
FreeAndNil(InFile);
TmpStream.Seek(0, soFromBeginning);
if Verbose then
begin
if not Simulate then
writeln('Writing ', GetOutName(ShortFileName, InPlace))
else
writeln('Is Binary: ', ShortFileName)
end;
if not Simulate then
begin
OutFile := TFileStream.Create(getOutName(Filename, InPlace), fmCreate);
try
OutFile.CopyFrom(TmpStream, 0);
finally
FreeAndNil(OutFile);
end;
end;
Result := 1;
end;
end
else
begin
if not IsTextResource(InFile) then
Exit;
ObjectTextToResource(InFile, TmpStream, AFormat);
if AFormat = sofText then
begin
FreeAndNil(InFile);
TmpStream.Seek(0, soFromBeginning);
if Verbose and not Simulate then
begin
if not Simulate then
writeln('Writing ', GetOutName(ShortFileName, InPlace))
else
writeln('Is Text: ', ShortFileName)
end;
if not Simulate then
begin
OutFile := TFileStream.Create(GetOutName(Filename, InPlace), fmCreate);
try
OutFile.CopyFrom(TmpStream, 0);
finally
FreeAndNil(OutFile);
end;
end;
Result := 1;
end;
end;
finally
InFile.Free;
TmpStream.Free;
end;
except
on E: Exception do
writeln('ERROR: (', E.Message, ') in ', ShortFilename);
end;
end;
function ConvertDFM(SubDirs, Inplace, BinToTxt, Simulate, Verbose: boolean; FileSpecs:
TStringlist; var TotalCount:integer): integer;
var F: TJvSearchFiles;
i, j: integer;
begin
Result := 0;
F := TJvSearchFiles.Create(nil);
try
if SubDirs then
F.DirOption := doIncludeSubDirs
else
F.DirOption := doExcludeSubDirs;
F.Options := F.Options - [soStripDirs];
if Verbose then
writeln('Building file list, please wait...');
for i := 0 to FileSpecs.Count - 1 do
begin
F.RootDirectory := ExtractFilePath(FileSpecs[i]);
if F.RootDirectory = '' then
F.RootDirectory := GetCurrentDir
else
F.RootDirectory := ExpandUNCFileName(F.RootDirectory);
F.DirParams.FileMask := '*.*';
F.FileParams.FileMask := ExtractFilename(FileSpecs[i]);
F.FileParams.SearchTypes := [stFileMask];
if F.FileParams.FileMask = '' then
F.FileParams.FileMask := '*.dfm';
F.Search;
TotalCount := F.Files.Count;
for j := 0 to F.Files.Count - 1 do
Inc(Result, InternalConvertDFM(Inplace, BinToTxt, Simulate, Verbose, F.Files[j]));
end;
finally
F.Free;
end;
end;
procedure Run;
var
DoSubDirs, DoInplace, DoBinToTxt, DoSimulate, DoVerbose: boolean;
Path: string;
i,TotalCount: integer;
FileSpecs: TStringlist;
begin
{ Command switches:
-s do subdirs
-i write inpace
-t bin -> txt
-b txt -> bin
-c simulate
-v verbose output
}
// always tell them who we are:
try
writeln('JEDI Form Conversion Utility Version 1.0');
if (ParamCount < 1) or GetCmdSwitchValue('?', ['-', '/'], Path, true) or
GetCmdSwitchValue('h', ['-', '/'], Path, true) then
ShowHelp
else
begin
FileSpecs := TStringlist.Create;
try
// Path is used as dummy here
DoSubDirs := GetCmdSwitchValue('s', ['-', '/'], Path, true);
DoInplace := GetCmdSwitchValue('i', ['-', '/'], Path, true);
DoBinToTxt := GetCmdSwitchValue('t', ['-', '/'], Path, true);
DoSimulate := GetCmdSwitchValue('c', ['-', '/'], Path, true);
DoVerbose := GetCmdSwitchValue('v', ['-', '/'], Path, true);
// Path is actually used here
if not GetCmdSwitchValue('@', [], Path, true) then
begin
for i := 1 to ParamCount do // we must still read entire command line to find any filespecs
if not (ParamStr(i)[1] in ['-', '/', '@']) then
FileSpecs.Add(ParamStr(i));
end
else if FileExists(Path) then // load file specs from a file
FileSpecs.LoadFromFile(Path);
if FileSpecs.Count = 0 then
writeln('ERROR: no files specified')
else
begin
i := ConvertDFM(DoSubDirs, DoInplace, DoBinToTxt, DoSimulate, DoVerbose, FileSpecs,TotalCount);
if DoSimulate then
writeln(TotalCount,' file(s) found, ',i, ' file(s) should have been converted')
else
writeln(TotalCount,' file(s) found, ',i, ' file(s) converted');
end;
finally
FileSpecs.Free;
end;
end;
except
on E: Exception do
writeln('ERROR: ', E.Message);
end;
end;
end.