From 0e887e13a22b4f3644a9e0718921fb59b6fc1414 Mon Sep 17 00:00:00 2001 From: mattias Date: Sun, 18 Aug 2002 08:55:41 +0000 Subject: [PATCH] implemented diff dialog git-svn-id: trunk@2895 - --- .gitattributes | 1 + ide/codetemplatedialog.pp | 24 +- ide/diffdialog.pas | 681 ++++++++++++++++++++++++++++++++++++++ ide/diffpatch.pas | 33 +- ide/main.pp | 56 +++- 5 files changed, 764 insertions(+), 31 deletions(-) create mode 100644 ide/diffdialog.pas diff --git a/.gitattributes b/.gitattributes index 00167a19c3..178d788d05 100644 --- a/.gitattributes +++ b/.gitattributes @@ -174,6 +174,7 @@ ide/compileroptions.pp svneol=native#text/pascal ide/compreg.pp svneol=native#text/pascal ide/customformeditor.pp svneol=native#text/pascal ide/debugmanager.pas svneol=native#text/pascal +ide/diffdialog.pas svneol=native#text/pascal ide/diffpatch.pas svneol=native#text/pascal ide/diskdiffsdialog.pas svneol=native#text/pascal ide/editdefinetree.pas svneol=native#text/pascal diff --git a/ide/codetemplatedialog.pp b/ide/codetemplatedialog.pp index e965dcef0a..26b52985fd 100644 --- a/ide/codetemplatedialog.pp +++ b/ide/codetemplatedialog.pp @@ -23,8 +23,6 @@ Abstract: A dialog for adding and editing code templates - ToDo: - -check if token already exists } unit CodeTemplateDialog; @@ -34,7 +32,7 @@ interface uses Classes, SysUtils, LCLLinux, LResources, Forms, Buttons, Controls, - SynEditAutoComplete, StdCtrls, SynEditKeyCmds, Dialogs; + SynEditAutoComplete, LazarusIDEStrConsts, StdCtrls, SynEditKeyCmds, Dialogs; type TCodeTemplateEditForm = class(TForm) @@ -69,8 +67,8 @@ begin try CodeTemplateEditForm.SynAutoComplete:=ASynAutoComplete; CodeTemplateEditForm.TemplateIndex:=ASynAutoComplete.Completions.Count; - CodeTemplateEditForm.Caption:='Add code template'; - CodeTemplateEditForm.OkButton.Caption:='Add'; + CodeTemplateEditForm.Caption:=lisCodeTemplAddCodeTemplate; + CodeTemplateEditForm.OkButton.Caption:=lisCodeTemplAdd; CodeTemplateEditForm.TokenEdit.Text:=Token; CodeTemplateEditForm.CommentEdit.Text:=Comment; Result:=CodeTemplateEditForm.ShowModal; @@ -94,8 +92,8 @@ begin try CodeTemplateEditForm.SynAutoComplete:=ASynAutoComplete; CodeTemplateEditForm.TemplateIndex:=Index; - CodeTemplateEditForm.Caption:='Edit code template'; - CodeTemplateEditForm.OkButton.Caption:='Change'; + CodeTemplateEditForm.Caption:=lisCodeTemplEditCodeTemplate; + CodeTemplateEditForm.OkButton.Caption:=lisCodeTemplChange; CodeTemplateEditForm.TokenEdit.Text:=ASynAutoComplete.Completions[Index]; CodeTemplateEditForm.CommentEdit.Text:= ASynAutoComplete.CompletionComments[Index]; @@ -126,7 +124,7 @@ begin with TokenLabel do begin Name:='TokenLabel'; Parent:=Self; - Caption:='Token:'; + Caption:=lisCodeTemplToken; Left:=12; Top:=6; Width:=Self.ClientWidth-Left-Left; @@ -148,7 +146,7 @@ begin with CommentLabel do begin Name:='CommentLabel'; Parent:=Self; - Caption:='Comment:'; + Caption:=lisCodeTemplComment; Left:=12; Top:=TokenEdit.Top+TokenEdit.Height+10; Width:=Self.ClientWidth-Left-Left; @@ -170,7 +168,7 @@ begin with OkButton do begin Name:='OkButton'; Parent:=Self; - Caption:='Ok'; + Caption:=lisLazBuildOk; OnClick:=@OkButtonClick; Left:=50; Top:=Self.ClientHeight-Height-12; @@ -182,7 +180,7 @@ begin with CancelButton do begin Name:='CancelButton'; Parent:=Self; - Caption:='Cancel'; + Caption:=dlgCancel; ModalResult:=mrCancel; Width:=80; Left:=Self.ClientWidth-50-Width; @@ -240,8 +238,8 @@ begin if (a<0) or (a=TemplateIndex) then ModalResult:=mrOk else begin - AText:=' A token '''+TokenEdit.Text+''' already exists! '; - ACaption:='Error'; + AText:=Format(lisCodeTemplATokenAlreadyExists, ['"', TokenEdit.Text, '"']); + ACaption:=lisCodeTemplError; // Application.MessageBox(PChar(AText),PChar(ACaption),0); MessageDlg(ACaption,AText,mterror,[mbok],0); diff --git a/ide/diffdialog.pas b/ide/diffdialog.pas new file mode 100644 index 0000000000..640c8bfc6f --- /dev/null +++ b/ide/diffdialog.pas @@ -0,0 +1,681 @@ +{ $Id$ } +{ + /*************************************************************************** + diffdialog.pp + ------------- + + + ***************************************************************************/ + + *************************************************************************** + * * + * This source 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 code 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. * + * * + * A copy of the GNU General Public License is available on the World * + * Wide Web at . You can also * + * obtain it by writing to the Free Software Foundation, * + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + * * + *************************************************************************** + + Author: Mattias Gaertner + + Abstract: + The TDiffDialog is the dialog for showing the differences between two files. + +} +unit DiffDialog; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, Forms, Controls, Buttons, ExtCtrls, StdCtrls, SynEdit, + LResources, LazarusIDEStrConsts, EditorOptions, IDEOptionDefs, InputHistory, + DiffPatch; + +type + TOnGetDiffFile = procedure(TextID: integer; OnlySelection: boolean; + var Source: string) of object; + + + { TDiffFile } + + TDiffFile = class + public + Name: string; + ID: integer; + SelectionAvailable: boolean; + constructor Create(const NewName: string; NewID: integer; + NewSelectionAvailable: boolean); + end; + + + { TDiffFiles } + + TDiffFiles = class(TList) + private + function GetItems(Index: integer): TDiffFile; + procedure SetItems(Index: integer; const AValue: TDiffFile); + public + procedure Clear; override; + function Add(DiffFile: TDiffFile): integer; + function IndexOfName(const Name: string): integer; + public + property Items[Index: integer]: TDiffFile read GetItems write SetItems; default; + end; + + + { TDiffDialog } + + TDiffDialog = class(TForm) + // text 1 + Text1GroupBox: TGroupBox; + Text1Combobox: TComboBox; + Text1OnlySelectionCheckBox: TCheckBox; + + // text 2 + Text2GroupBox: TGroupBox; + Text2Combobox: TComboBox; + Text2OnlySelectionCheckBox: TCheckBox; + + // diff preview + DiffGroupbox: TGroupBox; + DiffSynEdit: TSynEdit; + + // options + OptionsGroupBox: TGroupBox; + IgnoreCaseCheckBox: TCheckBox; + IgnoreEmptyLineChangesCheckBox: TCheckBox; + IgnoreHeadingSpacesCheckBox: TCheckBox; + IgnoreLineEndsCheckBox: TCheckBox; + IgnoreSpaceCharAmountCheckBox: TCheckBox; + IgnoreSpaceCharsCheckBox: TCheckBox; + IgnoreTrailingSpacesCheckBox: TCheckBox; + + // buttons + CloseButton: TButton; + OpenInEditorButton: TButton; + + procedure CloseButtonClick(Sender: TObject); + procedure DiffDialogResize(Sender: TObject); + procedure OnChangeFlag(Sender: TObject); + procedure OpenInEditorButtonClick(Sender: TObject); + procedure OptionsGroupBoxResize(Sender: TObject); + procedure Text1ComboboxChange(Sender: TObject); + procedure Text1GroupBoxResize(Sender: TObject); + procedure Text2ComboboxChange(Sender: TObject); + procedure Text2GroupBoxResize(Sender: TObject); + private + FOnGetDiffFile: TOnGetDiffFile; + fDiffNeedsUpdate: boolean; + FLockCount: integer; + procedure SetupComponents; + procedure UpdateDiff; + public + Files: TDiffFiles; + Text1: TDiffFile; + Text2: TDiffFile; + constructor Create(TheOwner: TComponent); override; + destructor Destroy; override; + procedure Init; + procedure FillTextComboBoxes; + procedure SetText1Index(NewIndex: integer); + procedure SetText2Index(NewIndex: integer); + procedure SaveSettings; + procedure SetDiffOptions(NewOptions: TTextDiffFlags); + function GetDiffOptions: TTextDiffFlags; + procedure BeginUpdate; + procedure EndUpdate; + public + property OnGetDiffFile: TOnGetDiffFile + read FOnGetDiffFile write FOnGetDiffFile; + end; + +function ShowDiffDialog(Files: TDiffFiles; Text1Index: integer; + OnGetDiffFile: TOnGetDiffFile; + var OpenDiffInEditor: boolean; var Diff: string): TModalResult; + + +implementation + +uses + Math; + + +function ShowDiffDialog(Files: TDiffFiles; Text1Index: integer; + OnGetDiffFile: TOnGetDiffFile; + var OpenDiffInEditor: boolean; var Diff: string): TModalResult; +var + DiffDlg: TDiffDialog; +begin + DiffDlg:=TDiffDialog.Create(Application); + DiffDlg.BeginUpdate; + DiffDlg.OnGetDiffFile:=OnGetDiffFile; + DiffDlg.Files:=Files; + DiffDlg.SetText1Index(Text1Index); + DiffDlg.Init; + DiffDlg.EndUpdate; + Result:=DiffDlg.ShowModal; + DiffDlg.SaveSettings; + + if Result=mrYes then begin + OpenDiffInEditor:=true; + Diff:=DiffDlg.DiffSynEdit.Text; + Result:=mrOk; + end; + + DiffDlg.Free; +end; + +{ TDiffDialog } + +procedure TDiffDialog.DiffDialogResize(Sender: TObject); +begin + // text 1 + with Text1GroupBox do begin + SetBounds(3,3,(Parent.ClientWidth-3*3) div 2,65); + end; + + // text 2 + with Text2GroupBox do begin + SetBounds(Text1GroupBox.Left+Text1GroupBox.Width+3,Text1GroupBox.Top, + Text1GroupBox.Width,Text1GroupBox.Height); + end; + + // diff preview + with DiffGroupbox do begin + SetBounds(Text1GroupBox.Left,Text1GroupBox.Top+Text1GroupBox.Height+5, + Parent.ClientWidth-2*Text1GroupBox.Left,Max(1,Parent.ClientHeight-226)); + end; + + // options + with OptionsGroupBox do begin + SetBounds(Text1GroupBox.Left,DiffGroupbox.Top+DiffGroupbox.Height+5, + DiffGroupbox.Width,106); + end; + + // buttons + with CloseButton do begin + SetBounds(Parent.ClientWidth-300,Parent.ClientHeight-32,75,Height); + end; + + with OpenInEditorButton do begin + SetBounds(CloseButton.Left+CloseButton.Width+10,CloseButton.Top, + 150,CloseButton.Height); + end; +end; + +procedure TDiffDialog.OnChangeFlag(Sender: TObject); +begin + UpdateDiff; +end; + +procedure TDiffDialog.OpenInEditorButtonClick(Sender: TObject); +begin + ModalResult:=mrYes; +end; + +procedure TDiffDialog.CloseButtonClick(Sender: TObject); +begin + ModalResult:=mrOk; +end; + +procedure TDiffDialog.OptionsGroupBoxResize(Sender: TObject); +var + y: Integer; + x: Integer; + W: Integer; +begin + y:=0; + x:=4; + W:=(OptionsGroupBox.ClientWidth div 2)-8; + + with IgnoreCaseCheckBox do begin + SetBounds(x,y,w,Height); + inc(y,Height+2); + end; + + with IgnoreEmptyLineChangesCheckBox do begin + SetBounds(x,y,w,Height); + inc(y,Height+2); + end; + + with IgnoreHeadingSpacesCheckBox do begin + SetBounds(x,y,w,Height); + inc(y,Height+2); + end; + + with IgnoreLineEndsCheckBox do begin + SetBounds(x,y,w+w,Height); + inc(y,Height+2); + end; + + x:=(OptionsGroupBox.ClientWidth div 2)+4; + y:=2; + with IgnoreSpaceCharAmountCheckBox do begin + SetBounds(x,y,w,Height); + inc(y,Height+2); + end; + + with IgnoreSpaceCharsCheckBox do begin + SetBounds(x,y,w,Height); + inc(y,Height+2); + end; + + with IgnoreTrailingSpacesCheckBox do begin + SetBounds(x,y,w,Height); + end; +end; + +procedure TDiffDialog.Text1ComboboxChange(Sender: TObject); +begin + SetText1Index(Text1Combobox.Items.IndexOf(Text1Combobox.Text)); +end; + +procedure TDiffDialog.Text1GroupBoxResize(Sender: TObject); +begin + with Text1Combobox do begin + SetBounds(0,0,Parent.ClientWidth,Height); + end; + + with Text1OnlySelectionCheckBox do begin + SetBounds(10,Text1Combobox.Top+Text1Combobox.Height+1, + Parent.ClientWidth-20,Height); + end; +end; + +procedure TDiffDialog.Text2ComboboxChange(Sender: TObject); +begin + SetText2Index(Text2Combobox.Items.IndexOf(Text2Combobox.Text)); +end; + +procedure TDiffDialog.Text2GroupBoxResize(Sender: TObject); +begin + with Text2Combobox do begin + SetBounds(0,0,Parent.ClientWidth,Height); + end; + + with Text2OnlySelectionCheckBox do begin + SetBounds(10,Text1Combobox.Top+Text1Combobox.Height+1, + Parent.ClientWidth-20,Height); + end; +end; + +procedure TDiffDialog.SetupComponents; +begin + // text 1 + Text1GroupBox:=TGroupBox.Create(Self); + with Text1GroupBox do begin + Name:='Text1GroupBox'; + Parent:=Self; + Caption:=lisDiffDlgText1; + OnResize:=@Text1GroupBoxResize; + end; + + Text1Combobox:=TComboBox.Create(Self); + with Text1Combobox do begin + Name:='Text1Combobox'; + Parent:=Text1GroupBox; + OnChange:=@Text1ComboboxChange; + end; + + Text1OnlySelectionCheckBox:=TCheckBox.Create(Self); + with Text1OnlySelectionCheckBox do begin + Name:='Text1OnlySelectionCheckBox'; + Parent:=Text1GroupBox; + Caption:=lisDiffDlgOnlySelection; + OnClick:=@OnChangeFlag; + end; + + // text 2 + Text2GroupBox:=TGroupBox.Create(Self); + with Text2GroupBox do begin + Name:='Text2GroupBox'; + Parent:=Self; + Caption:=lisDiffDlgText2; + OnResize:=@Text2GroupBoxResize; + end; + + Text2Combobox:=TComboBox.Create(Self); + with Text2Combobox do begin + Name:='Text2Combobox'; + Parent:=Text2GroupBox; + OnChange:=@Text2ComboboxChange; + end; + + Text2OnlySelectionCheckBox:=TCheckBox.Create(Self); + with Text2OnlySelectionCheckBox do begin + Name:='Text2OnlySelectionCheckBox'; + Parent:=Text2GroupBox; + Caption:=lisDiffDlgOnlySelection; + OnClick:=@OnChangeFlag; + end; + + // diff preview + DiffGroupbox:=TGroupBox.Create(Self); + with DiffGroupbox do begin + Name:='DiffGroupbox'; + Parent:=Self; + Caption:=lisMenuDiff; + end; + + DiffSynEdit:=TSynEdit.Create(Self); + with DiffSynEdit do begin + Name:='DiffSynEdit'; + Parent:=DiffGroupbox; + Gutter.Visible:=false; + Align:=alClient; + end; + + // options + OptionsGroupBox:=TGroupBox.Create(Self); + with OptionsGroupBox do begin + Name:='OptionsGroupBox'; + Parent:=Self; + Caption:=dlgFROpts; + OnResize:=@OptionsGroupBoxResize; + end; + + IgnoreCaseCheckBox:=TCheckBox.Create(Self); + with IgnoreCaseCheckBox do begin + Name:='IgnoreCaseCheckBox'; + Parent:=OptionsGroupBox; + Caption:=lisDiffDlgCaseInsensitive; + OnClick:=@OnChangeFlag; + end; + + IgnoreEmptyLineChangesCheckBox:=TCheckBox.Create(Self); + with IgnoreEmptyLineChangesCheckBox do begin + Name:='IgnoreEmptyLineChangesCheckBox'; + Parent:=OptionsGroupBox; + Caption:=lisDiffDlgIgnoreIfEmptyLinesWereAdd; + OnClick:=@OnChangeFlag; + end; + + IgnoreHeadingSpacesCheckBox:=TCheckBox.Create(Self); + with IgnoreHeadingSpacesCheckBox do begin + Name:='IgnoreHeadingSpacesCheckBox'; + Parent:=OptionsGroupBox; + Caption:=lisDiffDlgIgnoreSpacesAtStartOfLine; + OnClick:=@OnChangeFlag; + end; + + IgnoreTrailingSpacesCheckBox:=TCheckBox.Create(Self); + with IgnoreTrailingSpacesCheckBox do begin + Name:='IgnoreTrailingSpacesCheckBox'; + Parent:=OptionsGroupBox; + Caption:=lisDiffDlgIgnoreSpacesAtEndOfLine; + OnClick:=@OnChangeFlag; + end; + + IgnoreLineEndsCheckBox:=TCheckBox.Create(Self); + with IgnoreLineEndsCheckBox do begin + Name:='IgnoreLineEndsCheckBox'; + Parent:=OptionsGroupBox; + Caption:=lisDiffDlgIgnoreIfLineEndCharsDiffe; + OnClick:=@OnChangeFlag; + end; + + IgnoreSpaceCharAmountCheckBox:=TCheckBox.Create(Self); + with IgnoreSpaceCharAmountCheckBox do begin + Name:='IgnoreSpaceCharAmountCheckBox'; + Parent:=OptionsGroupBox; + Caption:=lisDiffDlgIgnoreIfSpaceCharsWereAdd; + OnClick:=@OnChangeFlag; + end; + + IgnoreSpaceCharsCheckBox:=TCheckBox.Create(Self); + with IgnoreSpaceCharsCheckBox do begin + Name:='IgnoreSpaceCharsCheckBox'; + Parent:=OptionsGroupBox; + Caption:=lisDiffDlgIgnoreSpaces; + OnClick:=@OnChangeFlag; + end; + + // buttons + CloseButton:=TButton.Create(Self); + with CloseButton do begin + Name:='CloseButton'; + Parent:=Self; + Caption:=lisMenuClose; + OnClick:=@CloseButtonClick; + end; + + OpenInEditorButton:=TButton.Create(Self); + with OpenInEditorButton do begin + Name:='OpenInEditorButton'; + Parent:=Self; + Caption:=lisDiffDlgOpenDiffInEditor; + OnClick:=@OpenInEditorButtonClick; + end; +end; + +procedure TDiffDialog.UpdateDiff; +var + Text1Src, Text2Src: string; + DiffTxt: String; +begin + if FLockCount>0 then begin + fDiffNeedsUpdate:=true; + exit; + end; + fDiffNeedsUpdate:=false; + if (Text1=nil) or (Text2=nil) then begin + DiffSynEdit.Lines.Text:=''; + end else begin + OnGetDiffFile(Text1.ID, + Text1.SelectionAvailable and Text1OnlySelectionCheckBox.Checked, + Text1Src); + OnGetDiffFile(Text2.ID, + Text2.SelectionAvailable and Text2OnlySelectionCheckBox.Checked, + Text2Src); + DiffTxt:=CreateTextDiff(Text1Src,Text2Src,GetDiffOptions); + DiffSynEdit.Lines.Text:=DiffTxt; + end; +end; + +constructor TDiffDialog.Create(TheOwner: TComponent); +begin + inherited Create(TheOwner); + if LazarusResources.Find(Classname)=nil then begin + Name:='DiffDialog'; + Caption := lisMenuDiff; + Width:=600; + Height:=400; + Position:=poScreenCenter; + OnResize:=@DiffDialogResize; + SetupComponents; + end; + IDEDialogLayoutList.ApplyLayout(Self,600,400); + OnResize(nil); +end; + +destructor TDiffDialog.Destroy; +begin + inherited Destroy; +end; + +procedure TDiffDialog.Init; +var + LastText2Name: String; + i: Integer; +begin + // fill all diff file names + FillTextComboBoxes; + + // get recent Text 2 + LastText2Name:=InputHistories.DiffText2; + if LastText2Name<>'' then + i:=Files.IndexOfName(LastText2Name); + if i<0 then i:=0; + if i=Files.IndexOf(Text2) then inc(i); + SetText2Index(i); + + // set recent options + SetDiffOptions(InputHistories.DiffFlags); + + // and action ... + UpdateDiff; +end; + +procedure TDiffDialog.FillTextComboBoxes; +var + i: Integer; +begin + // Text 1 + Text1Combobox.Items.BeginUpdate; + Text1Combobox.Items.Clear; + for i:=0 to Files.Count-1 do + Text1Combobox.Items.Add(Files[i].Name); + Text1Combobox.Items.EndUpdate; + + // Text 2 + Text2Combobox.Items.BeginUpdate; + Text2Combobox.Items.Clear; + for i:=0 to Files.Count-1 do + Text2Combobox.Items.Add(Files[i].Name); + Text2Combobox.Items.EndUpdate; +end; + +procedure TDiffDialog.SetText1Index(NewIndex: integer); +var + OldText1: TDiffFile; +begin + OldText1:=Text1; + if (NewIndex>=0) and (NewIndexOldText1 then UpdateDiff; +end; + +procedure TDiffDialog.SetText2Index(NewIndex: integer); +var + OldText2: TDiffFile; +begin + OldText2:=Text2; + if (NewIndex>=0) and (NewIndexOldText2 then UpdateDiff; +end; + +procedure TDiffDialog.SaveSettings; +begin + InputHistories.DiffFlags:=GetDiffOptions; + if Text2<>nil then begin + InputHistories.DiffText2:=Text2.Name; + InputHistories.DiffText2OnlySelection:=Text2OnlySelectionCheckBox.Checked; + end else begin + InputHistories.DiffText2:=''; + InputHistories.DiffText2OnlySelection:=false; + end; + IDEDialogLayoutList.SaveLayout(Self); +end; + +procedure TDiffDialog.SetDiffOptions(NewOptions: TTextDiffFlags); +begin + IgnoreCaseCheckBox.Checked:=tdfIgnoreCase in NewOptions; + IgnoreEmptyLineChangesCheckBox.Checked:=tdfIgnoreEmptyLineChanges in NewOptions; + IgnoreHeadingSpacesCheckBox.Checked:=tdfIgnoreHeadingSpaces in NewOptions; + IgnoreLineEndsCheckBox.Checked:=tdfIgnoreLineEnds in NewOptions; + IgnoreSpaceCharAmountCheckBox.Checked:=tdfIgnoreSpaceCharAmount in NewOptions; + IgnoreSpaceCharsCheckBox.Checked:=tdfIgnoreSpaceChars in NewOptions; + IgnoreTrailingSpacesCheckBox.Checked:=tdfIgnoreTrailingSpaces in NewOptions; +end; + +function TDiffDialog.GetDiffOptions: TTextDiffFlags; +begin + Result:=[]; + if IgnoreCaseCheckBox.Checked then + Include(Result,tdfIgnoreCase); + if IgnoreEmptyLineChangesCheckBox.Checked then + Include(Result,tdfIgnoreEmptyLineChanges); + if IgnoreHeadingSpacesCheckBox.Checked then + Include(Result,tdfIgnoreHeadingSpaces); + if IgnoreLineEndsCheckBox.Checked then + Include(Result,tdfIgnoreLineEnds); + if IgnoreSpaceCharAmountCheckBox.Checked then + Include(Result,tdfIgnoreSpaceCharAmount); + if IgnoreSpaceCharsCheckBox.Checked then + Include(Result,tdfIgnoreSpaceChars); + if IgnoreTrailingSpacesCheckBox.Checked then + Include(Result,tdfIgnoreTrailingSpaces); +end; + +procedure TDiffDialog.BeginUpdate; +begin + inc(FLockCount); +end; + +procedure TDiffDialog.EndUpdate; +begin + dec(FLockCount); + if (FLockCount=0) and fDiffNeedsUpdate then UpdateDiff; +end; + +{ TDiffFile } + +constructor TDiffFile.Create(const NewName: string; NewID: integer; + NewSelectionAvailable: boolean); +begin + Name:=NewName; + ID:=NewID; + SelectionAvailable:=NewSelectionAvailable; +end; + +{ TDiffFiles } + +function TDiffFiles.GetItems(Index: integer): TDiffFile; +begin + Result:=TDiffFile(inherited Items[Index]); +end; + +procedure TDiffFiles.SetItems(Index: integer; const AValue: TDiffFile); +begin + inherited Items[Index]:=AValue; +end; + +procedure TDiffFiles.Clear; +var + i: Integer; +begin + for i:=0 to Count-1 do + Items[i].Free; + inherited Clear; +end; + +function TDiffFiles.Add(DiffFile: TDiffFile): integer; +begin + Result:=inherited Add(DiffFile); +end; + +function TDiffFiles.IndexOfName(const Name: string): integer; +begin + Result:=Count-1; + while (Result>=0) and (Items[Result].Name<>Name) do dec(Result); +end; + +end. + diff --git a/ide/diffpatch.pas b/ide/diffpatch.pas index 16c1a2795a..39f376cf93 100644 --- a/ide/diffpatch.pas +++ b/ide/diffpatch.pas @@ -26,6 +26,9 @@ *************************************************************************** Author: Mattias Gaertner + + Abstract: + Methods for creating diffs and ToDo: applying them (patching). } unit DiffPatch; @@ -39,20 +42,30 @@ uses type TTextDiffFlag = ( + tdfIgnoreCase, // ignore case of letters + tdfIgnoreEmptyLineChanges,// ignore if empty lines were added or removed + tdfIgnoreHeadingSpaces, // ignore spaces at start of line + tdfIgnoreLineEnds, // ignore if line end chars differ (e.g. #10 = #13#10) tdfIgnoreSpaceCharAmount, // ignore if space chars were added or removed // except if all spaces were removed tdfIgnoreSpaceChars, // ignore spaces (newline chars not included) - tdfIgnoreHeadingSpaces, // ignore spaces at start of line - tdfIgnoreTrailingSpaces, // ignore spaces at end of line - tdfIgnoreEmptyLineChanges,// ignore if empty lines were added or removed - tdfIgnoreLineEnds, // ignore if line chars differ (e.g. #10 = #13#10) - tdfIgnoreCase // ignore case of letters + tdfIgnoreTrailingSpaces // ignore spaces at end of line ); TTextDiffFlags = set of TTextDiffFlag; function CreateTextDiff(const Text1, Text2: string; Flags: TTextDiffFlags ): string; +const + TextDiffFlagNames: array[TTextDiffFlag] of string = ( + 'IgnoreCase', + 'IgnoreEmptyLineChanges', + 'IgnoreHeadingSpaces', + 'IgnoreLineEnds', + 'IgnoreSpaceCharAmount', + 'IgnoreSpaceChars', + 'IgnoreTrailingSpaces' + ); implementation @@ -215,7 +228,7 @@ begin while (Pos1=End2) or (IsSpaceChars[Text2[Pos2]]); + until (Pos2>=End2) or (not IsSpaceChars[Text2[Pos2]]); end; end; end else begin @@ -265,7 +278,7 @@ begin // skip all spaces in Text1 and proceed the search repeat inc(Pos1); - until (Pos1>=End1) or (IsSpaceChars[Text1[Pos1]]); + until (Pos1>=End1) or (not IsSpaceChars[Text1[Pos1]]); end; end else begin // Text2 contains a space @@ -273,10 +286,10 @@ begin // skip all spaces in Text1 and Text2 and proceed the search repeat inc(Pos1); - until (Pos1>=End1) or (IsSpaceChars[Text1[Pos1]]); + until (Pos1>=End1) or (not IsSpaceChars[Text1[Pos1]]); repeat inc(Pos2); - until (Pos2>=End2) or (IsSpaceChars[Text2[Pos2]]); + until (Pos2>=End2) or (not IsSpaceChars[Text2[Pos2]]); end else begin // compare the space chars if Text1[Pos1]=Text2[Pos2] then begin diff --git a/ide/main.pp b/ide/main.pp index 6f645dadc2..c388245ab9 100644 --- a/ide/main.pp +++ b/ide/main.pp @@ -55,7 +55,7 @@ uses BuildLazDialog, MiscOptions, EditDefineTree, CodeToolsOptions, TypInfo, IDEOptionDefs, CodeToolsDefines, LocalsDlg, DebuggerDlg, InputHistory, DiskDiffsDialog, UnitDependencies, PublishProjectDlg, ClipBoardHistory, - ProcessList, InitialSetupDlgs, NewDialog, MakeResStrDlg, + ProcessList, InitialSetupDlgs, NewDialog, MakeResStrDlg, DiffDialog, // main ide BaseDebugManager, DebugManager, MainBar; @@ -175,6 +175,7 @@ type procedure mnuToolGuessUnclosedBlockClicked(Sender : TObject); procedure mnuToolGuessMisplacedIFDEFClicked(Sender : TObject); procedure mnuToolMakeResourceStringClicked(Sender : TObject); + procedure mnuToolDiffClicked(Sender : TObject); procedure mnuToolConvertDFMtoLFMClicked(Sender : TObject); procedure mnuToolBuildLazarusClicked(Sender : TObject); procedure mnuToolConfigBuildLazClicked(Sender : TObject); @@ -407,7 +408,7 @@ type destructor Destroy; override; // files/units - function DoNewEditorFile(NewUnitType:TNewUnitType; + function DoNewEditorFile(NewUnitType: TNewUnitType; NewFilename: string; NewFlags: TNewFlags): TModalResult; function DoNewOther: TModalResult; function DoSaveEditorFile(PageIndex:integer; @@ -452,14 +453,14 @@ type function DoBuildLazarus: TModalResult; // useful information methods - procedure GetCurrentUnit(var ActiveSourceEditor:TSourceEditor; - var ActiveUnitInfo:TUnitInfo); override; - procedure GetUnitWithPageIndex(PageIndex:integer; - var ActiveSourceEditor:TSourceEditor; var ActiveUnitInfo:TUnitInfo); + procedure GetCurrentUnit(var ActiveSourceEditor: TSourceEditor; + var ActiveUnitInfo: TUnitInfo); override; + procedure GetUnitWithPageIndex(PageIndex: integer; + var ActiveSourceEditor: TSourceEditor; var ActiveUnitInfo: TUnitInfo); procedure GetDesignerUnit(ADesigner: TDesigner; - var ActiveSourceEditor:TSourceEditor; var ActiveUnitInfo:TUnitInfo); + var ActiveSourceEditor: TSourceEditor; var ActiveUnitInfo: TUnitInfo); procedure GetUnitWithForm(AForm: TCustomForm; - var ActiveSourceEditor:TSourceEditor; var ActiveUnitInfo:TUnitInfo); + var ActiveSourceEditor: TSourceEditor; var ActiveUnitInfo: TUnitInfo); function GetSourceEditorForUnitInfo(AnUnitInfo: TUnitInfo): TSourceEditor; procedure UpdateDefaultPascalFileExtensions; function CreateSrcEditPageName(const AnUnitName, AFilename: string; @@ -518,6 +519,7 @@ type procedure DoGotoIncludeDirective; procedure SaveIncludeLinks; function DoMakeResourceString: TModalResult; + function DoDiff: TModalResult; // methods for debugging, compiling and external tools function DoJumpToCompilerMessage(Index:integer; @@ -1473,6 +1475,7 @@ begin itmToolGuessUnclosedBlock.OnClick := @mnuToolGuessUnclosedBlockClicked; itmToolGuessMisplacedIFDEF.OnClick := @mnuToolGuessMisplacedIFDEFClicked; itmToolMakeResourceString.OnClick := @mnuToolMakeResourceStringClicked; + itmToolDiff.OnClick := @mnuToolDiffClicked; itmToolConvertDFMtoLFM.OnClick := @mnuToolConvertDFMtoLFMClicked; itmToolBuildLazarus.OnClick := @mnuToolBuildLazarusClicked; itmToolConfigureBuildLazarus.OnClick := @mnuToolConfigBuildLazClicked; @@ -1819,6 +1822,9 @@ begin ecMakeResourceString: DoMakeResourceString; + ecDiff: + DoDiff; + ecConvertDFM2LFM: DoConvertDFMtoLFM; @@ -2276,6 +2282,11 @@ begin DoMakeResourceString; end; +procedure TMainIDE.mnuToolDiffClicked(Sender : TObject); +begin + DoDiff; +end; + procedure TMainIDE.mnuToolConvertDFMtoLFMClicked(Sender : TObject); begin DoConvertDFMtoLFM; @@ -7030,6 +7041,32 @@ begin end; end; +function TMainIDE.DoDiff: TModalResult; +var + ActiveSrcEdit: TSourceEditor; + ActiveUnitInfo: TUnitInfo; + OpenDiffInEditor: boolean; + DiffText: string; + Files: TDiffFiles; + NewDiffFilename: String; +begin + Result:=mrCancel; + GetCurrentUnit(ActiveSrcEdit,ActiveUnitInfo); + if ActiveSrcEdit=nil then exit; + + Files:=SourceNoteBook.GetDiffFiles; + Result:=ShowDiffDialog(Files,ActiveSrcEdit.PageIndex,@SourceNotebook.GetText, + OpenDiffInEditor,DiffText); + Files.Free; + if OpenDiffInEditor then begin + NewDiffFilename:=CreateSrcEditPageName('','diff.txt',-1); + Result:=DoNewEditorFile(nuText,NewDiffFilename,[]); + GetCurrentUnit(ActiveSrcEdit,ActiveUnitInfo); + if ActiveSrcEdit=nil then exit; + ActiveSrcEdit.EditorComponent.Lines.Text:=DiffText; + end; +end; + procedure TMainIDE.DoCompleteCodeAtCursor; var ActiveSrcEdit: TSourceEditor; @@ -7896,6 +7933,9 @@ end. { ============================================================================= $Log$ + Revision 1.486 2003/03/14 21:38:36 mattias + implemented diff dialog + Revision 1.485 2003/03/14 14:57:03 mattias make resourcestring dialog now checks for doubles (idents and values)