mirror of https://gitlab.com/basile.b/dexed.git
897 lines
24 KiB
Plaintext
897 lines
24 KiB
Plaintext
unit ce_editor;
|
|
|
|
{$I ce_defines.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, FileUtil, Forms, Controls, lcltype, Graphics, SynEditKeyCmds,
|
|
ComCtrls, SynEditHighlighter, ExtCtrls, Menus, SynMacroRecorder, dialogs,
|
|
SynPluginSyncroEdit, SynEdit, SynHighlighterMulti, ce_dialogs,
|
|
ce_widget, ce_interfaces, ce_synmemo, ce_dlang, ce_common, ce_dcd, ce_observer,
|
|
ce_sharedres, ce_controls, ce_writableComponent;
|
|
|
|
type
|
|
|
|
TCEEditorWidget = class;
|
|
|
|
TCEPagesOptions = class(TWritableLfmTextComponent, ICEEditableOptions, ICEEditableShortCut)
|
|
private
|
|
fEditorWidget: TCEEditorWidget;
|
|
fPageButtons: TCEPageControlButtons;
|
|
fPageOptions: TCEPageControlOptions;
|
|
fMoveLeft: TShortCut;
|
|
fMoveRight: TShortCut;
|
|
fNextPage: TShortCut;
|
|
fPrevPage: TShortCut;
|
|
fShCount: integer;
|
|
function optionedWantCategory(): string;
|
|
function optionedWantEditorKind: TOptionEditorKind;
|
|
function optionedWantContainer: TPersistent;
|
|
procedure optionedEvent(anEvent: TOptionEditorEvent);
|
|
function optionedOptionsModified: boolean;
|
|
//
|
|
function scedWantFirst: boolean;
|
|
function scedWantNext(out category, identifier: string; out aShortcut: TShortcut): boolean;
|
|
procedure scedSendItem(const category, identifier: string; aShortcut: TShortcut);
|
|
procedure scedSendDone;
|
|
published
|
|
property pageButtons: TCEPageControlButtons read fPageButtons write fPageButtons;
|
|
property pageOptions: TCEPageControlOptions read fPageOptions write fPageOptions;
|
|
property nextPage: TShortCut read fNextPage write fNextPage;
|
|
property previousPage: TShortCut read fPrevPage write fPrevPage;
|
|
property moveLeft: TShortCut read fMoveLeft write fMoveLeft;
|
|
property moveRight: TShortCut read fMoveRight write fMoveRight;
|
|
public
|
|
procedure Assign(Source: TPersistent); override;
|
|
procedure AssignTo(Target: TPersistent); override;
|
|
constructor construct(editorWidg: TCEEditorWidget);
|
|
destructor Destroy; override;
|
|
end;
|
|
|
|
{ TCEEditorWidget }
|
|
|
|
TCEEditorWidget = class(TCEWidget, ICEMultiDocObserver, ICEMultiDocHandler, ICEProjectObserver)
|
|
MenuItem1: TMenuItem;
|
|
MenuItem2: TMenuItem;
|
|
MenuItem3: TMenuItem;
|
|
MenuItem5: TMenuItem;
|
|
MenuItem6: TMenuItem;
|
|
MenuItem8: TMenuItem;
|
|
mnuedRename: TMenuItem;
|
|
mnuedInvAllNone: TMenuItem;
|
|
mnuedComm: TMenuItem;
|
|
mnuedPrev: TMenuItem;
|
|
mnuedNext: TMenuItem;
|
|
mnuedCallTip: TMenuItem;
|
|
mnuedDdoc: TMenuItem;
|
|
mnuedCopy: TMenuItem;
|
|
mnuedCut: TMenuItem;
|
|
mnuedPaste: TMenuItem;
|
|
MenuItem4: TMenuItem;
|
|
mnuedUndo: TMenuItem;
|
|
mnuedRedo: TMenuItem;
|
|
MenuItem7: TMenuItem;
|
|
mnuedJum2Decl: TMenuItem;
|
|
macRecorder: TSynMacroRecorder;
|
|
editorStatus: TStatusBar;
|
|
mnuEditor: TPopupMenu;
|
|
procedure MenuItem5Click(Sender: TObject);
|
|
procedure MenuItem6Click(Sender: TObject);
|
|
procedure MenuItem8Click(Sender: TObject);
|
|
procedure mnuedRenameClick(Sender: TObject);
|
|
procedure mnuedInvAllNoneClick(Sender: TObject);
|
|
procedure mnuedCommClick(Sender: TObject);
|
|
procedure mnuedPrevClick(Sender: TObject);
|
|
procedure mnuedNextClick(Sender: TObject);
|
|
procedure mnuedCallTipClick(Sender: TObject);
|
|
procedure mnuedCopyClick(Sender: TObject);
|
|
procedure mnuedCutClick(Sender: TObject);
|
|
procedure mnuedDdocClick(Sender: TObject);
|
|
procedure mnuEditorPopup(Sender: TObject);
|
|
procedure mnuedPasteClick(Sender: TObject);
|
|
procedure mnuedUndoClick(Sender: TObject);
|
|
procedure mnuedRedoClick(Sender: TObject);
|
|
procedure mnuedJum2DeclClick(Sender: TObject);
|
|
protected
|
|
procedure updateDelayed; override;
|
|
procedure updateImperative; override;
|
|
private
|
|
fOptions: TCEPagesOptions;
|
|
pageControl: TCEPageControl;
|
|
fKeyChanged: boolean;
|
|
fDoc: TCESynMemo;
|
|
fProj: ICECommonProject;
|
|
fTokList: TLexTokenList;
|
|
fModStart: boolean;
|
|
fLastCommand: TSynEditorCommand;
|
|
procedure PageControlChanged(Sender: TObject);
|
|
procedure PageControlChanging(Sender: TObject; var AllowChange: Boolean);
|
|
procedure updateStatusBar;
|
|
procedure updatePageCaption;
|
|
procedure pageBtnAddCLick(Sender: TObject);
|
|
procedure pageCloseBtnClick(Sender: TObject);
|
|
procedure lexFindToken(const aToken: PLexToken; out doStop: boolean);
|
|
procedure memoKeyPress(Sender: TObject; var Key: char);
|
|
procedure memoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
|
|
procedure memoKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
|
|
procedure memoMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
procedure memoCtrlClick(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
procedure memoMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
|
|
procedure getSymbolLoc;
|
|
procedure focusedEditorChanged;
|
|
procedure memoCmdProcessed(Sender: TObject; var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer);
|
|
//
|
|
procedure docNew(aDoc: TCESynMemo);
|
|
procedure docClosing(aDoc: TCESynMemo);
|
|
procedure docFocused(aDoc: TCESynMemo);
|
|
procedure docChanged(aDoc: TCESynMemo);
|
|
//
|
|
procedure projNew(aProject: ICECommonProject);
|
|
procedure projChanged(aProject: ICECommonProject);
|
|
procedure projClosing(aProject: ICECommonProject);
|
|
procedure projFocused(aProject: ICECommonProject);
|
|
procedure projCompiling(aProject: ICECommonProject);
|
|
procedure projCompiled(aProject: ICECommonProject; success: boolean);
|
|
//
|
|
function SingleServiceName: string;
|
|
function documentCount: Integer;
|
|
function getDocument(index: Integer): TCESynMemo;
|
|
function findDocument(aFilename: string): TCESynMemo;
|
|
procedure openDocument(aFilename: string);
|
|
function closeDocument(index: Integer): boolean;
|
|
function closeDocument(doc: TCESynMemo): boolean;
|
|
public
|
|
constructor create(aOwner: TComponent); override;
|
|
destructor destroy; override;
|
|
function closeQuery: boolean; override;
|
|
end;
|
|
|
|
implementation
|
|
{$R *.lfm}
|
|
|
|
uses
|
|
ce_lcldragdrop;
|
|
const
|
|
optname = 'editorpages.txt';
|
|
|
|
{$REGION TCEPagesOptions -------------------------------------------------------}
|
|
constructor TCEPagesOptions.construct(editorWidg: TCEEditorWidget);
|
|
var
|
|
fname: string;
|
|
begin
|
|
fEditorWidget := editorWidg;
|
|
inherited create(editorWidg);
|
|
EntitiesConnector.addObserver(self);
|
|
//
|
|
fname := getCoeditDocPath + optname;
|
|
if fname.fileExists then
|
|
begin
|
|
loadFromFile(fname);
|
|
assignTo(fEditorWidget);
|
|
end
|
|
else Assign(fEditorWidget);
|
|
end;
|
|
|
|
destructor TCEPagesOptions.Destroy;
|
|
begin
|
|
saveToFile(getCoeditDocPath + optname);
|
|
EntitiesConnector.removeObserver(self);
|
|
inherited;
|
|
end;
|
|
|
|
procedure TCEPagesOptions.Assign(Source: TPersistent);
|
|
begin
|
|
if Source = fEditorWidget then
|
|
begin
|
|
fPageButtons := fEditorWidget.pageControl.buttons;
|
|
fPageOptions := fEditorWidget.pageControl.options;
|
|
end
|
|
else inherited;
|
|
end;
|
|
|
|
procedure TCEPagesOptions.AssignTo(Target: TPersistent);
|
|
begin
|
|
if Target = fEditorWidget then
|
|
begin
|
|
fEditorWidget.pageControl.buttons := fPageButtons;
|
|
fEditorWidget.pageControl.options := fPageOptions;
|
|
end
|
|
else inherited;
|
|
end;
|
|
|
|
function TCEPagesOptions.optionedWantCategory(): string;
|
|
begin
|
|
exit('Editor pages')
|
|
end;
|
|
|
|
function TCEPagesOptions.optionedWantEditorKind: TOptionEditorKind;
|
|
begin
|
|
exit(oekGeneric);
|
|
end;
|
|
|
|
function TCEPagesOptions.optionedWantContainer: TPersistent;
|
|
begin
|
|
exit(self);
|
|
end;
|
|
|
|
procedure TCEPagesOptions.optionedEvent(anEvent: TOptionEditorEvent);
|
|
begin
|
|
case anEvent of
|
|
oeeAccept: assignTo(fEditorWidget);
|
|
oeeCancel: Assign(fEditorWidget);
|
|
end;
|
|
end;
|
|
|
|
function TCEPagesOptions.optionedOptionsModified: boolean;
|
|
begin
|
|
exit(false);
|
|
end;
|
|
|
|
function TCEPagesOptions.scedWantFirst: boolean;
|
|
begin
|
|
fShCount := 0;
|
|
exit(true);
|
|
end;
|
|
|
|
function TCEPagesOptions.scedWantNext(out category, identifier: string; out aShortcut: TShortcut): boolean;
|
|
begin
|
|
category := 'Editor pages';
|
|
case fShCount of
|
|
0: begin identifier := 'Select next page'; aShortcut:= fNextPage; end;
|
|
1: begin identifier := 'Select previous page'; aShortcut:= fPrevPage; end;
|
|
2: begin identifier := 'Move page left'; aShortcut:= fMoveLeft; end;
|
|
3: begin identifier := 'Move page right'; aShortcut:= fMoveRight; end;
|
|
end;
|
|
fShCount += 1;
|
|
result := fShCount <> 4;
|
|
end;
|
|
|
|
procedure TCEPagesOptions.scedSendItem(const category, identifier: string; aShortcut: TShortcut);
|
|
begin
|
|
if fShCount = 4 then
|
|
fShCount := 0;
|
|
case fShCount of
|
|
0: fNextPage := aShortcut;
|
|
1: fPrevPage := aShortcut;
|
|
2: fMoveLeft := aShortcut;
|
|
3: fMoveRight:= aShortcut;
|
|
end;
|
|
end;
|
|
|
|
procedure TCEPagesOptions.scedSendDone;
|
|
begin
|
|
fShCount := 0;
|
|
end;
|
|
{$ENDREGION}
|
|
|
|
{$REGION Standard Comp/Obj------------------------------------------------------}
|
|
constructor TCEEditorWidget.create(aOwner: TComponent);
|
|
begin
|
|
inherited;
|
|
//
|
|
pageControl := TCEPageControl.Create(self);
|
|
pageControl.Parent := Content;
|
|
pageControl.align := alClient;
|
|
pageControl.onChanged:= @PageControlChanged;
|
|
pageControl.onChanging:=@PageControlChanging;
|
|
pageControl.closeButton.OnClick:=@pageCloseBtnClick;
|
|
pageControl.addButton.OnClick:=@pageBtnAddCLick;
|
|
pageControl.OnDragDrop:= @ddHandler.DragDrop;
|
|
pageControl.OnDragOver:= @ddHandler.DragOver;
|
|
AssignPng(pageControl.moveLeftButton, 'GO_PREVIOUS');
|
|
AssignPng(pageControl.moveRightButton, 'GO_NEXT');
|
|
AssignPng(pageControl.addButton, 'DOCUMENT_ADD');
|
|
AssignPng(pageControl.closeButton, 'DOCUMENT_DELETE');
|
|
AssignPng(pageControl.splitButton, 'SPLITTER');
|
|
|
|
fTokList := TLexTokenList.Create;
|
|
//
|
|
AssignPng(mnuedCopy.Bitmap, 'COPY');
|
|
AssignPng(mnuedCut.Bitmap, 'CUT');
|
|
AssignPng(mnuedPaste.Bitmap, 'PASTE');
|
|
AssignPng(mnuedUndo.Bitmap, 'ARROW_UNDO');
|
|
AssignPng(mnuedRedo.Bitmap, 'ARROW_REDO');
|
|
AssignPng(mnuedJum2Decl.Bitmap, 'ARROW_SHOE');
|
|
AssignPng(mnuedCopy.Bitmap, 'COPY');
|
|
AssignPng(mnuedNext.Bitmap, 'GO_NEXT');
|
|
AssignPng(mnuedPrev.Bitmap, 'GO_PREVIOUS');
|
|
AssignPng(mnuedRename.Bitmap, 'PENCIL');
|
|
//
|
|
EntitiesConnector.addObserver(self);
|
|
EntitiesConnector.addSingleService(self);
|
|
//
|
|
fOptions:= TCEPagesOptions.construct(self);
|
|
end;
|
|
|
|
destructor TCEEditorWidget.destroy;
|
|
var
|
|
i: integer;
|
|
begin
|
|
EntitiesConnector.removeObserver(self);
|
|
for i := PageControl.PageCount-1 downto 0 do
|
|
if PageControl.Pages[i].ControlCount > 0 then
|
|
if (PageControl.Pages[i].Controls[0] is TCESynMemo) then
|
|
PageControl.Pages[i].Controls[0].Free;
|
|
fTokList.Free;
|
|
fOptions.Free;
|
|
inherited;
|
|
end;
|
|
|
|
function TCEEditorWidget.closeQuery: boolean;
|
|
begin
|
|
result := inherited and Parent.isNil;
|
|
end;
|
|
|
|
{$ENDREGION}
|
|
|
|
{$REGION ICEMultiDocObserver ---------------------------------------------------}
|
|
procedure TCEEditorWidget.docNew(aDoc: TCESynMemo);
|
|
var
|
|
pge: TCEPage;
|
|
begin
|
|
pge := pageControl.addPage;
|
|
//
|
|
aDoc.Align := alClient;
|
|
aDoc.Parent := pge;
|
|
//
|
|
aDoc.OnKeyDown := @memoKeyDown;
|
|
aDoc.OnKeyUp := @memoKeyUp;
|
|
aDoc.OnKeyPress := @memoKeyPress;
|
|
aDoc.OnMouseDown := @memoMouseDown;
|
|
aDoc.OnMouseMove := @memoMouseMove;
|
|
aDoc.OnClickLink := @memoCtrlClick;
|
|
aDoc.OnCommandProcessed:= @memoCmdProcessed;
|
|
//
|
|
fDoc := aDoc;
|
|
focusedEditorChanged;
|
|
updateImperative;
|
|
end;
|
|
|
|
procedure TCEEditorWidget.docClosing(aDoc: TCESynMemo);
|
|
begin
|
|
if aDoc.isNil then
|
|
exit;
|
|
aDoc.Parent := nil;
|
|
if aDoc = fDoc then
|
|
fDoc := nil;
|
|
pageControl.deletePage(pageControl.pageIndex);
|
|
updateImperative;
|
|
end;
|
|
|
|
procedure TCEEditorWidget.docFocused(aDoc: TCESynMemo);
|
|
begin
|
|
if fDoc.isNotNil and pageControl.currentPage.isNotNil and
|
|
(pageControl.currentPage.Caption = '<new document>') then
|
|
updatePageCaption;
|
|
if aDoc = fDoc then exit;
|
|
fDoc := aDoc;
|
|
focusedEditorChanged;
|
|
updateImperative;
|
|
end;
|
|
|
|
procedure TCEEditorWidget.docChanged(aDoc: TCESynMemo);
|
|
begin
|
|
if fDoc <> aDoc then
|
|
exit;
|
|
fKeyChanged := true;
|
|
beginDelayedUpdate;
|
|
end;
|
|
{$ENDREGION}
|
|
|
|
{$REGION ICECommonProject ------------------------------------------------------}
|
|
procedure TCEEditorWidget.projNew(aProject: ICECommonProject);
|
|
begin
|
|
end;
|
|
|
|
procedure TCEEditorWidget.projChanged(aProject: ICECommonProject);
|
|
begin
|
|
end;
|
|
|
|
procedure TCEEditorWidget.projClosing(aProject: ICECommonProject);
|
|
begin
|
|
if fProj = aProject then
|
|
fProj := nil;
|
|
end;
|
|
|
|
procedure TCEEditorWidget.projFocused(aProject: ICECommonProject);
|
|
begin
|
|
fProj := aProject;
|
|
end;
|
|
|
|
procedure TCEEditorWidget.projCompiling(aProject: ICECommonProject);
|
|
begin
|
|
end;
|
|
|
|
procedure TCEEditorWidget.projCompiled(aProject: ICECommonProject; success: boolean);
|
|
begin
|
|
end;
|
|
{$ENDREGION}
|
|
|
|
{$REGION ICEMultiDocHandler ----------------------------------------------------}
|
|
function TCEEditorWidget.SingleServiceName: string;
|
|
begin
|
|
exit('ICEMultiDocHandler');
|
|
end;
|
|
|
|
function TCEEditorWidget.documentCount: Integer;
|
|
begin
|
|
exit(PageControl.PageCount);
|
|
end;
|
|
|
|
function TCEEditorWidget.getDocument(index: Integer): TCESynMemo;
|
|
begin
|
|
exit(TCESynMemo(pageControl.Pages[index].Controls[0]));
|
|
end;
|
|
|
|
function TCEEditorWidget.findDocument(aFilename: string): TCESynMemo;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
for i := 0 to PageControl.PageCount-1 do
|
|
begin
|
|
result := getDocument(i);
|
|
if result.fileName = aFilename then
|
|
exit;
|
|
end;
|
|
result := nil;
|
|
end;
|
|
|
|
procedure TCEEditorWidget.openDocument(aFilename: string);
|
|
var
|
|
doc: TCESynMemo;
|
|
begin
|
|
doc := findDocument(aFilename);
|
|
if doc.isNotNil then begin
|
|
PageControl.currentPage := TCEPage(doc.Parent);
|
|
exit;
|
|
end;
|
|
doc := TCESynMemo.Create(nil);
|
|
fDoc.loadFromFile(aFilename);
|
|
if assigned(fProj) and (fProj.filename = fDoc.fileName) then
|
|
begin
|
|
if fProj.getFormat = pfNative then
|
|
fDoc.Highlighter := LfmSyn
|
|
else
|
|
fDoc.Highlighter := JsSyn;
|
|
end;
|
|
end;
|
|
|
|
function TCEEditorWidget.closeDocument(index: Integer): boolean;
|
|
var
|
|
doc: TCESynMemo;
|
|
begin
|
|
doc := getDocument(index);
|
|
if doc.isNil then exit(false);
|
|
if (doc.modified or (doc.fileName = doc.tempFilename)) and
|
|
(dlgFileChangeClose(doc.fileName) = mrCancel) then exit(false);
|
|
doc.disableFileDateCheck:=true;
|
|
pageControl.pageIndex:=index;
|
|
doc.Free;
|
|
result := true;
|
|
end;
|
|
|
|
function TCEEditorWidget.closeDocument(doc: TCESynMemo): boolean;
|
|
var
|
|
page: TCEPage = nil;
|
|
begin
|
|
page := TCEPage(doc.Parent);
|
|
if page.isNil then
|
|
exit(false);
|
|
exit(closeDocument(page.index));
|
|
end;
|
|
{$ENDREGION}
|
|
|
|
{$REGION PageControl/Editor things ---------------------------------------------}
|
|
procedure TCEEditorWidget.pageCloseBtnClick(Sender: TObject);
|
|
begin
|
|
closeDocument(PageControl.PageIndex);
|
|
end;
|
|
|
|
procedure TCEEditorWidget.pageBtnAddCLick(Sender: TObject);
|
|
begin
|
|
TCESynMemo.Create(nil);
|
|
pageControl.currentPage.Caption:='<new document>';
|
|
end;
|
|
|
|
procedure TCEEditorWidget.focusedEditorChanged;
|
|
begin
|
|
if fDoc.isNil then exit;
|
|
//
|
|
macRecorder.Editor:= fDoc;
|
|
fDoc.PopupMenu := mnuEditor;
|
|
fDoc.hideCallTips;
|
|
fDoc.hideDDocs;
|
|
if (pageControl.currentPage.Caption = '') or
|
|
(pageControl.currentPage.Caption ='<new document>') then
|
|
begin
|
|
fKeyChanged := true;
|
|
beginDelayedUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TCEEditorWidget.PageControlChanged(Sender: TObject);
|
|
begin
|
|
if fDoc.isNil then exit;
|
|
fDoc.hideCallTips;
|
|
fDoc.hideDDocs;
|
|
end;
|
|
|
|
procedure TCEEditorWidget.PageControlChanging(Sender: TObject; var AllowChange: Boolean);
|
|
begin
|
|
if fDoc.isNil then exit;
|
|
fDoc.hideCallTips;
|
|
fDoc.hideDDocs;
|
|
end;
|
|
|
|
procedure TCEEditorWidget.memoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
|
|
var
|
|
sh: TShortCut;
|
|
begin
|
|
case Key of
|
|
VK_CLEAR,VK_RETURN,VK_BACK :
|
|
fKeyChanged := true;
|
|
VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT:
|
|
if Shift = [] then
|
|
updateImperative;
|
|
else begin
|
|
// note: keys conflict can lead to a lose of focus, i.e shortcut
|
|
// to select next page cant be repeated.
|
|
sh := KeyToShortCut(Key, shift);
|
|
if sh = fOptions.fNextPage then
|
|
begin
|
|
pageControl.pageIndex:= (pageControl.pageIndex + 1) mod pageControl.pageCount;
|
|
end
|
|
else if sh = fOptions.fPrevPage then
|
|
begin
|
|
if pageControl.pageIndex - 1 < 0 then
|
|
pageControl.pageIndex:= pageControl.pageCount - 1
|
|
else
|
|
pageControl.pageIndex:= pageControl.pageIndex - 1;
|
|
end
|
|
else if sh = fOptions.fMoveLeft then
|
|
pageControl.movePageLeft
|
|
else if sh = fOptions.fMoveRight then
|
|
pageControl.movePageRight;
|
|
end;
|
|
end;
|
|
if fKeyChanged then
|
|
beginDelayedUpdate;
|
|
end;
|
|
|
|
procedure TCEEditorWidget.memoKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
|
|
begin
|
|
case fLastCommand of
|
|
ecSelectionStart..ecSelectionEnd: updateImperative;
|
|
ecLeft..ecHalfWordRight: updateImperative;
|
|
end;
|
|
end;
|
|
|
|
procedure TCEEditorWidget.memoCmdProcessed(Sender: TObject; var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer);
|
|
begin
|
|
fLastCommand := Command;
|
|
//
|
|
case Command of
|
|
ecJumpToDeclaration:
|
|
getSymbolLoc;
|
|
ecRecordMacro:
|
|
begin
|
|
if macRecorder.State = msStopped then
|
|
macRecorder.RecordMacro(fDoc)
|
|
else
|
|
macRecorder.Stop;
|
|
updateImperative;
|
|
end;
|
|
ecPlayMacro:
|
|
begin
|
|
macRecorder.Stop;
|
|
macRecorder.PlaybackMacro(fDoc);
|
|
updateImperative;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TCEEditorWidget.memoKeyPress(Sender: TObject; var Key: char);
|
|
begin
|
|
fKeyChanged := true;
|
|
beginDelayedUpdate;
|
|
end;
|
|
|
|
procedure TCEEditorWidget.memoMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
updateImperative;
|
|
end;
|
|
|
|
procedure TCEEditorWidget.memoMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
if not (ssLeft in Shift) then exit;
|
|
beginDelayedUpdate;
|
|
end;
|
|
|
|
procedure TCEEditorWidget.memoCtrlClick(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
getSymbolLoc;
|
|
end;
|
|
|
|
procedure TCEEditorWidget.getSymbolLoc;
|
|
var
|
|
page: TCEPage;
|
|
srcpos, i, sum, linelen: Integer;
|
|
fname: string;
|
|
len: byte;
|
|
begin
|
|
if not DcdWrapper.available then exit;
|
|
//
|
|
DcdWrapper.getDeclFromCursor(fname, srcpos);
|
|
if (fname <> fDoc.fileName) and fname.fileExists then
|
|
begin
|
|
page := pageControl.splitPage;
|
|
if assigned(page) then
|
|
begin
|
|
fDoc := TCESynMemo(page.Controls[0]);
|
|
if fDoc.fileName <> fname then
|
|
openDocument(fname);
|
|
end
|
|
else openDocument(fname);
|
|
end;
|
|
if srcpos <> -1 then
|
|
begin
|
|
sum := 0;
|
|
len := getLineEndingLength(fDoc.fileName);
|
|
for i := 0 to fDoc.Lines.Count-1 do
|
|
begin
|
|
linelen := fDoc.Lines[i].length;
|
|
if sum + linelen + len > srcpos then
|
|
begin
|
|
fDoc.CaretY := i + 1;
|
|
fDoc.CaretX := srcpos - sum + len;
|
|
fDoc.SelectWord;
|
|
fDoc.EnsureCursorPosVisible;
|
|
break;
|
|
end;
|
|
sum += linelen;
|
|
sum += len;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TCEEditorWidget.updateStatusBar;
|
|
const
|
|
modstr: array[boolean] of string = ('...', 'MODIFIED');
|
|
begin
|
|
if fDoc = nil then
|
|
begin
|
|
editorStatus.Panels[0].Text := '';
|
|
editorStatus.Panels[1].Text := '';
|
|
editorStatus.Panels[2].Text := '';
|
|
editorStatus.Panels[3].Text := '';
|
|
editorStatus.Panels[4].Text := '';
|
|
end else
|
|
begin
|
|
editorStatus.Panels[0].Text := format('%d : %d | %d', [fDoc.CaretY, fDoc.CaretX, fDoc.SelEnd - fDoc.SelStart]);
|
|
editorStatus.Panels[1].Text := modstr[fDoc.modified];
|
|
if macRecorder.State = msRecording then
|
|
editorStatus.Panels[2].Text := 'recording macro'
|
|
else if macRecorder.IsEmpty then
|
|
editorStatus.Panels[2].Text := 'no macro'
|
|
else
|
|
editorStatus.Panels[2].Text := 'macro ready';
|
|
if fDoc.ReadOnly then
|
|
begin
|
|
editorStatus.Panels[3].Width:= 120;
|
|
editorStatus.Panels[3].Text := '(read-only)';
|
|
end else
|
|
editorStatus.Panels[3].Width:= 0;
|
|
editorStatus.Panels[4].Text := fDoc.fileName;
|
|
end;
|
|
end;
|
|
|
|
procedure TCEEditorWidget.updatePageCaption;
|
|
var
|
|
md: string = '<new document>';
|
|
begin
|
|
if fDoc.isNotNil then
|
|
begin
|
|
if fDoc.isDSource then
|
|
begin
|
|
lex(fDoc.Lines.Text, fTokList, @lexFindToken);
|
|
md := getModuleName(fTokList);
|
|
fTokList.Clear;
|
|
if md.isEmpty then
|
|
md := fDoc.fileName.extractFileName;
|
|
end
|
|
else if fDoc.fileName.fileExists then
|
|
md := fDoc.fileName.extractFileName
|
|
end;
|
|
pageControl.currentPage.Caption := md;
|
|
end;
|
|
|
|
procedure TCEEditorWidget.updateImperative;
|
|
begin
|
|
updateStatusBar;
|
|
if fDoc.isNotNil then
|
|
updatePageCaption;
|
|
end;
|
|
|
|
procedure TCEEditorWidget.updateDelayed;
|
|
begin
|
|
if fDoc = nil then
|
|
exit;
|
|
updateStatusBar;
|
|
if not fKeyChanged then
|
|
exit;
|
|
if fDoc.isNotNil then
|
|
updatePageCaption;
|
|
end;
|
|
|
|
procedure TCEEditorWidget.lexFindToken(const aToken: PLexToken; out doStop: boolean);
|
|
begin
|
|
if (aToken^.kind = ltkKeyword) and (aToken^.data = 'module') then
|
|
begin
|
|
fModStart := true;
|
|
exit;
|
|
end;
|
|
if fModStart and (aToken^.kind = ltkSymbol) and (aToken^.data = ';') then
|
|
begin
|
|
doStop := true;
|
|
fModStart := false;
|
|
end;
|
|
end;
|
|
{$ENDREGION}
|
|
|
|
{$REGION Editor context menu ---------------------------------------------------}
|
|
procedure TCEEditorWidget.mnuedCopyClick(Sender: TObject);
|
|
begin
|
|
if fDoc.isNotNil then
|
|
fDoc.ExecuteCommand(ecCopy, '', nil);
|
|
end;
|
|
|
|
procedure TCEEditorWidget.mnuedCallTipClick(Sender: TObject);
|
|
begin
|
|
if fDoc.isNil then
|
|
exit;
|
|
mnuEditor.Close;
|
|
fDoc.hideDDocs;
|
|
if not fDoc.IsDSource and not fDoc.alwaysAdvancedFeatures then
|
|
exit;
|
|
fDoc.showCallTips;
|
|
end;
|
|
|
|
procedure TCEEditorWidget.mnuedCommClick(Sender: TObject);
|
|
begin
|
|
if fDoc.isNotNil then
|
|
fDoc.CommandProcessor(ecCommentSelection, '', nil);
|
|
end;
|
|
|
|
procedure TCEEditorWidget.mnuedPrevClick(Sender: TObject);
|
|
begin
|
|
if fDoc.isNotNil then
|
|
fDoc.CommandProcessor(ecPreviousLocation, '', nil);
|
|
end;
|
|
|
|
procedure TCEEditorWidget.mnuedNextClick(Sender: TObject);
|
|
begin
|
|
if fDoc.isNotNil then
|
|
fDoc.CommandProcessor(ecNextLocation, '', nil);
|
|
end;
|
|
|
|
procedure TCEEditorWidget.mnuedInvAllNoneClick(Sender: TObject);
|
|
begin
|
|
if fDoc.isNil then
|
|
exit;
|
|
if not fDoc.IsDSource and not fDoc.alwaysAdvancedFeatures then
|
|
exit;
|
|
fDoc.CommandProcessor(ecSwapVersionAllNone, '', nil);
|
|
end;
|
|
|
|
procedure TCEEditorWidget.MenuItem5Click(Sender: TObject);
|
|
begin
|
|
if fDoc.isNil then
|
|
exit;
|
|
if not fDoc.IsDSource and not fDoc.alwaysAdvancedFeatures then
|
|
exit;
|
|
with TSaveDialog.Create(nil) do
|
|
try
|
|
if execute then
|
|
begin
|
|
fTokList.Clear;
|
|
lex(fDoc.Text, fTokList, nil);
|
|
fTokList.saveToFile(FileName);
|
|
fTokList.Clear;
|
|
end;
|
|
finally
|
|
free;
|
|
end;
|
|
end;
|
|
|
|
procedure TCEEditorWidget.MenuItem8Click(Sender: TObject);
|
|
var
|
|
str: TStringList;
|
|
begin
|
|
if fDoc.isNil then
|
|
exit;
|
|
if not fDoc.IsDSource and not fDoc.alwaysAdvancedFeatures then
|
|
exit;
|
|
with TSaveDialog.Create(nil) do
|
|
try
|
|
if execute then
|
|
begin
|
|
str := TStringList.Create;
|
|
fTokList.Clear;
|
|
lex(fDoc.Text, fTokList, nil, [lxoNoComments]);
|
|
getImports(fTOkList, str);
|
|
str.SaveToFile(filename);
|
|
fTokList.Clear;
|
|
str.Free;
|
|
end;
|
|
finally
|
|
free;
|
|
end;
|
|
end;
|
|
|
|
procedure TCEEditorWidget.MenuItem6Click(Sender: TObject);
|
|
begin
|
|
if fDoc.isNotNil then
|
|
fDoc.CommandProcessor(ecCommentIdentifier, '', nil);
|
|
end;
|
|
|
|
procedure TCEEditorWidget.mnuedRenameClick(Sender: TObject);
|
|
begin
|
|
if fDoc.isNotNil then
|
|
fDoc.CommandProcessor(ecRenameIdentifier, '', nil);
|
|
end;
|
|
|
|
procedure TCEEditorWidget.mnuedCutClick(Sender: TObject);
|
|
begin
|
|
if fDoc.isNotNil then
|
|
fDoc.ExecuteCommand(ecCut, '', nil);
|
|
end;
|
|
|
|
procedure TCEEditorWidget.mnuedDdocClick(Sender: TObject);
|
|
begin
|
|
if fDoc.isNil then exit;
|
|
mnuEditor.Close;
|
|
fDoc.hideCallTips;
|
|
if not fDoc.IsDSource and not fDoc.alwaysAdvancedFeatures then
|
|
exit;
|
|
fDoc.showDDocs;
|
|
end;
|
|
|
|
procedure TCEEditorWidget.mnuedPasteClick(Sender: TObject);
|
|
begin
|
|
if fDoc.isNotNil then
|
|
fDoc.ExecuteCommand(ecPaste, '', nil);
|
|
end;
|
|
|
|
procedure TCEEditorWidget.mnuedUndoClick(Sender: TObject);
|
|
begin
|
|
if fDoc.isNotNil then
|
|
fDoc.ExecuteCommand(ecUndo, '', nil);
|
|
end;
|
|
|
|
procedure TCEEditorWidget.mnuedRedoClick(Sender: TObject);
|
|
begin
|
|
if fDoc.isNotNil then
|
|
fDoc.ExecuteCommand(ecRedo, '', nil);
|
|
end;
|
|
|
|
procedure TCEEditorWidget.mnuedJum2DeclClick(Sender: TObject);
|
|
begin
|
|
if fDoc.isNotNil then
|
|
getSymbolLoc;
|
|
end;
|
|
|
|
procedure TCEEditorWidget.mnuEditorPopup(Sender: TObject);
|
|
begin
|
|
if fDoc.isNil then exit;
|
|
//
|
|
mnuedCut.Enabled:=fDoc.SelAvail;
|
|
mnuedPaste.Enabled:=fDoc.CanPaste;
|
|
mnuedCopy.Enabled:=fDoc.SelAvail;
|
|
mnuedUndo.Enabled:=fDoc.CanUndo;
|
|
mnuedRedo.Enabled:=fDoc.CanRedo;
|
|
mnuedJum2Decl.Enabled:=fDoc.isDSource;
|
|
end;
|
|
{$ENDREGION}
|
|
end.
|