diff --git a/components/messagecomposer/languages/messagecomposer.po b/components/messagecomposer/languages/messagecomposer.po index 2b715ed709..519dcdbc30 100644 --- a/components/messagecomposer/languages/messagecomposer.po +++ b/components/messagecomposer/languages/messagecomposer.po @@ -4,43 +4,43 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: messagecomposer:smessagecomposercaption -msgid "Message Composer ..." -msgstr "" - -#: messagecomposer:smsgcaption -msgid "The message to be shown" -msgstr "" - -#: messagecomposer:spromptcaption -msgid "Text asking the user for input" -msgstr "" - -#: messagecomposer:smaskinput -msgid "Mask Input" -msgstr "" - -#: messagecomposer:ssourcewrapper -msgid "SOURCE WRAPPER" +#: messagecomposer:rscancel +msgid "Cancel" msgstr "" #: messagecomposer:skindofmessage msgid "KIND OF MESSAGE" msgstr "" -#: messagecomposer:snotimplementedyet -msgid "Not Implemented Yet" +#: messagecomposer:smaskinput +msgid "Mask Input" msgstr "" -#: messagecomposer:rstest -msgid "Test" +#: messagecomposer:smessagecomposercaption +msgid "Message Composer ..." +msgstr "" + +#: messagecomposer:snotimplementedyet +msgid "Not Implemented Yet" msgstr "" #: messagecomposer:rsok msgid "Ok" msgstr "" -#: messagecomposer:rscancel -msgid "Cancel" +#: messagecomposer:ssourcewrapper +msgid "SOURCE WRAPPER" +msgstr "" + +#: messagecomposer:rstest +msgid "Test" +msgstr "" + +#: messagecomposer:spromptcaption +msgid "Text asking the user for input" +msgstr "" + +#: messagecomposer:smsgcaption +msgid "The message to be shown" msgstr "" diff --git a/ide/inputhistory.pas b/ide/inputhistory.pas index cb3f1b54c3..327d646900 100644 --- a/ide/inputhistory.pas +++ b/ide/inputhistory.pas @@ -35,9 +35,13 @@ unit InputHistory; interface uses - Classes, SysUtils, FileUtil, DiffPatch, IDEProcs, + Classes, SysUtils, FileUtil, DiffPatch, IDEProcs, AvgLvlTree, Laz_XMLCfg, LazConf, Dialogs, LCLProc; +{$ifdef Windows} +{$define CaseInsensitiveFilenames} +{$endif} + const // these are the names of the various history lists in the IDE: hlPublishProjectDestDirs = 'PublishProjectDestinationDirectories'; @@ -194,6 +198,9 @@ type // various history lists FHistoryLists: THistoryLists; + // file encodings + fFileEncodings: TStringToStringTree; + procedure SetFilename(const AValue: string); public constructor Create; @@ -269,6 +276,9 @@ type write FLastConvertDelphiPackage; property LastConvertDelphiUnit: string read FLastConvertDelphiUnit write FLastConvertDelphiUnit; + + // file encodings + property FileEncodings: TStringToStringTree read fFileEncodings write fFileEncodings; end; const @@ -332,19 +342,22 @@ begin FFPCConfigCache:=TFPCConfigCache.Create; + fFileEncodings:=TStringToStringTree.Create({$IFDEF CaseInsensitiveFilenames}false{$ELSE}true{$ENDIF}); + Clear; end; destructor TInputHistories.Destroy; begin - FHistoryLists.Free; - FFileDialogSettings.HistoryList.Free; - FUnitDependenciesHistory.Free; - FFindHistory.Free; - FReplaceHistory.Free; - FFindInFilesPathHistory.Free; - FFindInFilesMaskHistory.Free; - FFPCConfigCache.Free; + FreeAndNil(FHistoryLists); + FreeAndNil(FFileDialogSettings.HistoryList); + FreeAndNil(FUnitDependenciesHistory); + FreeAndNil(FFindHistory); + FreeAndNil(FReplaceHistory); + FreeAndNil(FFindInFilesPathHistory); + FreeAndNil(FFindInFilesMaskHistory); + FreeAndNil(FFPCConfigCache); + FreeAndNil(fFileEncodings); inherited Destroy; end; @@ -367,6 +380,7 @@ begin FFPCConfigCache.Clear; FLastConvertDelphiProject:=''; FLastConvertDelphiUnit:=''; + fFileEncodings.Clear; end; procedure TInputHistories.LoadFromXMLConfig(XMLConfig: TXMLConfig; diff --git a/ide/lazarusidestrconsts.pas b/ide/lazarusidestrconsts.pas index 481b3b1c1d..23273a0c02 100644 --- a/ide/lazarusidestrconsts.pas +++ b/ide/lazarusidestrconsts.pas @@ -1566,6 +1566,16 @@ resourcestring uemNextBookmark = 'Goto next Bookmark'; uemPrevBookmark = 'Goto previous Bookmark'; uemBookmarkN = 'Bookmark'; + lisChangeEncoding = 'Change Encoding'; + lisEncodingOfFileOnDiskIsNewEncodingIs2 = 'Encoding of file %s%s%s%son disk ' + +'is %s. New encoding is %s.'; + lisChangeFile = 'Change file'; + lisEncodingOfFileOnDiskIsNewEncodingIs = 'Encoding of file %s%s%s%son disk ' + +'is %s. New encoding is %s.'; + lisReopenWithAnotherEncoding = 'Reopen with another encoding'; + lisAbandonChanges = 'Abandon changes?'; + lisAllYourModificationsToWillBeLostAndTheFileReopened = 'All your modificatio' + +'ns to %s%s%s%swill be lost and the file reopened.'; lisOpenLfm = 'Open %s'; uemSetBookmark = '&Set Bookmark'; uemReadOnly = 'Read Only'; @@ -2153,6 +2163,7 @@ resourcestring lisCodeToolsDefsErrorWhileWritingProjectInfoFile = 'Error while writing ' +'project info file %s%s%s%s%s'; lisCodeToolsDefsReadError = 'Read error'; + lisUnableToRead = 'Unable to read %s'; lisErrorReadingPackageListFromFile = 'Error reading package list from file%' +'s%s%s%s'; lisTheCurrentUnitPathForTheFileIsThePathToTheLCLUnits = 'The current unit ' diff --git a/ide/main.pp b/ide/main.pp index 19b0711e42..e98af9f085 100644 --- a/ide/main.pp +++ b/ide/main.pp @@ -684,7 +684,7 @@ type NewFlags: TNewFlags; NewOwner: TObject): TModalResult; override; function DoNewOther: TModalResult; function DoSaveEditorFile(PageIndex:integer; - Flags: TSaveFlags): TModalResult; + Flags: TSaveFlags): TModalResult; override; function DoCloseEditorFile(PageIndex:integer; Flags: TCloseFlags):TModalResult; override; function DoCloseEditorFile(const Filename: string; @@ -11742,7 +11742,11 @@ procedure TMainIDE.OnCodeBufferDecodeLoaded(Code: TCodeBuffer; const Filename: string; var Source, DiskEncoding, MemEncoding: string); begin //DebugLn(['TMainIDE.OnCodeBufferDecodeLoaded Filename=',Filename,' Encoding=',GuessEncoding(Source)]); - DiskEncoding:=GuessEncoding(Source); + DiskEncoding:=''; + if InputHistories<>nil then + DiskEncoding:=InputHistories.FileEncodings[Filename]; + if DiskEncoding='' then + DiskEncoding:=GuessEncoding(Source); MemEncoding:=EncodingUTF8; if (DiskEncoding<>MemEncoding) then begin {$IFDEF VerboseIDEEncoding} diff --git a/ide/sourceeditor.pp b/ide/sourceeditor.pp index 3c20e6ab58..c0bbc87fb7 100644 --- a/ide/sourceeditor.pp +++ b/ide/sourceeditor.pp @@ -52,7 +52,7 @@ uses SynEditAutoComplete, SynEditKeyCmds, SynCompletion, // IDE interface MacroIntf, ProjectIntf, SrcEditorIntf, MenuIntf, LazIDEIntf, PackageIntf, - IDEHelpIntf, IDEWindowIntf, IDEImagesIntf, + IDEDialogs, IDEHelpIntf, IDEWindowIntf, IDEImagesIntf, // IDE units LazarusIDEStrConsts, LazConf, IDECommands, EditorOptions, KeyMapping, Project, WordCompletion, FindReplaceDialog, FindInFilesDlg, IDEProcs, IDEOptionDefs, @@ -3871,20 +3871,67 @@ var SrcEdit: TSourceEditor; NewEncoding: String; OldEncoding: String; + CurResult: TModalResult; begin SrcEdit:=GetActiveSE; if SrcEdit=nil then exit; if Sender is TIDEMenuItem then begin IDEMenuItem:=TIDEMenuItem(Sender); NewEncoding:=IDEMenuItem.Caption; + if SysUtils.CompareText(copy(NewEncoding,1,length(EncodingAnsi)+2),EncodingAnsi+' (')=0 + then begin + // the ansi encoding is shown as 'ansi (system encoding)' -> cut + NewEncoding:=EncodingAnsi; + end; DebugLn(['TSourceNotebook.EncodingClicked ',NewEncoding]); if SrcEdit.CodeBuffer<>nil then begin OldEncoding:=NormalizeEncoding(SrcEdit.CodeBuffer.DiskEncoding); if OldEncoding='' then OldEncoding:=GetSystemEncoding; if NewEncoding<>SrcEdit.CodeBuffer.DiskEncoding then begin - DebugLn(['TSourceNotebook.EncodingClicked ToDo: change encoding']); - ShowMessage('Changing the encoding is not yet implemented. Please use tools like iconv or recode.'); + DebugLn(['TSourceNotebook.EncodingClicked Old=',OldEncoding,' New=',NewEncoding]); + if SrcEdit.ReadOnly then begin + CurResult:=IDEQuestionDialog(lisChangeEncoding, + Format(lisEncodingOfFileOnDiskIsNewEncodingIs, ['"', + SrcEdit.CodeBuffer.Filename, '"', #13, OldEncoding, NewEncoding]), + mtConfirmation, [mrOk, lisReopenWithAnotherEncoding, mrCancel], ''); + end else begin + CurResult:=IDEQuestionDialog(lisChangeEncoding, + Format(lisEncodingOfFileOnDiskIsNewEncodingIs2, ['"', + SrcEdit.CodeBuffer.Filename, '"', #13, OldEncoding, NewEncoding]), + mtConfirmation, [mrYes, lisChangeFile, mrOk, + lisReopenWithAnotherEncoding, mrCancel], ''); + end; + if CurResult=mrYes then begin + // change file + SrcEdit.CodeBuffer.DiskEncoding:=NewEncoding; + SrcEdit.Modified:=true; + DebugLn(['TSourceNotebook.EncodingClicked ',SrcEdit.CodeBuffer.DiskEncoding]); + if LazarusIDE.DoSaveEditorFile(SrcEdit.PageIndex,[])<>mrOk then begin + DebugLn(['TSourceNotebook.EncodingClicked LazarusIDE.DoSaveEditorFile failed']); + end; + end else if CurResult=mrOK then begin + if SrcEdit.Modified then begin + if IDEQuestionDialog(lisAbandonChanges, + Format(lisAllYourModificationsToWillBeLostAndTheFileReopened, [ + '"', SrcEdit.CodeBuffer.Filename, '"', #13]), + mtConfirmation,[mbOk,mbAbort],'')<>mrOk + then begin + exit; + end; + end; + // set override + InputHistories.FileEncodings[SrcEdit.CodeBuffer.Filename]:=NewEncoding; + if not SrcEdit.CodeBuffer.Revert then begin + IDEMessageDialog(lisCodeToolsDefsReadError, + Format(lisUnableToRead, [SrcEdit.CodeBuffer.Filename]), + mtError,[mbCancel],''); + exit; + end; + SrcEdit.EditorComponent.BeginUpdate; + SrcEdit.CodeBuffer.AssignTo(SrcEdit.EditorComponent.Lines,true); + SrcEdit.EditorComponent.EndUpdate; + end; end; end; end; diff --git a/ideintf/lazideintf.pas b/ideintf/lazideintf.pas index 4eab48a938..4d069e19ec 100644 --- a/ideintf/lazideintf.pas +++ b/ideintf/lazideintf.pas @@ -169,6 +169,8 @@ type function DoNewFile(NewFileDescriptor: TProjectFileDescriptor; var NewFilename: string; const NewSource: string; NewFlags: TNewFlags; NewOwner: TObject): TModalResult; virtual; abstract; + function DoSaveEditorFile(PageIndex:integer; + Flags: TSaveFlags): TModalResult; virtual; abstract; function DoCloseEditorFile(PageIndex:integer; Flags: TCloseFlags):TModalResult; virtual; abstract; function DoCloseEditorFile(const Filename: string;