SynEdit: Extend Syncro edit, key-combo for case/context sensitivity Issue #40808 / key-combo to add/change/remove cells

This commit is contained in:
Martin 2024-03-07 20:41:42 +01:00
parent 6aebfc86ab
commit 46516b161f
9 changed files with 906 additions and 272 deletions

View File

@ -442,23 +442,41 @@ const
ecIdePSyncroEdNextFirstCellSel = ecFirstPlugin + 59;
ecIdePSyncroEdPrevFirstCell = ecFirstPlugin + 60;
ecIdePSyncroEdPrevFirstCellSel = ecFirstPlugin + 61;
ecIdePSyncroEdGrowCellLeft = ecFirstPlugin + 62;
ecIdePSyncroEdShrinkCellLeft = ecFirstPlugin + 63;
ecIdePSyncroEdGrowCellRight = ecFirstPlugin + 64;
ecIdePSyncroEdShrinkCellRight = ecFirstPlugin + 65;
ecIdePSyncroEdAddCell = ecFirstPlugin + 66;
ecIdePSyncroEdAddCellCase = ecFirstPlugin + 67;
ecIdePSyncroEdAddCellCtx = ecFirstPlugin + 68;
ecIdePSyncroEdAddCellCtxCase = ecFirstPlugin + 69;
ecIdePSyncroEdDelCell = ecFirstPlugin + 70;
// TSynPluginSyncroEdit - Out off cell
ecIdePSyncroEdOutNextCell = ecFirstPlugin + 70;
ecIdePSyncroEdOutNextCellSel = ecFirstPlugin + 71;
ecIdePSyncroEdOutPrevCell = ecFirstPlugin + 72;
ecIdePSyncroEdOutPrevCellSel = ecFirstPlugin + 73;
ecIdePSyncroEdOutCellHome = ecFirstPlugin + 74;
ecIdePSyncroEdOutCellEnd = ecFirstPlugin + 75;
ecIdePSyncroEdOutCellSelect = ecFirstPlugin + 76;
ecIdePSyncroEdOutEscape = ecFirstPlugin + 77;
ecIdePSyncroEdOutNextFirstCell = ecFirstPlugin + 78;
ecIdePSyncroEdOutNextFirstCellSel = ecFirstPlugin + 79;
ecIdePSyncroEdOutPrevFirstCell = ecFirstPlugin + 80;
ecIdePSyncroEdOutPrevFirstCellSel = ecFirstPlugin + 81;
ecIdePSyncroEdOutNextCell = ecFirstPlugin + 80;
ecIdePSyncroEdOutNextCellSel = ecFirstPlugin + 81;
ecIdePSyncroEdOutPrevCell = ecFirstPlugin + 82;
ecIdePSyncroEdOutPrevCellSel = ecFirstPlugin + 83;
ecIdePSyncroEdOutCellHome = ecFirstPlugin + 84;
ecIdePSyncroEdOutCellEnd = ecFirstPlugin + 85;
ecIdePSyncroEdOutCellSelect = ecFirstPlugin + 86;
ecIdePSyncroEdOutEscape = ecFirstPlugin + 87;
ecIdePSyncroEdOutNextFirstCell = ecFirstPlugin + 88;
ecIdePSyncroEdOutNextFirstCellSel = ecFirstPlugin + 89;
ecIdePSyncroEdOutPrevFirstCell = ecFirstPlugin + 90;
ecIdePSyncroEdOutPrevFirstCellSel = ecFirstPlugin + 91;
// grow/shrink 92..95 (reserved)
ecIdePSyncroEdOutAddCell = ecFirstPlugin + 96;
ecIdePSyncroEdOutAddCellCase = ecFirstPlugin + 97;
ecIdePSyncroEdOutAddCellCtx = ecFirstPlugin + 98;
ecIdePSyncroEdOutAddCellCtxCase = ecFirstPlugin + 99;
// del 100 (reserved)
// TSynPluginSyncroEdit - selecting
ecIdePSyncroEdSelStart = ecFirstPlugin + 90;
ecIdePSyncroEdSelStart = ecFirstPlugin + 110;
ecIdePSyncroEdSelStartCase = ecFirstPlugin + 111;
ecIdePSyncroEdSelStartCtx = ecFirstPlugin + 112;
ecIdePSyncroEdSelStartCtxCase = ecFirstPlugin + 113;
const
// Mouse command offsets
@ -1967,7 +1985,7 @@ begin
end;
const
IDEEditorCommandStrs: array[0..323] of TIdentMapEntry = ( // DRB reduced elements from 323
IDEEditorCommandStrs: array[0..337] of TIdentMapEntry = ( // DRB reduced elements from 323
// search
(Value: ecFind; Name: 'ecFind'),
(Value: ecFindAgain; Name: 'ecFindAgain'),
@ -2331,6 +2349,13 @@ const
(Value: ecIdePSyncroEdNextFirstCellSel; Name: 'ecIdePSyncroEdNextFirstCellSel'),
(Value: ecIdePSyncroEdPrevFirstCell; Name: 'ecIdePSyncroEdPrevFirstCell'),
(Value: ecIdePSyncroEdPrevFirstCellSel; Name: 'ecIdePSyncroEdPrevFirstCellSel'),
(Value: ecIdePSyncroEdGrowCellLeft; Name: 'ecIdePSyncroEdGrowCellLeft'),
(Value: ecIdePSyncroEdShrinkCellLeft; Name: 'ecIdePSyncroEdShrinkCellLeft'),
(Value: ecIdePSyncroEdGrowCellRight; Name: 'ecIdePSyncroEdGrowCellRight'),
(Value: ecIdePSyncroEdShrinkCellRight; Name: 'ecIdePSyncroEdShrinkCellRight'),
(Value: ecIdePSyncroEdAddCell; Name: 'ecIdePSyncroEdAddCell'),
(Value: ecIdePSyncroEdAddCellCtx; Name: 'ecIdePSyncroEdAddCellCtx'),
(Value: ecIdePSyncroEdDelCell; Name: 'ecIdePSyncroEdDelCell'),
// TSynPluginSyncroEdit - Out off cell
(Value: ecIdePSyncroEdOutNextCell; Name: 'ecIdePSyncroEdOutNextCell'),
@ -2345,9 +2370,20 @@ const
(Value: ecIdePSyncroEdOutNextFirstCellSel; Name: 'ecIdePSyncroEdOutNextFirstCellSel'),
(Value: ecIdePSyncroEdOutPrevFirstCell; Name: 'ecIdePSyncroEdOutPrevFirstCell'),
(Value: ecIdePSyncroEdOutPrevFirstCellSel; Name: 'ecIdePSyncroEdOutPrevFirstCellSel'),
// (Value: ecIdePSyncroEdGrowCellLeft; Name: 'ecIdePSyncroEdGrowCellLeft'),
// (Value: ecIdePSyncroEdShrinkCellLeft; Name: 'ecIdePSyncroEdShrinkCellLeft'),
// (Value: ecIdePSyncroEdGrowCellRight; Name: 'ecIdePSyncroEdGrowCellRight'),
// (Value: ecIdePSyncroEdShrinkCellRight; Name: 'ecIdePSyncroEdShrinkCellRight'),
(Value: ecIdePSyncroEdOutAddCell; Name: 'ecIdePSyncroEdOutAddCell'),
(Value: ecIdePSyncroEdOutAddCellCase; Name: 'ecIdePSyncroEdOutAddCellCase'),
(Value: ecIdePSyncroEdOutAddCellCtx; Name: 'ecIdePSyncroEdOutAddCellCtx'),
(Value: ecIdePSyncroEdOutAddCellCtxCase; Name: 'ecIdePSyncroEdOutAddCellCtxCase'),
// TSynPluginSyncroEdit - selecting
(Value: ecIdePSyncroEdSelStart; Name: 'ecIdePSyncroEdSelStart')
(Value: ecIdePSyncroEdSelStart; Name: 'ecIdePSyncroEdSelStart'),
(Value: ecIdePSyncroEdSelStartCase; Name: 'ecIdePSyncroEdSelStartCase'),
(Value: ecIdePSyncroEdSelStartCtx; Name: 'ecIdePSyncroEdSelStartCtx'),
(Value: ecIdePSyncroEdSelStartCtxCase; Name: 'ecIdePSyncroEdSelStartCtxCase')
);
function IdentToIDECommand(const Ident: string; var Cmd: longint): boolean;

View File

@ -1010,7 +1010,8 @@ type
out Attri: TSynHighlighterAttributes): boolean;
function GetHighlighterAttriAtRowColEx(XY: TPoint; out Token: string;
out TokenType, Start: Integer;
out Attri: TSynHighlighterAttributes): boolean; //L505
out Attri: TSynHighlighterAttributes): boolean;
function GetHighlighterAttriAtRowColEx(XY: TPoint; out TokenType: Integer; ContinueIfPossible: boolean = False): boolean;
procedure CaretAtIdentOrString(XY: TPoint; out AtIdent, NearString: Boolean);
procedure GetWordBoundsAtRowCol(const XY: TPoint; out StartX, EndX: integer); override;
function GetWordAtRowCol(XY: TPoint): string; override;
@ -9670,14 +9671,14 @@ var
PosX, PosY: integer;
Line: string;
begin
PosY := XY.Y -1;
PosY := ToIdx(XY.Y);
if Assigned(Highlighter) and (PosY >= 0) and (PosY < FTheLinesView.Count) then
begin
Line := FTheLinesView[PosY];
fHighlighter.CurrentLines := FTheLinesView;
Highlighter.StartAtLineIndex(PosY);
PosX := XY.X;
if (PosX > 0) and (PosX <= Length(Line)) then begin
fHighlighter.CurrentLines := FTheLinesView;
Highlighter.StartAtLineIndex(PosY);
while not Highlighter.GetEol do begin
Start := Highlighter.GetTokenPos + 1;
Token := Highlighter.GetToken;
@ -9696,6 +9697,40 @@ begin
Result := False;
end;
function TCustomSynEdit.GetHighlighterAttriAtRowColEx(XY: TPoint; out TokenType: Integer;
ContinueIfPossible: boolean): boolean;
var
PosX, PosY, Start: integer;
Line: string;
begin
PosY := ToIdx(XY.Y);
if Assigned(Highlighter) and (PosY >= 0) and (PosY < FTheLinesView.Count) then
begin
Line := FTheLinesView[PosY];
PosX := XY.X;
if (PosX > 0) and (PosX <= Length(Line)) then begin
if (not ContinueIfPossible) or
(fHighlighter.CurrentLines <> FTheLinesView) or
(fHighlighter.LineIndex <> PosY) or
(fHighlighter.GetTokenPos + 1 + Highlighter.GetTokenLen >= PosX)
then begin
fHighlighter.CurrentLines := FTheLinesView;
Highlighter.StartAtLineIndex(PosY);
end;
while not Highlighter.GetEol do begin
Start := Highlighter.GetTokenPos + 1;
if (PosX >= Start) and (PosX < Start + Highlighter.GetTokenLen) then begin
TokenType := Highlighter.GetTokenKind;
exit(True);
end;
Highlighter.Next;
end;
end;
end;
TokenType := -1;
Result := False;
end;
procedure TCustomSynEdit.CaretAtIdentOrString(XY: TPoint; out AtIdent, NearString: Boolean);
// This is optimized to check if cursor is on identifier or string.
var

