diff options
Diffstat (limited to 'UChecksumDruid.pas')
| -rw-r--r-- | UChecksumDruid.pas | 629 |
1 files changed, 629 insertions, 0 deletions
diff --git a/UChecksumDruid.pas b/UChecksumDruid.pas new file mode 100644 index 0000000..81266f6 --- /dev/null +++ b/UChecksumDruid.pas @@ -0,0 +1,629 @@ +(* + Tux Commander - UChecksumDruid - Checksum calculation druid + Copyright (C) 2004 Tomas Bzatek <tbzatek@users.sourceforge.net>
+ Check for updates on tuxcmd.sourceforge.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*) +unit UChecksumDruid; + +interface + +uses + glib2, gdk2, gtk2, SysUtils, Types, Classes, Variants, GTKControls, GTKForms, GTKStdCtrls, GTKExtCtrls, GTKConsts, + GTKView, GTKText, GTKUtils, + UEngines; + +type + TFChecksumDruid = class(TGTKDialog) + CancelButton, BackButton, ForwardButton: TGTKButton; + ButtonBox: TGTKHButtonBox; + TitleLabel, Page1Label, Page4Label, FilenameLabel, Page6Label, Page7Label, ProcessingLabel, Page6Spacer, ErrorLabel: TGTKLabel; + TitleLabelBox, PageAreaColor, LeftSpacer, Page2Color, Page3Color, Page4Color, Page5Color, Page6Color, LeftSpacer7: TGTKEventBox; + Page1, FileNameHBox, SeparateFileCheckHBox, Page7, ProgressHBox, ErrorTextViewHBox: TGTKHBox; + Page2, Page3, Page4, Page5, Page6: TGTKEventBox; + DruidArea, PageArea, Page2ClientArea, Page3ClientArea, Page5ClientArea, Page6ClientArea: TGTKVBox; + FileNameEntry: TGTKEntry; + SeparateFileCheckBox: TGTKCheckButton; + SFVRadioButton, MD5RadioButton: TGTKRadioButton; + Progress: TGTKProgressBar; + ErrorLabelScrolledWindow: TGTKScrolledWindow; + procedure FormCreate(Sender: TObject); override; + procedure FormDestroy(Sender: TObject); + procedure FormResponse(Sender: TObject; const ResponseID: integer); + procedure CancelButtonClick(Sender: TObject); + procedure BackButtonClick(Sender: TObject); + procedure ForwardButtonClick(Sender: TObject); + procedure FileNameEntryChanged(Sender: TObject); + procedure SeparateFileCheckBoxToggled(Sender: TObject); + procedure FormKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean); + private + ColorFG, ColorBG, ColorGray: PGdkColor; + CurrentPage: integer; + Processing, Stop, StopBreak: boolean; + Buffer: Pointer; + FileDes: TEngineFileDes; + BufferPos: integer; + procedure CreatePages; + procedure SetCurrentPage(const Num: integer; const GoingForward: boolean); + procedure Process; + function ProcessFile(const FName: string; const IsItSFV: boolean; var HashString: string): boolean; + procedure CheckStop; + procedure WriteLine(const FName, CheckedFName, HashString: string; const IsItSFV, CreateFile, CloseFile: boolean); + procedure WriteSFVComment(const FName: string); + public + Engine: TPanelEngine; + FileNames: TStringList; + DirName: string; + end; + +const NumPages = 7; + +var + FChecksumDruid: TFChecksumDruid; + +implementation + +uses ULocale, UCoreUtils, Libc, UCore, DateUtils, UConfig, StrUtils; + + +procedure TFChecksumDruid.FormCreate(Sender: TObject); +begin + CurrentPage := 0; + Processing := False; + Stop := False; + StopBreak := False; + Buffer := nil; + BufferPos := 0; + SetDefaultSize(400, 210); + Caption := LANGCreateChecksumsCaption; + OnDestroy := FormDestroy; + OnResponse := FormResponse; + FileNames := TStringList.Create; + ShowSeparator := False; + Buttons := []; + ActionArea.SetSizeRequest(0, 0); + DruidArea := TGTKVBox.Create(Self); + DruidArea.BorderWidth := 2; + ClientArea.AddControlEx(DruidArea, True, True, 0); + CancelButton := TGTKButton.CreateFromStock(Self, 'gtk-cancel'); + CancelButton.OnClick := CancelButtonClick; + BackButton := TGTKButton.CreateFromStock(Self, 'gtk-go-back'); + BackButton.OnClick := BackButtonClick; + ForwardButton := TGTKButton.CreateFromStock(Self, 'gtk-go-forward'); + ForwardButton.OnClick := ForwardButtonClick; + ButtonBox := TGTKHButtonBox.Create(Self); + ButtonBox.Layout := blEnd; + ButtonBox.Spacing := 10; + ButtonBox.BorderWidth := 5; + ButtonBox.AddControlEx(CancelButton, False, False, 0); + ButtonBox.AddControlEx(BackButton, False, False, 0); + ButtonBox.AddControlEx(ForwardButton, False, False, 0); + ClientArea.AddControlEndEx(ButtonBox, False, False, 0); + ColorFG := GetDefaultForegroundColor(3); + ColorBG := GetDefaultBackgroundColor(3); + ColorGray := GetDefaultBackgroundColor(2); + TitleLabel := TGTKLabel.Create(Self); + TitleLabelBox := TGTKEventBox.Create(Self); + TitleLabelBox.AddControl(TitleLabel); + TitleLabelBox.BorderWidth := 0; + TitleLabel.SetAlignment(0, 0.5); + TitleLabel.SetPadding(5, 5); + TitleLabel.SetForegroundColor(ColorFG); + TitleLabelBox.SetBackgroundColor(ColorBG); + DruidArea.AddControlEx(TitleLabelBox, False, False, 0); + PageAreaColor := TGTKEventBox.Create(Self); + PageAreaColor.SetBackgroundColor(ColorGray); + PageArea := TGTKVBox.Create(Self); + PageAreaColor.AddControl(PageArea); + DruidArea.AddControlEx(PageAreaColor, True, True, 0); + + CreatePages; + + SetCurrentPage(1, True); + OnKeyDown := FormKeyDown; +end; + +procedure TFChecksumDruid.FormDestroy(Sender: TObject); +begin + FileNames.Free; +end; + +procedure TFChecksumDruid.FormResponse(Sender: TObject; const ResponseID: integer); +begin + Stop := True; +end; + +procedure TFChecksumDruid.FormKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean); +begin +// if Key = GDK_ESCAPE then ModalResult := mbCancel; + if (Key = GDK_RETURN) or (Key = GDK_KP_ENTER) then ForwardButtonClick(Sender); +end; + +procedure TFChecksumDruid.CreatePages; +begin + Page1 := TGTKHBox.Create(Self); + Page1.Homogeneous := False; + LeftSpacer := TGTKEventBox.Create(Self); + LeftSpacer.SetBackgroundColor(ColorBG); + LeftSpacer.SetSizeRequest(100, -1); + Page1Label := TGTKLabel.Create(Self); + Page1Label.LineWrap := True; + Page1Label.SetAlignment(0.5, 0.5); + Page1Label.Caption := LANGCCHKSUMPage1Text; + Page1.AddControlEx(LeftSpacer, False, False, 0); + Page1.AddControlEx(Page1Label, True, True, 0); + + Page2 := TGTKEventBox.Create(Self); + Page2.SetBackgroundColor(0, 0, 0); + Page2Color := TGTKEventBox.Create(Self); + Page2Color.BorderWidth := 1; + Page2Color.SetBackgroundColor(ColorGray); + Page2.AddControl(Page2Color); + Page2ClientArea := TGTKVBox.Create(Self); + Page2Color.AddControl(Page2ClientArea); + SFVRadioButton := TGTKRadioButton.Create(Self); + SFVRadioButton.Caption := LANGCCHKSUMSFVFile; + MD5RadioButton := TGTKRadioButton.Create(Self); + MD5RadioButton.Caption := LANGCCHKSUMMD5sumFile; + MD5RadioButton.SetRadioGroup(SFVRadioButton); + SFVRadioButton.Checked := True; + Page2ClientArea.AddControlEx(SFVRadioButton, False, False, 3); + Page2ClientArea.AddControlEx(MD5RadioButton, False, False, 3); + Page2ClientArea.BorderWidth := 30; + + Page3 := TGTKEventBox.Create(Self); + Page3.SetBackgroundColor(0, 0, 0); + Page3Color := TGTKEventBox.Create(Self); + Page3Color.BorderWidth := 1; + Page3Color.SetBackgroundColor(ColorGray); + Page3.AddControl(Page3Color); + Page3ClientArea := TGTKVBox.Create(Self); + Page3Color.AddControl(Page3ClientArea); + FilenameLabel := TGTKLabel.Create(Self); + FilenameLabel.Caption := LANGCCHKSUMFileName; + FilenameLabel.UseUnderline := True; + FileNameEntry := TGTKEntry.Create(Self); + FileNameEntry.Text := 'checksums.sfv'; + FileNameEntry.SetSizeRequest(215, -1); + FileNameEntry.OnChanged := FileNameEntryChanged; + FilenameLabel.FocusControl := FileNameEntry; + SeparateFileCheckBox := TGTKCheckButton.CreateWithLabel(Self, LANGCCHKSUMCreateSeparateChecksumFiles); + SeparateFileCheckBox.OnToggled := SeparateFileCheckBoxToggled; + Page3ClientArea.BorderWidth := 30; + FileNameHBox := TGTKHBox.Create(Self); + FileNameHBox.Homogeneous := False; + FileNameHBox.AddControlEx(FilenameLabel, False, False, 5); + FileNameHBox.AddControlEx(FileNameEntry, False, False, 5); + Page3ClientArea.AddControlEx(FileNameHBox, False, False, 0); + SeparateFileCheckHBox := TGTKHBox.Create(Self); + SeparateFileCheckHBox.Homogeneous := False; + SeparateFileCheckHBox.AddControlEx(SeparateFileCheckBox, False, False, 20); + SeparateFileCheckHBox.AddControlEx(TGTKLabel.Create(Self), True, True, 0); + Page3ClientArea.AddControlEx(SeparateFileCheckHBox, False, False, 5); + + Page4 := TGTKEventBox.Create(Self); + Page4.SetBackgroundColor(0, 0, 0); + Page4Color := TGTKEventBox.Create(Self); + Page4Color.BorderWidth := 1; + Page4Color.SetBackgroundColor(ColorGray); + Page4.AddControl(Page4Color); + Page4Label := TGTKLabel.Create(Self); + Page4Label.LineWrap := True; + Page4Label.SetAlignment(0.5, 0.5); + Page4Label.Caption := LANGCCHKSUMPage4Text; + Page4Color.AddControl(Page4Label); + + Page5 := TGTKEventBox.Create(Self); + Page5.SetBackgroundColor(0, 0, 0); + Page5Color := TGTKEventBox.Create(Self); + Page5Color.BorderWidth := 1; + Page5Color.SetBackgroundColor(ColorGray); + Page5.AddControl(Page5Color); + Page5ClientArea := TGTKVBox.Create(Self); + Page5Color.AddControl(Page5ClientArea); + ProcessingLabel := TGTKLabel.Create(Self); + ProcessingLabel.Caption := Format(LANGCCHKSUMNowProcessingFileS, ['---']); + ProcessingLabel.XPadding := 20; + ProcessingLabel.XAlign := 0; + ProcessingLabel.YPadding := 10; + ProcessingLabel.SetSizeRequest(10, -1); + Page5ClientArea.AddControlEx(ProcessingLabel, False, False, 10); + ProgressHBox := TGTKHBox.Create(Self); + Progress := TGTKProgressBar.Create(Self); + ProgressHBox.AddControlEx(Progress, True, True, 20); + Page5ClientArea.AddControlEx(ProgressHBox, True, True, 10); + Page5ClientArea.AddControlEx(TGTKLabel.Create(Self), True, True, 0); + + Page6 := TGTKEventBox.Create(Self); + Page6.SetBackgroundColor(0, 0, 0); + Page6Color := TGTKEventBox.Create(Self); + Page6Color.BorderWidth := 1; + Page6Color.SetBackgroundColor(ColorGray); + Page6.AddControl(Page6Color); + Page6Label := TGTKLabel.Create(Self); + Page6Label.LineWrap := True; + Page6Label.SetAlignment(0.5, 0.4); + Page6Label.Caption := LANGCCHKSUMPage6Text; + Page6Label.UseMarkup := True; + Page6Label.XAlign := 0.05; + Page6Label.YAlign := 0; + Page6Spacer := TGTKLabel.Create(Self); + Page6Spacer.SetSizeRequest(-1, 6); + Page6ClientArea := TGTKVBox.Create(Self); + Page6ClientArea.AddControlEx(Page6Spacer, False, False, 0); + Page6ClientArea.AddControlEx(Page6Label, False, False, 0); + Page6Color.AddControl(Page6ClientArea); + ErrorLabel := TGTKLabel.Create(Self); + ErrorLabel.Selectable := True; + ErrorLabel.SetAlignment(0, 0); + ErrorLabel.SetPadding(2, 2); + ErrorLabel.Alignment := taLeftJustify; + ErrorLabelScrolledWindow := TGTKScrolledWindow.Create(Self); + ErrorLabelScrolledWindow.HorizScrollBarPolicy := sbAutomatic; + ErrorLabelScrolledWindow.VertScrollBarPolicy := sbAutomatic; + ErrorLabelScrolledWindow.AddWithViewPort(ErrorLabel); + ErrorTextViewHBox := TGTKHBox.Create(Self); + ErrorTextViewHBox.AddControlEx(ErrorLabelScrolledWindow, True, True, 25); + Page6ClientArea.AddControlEx(ErrorTextViewHBox, True, True, 10); + + Page7 := TGTKHBox.Create(Self); + Page7.Homogeneous := False; + LeftSpacer7 := TGTKEventBox.Create(Self); + LeftSpacer7.SetBackgroundColor(ColorBG); + LeftSpacer7.SetSizeRequest(100, -1); + Page7Label := TGTKLabel.Create(Self); + Page7Label.LineWrap := True; + Page1Label.SetAlignment(0.5, 0.5); + Page7Label.Caption := LANGCCHKSUMPage7Text; + Page7.AddControlEx(LeftSpacer7, False, False, 0); + Page7.AddControlEx(Page7Label, True, True, 0); + + PageArea.AddControlEx(Page1, True, True, 0); + PageArea.AddControlEx(Page2, True, True, 0); + PageArea.AddControlEx(Page3, True, True, 0); + PageArea.AddControlEx(Page4, True, True, 0); + PageArea.AddControlEx(Page5, True, True, 0); + PageArea.AddControlEx(Page6, True, True, 0); + PageArea.AddControlEx(Page7, True, True, 0); +end; + + +(********************************************************************************************************************************) +procedure TFChecksumDruid.SetCurrentPage(const Num: integer; const GoingForward: boolean); +const Ext: array[boolean] of string = ('.md5', '.sfv'); +var s: string; + i: TEngineFileDes; + Error: integer; +begin + // A simple test before we can continue + if (CurrentPage = 3) and (not SeparateFileCheckBox.Checked) and GoingForward then begin + s := UTF8ToANSI(FileNameEntry.Text); + i := Engine.OpenFile(s, omWrite, Error); + if Error <> 0 then begin + Application.MessageBox(Format(LANGCCHKSUMAnErrorOccuredWhileOpeningFileSS, [ANSIToUTF8(ExtractFileName(s)), ANSIToUTF8(GetErrorString(Error))]), + [mbOK], mbError, mbNone, mbOK); + Exit; + end; + Engine.CloseFile(i); + end; + // Changing page + CurrentPage := Num; + if CurrentPage < 1 then CurrentPage := 1; + if CurrentPage > NumPages then CurrentPage := NumPages; + case CurrentPage of + 1: TitleLabel.SetMarkup(LANGCCHKSUMPage1Title); + 2: TitleLabel.SetMarkup(LANGCCHKSUMPage2Title); + 3: TitleLabel.SetMarkup(LANGCCHKSUMPage3Title); + 4: TitleLabel.SetMarkup(LANGCCHKSUMPage4Title); + 5: TitleLabel.SetMarkup(LANGCCHKSUMPage5Title); + 6: TitleLabel.SetMarkup(LANGCCHKSUMPage6Title); + 7: TitleLabel.SetMarkup(LANGCCHKSUMPage7Title); + end; + Page1.Visible := CurrentPage = 1; + Page2.Visible := CurrentPage = 2; + Page3.Visible := CurrentPage = 3; + Page4.Visible := CurrentPage = 4; + Page5.Visible := CurrentPage = 5; + Page6.Visible := CurrentPage = 6; + Page7.Visible := CurrentPage = 7; + BackButton.Enabled := CurrentPage > 1; + ForwardButton.Enabled := CurrentPage < NumPages; + if CurrentPage < NumPages then begin + if not ForwardButton.UseStock then ForwardButton.Caption := 'gtk-go-forward'; + ForwardButton.UseStock := True; + end else begin + ForwardButton.UseStock := False; + ForwardButton.Caption := LANGCCHKSUMFinishCaption; + end; + // after page changed + case CurrentPage of + 1: ForwardButton.SetFocus; + 2: if SFVRadioButton.Checked then SFVRadioButton.SetFocus + else MD5RadioButton.SetFocus; + 3: begin + SeparateFileCheckBox.Visible := MD5RadioButton.Checked and (FileNames.Count > 1); + FileNameEntry.Enabled := (not SeparateFileCheckBox.Checked) or (not SeparateFileCheckBox.Visible); + if FileNames.Count = 1 + then FileNameEntry.Text := ANSIToUTF8(ExtractFileName(FileNames[0]) + Ext[SFVRadioButton.Checked]) + else FileNameEntry.Text := ANSIToUTF8(DirName + Ext[SFVRadioButton.Checked]); + FileNameEntry.SetFocus; + FileNameEntryChanged(Self); + end; + 4: ForwardButton.SetFocus; + 5: Process; + 6: begin + BackButton.SetFocus; + ForwardButton.Enabled := False; + s := ErrorLabel.Caption; + if (Length(s) > 1) and (s[Length(s)] = #10) then Delete(s, Length(s), 1); + ErrorLabel.Caption := s; + end; + 7: begin + BackButton.Enabled := False; + CancelButton.Enabled := False; + ForwardButton.Enabled := True; + ForwardButton.SetFocus; + end; + end; +end; + +procedure TFChecksumDruid.CancelButtonClick(Sender: TObject); +begin + ModalResult := mbCancel; +end; + +procedure TFChecksumDruid.BackButtonClick(Sender: TObject); +begin + SetCurrentPage(CurrentPage - 1 - Ord(CurrentPage = 6), False); +end; + +procedure TFChecksumDruid.ForwardButtonClick(Sender: TObject); +begin + if CurrentPage = 7 then ModalResult := mbOK + else SetCurrentPage(CurrentPage + 1, True); +end; + +procedure TFChecksumDruid.FileNameEntryChanged(Sender: TObject); +begin + ForwardButton.Enabled := Length(Trim(FileNameEntry.Text)) > 0; +end; + +procedure TFChecksumDruid.SeparateFileCheckBoxToggled(Sender: TObject); +begin + FileNameEntry.Enabled := not SeparateFileCheckBox.Checked; +end; + +(********************************************************************************************************************************) +procedure TFChecksumDruid.CheckStop; +begin + if Stop and (not StopBreak) then + if Application.MessageBox(LANGCCHKSUMAreYouSureYouWantToAbortTheProcessing, [mbYes, mbNo], mbQuestion, mbNone, mbNo) = mbYes + then StopBreak := True + else begin Stop := False; StopBreak := False; end; +end; + +procedure TFChecksumDruid.Process; +const Ext: array[boolean] of string = ('.md5', '.sfv'); +var i: integer; + MaxSize, LastValue: Int64; + Stat: PDataItemSL; + s, s2: string; +begin + if FileNames.Count = 0 then begin + SetCurrentPage(7, True); + Exit; + end; + FileNames.Sorted := True; + CancelButton.SetFocus; + ForwardButton.Enabled := False; + BackButton.Enabled := False; + Processing := True; + Stop := False; + StopBreak := False; + ErrorLabel.Caption := ''; + Application.ProcessMessages; + + // Compute maximal size of selected files + MaxSize := 0; + for i := 0 to FileNames.Count - 1 do begin + Stat := Engine.GetFileInfoSL(FileNames[i]); + if Assigned(Stat) then Inc(MaxSize, Stat.Size); + end; + Progress.Max := MaxSize; + Progress.Value := 0; + Progress.Text := '0 %'; + + if SFVRadioButton.Checked then WriteSFVComment(ProcessPattern(Engine, UTF8ToANSI(FileNameEntry.Text), IncludeTrailingPathDelimiter(ExtractFilePath(FileNames[0])), '', False)); + // Process each file + for i := 0 to FileNames.Count - 1 do begin + ProcessingLabel.Caption := Format(LANGCCHKSUMNowProcessingFileS, [ANSIToUTF8(ExtractFileName(FileNames[i]))]); + LastValue := Progress.Value; + Stat := Engine.GetFileInfoSL(FileNames[i]); + Application.ProcessMessages; + try + if ProcessFile(FileNames[i], SFVRadioButton.Checked, s) then begin + if not SeparateFileCheckBox.Checked + then s2 := ProcessPattern(Engine, UTF8ToANSI(FileNameEntry.Text), IncludeTrailingPathDelimiter(ExtractFilePath(FileNames[0])), '', False) + else s2 := IncludeTrailingPathDelimiter(ExtractFilePath(FileNames[i])) + ExtractFileName(FileNames[i]) + Ext[SFVRadioButton.Checked]; + WriteLine(s2, FileNames[i], s, SFVRadioButton.Checked, ((i = 0) and MD5RadioButton.Checked) or SeparateFileCheckBox.Checked, + (i = FileNames.Count - 1) or SeparateFileCheckBox.Checked); + end; + except end; + if Assigned(Stat) then Progress.Value := LastValue + Stat.Size; + Progress.Text := Format('%d %%', [Trunc(Progress.Fraction * 100)]); + Application.ProcessMessages; + CheckStop; + if StopBreak then Break; + end; + + Application.ProcessMessages; + Processing := False; + Stop := False; + StopBreak := False; + Application.ProcessMessages; + SetCurrentPage(7 - Ord(ErrorLabel.Caption <> ''), ErrorLabel.Caption = ''); +end; + +function TFChecksumDruid.ProcessFile(const FName: string; const IsItSFV: boolean; var HashString: string): boolean; +const ChksumBlockSize = 65536*4; +var FD: TEngineFileDes; + Error, Count: integer; + Buffer: Pointer; + CRC: LongWord; + MD5Hash: THash_MD5; +begin + HashString := ''; + Result := False; + try + Buffer := Libc.malloc(ChksumBlockSize); + Libc.memset(Buffer, 0, ChksumBlockSize); + except + ErrorLabel.Caption := ErrorLabel.Caption + LANGAnErrorOccuredWhileInitializingMemoryBlock + #10; + Exit; + end; + CRC := $FFFFFFFF; + MD5Hash := nil; + if not IsItSFV then MD5Hash := THash_MD5.Create; + + FD := Engine.OpenFile(FName, omRead, Error); + if Error <> 0 then begin + ErrorLabel.Caption := ErrorLabel.Caption + Format(LANGCCHKSUMAnErrorOccuredWhileOpeningFileSS, [ANSIToUTF8(ExtractFileName(FName)), ANSIToUTF8(GetErrorString(Error))]); + Exit; + end; + repeat + Count := Engine.ReadFile(FD, Buffer, ChksumBlockSize, Error); + if Error <> 0 then begin + ErrorLabel.Caption := ErrorLabel.Caption + Format(LANGCCHKSUMAnErrorOccuredWhileReadingFileSS, [ANSIToUTF8(ExtractFileName(FName)), ANSIToUTF8(GetErrorString(Error))]); + Engine.CloseFile(FD); + Exit; + end; + if IsItSFV then CRC := CRC32(CRC, Buffer, Count) + else MD5Hash.Calc(Buffer^, Count); + Progress.Value := Progress.Value + Count; + Progress.Text := Format('%d %%', [Trunc(Progress.Fraction * 100)]); + Application.ProcessMessages; + CheckStop; + until (Count < ChksumBlockSize) or Stop; + Engine.CloseFile(FD); + Libc.free(Buffer); + + if IsItSFV then HashString := IntToHex(not CRC, 8) else + begin + MD5Hash.Done; + HashString := MD5Hash.GetKeyStrH; + MD5Hash.Free; + end; + Result := True; +end; + +const ChksumBlockSize = 32768; // Maximum of PByteArray + +procedure TFChecksumDruid.WriteLine(const FName, CheckedFName, HashString: string; const IsItSFV, CreateFile, CloseFile: boolean); +var i, Error, Count: integer; + s: string; +begin + if CreateFile then begin + FileDes := Engine.OpenFile(FName, omWrite, Error); + if Error <> 0 then begin + ErrorLabel.Caption := ErrorLabel.Caption + Format(LANGCCHKSUMAnErrorOccuredWhileOpeningFileSS, [ANSIToUTF8(ExtractFileName(FName)), ANSIToUTF8(GetErrorString(Error))]); + Exit; + end; + try + Buffer := Libc.malloc(ChksumBlockSize); + Libc.memset(Buffer, 0, ChksumBlockSize); + except + ErrorLabel.Caption := ErrorLabel.Caption + LANGAnErrorOccuredWhileInitializingMemoryBlock + #10; + Exit; + end; + BufferPos := -1; + end; + if Buffer = nil then Exit; + + if IsItSFV then s := Format('%s %s'#13#10, [ExtractFileName(CheckedFName), Trim(ANSIUpperCase(HashString))]) + else s := Format('%s %s'#10, [Trim(AnsiLowerCase(HashString)), ExtractFileName(CheckedFName)]); + for i := 1 to Length(s) do begin + if BufferPos + 1 >= ChksumBlockSize then begin + Count := Engine.WriteFile(FileDes, Buffer, ChksumBlockSize, Error); + BufferPos := -1; + if (Error <> 0) or (Count <> ChksumBlockSize) then begin + ErrorLabel.Caption := ErrorLabel.Caption + Format(LANGCCHKSUMAnErrorOccuredWhileWritingFileSS, [ANSIToUTF8(ExtractFileName(FName)), ANSIToUTF8(GetErrorString(Error))]); + Exit; + end; + end; + Inc(BufferPos); + PByteArray(Buffer)^[BufferPos] := Byte(s[i]); + end; + + if CloseFile then begin + Inc(BufferPos); // Counting with zero-starting element + Count := Engine.WriteFile(FileDes, Buffer, BufferPos, Error); + if (Error <> 0) or (Count <> BufferPos) then begin + ErrorLabel.Caption := ErrorLabel.Caption + Format(LANGCCHKSUMAnErrorOccuredWhileWritingFileSS, [ANSIToUTF8(ExtractFileName(FName)), ANSIToUTF8(GetErrorString(Error))]); + Exit; + end; + BufferPos := -1; + Engine.CloseFile(FileDes); + Libc.free(Buffer); + end; +end; + +procedure TFChecksumDruid.WriteSFVComment(const FName: string); +var i, Error, Count: integer; + Stat: PDataItemSL; + s: string; +begin + FileDes := Engine.OpenFile(FName, omWrite, Error); + if Error <> 0 then begin + ErrorLabel.Caption := ErrorLabel.Caption + Format(LANGCCHKSUMAnErrorOccuredWhileOpeningFileSS, [ANSIToUTF8(ExtractFileName(FName)), ANSIToUTF8(GetErrorString(Error))]); + Exit; + end; + try + Buffer := Libc.malloc(ChksumBlockSize); + Libc.memset(Buffer, 0, ChksumBlockSize); + except + ErrorLabel.Caption := ErrorLabel.Caption + LANGAnErrorOccuredWhileInitializingMemoryBlock + #10; + Exit; + end; + BufferPos := -1; + if Buffer = nil then Exit; + + s := Format('; Generated by WIN-SFV32 v1 [added for sfv32 compatibility]'#13#10'; Using Tux Commander v%s [%s] on %s'#13#10 + + '; http://tuxcmd.sourceforge.net/'#13#10'; '#13#10'; /----'#13#10, [ConstAboutVersion, ConstAboutBuildDate, + FormatDateTime('mm.dd.yyyy "at" hh:nn:ss', Now)]); + for i := 0 to FileNames.Count - 1 do begin + Stat := Engine.GetFileInfoSL(FileNames[i]); + if Assigned(Stat) then s := s + Format('; %s %s %s'#13#10, [PadRightStr(IntToStr(Stat^.Size), 11), + FormatDateTime('hh:nn.ss yyyy-mm-dd', Stat^.ModifyTime), ExtractFileName(FileNames[i])]); + end; + s := s + '; \----'#13#10'; '#13#10; + + for i := 1 to Length(s) do begin + if BufferPos + 1 >= ChksumBlockSize then begin + Count := Engine.WriteFile(FileDes, Buffer, ChksumBlockSize, Error); + BufferPos := -1; + if (Error <> 0) or (Count <> ChksumBlockSize) then begin + ErrorLabel.Caption := ErrorLabel.Caption + Format(LANGCCHKSUMAnErrorOccuredWhileWritingFileSS, [ANSIToUTF8(ExtractFileName(FName)), ANSIToUTF8(GetErrorString(Error))]); + Exit; + end; + end; + Inc(BufferPos); + PByteArray(Buffer)^[BufferPos] := Byte(s[i]); + end; +end; + +end. + + |
