mirror of https://gitlab.com/basile.b/dexed.git
342 lines
8.7 KiB
Plaintext
342 lines
8.7 KiB
Plaintext
unit ce_synmemo;
|
|
|
|
{$I ce_defines.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, SynEdit, SynMemo, ce_d2syn, ce_txtsyn ,SynEditHighlighter,
|
|
controls, lcltype, LazSynEditText, SynEditKeyCmds, SynHighlighterLFM, SynEditMouseCmds,
|
|
ce_common, ce_observer;
|
|
|
|
type
|
|
|
|
TCESynMemoPositions = class
|
|
private
|
|
fPos: Integer;
|
|
fMax: Integer;
|
|
fList: TFPList;
|
|
fMemo: TSynMemo;
|
|
public
|
|
constructor create(aMemo: TSynMemo);
|
|
destructor destroy; override;
|
|
procedure store;
|
|
procedure back;
|
|
procedure next;
|
|
end;
|
|
|
|
TCESynMemo = class(TSynMemo)
|
|
private
|
|
fFilename: string;
|
|
fModified: boolean;
|
|
fFileDate: double;
|
|
fIsDSource: boolean;
|
|
fIsTxtFile: boolean;
|
|
fIsConfig: boolean;
|
|
fIdentifier: string;
|
|
fTempFileName: string;
|
|
fMultiDocSubject: TCECustomSubject;
|
|
fStoredFontSize: Integer;
|
|
fPositions: TCESynMemoPositions;
|
|
procedure changeNotify(Sender: TObject);
|
|
procedure identifierToD2Syn;
|
|
protected
|
|
procedure SetHighlighter(const Value: TSynCustomHighlighter); override;
|
|
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
|
|
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
|
|
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y:Integer); override;
|
|
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y:Integer); override;
|
|
public
|
|
constructor Create(aOwner: TComponent); override;
|
|
destructor destroy; override;
|
|
procedure setFocus; override;
|
|
procedure UpdateShowing; override;
|
|
procedure DoEnter; override;
|
|
//
|
|
procedure checkFileDate;
|
|
procedure loadFromFile(const aFilename: string);
|
|
procedure saveToFile(const aFilename: string);
|
|
procedure save;
|
|
//
|
|
property Identifier: string read fIdentifier;
|
|
property fileName: string read fFilename;
|
|
property modified: boolean read fModified;
|
|
property tempFilename: string read fTempFileName;
|
|
//
|
|
property isDSource: boolean read fIsDSource;
|
|
property isProjectSource: boolean read fIsConfig;
|
|
end;
|
|
|
|
var
|
|
D2Syn: TSynD2Syn;
|
|
LfmSyn: TSynLfmSyn;
|
|
TxtSyn: TSynTxtSyn;
|
|
|
|
implementation
|
|
|
|
uses
|
|
graphics, ce_interfaces;
|
|
|
|
{$REGION TCESynMemoPositions ---------------------------------------------------}
|
|
constructor TCESynMemoPositions.create(aMemo: TSynMemo);
|
|
begin
|
|
fList := TFPList.Create;
|
|
fMax := 20;
|
|
fMemo := aMemo;
|
|
fPos := -1;
|
|
end;
|
|
|
|
destructor TCESynMemoPositions.destroy;
|
|
begin
|
|
fList.Free;
|
|
inherited;
|
|
end;
|
|
|
|
procedure TCESynMemoPositions.back;
|
|
begin
|
|
Inc(fPos);
|
|
{$WARNINGS OFF}
|
|
if fPos < fList.Count then
|
|
fMemo.CaretY := NativeInt(fList.Items[fPos])
|
|
{$WARNINGS ON}
|
|
else Dec(fPos);
|
|
end;
|
|
|
|
procedure TCESynMemoPositions.next;
|
|
begin
|
|
Dec(fPos);
|
|
{$WARNINGS OFF}
|
|
if fPos > -1 then
|
|
fMemo.CaretY := NativeInt(fList.Items[fPos])
|
|
{$WARNINGS ON}
|
|
else Inc(fPos);
|
|
end;
|
|
|
|
procedure TCESynMemoPositions.store;
|
|
begin
|
|
fPos := 0;
|
|
{$WARNINGS OFF}
|
|
if fList.Count > 0 then
|
|
if NativeInt(fList.Items[fPos]) = fMemo.CaretY then
|
|
exit;
|
|
fList.Insert(0, Pointer(NativeInt(fMemo.CaretY)));
|
|
{$WARNINGS ON}
|
|
while fList.Count > fMax do
|
|
fList.Delete(fList.Count-1);
|
|
end;
|
|
{$ENDREGION --------------------------------------------------------------------}
|
|
|
|
{$REGION TCESynMemo ------------------------------------------------------------}
|
|
constructor TCESynMemo.Create(aOwner: TComponent);
|
|
begin
|
|
inherited;
|
|
Font.Quality := fqProof;
|
|
//Font.CharSet := OEM_CHARSET;
|
|
Font.Pitch := fpFixed;
|
|
TabWidth := 4;
|
|
BlockIndent := 4;
|
|
Font.Size:= 10;
|
|
Options :=
|
|
[eoAutoIndent, eoBracketHighlight, eoGroupUndo, eoTabsToSpaces,
|
|
eoDragDropEditing, eoShowCtrlMouseLinks, eoEnhanceHomeKey, eoTabIndent];
|
|
Options2 :=
|
|
[eoEnhanceEndKey, eoFoldedCopyPaste, eoOverwriteBlock];
|
|
fStoredFontSize := Font.Size;
|
|
|
|
MouseOptions := MouseOptions +
|
|
[emAltSetsColumnMode, emDragDropEditing, emCtrlWheelZoom];
|
|
Gutter.LineNumberPart.ShowOnlyLineNumbersMultiplesOf := 5;
|
|
Gutter.LineNumberPart.MarkupInfo.Foreground := clGray;
|
|
Gutter.SeparatorPart.LineOffset := 1;
|
|
Gutter.SeparatorPart.LineWidth := 1;
|
|
Gutter.SeparatorPart.MarkupInfo.Foreground := clGray;
|
|
Gutter.CodeFoldPart.MarkupInfo.Foreground := clGray;
|
|
//
|
|
Highlighter := D2Syn;
|
|
D2Syn.FoldKinds := [fkBrackets, fkComments1, fkComments2, fkStrings];
|
|
//
|
|
fTempFileName := GetTempDir(false) + 'temp_' + uniqueObjStr(self) + '.d';
|
|
fFilename := '<new document>';
|
|
fModified := false;
|
|
ShowHint := true;
|
|
TextBuffer.AddNotifyHandler(senrUndoRedoAdded, @changeNotify);
|
|
//
|
|
fPositions := TCESynMemoPositions.create(self);
|
|
fMultiDocSubject := TCEMultiDocSubject.create;
|
|
subjDocNew(TCEMultiDocSubject(fMultiDocSubject), self);
|
|
end;
|
|
|
|
destructor TCESynMemo.destroy;
|
|
begin
|
|
subjDocClosing(TCEMultiDocSubject(fMultiDocSubject), self);
|
|
fMultiDocSubject.Free;
|
|
fPositions.Free;
|
|
//
|
|
if fileExists(fTempFileName) then
|
|
sysutils.DeleteFile(fTempFileName);
|
|
inherited;
|
|
end;
|
|
|
|
procedure TCESynMemo.setFocus;
|
|
begin
|
|
inherited;
|
|
if not Visible then exit;
|
|
checkFileDate;
|
|
identifierToD2Syn;
|
|
subjDocFocused(TCEMultiDocSubject(fMultiDocSubject), self);
|
|
end;
|
|
|
|
procedure TCESynMemo.UpdateShowing;
|
|
begin
|
|
inherited;
|
|
if not Visible then exit;
|
|
identifierToD2Syn;
|
|
subjDocFocused(TCEMultiDocSubject(fMultiDocSubject), self);
|
|
end;
|
|
|
|
procedure TCESynMemo.DoEnter;
|
|
begin
|
|
Inherited;
|
|
checkFileDate;
|
|
identifierToD2Syn;
|
|
end;
|
|
|
|
procedure TCESynMemo.SetHighlighter(const Value: TSynCustomHighlighter);
|
|
begin
|
|
inherited;
|
|
fIsDSource := Highlighter = D2Syn;
|
|
fIsConfig := Highlighter = LfmSyn;
|
|
fIsTxtFile := Highlighter = TxtSyn;
|
|
end;
|
|
|
|
procedure TCESynMemo.identifierToD2Syn;
|
|
begin
|
|
fIdentifier := GetWordAtRowCol(LogicalCaretXY);
|
|
if fIsDSource then
|
|
D2Syn.CurrentIdentifier := fIdentifier
|
|
else if fIsTxtFile then
|
|
TxtSyn.CurrIdent := fIdentifier;
|
|
end;
|
|
|
|
procedure TCESynMemo.changeNotify(Sender: TObject);
|
|
begin
|
|
identifierToD2Syn;
|
|
fModified := true;
|
|
fPositions.store;
|
|
subjDocChanged(TCEMultiDocSubject(fMultiDocSubject), self);
|
|
end;
|
|
|
|
procedure TCESynMemo.loadFromFile(const aFilename: string);
|
|
var
|
|
ext: string;
|
|
begin
|
|
ext := extractFileExt(aFilename);
|
|
if dExtList.IndexOf(ext) = -1 then
|
|
Highlighter := TxtSyn;
|
|
Lines.LoadFromFile(aFilename);
|
|
fFilename := aFilename;
|
|
FileAge(fFilename, fFileDate);
|
|
fModified := false;
|
|
subjDocChanged(TCEMultiDocSubject(fMultiDocSubject), self);
|
|
end;
|
|
|
|
procedure TCESynMemo.saveToFile(const aFilename: string);
|
|
var
|
|
ext: string;
|
|
begin
|
|
Lines.SaveToFile(aFilename);
|
|
fFilename := aFilename;
|
|
ext := extractFileExt(aFilename);
|
|
if dExtList.IndexOf(ext) <> -1 then
|
|
Highlighter := D2Syn;
|
|
FileAge(fFilename, fFileDate);
|
|
fModified := false;
|
|
if fFilename <> fTempFileName then
|
|
subjDocChanged(TCEMultiDocSubject(fMultiDocSubject), self);
|
|
end;
|
|
|
|
procedure TCESynMemo.save;
|
|
begin
|
|
Lines.SaveToFile(fFilename);
|
|
FileAge(fFilename, fFileDate);
|
|
fModified := false;
|
|
if fFilename <> fTempFileName then
|
|
subjDocChanged(TCEMultiDocSubject(fMultiDocSubject), self);
|
|
end;
|
|
|
|
procedure TCESynMemo.checkFileDate;
|
|
var
|
|
newDate: double;
|
|
begin
|
|
if fFilename = fTempFileName then exit;
|
|
if not FileAge(fFilename, newDate) then exit;
|
|
if fFileDate = newDate then exit;
|
|
if fFileDate <> 0.0 then
|
|
begin
|
|
if dlgOkCancel(format('"%s" has been modified by another program, load the new version ?',
|
|
[shortenPath(fFilename, 25)])) = mrOk then
|
|
begin
|
|
Lines.LoadFromFile(fFilename);
|
|
fModified := false;
|
|
end;
|
|
end;
|
|
fFileDate := newDate;
|
|
end;
|
|
|
|
procedure TCESynMemo.KeyDown(var Key: Word; Shift: TShiftState);
|
|
begin
|
|
if Key in [VK_PRIOR, VK_NEXT] then
|
|
fPositions.store;
|
|
//
|
|
inherited;
|
|
identifierToD2Syn;
|
|
//
|
|
if (Shift = [ssCtrl]) then case Key of
|
|
VK_ADD: if Font.Size < 50 then Font.Size := Font.Size + 1;
|
|
VK_SUBTRACT: if Font.Size > 3 then Font.Size := Font.Size - 1;
|
|
VK_DECIMAL: Font.Size := fStoredFontSize;
|
|
end;
|
|
end;
|
|
|
|
procedure TCESynMemo.MouseMove(Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
inherited;
|
|
if ssLeft in Shift then
|
|
identifierToD2Syn;
|
|
end;
|
|
|
|
procedure TCESynMemo.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y:Integer);
|
|
begin
|
|
inherited;
|
|
identifierToD2Syn;
|
|
end;
|
|
|
|
procedure TCESynMemo.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y:Integer);
|
|
begin
|
|
inherited;
|
|
if (Button = mbMiddle) and (Shift = [ssCtrl]) then
|
|
Font.Size := fStoredFontSize
|
|
else if Button = mbExtra1 then
|
|
fPositions.back
|
|
else if Button = mbExtra2 then
|
|
fPositions.next
|
|
else if Button = mbLeft then
|
|
fPositions.store;
|
|
end;
|
|
{$ENDREGION --------------------------------------------------------------------}
|
|
|
|
initialization
|
|
D2Syn := TSynD2Syn.create(nil);
|
|
LfmSyn := TSynLFMSyn.Create(nil);
|
|
TxtSyn := TSynTxtSyn.create(nil);
|
|
//
|
|
LfmSyn.KeyAttri.Foreground := clNavy;
|
|
LfmSyn.KeyAttri.Style := [fsBold];
|
|
LfmSyn.NumberAttri.Foreground := clMaroon;
|
|
LfmSyn.StringAttri.Foreground := clBlue;
|
|
finalization
|
|
D2Syn.Free;
|
|
LfmSyn.Free;
|
|
TxtSyn.Free;
|
|
end.
|