View File

@ -377,7 +377,6 @@ type
// code fold - only valid if hcCodeFolding in Capabilities
procedure SetCurrentLines(const AValue: TSynEditStringsBase); virtual; // todo remove virtual
procedure DoCurrentLinesChanged; virtual;
property LineIndex: Integer read FLineIndex;
property CurrentRanges: TSynHighlighterRangeList read FCurrentRanges;
function GetDrawDivider(Index: integer): TSynDividerDrawConfigSetting; virtual;
function GetDividerDrawConfig(Index: Integer): TSynDividerDrawConfig; virtual;
@ -413,6 +412,7 @@ type
function GetTokenAttribute: TSynHighlighterAttributes; virtual; abstract;
function GetTokenKind: integer; virtual; abstract;
function GetTokenPos: Integer; virtual; abstract; // 0-based
function GetTokenLen: Integer; virtual;
function IsKeyword(const AKeyword: string): boolean; virtual; // DJLP 2000-08-09
procedure Next; virtual; abstract;
procedure NextToEol;
@ -440,6 +440,7 @@ type
procedure SetLine(const NewValue: String;
LineNumber:Integer // 0 based
); virtual;
property LineIndex: Integer read FLineIndex;
public
function UseUserSettings(settingIndex: integer): boolean; virtual;
procedure EnumUserSettings(Settings: TStrings); virtual;
@ -1536,6 +1537,13 @@ begin
Result := nil;
end;
function TSynCustomHighlighter.GetTokenLen: Integer;
var
x: PChar;
begin
GetTokenEx(x, Result);
end;
procedure TSynCustomHighlighter.SetWordBreakChars(AChars: TSynIdentChars);
begin
fWordBreakChars := AChars;

View File

@ -641,6 +641,7 @@ type
function GetTokenID: TtkTokenKind;
function GetTokenKind: integer; override;
function GetTokenPos: Integer; override;
function GetTokenLen: Integer; override;
function IsKeyword(const AKeyword: string): boolean; override;
procedure Next; override;
@ -4456,6 +4457,11 @@ begin
Result := fTokenPos;
end;
function TSynPasSyn.GetTokenLen: Integer;
begin
Result := Run-fTokenPos;
end;
function TSynPasSyn.GetRange: Pointer;
begin
// For speed reasons, we work with fRange instead of CodeFoldRange.RangeType

File diff suppressed because it is too large Load Diff

View File

@ -26,9 +26,9 @@ unit SynPluginSyncronizedEditBase;
interface
uses
Classes, SysUtils, Graphics,
Classes, SysUtils, Graphics, StrUtils,
SynEditMiscClasses, SynEdit, SynEditMarkup, SynEditMiscProcs, LazSynEditText,
SynEditTextTrimmer, SynEditKeyCmds, SynEditTextBase;
SynEditTextTrimmer, SynEditKeyCmds, SynEditTextBase, LazUTF8;
type
@ -69,10 +69,11 @@ type
destructor Destroy; override;
procedure Clear;
function Add(aCell: TSynPluginSyncronizedEditCell): Integer;
function AddNew: TSynPluginSyncronizedEditCell; virtual;
function AddNew: TSynPluginSyncronizedEditCell; virtual; // only add sorted
procedure Delete(aIndex: Integer);
function IndexOf(aCell: TSynPluginSyncronizedEditCell): Integer;
function IndexOf(aX, aY: Integer; IncludeLast: Boolean = False; aCurrentCellIdx: Integer = -1): Integer;
function IndexOfNext(aX, aY: Integer; IncludeLast: Boolean = False; aCurrentCellIdx: Integer = -1): Integer;
function IsInCell(aX, aY, ACellIdx: Integer; IncludeLast: Boolean = False): Boolean;
function Count: Integer;
function GroupCount(aGroup: Integer): Integer;
@ -282,6 +283,9 @@ type
- various helpers, to set the caret/block
*)
TSynPluginSyncroScanMode = (spssNoCase, spssWithCase, spssCtxNoCase, spssCtxWithCase);
TSynPluginSyncroScanModes = set of TSynPluginSyncroScanMode;
TSynPluginCustomSyncroEdit = class(TSynPluginSyncronizedEditBase)
private
FLastCell: Integer;
@ -306,6 +310,15 @@ type
procedure NextCell(SetSelect: Boolean = True; SkipSameIndex: Boolean = False; FirstsOnly: Boolean = False);
procedure CellCaretHome;
procedure CellCaretEnd;
function MovePointLeft(p: TPoint; out ARes: TPoint; AllowLineWrap: Boolean): Boolean;
function MovePointRight(p: TPoint; out ARes: TPoint; AllowLineWrap: Boolean): Boolean;
procedure RemoveSingleGroupCells;
procedure ShrinkCell(AGroup: Integer; ARightSide: Boolean);
procedure GrowCell(AGroup: Integer; ARightSide: Boolean);
procedure ResizeCell(ARightSide: Boolean; AShrink: Boolean);
procedure AddGroupFromSelection(AScanMode: TSynPluginSyncroScanMode);
procedure RemoveCurrentCell;
public
constructor Create(AOwner: TComponent); override;
//destructor Destroy; override;
@ -432,10 +445,19 @@ end;
function TSynPluginSyncronizedEditList.Add(aCell: TSynPluginSyncronizedEditCell): Integer;
var
i: Integer;
i, n: Integer;
begin
if aCell.LogStart.Y = High(Integer) then
n := -1
else
n := IndexOfNext(aCell.LogStart.x, aCell.LogStart.Y);
i := length(FCells);
SetLength(FCells, i + 1);
if (n >= 0) and (n < i) then begin
move(FCells[n], FCells[n+1], SizeOf(FCells[0]) * (i-n));
i := n;
end;
FCells[i] := aCell;
Result := i;
if assigned(FOnCellChange) then
@ -445,6 +467,7 @@ end;
function TSynPluginSyncronizedEditList.AddNew: TSynPluginSyncronizedEditCell;
begin
Result := TSynPluginSyncronizedEditCell.Create;
Result.FLogStart.y := high(Integer);
Add(Result);
end;
@ -452,13 +475,13 @@ procedure TSynPluginSyncronizedEditList.Delete(aIndex: Integer);
var
i: Integer;
begin
if assigned(FOnCellChange) then
FOnCellChange(aIndex, FCells[aIndex], nil);
FCells[aIndex].Free;
i := length(FCells) - 1;
if aIndex < i then
System.Move(FCells[aIndex+1], FCells[aIndex], (i-aIndex) * SizeOf(TSynPluginSyncronizedEditCell));
SetLength(FCells, i);
if assigned(FOnCellChange) then
FOnCellChange(aIndex, FCells[i], nil);
end;
function TSynPluginSyncronizedEditList.IndexOf(aCell: TSynPluginSyncronizedEditCell): Integer;
@ -485,7 +508,7 @@ begin
if IncludeLast then
a := 1
else
a := 0;;
a := 0;
for i := 0 to Count -1 do begin
if (FCells[i].Group >= 0) and
( (FCells[i].LogStart.Y < aY) or
@ -498,11 +521,37 @@ begin
Result := -1;
end;
function TSynPluginSyncronizedEditList.IndexOfNext(aX, aY: Integer;
IncludeLast: Boolean; aCurrentCellIdx: Integer): Integer;
var
a, i: Integer;
begin
// If 2 cells touch, prefer current cell
if (aCurrentCellIdx >= 0) and IsInCell(aX, aY, aCurrentCellIdx, IncludeLast) then begin
Result := aCurrentCellIdx;
exit;
end;
if IncludeLast then
a := 1
else
a := 0;
for i := 0 to Count -1 do begin
if (FCells[i].Group >= 0) and
( (FCells[i].LogEnd.Y > aY) or
((FCells[i].LogEnd.Y = aY) and (FCells[i].LogEnd.X + a > aX)) )
then
exit(i);
end;
Result := -1;
end;
function TSynPluginSyncronizedEditList.IsInCell(aX, aY, ACellIdx: Integer;
IncludeLast: Boolean): Boolean;
var
a: Integer;
begin
if ACellIdx >= Length(FCells) then exit(False);
if IncludeLast then
a := 1
else
@ -525,10 +574,12 @@ var
i: Integer;
begin
i := 0;
Result := 0;
while i < length(FCells) do
Result := 0;
while i < length(FCells) do begin
if FCells[i].Group = aGroup then
inc(Result);
inc(i);
end;
end;
{ TSynPluginSyncronizedEditMarkupBase }
@ -728,9 +779,9 @@ end;
procedure TSynPluginSyncronizedEditMarkupArea.CellChanged(aIndex: Integer; aOldVal,
aNewVal: TSynPluginSyncronizedEditCell);
begin
if (aOldVal <> nil) and (aOldVal.Group = CellGroupForArea) then
if (aOldVal <> nil) and (aOldVal.Group = CellGroupForArea) and (aOldVal.LogStart.Y <> high(Integer)) then
InvalidateSynLines(aOldVal.LogStart.Y, aOldVal.LogEnd.Y);
if (aNewVal <> nil) and (aNewVal.Group = CellGroupForArea) then
if (aNewVal <> nil) and (aNewVal.Group = CellGroupForArea) and (aNewVal.LogStart.Y <> high(Integer)) then
InvalidateSynLines(aNewVal.LogStart.Y, aNewVal.LogEnd.Y);
end;
@ -1636,6 +1687,339 @@ begin
Editor.BlockBegin := Cells[CurrentCell].LogEnd;
end;
function TSynPluginCustomSyncroEdit.MovePointLeft(p: TPoint; out ARes: TPoint;
AllowLineWrap: Boolean): Boolean;
begin
Result := False;
p := FriendEdit.LogicalToPhysicalPos(p);
if p.X = 1 then begin
if (not AllowLineWrap) or (p.Y = 1) then
exit;
ARes.Y := p.Y - 1;
ARes.X := Length(FriendEdit.Lines[ToIdx(ARes.y)]) + 1;
Result := True;
exit;
end;
Dec(p.X);
ARes := FriendEdit.PhysicalToLogicalPos(p);
Result := True;
end;
function TSynPluginCustomSyncroEdit.MovePointRight(p: TPoint; out ARes: TPoint;
AllowLineWrap: Boolean): Boolean;
begin
Result := False;
p := FriendEdit.LogicalToPhysicalPos(p);
if p.X > Length(FriendEdit.Lines[ToIdx(p.Y)]) then begin
if (not AllowLineWrap) or (p.Y >= FriendEdit.Lines.Count) then
exit;
ARes.Y := p.Y + 1;
ARes.X := 1;
Result := True;
exit;
end;
Inc(p.X);
ARes := FriendEdit.PhysicalToLogicalPos(p);
Result := True;
end;
procedure TSynPluginCustomSyncroEdit.RemoveSingleGroupCells;
var
i, j, g: Integer;
begin
i := 0;
while i < Cells.Count do begin
g := Cells[i].Group;
if g < 0 then begin
inc(i);
continue;
end;
j := i - 1;
while (j >= 0) and (Cells[j].Group <> g) do
dec(j);
Cells[i].FFirstInGroup := j < 0;
if j < 0 then begin
j := Cells.Count - 1;
while j > i do begin
if Cells[j].Group = g then break;
dec(j);
end;
if j = i then begin
Cells.Delete(i);
dec(i);
end;
end;
inc(i);
end;
end;
procedure TSynPluginCustomSyncroEdit.ShrinkCell(AGroup: Integer;
ARightSide: Boolean);
var
i2: Integer;
c2: TSynPluginSyncronizedEditCell;
NewPos: TPoint;
DidDelete: Boolean;
begin
DidDelete := False;
for i2 := Cells.Count - 1 downto 0 do begin
if i2 >= Cells.Count then Continue;
c2 := Cells[i2];
if c2.Group <> AGroup then Continue;
if ARightSide then begin
MovePointLeft(c2.LogEnd, NewPos, c2.LogEnd.y <> c2.LogStart.y);
if CompareCarets(NewPos, c2.LogEnd) <= 0 then begin
Cells.Delete(i2);
DidDelete := True;
end
else
Cells[i2].LogEnd := NewPos;
end
else begin
MovePointRight(c2.LogStart, NewPos, c2.LogEnd.y <> c2.LogStart.y);
if CompareCarets(c2.LogStart, NewPos) <= 0 then begin
Cells.Delete(i2);
DidDelete := True;
end
else
Cells[i2].LogStart := NewPos;
end;
end;
if DidDelete then
RemoveSingleGroupCells;
UpdateCurrentCell;
FriendEdit.Invalidate;
end;
procedure TSynPluginCustomSyncroEdit.GrowCell(AGroup: Integer;
ARightSide: Boolean);
var
i2, i3: Integer;
c2: TSynPluginSyncronizedEditCell;
NewPos: TPoint;
DidDelete: Boolean;
begin
DidDelete := False;
for i2 := Cells.Count - 1 downto 0 do begin
if i2 >= Cells.Count then Continue;
c2 := Cells[i2];
if c2.Group <> AGroup then Continue;
if ARightSide then begin
MovePointRight(c2.LogEnd, NewPos, False);
i3 := Cells.IndexOf(NewPos.X, NewPos.Y, True {touch});
Cells[i2].LogEnd := NewPos;
end
else begin
MovePointLeft(c2.LogStart, NewPos, False);
i3 := Cells.IndexOf(NewPos.X, NewPos.Y, True {touch});
Cells[i2].LogStart := NewPos;
end;
if (i3 >= 0) then begin
Cells.Delete(i3);
DidDelete := True;
end;
end;
if DidDelete then
RemoveSingleGroupCells;
UpdateCurrentCell;
FriendEdit.Invalidate;
end;
procedure TSynPluginCustomSyncroEdit.ResizeCell(ARightSide: Boolean;
AShrink: Boolean);
var
i, g, i2, i3: Integer;
c, c2: TSynPluginSyncronizedEditCell;
NewPos: TPoint;
r: Boolean;
begin
i := CurrentCell;
if i < 0 then
exit;
c := Cells[i];
g := c.Group;
if g < 0 then exit;
for i2 := 0 to Cells.Count - 1 do begin
c2 := Cells[i2];
if c2.Group <> g then Continue;
if ARightSide then begin
if AShrink
then r := MovePointLeft(c2.LogEnd, NewPos, c2.LogEnd.y <> c2.LogStart.y)
else r := MovePointRight(c2.LogEnd, NewPos, False);
end
else begin
if AShrink
then r := MovePointRight(c2.LogStart, NewPos, c2.LogEnd.y <> c2.LogStart.y)
else r := MovePointLeft(c2.LogStart, NewPos, False);
end;
if not r then
exit;
if AShrink then begin
if (i = i2) then begin
// check current cell can shrink
if ARightSide then begin
if CompareCarets(NewPos, c2.LogEnd) <= 0 then exit;
end
else
if CompareCarets(c2.LogStart, NewPos) <= 0 then exit;
end;
end
else begin
// growing
i3 := Cells.IndexOf(NewPos.X, NewPos.Y, True {touch});
if (i3 >= 0) and (Cells[i3].Group = g) then
exit;
end;
end;
if AShrink then
ShrinkCell(g, ARightSide)
else
GrowCell(g, ARightSide);
end;
procedure TSynPluginCustomSyncroEdit.AddGroupFromSelection(AScanMode: TSynPluginSyncroScanMode);
function FindNextStart(AText: String; AStartPos, AMaxPos: TPoint): TPoint;
var
l: String;
begin
Result.Y := -1;
repeat
l := TextBuffer[ToIdx(AStartPos.Y)];
if AScanMode in [spssNoCase, spssCtxNoCase] then
l := Utf8LowerCase(l);
Result.X := PosEx(AText, l, AStartPos.X);
if (Result.X > 0) and
( (AStartPos.Y < AMaxPos.Y) or
((AStartPos.y = AMaxPos.y) and (Result.x + Length(AText) <= AMaxPos.X))
)
then begin
Result.Y := AStartPos.Y;
exit;
end;
AStartPos.X := 1;
inc(AStartPos.Y);
until AStartPos.y > AMaxPos.Y;
end;
function FindNextStart(AText: String; AStartPos, AMaxPos: TPoint; AScope: integer): TPoint;
var
tt: Integer;
begin
repeat
Result := FindNextStart(AText, AStartPos, AMaxPos);
if not (AScanMode in [spssCtxNoCase, spssCtxWithCase]) then
exit;
if Result.Y < 0 then
exit;
TSynEdit(FriendEdit).GetHighlighterAttriAtRowColEx(Result, tt, True);
if tt = AScope then
exit;
AStartPos := Result;
AStartPos.x := AStartPos.x + Length(AText);
until False;
end;
var
Grp: Integer;
DidDelete: boolean;
procedure AddFndCell(p, p2: TPoint; AsFirst: boolean = False);
var
nc: TSynPluginSyncronizedEditCell;
Existing: Integer;
begin
Existing := Cells.IndexOfNext(p.X, p.Y);
if Existing >= 0 then
while (Existing < Cells.Count) and (CompareCarets(Cells[Existing].LogStart, p2) > 0) do begin
Cells.Delete(Existing);
DidDelete := True;
end;
nc := TSynPluginSyncronizedEditCell.Create;
nc.LogStart := p;
nc.LogEnd := p2;
nc.Group := Grp;
nc.FirstInGroup := AsFirst;
Cells.Add(nc);
end;
var
BndCell: TSynPluginSyncronizedEditCell;
t: String;
p: TPoint;
Fnd, FndEnd, Fnd2, FndEnd2: TPoint;
Ctx, i: Integer;
begin
if (not FriendEdit.SelAvail) or (FriendEdit.BlockBegin.y <> FriendEdit.BlockEnd.Y) then
exit;
BndCell := Cells.GroupCell[-1, 0];
if BndCell = nil then
exit;
DidDelete := False;
Grp := 1;
for i := 0 to Cells.Count - 1 do
if Cells[i].Group >= Grp then
Grp := Cells[i].Group + 1;
Ctx := 0;
if AScanMode in [spssCtxNoCase, spssCtxWithCase] then
TSynEdit(FriendEdit).GetHighlighterAttriAtRowColEx(FriendEdit.BlockBegin, Ctx, False);
t := FriendEdit.SelText;
if AScanMode in [spssNoCase, spssCtxNoCase] then
t := UTF8LowerCase(t);
p := BndCell.LogStart;
Fnd := FindNextStart(t, p, BndCell.LogEnd, Ctx);
FndEnd := Fnd;
inc(FndEnd.X, Length(t));
if (Fnd.Y < 0) then
exit;
p := FndEnd;
Fnd2 := FindNextStart(t, p, BndCell.LogEnd, Ctx);
FndEnd2 := Fnd2;
inc(FndEnd2.X, Length(t));
if (Fnd2.Y < 0) then
exit;
AddFndCell(Fnd, FndEnd, True);
while Fnd2.y >= 0 do begin
AddFndCell(Fnd2, FndEnd2);
p := FndEnd2;
Fnd2 := FindNextStart(t, p, BndCell.LogEnd, Ctx);
FndEnd2 := Fnd2;
inc(FndEnd2.X, Length(t));
end;
if DidDelete then
RemoveSingleGroupCells;
UpdateCurrentCell;
FriendEdit.Invalidate;
end;
procedure TSynPluginCustomSyncroEdit.RemoveCurrentCell;
begin
if (CurrentCell < 0) or (CurrentCell >= Cells.Count) then
exit;
Cells.Delete(CurrentCell);
RemoveSingleGroupCells;
CurrentCell := -1;
FriendEdit.Invalidate;
end;
constructor TSynPluginCustomSyncroEdit.Create(AOwner: TComponent);
begin
FPaintLock := 0;

View File

@ -117,11 +117,11 @@ begin
for i := 0 to hsh.HashSize - 1 do begin
he := hsh.HashEntry[i, 0];
if he.Count > 0 then begin
debugln(['hash for ', i,', ', 0, ' Cnt=', he.Count, ' hsh=', he.Hash, ' nxt=', he.Next, ' y=', he.LineIdx, ' x=', he.BytePos, ' ln=', he.Len]);
debugln(['hash for ', i,', ', 0, ' Cnt=', he.Count, ' hsh=', he.Hash, ' nxt=', he.Next, ' y=', he.LineIdx, ' x=', he.BytePos, ' Wrd=', he.Word]);
j := 1;
he := hsh.HashEntry[i, j];
while he.Count > 0 do begin
debugln([' hash for ', i,', ', j, ' Cnt=', he.Count, ' hsh=', he.Hash, ' nxt=', he.Next, ' y=', he.LineIdx, ' x=', he.BytePos, ' ln=', he.Len]);
debugln([' hash for ', i,', ', j, ' Cnt=', he.Count, ' hsh=', he.Hash, ' nxt=', he.Next, ' y=', he.LineIdx, ' x=', he.BytePos, ' Wrd=', he.Word]);
inc(j);
he := hsh.HashEntry[i, j];
end;
@ -375,34 +375,30 @@ var
function Check(Msg, Wrd: String; Cnt: Integer): TSynPluginSyncroEditWordsHashEntry;
begin
Result:= hsh.GetWord(@Wrd[1], length(Wrd));
Result:= hsh.GetWord(Wrd);
AssertEquals(Msg + ' ' + Wrd + ' Cnt', Cnt, Result.Count);
if Cnt > 0 then
AssertEquals(Msg + ' ' + Wrd + ' Len', length(Wrd), Result.Len);
AssertEquals(Msg + ' ' + Wrd + ' Len', Wrd, Result.Word);
end;
procedure Add(Wrd: String; Y, X: Integer);
begin
hsh.AddWord(y, x, length(Wrd), @Wrd[1]);
hsh.AddWord(y, x, Wrd);
//Dump(hsh);
end;
procedure Del(Wrd: String);
begin
hsh.RemoveWord(length(Wrd), @Wrd[1]);
hsh.RemoveWord(Wrd);
//Dump(hsh);
end;
var
lwl: TSynPluginSyncroEditLowerLineCache;
s: String;
s, s2: String;
i: Integer;
begin
lwl := TSynPluginSyncroEditLowerLineCache.Create;
lwl.Lines := SynEdit.ViewedTextBuffer;
try
hsh := TSynPluginSyncroEditWordsHash.Create;
hsh.LowerLines := lwl;
SynEdit.Lines.Add('Test abc');
SynEdit.Lines.Add('test abc');
SynEdit.Lines.Add('atdesktop before2 252'); // supposed to have the same hash on a 4096 table
SynEdit.Lines.Add('mk_equal ecpageup'); // same big hash
@ -411,9 +407,12 @@ begin
Del('test'); Check('one word one down again', 'test', 1);
Del('test'); Check('one word gone', 'test', 0);
s:= 'atdesktop before2 252';
AssertEquals('clash for atdesktop before2', hsh.GetWordModHash(@s[1], 9), hsh.GetWordModHash(@s[11], 7));
AssertEquals('clash for atdesktop 252', hsh.GetWordModHash(@s[1], 9), hsh.GetWordModHash(@s[19], 3));
s:= 'atdesktop';
s2:= 'before2';
AssertEquals('clash for atdesktop before2', hsh.GetWordModHash(s), hsh.GetWordModHash(s2));
s:= 'atdesktop';
s2:= '252';
AssertEquals('clash for atdesktop 252', hsh.GetWordModHash(s), hsh.GetWordModHash(s2));
(* repeat test, but with double entry*)
// add word with bad pointer, so we can create a clash
@ -464,7 +463,6 @@ begin
finally
hsh.free;
lwl.Free;
end;
end;

View File

@ -941,6 +941,13 @@ begin
ecIdePSyncroEdCellEnd: Result := srkmecSynPSyncroEdCellEnd;
ecIdePSyncroEdCellSelect: Result := srkmecSynPSyncroEdCellSelect;
ecIdePSyncroEdEscape: Result := srkmecSynPSyncroEdEscape;
ecIdePSyncroEdGrowCellLeft: Result := srkmecSynPSyncroEdGrowCellLeft;
ecIdePSyncroEdShrinkCellLeft: Result := srkmecSynPSyncroEdShrinkCellLeft;
ecIdePSyncroEdGrowCellRight: Result := srkmecSynPSyncroEdGrowCellRight;
ecIdePSyncroEdShrinkCellRight: Result := srkmecSynPSyncroEdShrinkCellRight;
ecIdePSyncroEdAddCell: Result := srkmecSynPSyncroEdAddCell;
ecIdePSyncroEdAddCellCtx: Result := srkmecSynPSyncroEdAddCellCtx;
ecIdePSyncroEdDelCell: Result := srkmecSynPSyncroEdDelCell;
// SyncroEdit
ecIdePSyncroEdOutNextCell: Result := srkmecSynPSyncroEdNextCell;
ecIdePSyncroEdOutNextCellSel: Result := srkmecSynPSyncroEdNextCellSel;
@ -954,8 +961,19 @@ begin
ecIdePSyncroEdOutCellEnd: Result := srkmecSynPSyncroEdCellEnd;
ecIdePSyncroEdOutCellSelect: Result := srkmecSynPSyncroEdCellSelect;
ecIdePSyncroEdOutEscape: Result := srkmecSynPSyncroEdEscape;
//ecIdePSyncroEdOutGrowCellLeft: Result := srkmecSynPSyncroEdGrowCellLeft;
//ecIdePSyncroEdOutShrinkCellLeft: Result := srkmecSynPSyncroEdShrinkCellLeft;
//ecIdePSyncroEdOutGrowCellRight: Result := srkmecSynPSyncroEdGrowCellRight;
//ecIdePSyncroEdOutShrinkCellRight: Result := srkmecSynPSyncroEdShrinkCellRight;
ecIdePSyncroEdOutAddCell: Result := srkmecSynPSyncroEdAddCell;
ecIdePSyncroEdOutAddCellCase: Result := srkmecSynPSyncroEdAddCellCase;
ecIdePSyncroEdOutAddCellCtx: Result := srkmecSynPSyncroEdAddCellCtx;
ecIdePSyncroEdOutAddCellCtxCase: Result := srkmecSynPSyncroEdAddCellCtxCase;
// SyncroEdit, during selection
ecIdePSyncroEdSelStart: Result := srkmecSynPSyncroEdStart;
ecIdePSyncroEdSelStartCase: Result := srkmecSynPSyncroEdStartCase;
ecIdePSyncroEdSelStartCtx: Result := srkmecSynPSyncroEdStartCtx;
ecIdePSyncroEdSelStartCtxCase: Result := srkmecSynPSyncroEdStartCtxCase;
else
begin
@ -1600,6 +1618,13 @@ begin
ecIdePSyncroEdCellEnd: SetSingle(VK_END,[]);
ecIdePSyncroEdCellSelect: SetSingle(VK_A,[XCtrl]);
ecIdePSyncroEdEscape: SetSingle(VK_ESCAPE,[]);
ecIdePSyncroEdGrowCellLeft: SetSingle(VK_LCL_COMMA,[ssCtrl,ssShift]);
ecIdePSyncroEdShrinkCellLeft: SetSingle(VK_LCL_COMMA,[ssCtrl,ssShift,ssAlt]);
ecIdePSyncroEdGrowCellRight: SetSingle(VK_LCL_POINT,[ssCtrl,ssShift]);
ecIdePSyncroEdShrinkCellRight: SetSingle(VK_LCL_POINT,[ssCtrl,ssShift,ssAlt]);
// ecIdePSyncroEdAddCell: SetSingle(VK_J,[ssCtrl]);
// ecIdePSyncroEdAddCellCtx: SetSingle(VK_J,[ssCtrl,ssShift]);
ecIdePSyncroEdDelCell: SetSingle(VK_K,[ssCtrl,ssShift,ssAlt]);
// SyncroEdit
ecIdePSyncroEdOutNextCell: SetSingle(VK_RIGHT,[XCtrl]);
ecIdePSyncroEdOutNextCellSel: SetSingle(VK_TAB,[]);
@ -1609,8 +1634,15 @@ begin
ecIdePSyncroEdOutCellEnd: SetSingle(VK_UNKNOWN,[]);
ecIdePSyncroEdOutCellSelect: SetSingle(VK_UNKNOWN,[]);
ecIdePSyncroEdOutEscape: SetSingle(VK_ESCAPE,[]);
ecIdePSyncroEdOutAddCell: SetSingle(VK_J,[ssCtrl]);
ecIdePSyncroEdOutAddCellCase: SetSingle(VK_J,[ssCtrl,ssShift]);
ecIdePSyncroEdOutAddCellCtx: SetSingle(VK_J,[ssCtrl,ssAlt]);
ecIdePSyncroEdOutAddCellCtxCase: SetSingle(VK_J,[ssCtrl,ssShift,ssAlt]);
// SyncroEdit, during selection
ecIdePSyncroEdSelStart: SetSingle(VK_J,[XCtrl]);
ecIdePSyncroEdSelStart: SetSingle(VK_J,[ssCtrl]);
ecIdePSyncroEdSelStartCase: SetSingle(VK_J,[ssCtrl,ssShift]);
ecIdePSyncroEdSelStartCtx: SetSingle(VK_J,[ssCtrl,ssAlt]);
ecIdePSyncroEdSelStartCtxCase: SetSingle(VK_J,[ssCtrl,ssShift,ssAlt]);
else
begin
@ -2046,6 +2078,13 @@ begin
ecIdePSyncroEdCellEnd: SetSingle(VK_END,[]);
ecIdePSyncroEdCellSelect: SetSingle(VK_A,[ssCtrl]);
ecIdePSyncroEdEscape: SetSingle(VK_ESCAPE,[]);
ecIdePSyncroEdGrowCellLeft: SetSingle(VK_LCL_COMMA,[ssCtrl,ssShift]);
ecIdePSyncroEdShrinkCellLeft: SetSingle(VK_LCL_COMMA,[ssCtrl,ssShift,ssAlt]);
ecIdePSyncroEdGrowCellRight: SetSingle(VK_LCL_POINT,[ssCtrl,ssShift]);
ecIdePSyncroEdShrinkCellRight: SetSingle(VK_LCL_POINT,[ssCtrl,ssShift,ssAlt]);
// ecIdePSyncroEdAddCell: SetSingle(VK_J,[ssCtrl]);
// ecIdePSyncroEdAddCellCtx: SetSingle(VK_J,[ssCtrl,ssShift]);
ecIdePSyncroEdDelCell: SetSingle(VK_K,[ssCtrl,ssShift,ssAlt]);
// SyncroEdit
ecIdePSyncroEdOutNextCell: SetSingle(VK_RIGHT,[ssCtrl]);
ecIdePSyncroEdOutNextCellSel: SetSingle(VK_TAB,[]);
@ -2055,8 +2094,15 @@ begin
ecIdePSyncroEdOutCellEnd: SetSingle(VK_UNKNOWN,[]);
ecIdePSyncroEdOutCellSelect: SetSingle(VK_UNKNOWN,[]);
ecIdePSyncroEdOutEscape: SetSingle(VK_ESCAPE,[]);
ecIdePSyncroEdOutAddCell: SetSingle(VK_J,[ssCtrl]);
ecIdePSyncroEdOutAddCellCase: SetSingle(VK_J,[ssCtrl,ssShift]);
ecIdePSyncroEdOutAddCellCtx: SetSingle(VK_J,[ssCtrl,ssAlt]);
ecIdePSyncroEdOutAddCellCtxCase: SetSingle(VK_J,[ssCtrl,ssShift,ssAlt]);
// SyncroEdit, during selection
ecIdePSyncroEdSelStart: SetSingle(VK_J,[ssCtrl]);
ecIdePSyncroEdSelStartCase: SetSingle(VK_J,[ssCtrl,ssShift]);
ecIdePSyncroEdSelStartCtx: SetSingle(VK_J,[ssCtrl,ssAlt]);
ecIdePSyncroEdSelStartCtxCase: SetSingle(VK_J,[ssCtrl,ssShift,ssAlt]);
else
begin
@ -2686,6 +2732,13 @@ begin
ecIdePSyncroEdCellEnd: SetSingle(VK_END,[]);
ecIdePSyncroEdCellSelect: SetSingle(VK_A,[ssCtrl]);
ecIdePSyncroEdEscape: SetSingle(VK_ESCAPE,[]);
ecIdePSyncroEdGrowCellLeft: SetSingle(VK_LCL_COMMA,[ssCtrl,ssShift]);
ecIdePSyncroEdShrinkCellLeft: SetSingle(VK_LCL_COMMA,[ssCtrl,ssShift,ssAlt]);
ecIdePSyncroEdGrowCellRight: SetSingle(VK_LCL_POINT,[ssCtrl,ssShift]);
ecIdePSyncroEdShrinkCellRight: SetSingle(VK_LCL_POINT,[ssCtrl,ssShift,ssAlt]);
// ecIdePSyncroEdAddCell: SetSingle(VK_J,[ssCtrl]);
// ecIdePSyncroEdAddCellCtx: SetSingle(VK_J,[ssCtrl,ssShift]);
ecIdePSyncroEdDelCell: SetSingle(VK_K,[ssCtrl,ssShift,ssAlt]);
// SyncroEdit
ecIdePSyncroEdOutNextCell: SetSingle(VK_RIGHT,[ssCtrl]);
ecIdePSyncroEdOutNextCellSel: SetSingle(VK_TAB,[]);
@ -2695,8 +2748,15 @@ begin
ecIdePSyncroEdOutCellEnd: SetSingle(VK_UNKNOWN,[]);
ecIdePSyncroEdOutCellSelect: SetSingle(VK_UNKNOWN,[]);
ecIdePSyncroEdOutEscape: SetSingle(VK_ESCAPE,[]);
ecIdePSyncroEdOutAddCell: SetSingle(VK_J,[ssCtrl]);
ecIdePSyncroEdOutAddCellCase: SetSingle(VK_J,[ssCtrl,ssShift]);
ecIdePSyncroEdOutAddCellCtx: SetSingle(VK_J,[ssCtrl,ssAlt]);
ecIdePSyncroEdOutAddCellCtxCase: SetSingle(VK_J,[ssCtrl,ssShift,ssAlt]);
// SyncroEdit, during selection
ecIdePSyncroEdSelStart: SetSingle(VK_J,[ssCtrl]);
ecIdePSyncroEdSelStartCase: SetSingle(VK_J,[ssCtrl,ssShift]);
ecIdePSyncroEdSelStartCtx: SetSingle(VK_J,[ssCtrl,ssAlt]);
ecIdePSyncroEdSelStartCtxCase: SetSingle(VK_J,[ssCtrl,ssShift,ssAlt]);
else
begin
@ -3161,6 +3221,13 @@ begin
AddDefault(C, 'Edit Syncro Goto last pos in cell', srkmecSynPSyncroEdCellEnd, ecIdePSyncroEdCellEnd);
AddDefault(C, 'Edit Syncro Select cell', srkmecSynPSyncroEdCellSelect, ecIdePSyncroEdCellSelect);
AddDefault(C, 'Edit Syncro Escape', srkmecSynPSyncroEdEscape, ecIdePSyncroEdEscape);
AddDefault(C, 'Edit Syncro Grow cell on the left', srkmecSynPSyncroEdGrowCellLeft, ecIdePSyncroEdGrowCellLeft);
AddDefault(C, 'Edit Syncro Shrink cell on the left', srkmecSynPSyncroEdShrinkCellLeft, ecIdePSyncroEdShrinkCellLeft);
AddDefault(C, 'Edit Syncro Grow cell on the right', srkmecSynPSyncroEdGrowCellRight, ecIdePSyncroEdGrowCellRight);
AddDefault(C, 'Edit Syncro Shrink cell on the right', srkmecSynPSyncroEdShrinkCellRight, ecIdePSyncroEdShrinkCellRight);
// AddDefault(C, 'Edit Syncro Add Cell', srkmecSynPSyncroEdAddCell, ecIdePSyncroEdAddCell);
// AddDefault(C, 'Edit Syncro Add Cell (Context)', srkmecSynPSyncroEdAddCellCtx, ecIdePSyncroEdAddCellCtx);
AddDefault(C, 'Edit Syncro Remove current Cell', srkmecSynPSyncroEdDelCell, ecIdePSyncroEdDelCell);
// Syncro editing not in cell
C:=Categories[AddCategory('Syncro Edit Off', srkmCatSyncroEditOff, IDECmdScopeSrcEditOnlySyncroEditOff)];
@ -3176,10 +3243,17 @@ begin
AddDefault(C, 'Edit Syncro (off) Goto last pos in cell', srkmecSynPSyncroEdCellEnd, ecIdePSyncroEdOutCellEnd);
AddDefault(C, 'Edit Syncro (off) Select cell', srkmecSynPSyncroEdCellSelect, ecIdePSyncroEdOutCellSelect);
AddDefault(C, 'Edit Syncro (off) Escape', srkmecSynPSyncroEdEscape, ecIdePSyncroEdOutEscape);
AddDefault(C, 'Edit Syncro Add Cell', srkmecSynPSyncroEdAddCell, ecIdePSyncroEdOutAddCell);
AddDefault(C, 'Edit Syncro Add Cell (Case)', srkmecSynPSyncroEdAddCellCase, ecIdePSyncroEdOutAddCellCase);
AddDefault(C, 'Edit Syncro Add Cell (Context)', srkmecSynPSyncroEdAddCellCtx, ecIdePSyncroEdOutAddCellCtx);
AddDefault(C, 'Edit Syncro Add Cell (Context/Case)', srkmecSynPSyncroEdAddCellCtxCase, ecIdePSyncroEdOutAddCellCtxCase);
// Syncro editing still selecting
C:=Categories[AddCategory('Syncro Edit Sel', srkmCatSyncroEditSel, IDECmdScopeSrcEditOnlySyncroEditSel)];
AddDefault(C, 'Edit Syncro (sel) Start', srkmecSynPSyncroEdStart, ecIdePSyncroEdSelStart);
AddDefault(C, 'Edit Syncro (sel) Start (Case)', srkmecSynPSyncroEdStartCase, ecIdePSyncroEdSelStartCase);
AddDefault(C, 'Edit Syncro (sel) Start (Context)', srkmecSynPSyncroEdStartCtx, ecIdePSyncroEdSelStartCtx);
AddDefault(C, 'Edit Syncro (sel) Start (Context/Case)', srkmecSynPSyncroEdStartCtxCase, ecIdePSyncroEdSelStartCtxCase);
// source notebook - without menu items in the IDE bar
C:=Categories[AddCategory('SourceNotebook',srkmCatSrcNoteBook,IDECmdScopeSrcEditOnly)];

View File

@ -3369,6 +3369,18 @@ resourcestring
srkmecSynPSyncroEdCellSelect = 'Select Cell';
srkmecSynPSyncroEdEscape = 'Escape';
srkmecSynPSyncroEdStart = 'Start Syncro edit';
srkmecSynPSyncroEdStartCase = 'Start Syncro edit (case-sensitive)';
srkmecSynPSyncroEdStartCtx = 'Start Syncro edit (context-sensitive)';
srkmecSynPSyncroEdStartCtxCase = 'Start Syncro edit (context & case-sensitive)';
srkmecSynPSyncroEdGrowCellLeft = 'Grow cell on the left';
srkmecSynPSyncroEdShrinkCellLeft = 'Shrink cell on the left';
srkmecSynPSyncroEdGrowCellRight = 'Grow cell on the right';
srkmecSynPSyncroEdShrinkCellRight = 'Shrink cell on the right';
srkmecSynPSyncroEdAddCell = 'Add Cell';
srkmecSynPSyncroEdAddCellCase = 'Add Cell (Case-sensitive)';
srkmecSynPSyncroEdAddCellCtx = 'Add Cell (Context-sensitive))';
srkmecSynPSyncroEdAddCellCtxCase = 'Add Cell (Context & case-sensitive))';
srkmecSynPSyncroEdDelCell = 'Remove current Cell';
// run menu
srkmecCompile = 'compile program/project';