From a022fcedecd0af10d0965a5c9e4216acbee63fed Mon Sep 17 00:00:00 2001 From: Basile Burg Date: Thu, 10 Dec 2015 06:24:01 +0100 Subject: [PATCH] editor options, store completion menu lines in windows rather than height --- etc/syneditmarkupfoldcolors.pas | 500 -------------------------------- src/ce_editoroptions.pas | 84 +++--- src/ce_synmemo.pas | 13 +- 3 files changed, 51 insertions(+), 546 deletions(-) delete mode 100644 etc/syneditmarkupfoldcolors.pas diff --git a/etc/syneditmarkupfoldcolors.pas b/etc/syneditmarkupfoldcolors.pas deleted file mode 100644 index 4cac3f56..00000000 --- a/etc/syneditmarkupfoldcolors.pas +++ /dev/null @@ -1,500 +0,0 @@ -unit SynEditMarkupFoldColors; - -{$mode objfpc}{$H+} - -interface - -uses - Classes, SysUtils,Graphics, SynEditMarkup, SynEditMiscClasses, Controls, - LCLProc, SynEditHighlighter, SynEditHighlighterFoldBase; - -type - - PMarkupFoldColorInfo = ^TMarkupFoldColorInfo; - TMarkupFoldColorInfo = record - Y, X, X2: Integer; - ColorIdx: Integer; - Border : Boolean; - end; - - TMarkupFoldColorInfos = array of TMarkupFoldColorInfo; - TSynFoldNodeInfos = array of TSynFoldNodeInfo; //for quick compare detection - - { TSynEditMarkupFoldColors } - - TSynEditMarkupFoldColors = class(TSynEditMarkup) - private - FDefaultGroup: integer; - // Physical Position - FHighlights : TMarkupFoldColorInfos; //array of TMarkupFoldColorInfo; - Colors : array of TColor; - CurrentY : integer; //?? - FCaretY : integer; // flag identify for refresh begin______ - FPrevCaretText : string; // flag identify for refresh begin______ - - procedure DoMarkupFoldAtRow(aRow: Integer); - procedure DoMarkupParentFoldAtRow(aRow: Integer); - function GetFoldHighLighter: TSynCustomFoldHighlighter; - protected - // Notifications about Changes to the text - procedure DoTextChanged({%H-}StartLine, EndLine, {%H-}ACountDiff: Integer); override; // 1 based - procedure DoCaretChanged(Sender: TObject); override; - public - constructor Create(ASynEdit : TSynEditBase); - function GetMarkupAttributeAtRowCol(const aRow: Integer; - const aStartCol: TLazSynDisplayTokenBound; - const {%H-}AnRtlInfo: TLazSynDisplayRtlInfo): TSynSelectedColor; override; - procedure GetNextMarkupColAfterRowCol(const aRow: Integer; - const aStartCol: TLazSynDisplayTokenBound; - const {%H-}AnRtlInfo: TLazSynDisplayRtlInfo; - out ANextPhys, ANextLog: Integer); override; - - procedure PrepareMarkupForRow(aRow : Integer); override; - property DefaultGroup : integer read FDefaultGroup write FDefaultGroup; - end; - -implementation -uses - Forms {debug}, - SynEdit,SynEditTypes, SynEditFoldedView, SynEditMiscProcs; - - function CompareFI(Item1, Item2: Pointer): Integer; - begin - result := PMarkupFoldColorInfo(Item1)^.X - PMarkupFoldColorInfo(Item2)^.X; - end; - - function SortLeftMostFI(a: TMarkupFoldColorInfos): TMarkupFoldColorInfos; - var - l : TFpList; - i : integer; - begin - l := TFpList.Create; - for i := 0 to Pred(Length(a)) do - l.Add( PMarkupFoldColorInfo(@a[i]) ); - l.Sort(@CompareFI); - - SetLength(result, Length(a)); - for i := 0 to Pred(l.Count) do - result[i] := PMarkupFoldColorInfo(l[i])^; - l.Free; - end; - -{ TSynEditMarkupFoldColors } - -constructor TSynEditMarkupFoldColors.Create(ASynEdit: TSynEditBase); -begin - inherited Create(ASynEdit); - MarkupInfo.Foreground := clGreen; - MarkupInfo.Background := clNone; //clFuchsia; - MarkupInfo.Style := []; - MarkupInfo.StyleMask := []; - MarkupInfo.FrameEdges:= sfeLeft;//sfeBottom;//sfeAround;// - - SetLength(Colors, 6); - Colors[0] := clRed; - Colors[1] := $000098F7; //orange - Colors[2] := $0022CC40; //green - Colors[3] := $00D1D54A; // $0098CC42; //teal - Colors[4] := $00FF682A; //blue - Colors[5] := $00CF00C4; //purple -end; - -function TSynEditMarkupFoldColors.GetMarkupAttributeAtRowCol( - const aRow: Integer; const aStartCol: TLazSynDisplayTokenBound; - const AnRtlInfo: TLazSynDisplayRtlInfo): TSynSelectedColor; -var - i : integer; -begin - Result := nil; - if (CurrentY = aRow) then - for i := 0 to length(FHighlights)-1 do - with FHighlights[i] do - if (aStartCol.Logical >= x) and (aStartCol.Logical < X2) then - begin - if ColorIdx >= 0 then - begin - MarkupInfo.FrameColor:= clNone; - MarkupInfo.Foreground:= clNone; - - Result := MarkupInfo; - MarkupInfo.SetFrameBoundsLog(x, x2); - if Border then - MarkupInfo.FrameColor:= Colors[ColorIdx] - else - MarkupInfo.Foreground := Colors[ColorIdx] - end; - - break; - end -end; - -procedure TSynEditMarkupFoldColors.GetNextMarkupColAfterRowCol( - const aRow: Integer; const aStartCol: TLazSynDisplayTokenBound; - const AnRtlInfo: TLazSynDisplayRtlInfo; out ANextPhys, ANextLog: Integer); -var i : integer; -begin - ANextLog := -1; - ANextPhys := -1; - if (CurrentY = aRow) then - for i := 0 to length(FHighlights)-1 do begin - if FHighlights[i].X <= aStartCol.Logical then - continue; - if FHighlights[i].X2 < aStartCol.Logical then - continue; - ANextLog := FHighlights[i].X; - break; - end; -end; - -procedure TSynEditMarkupFoldColors.DoMarkupFoldAtRow(aRow: Integer); - - procedure AddHighlight( ANode: TSynFoldNodeInfo ); - var x,lvl : integer; - begin - //exit; //debug - x := Length(FHighlights); - SetLength(FHighlights, x+1); - with FHighlights[x] do begin - Border := False; - Y := ANode.LineIndex + 1; - X := ANode.LogXStart + 1; - X2 := ANode.LogXEnd + 1; - if sfaOpen in ANode.FoldAction then begin - lvl := ANode.FoldLvlStart; - //lvl := ANode.NestLvlStart; //http://forum.lazarus.freepascal.org/index.php/topic,30122.msg194841.html#msg194841 - ColorIdx := lvl mod (length(Colors)); - end - else - if sfaClose in ANode.FoldAction then begin - lvl := ANode.FoldLvlEnd; - ColorIdx := lvl mod (length(Colors)); - end - else - ColorIdx := -1; - - - {if sfaOpen in ANode.FoldAction then - lvl := ANode.NestLvlStart - else - lvl := ANode.NestLvlEnd; - ColorIdx := lvl mod (length(Colors)); - } - - end; - end; - -var - y,i : integer; - HL: TSynCustomFoldHighlighter; - NodeList: TLazSynFoldNodeInfoList; - TmpNode: TSynFoldNodeInfo; - -begin - y := aRow -1; - - HL := TCustomSynEdit(self.SynEdit).Highlighter as TSynCustomFoldHighlighter; - HL.CurrentLines := Lines; - HL.FoldNodeInfo[y].ClearFilter; // only needed once, in case the line was already used - - NodeList := HL.FoldNodeInfo[y]; - NodeList.AddReference; - try - NodeList.ActionFilter := [ - {sfaMarkup,} - sfaFold - //sfaFoldFold - //sfaFoldHide - //sfaSingleLine - //sfaMultiLine - //sfaOpen - ]; - //NodeList.FoldFlags:= [sfbIncludeDisabled]; - i := 0; - repeat - TmpNode := NodeList[i]; - - //find till valid - while (sfaInvalid in TmpNode.FoldAction) and (i < NodeList.Count) do - begin - inc(i); - TmpNode := NodeList[i]; - end; - if not (sfaInvalid in TmpNode.FoldAction) then - AddHighlight(TmpNode); - - inc(i); - until i >= NodeList.Count; - - finally - NodeList.ReleaseReference; - end; -end; - -procedure TSynEditMarkupFoldColors.DoMarkupParentFoldAtRow(aRow: Integer); - - procedure AddVerticalLine( ANode: TSynFoldNodeInfo ); - var x,i,lvl : integer; - begin - //don't replace; don't add when already found - x := ANode.LogXStart + 1; - for i := 0 to Pred(length(FHighlights)) do - if FHighlights[i].X = x then - exit; - - x := Length(FHighlights); - SetLength(FHighlights, x+1); - with FHighlights[x] do begin - Border := ANode.LineIndex + 1 <> aRow; - Y := aRow;//ANode.LineIndex + 1; - X := ANode.LogXStart + 1; - X2 := X+1; //ANode.LogXEnd + 1; - if sfaOpen in ANode.FoldAction then begin - lvl := ANode.FoldLvlStart; - ColorIdx := lvl mod (length(Colors)); - end - else - if sfaClose in ANode.FoldAction then begin - lvl := ANode.FoldLvlEnd; - ColorIdx := lvl mod (length(Colors)); - end - else - begin - ColorIdx := -1; - lvl := ANode.NestLvlStart; - ColorIdx := lvl mod (length(Colors)); - end; - - { - if sfaOpen in ANode.FoldAction then - lvl := ANode.NestLvlStart - else - lvl := ANode.NestLvlEnd; - - //ColorIdx := ANode.NodeIndex mod (length(Colors)); - - lvl := ANode.NestLvlEnd; - //lvl := Longint(ANode.FoldTypeCompatible); - ColorIdx := lvl mod (length(Colors)); - } - - - end; - end; -var - i,y: Integer; - Nest : TLazSynEditNestedFoldsList; - TmpNode: TSynFoldNodeInfo; - -begin - y := aRow-1; - Nest := TLazSynEditNestedFoldsList.Create(@GetFoldHighLighter); - Nest.ResetFilter; - Nest.Clear; - Nest.Line := y; - Nest.FoldGroup := FDefaultGroup;//1;//FOLDGROUP_PASCAL; - Nest.FoldFlags := [];//[sfbIncludeDisabled]; // - Nest.IncludeOpeningOnLine := True; //False; // - - //i := 0; while i < Nest.Count do - i := Nest.Count -1; while i >= 0 do //from right to left - begin - TmpNode := Nest.HLNode[i]; - - //find till valid - while (sfaInvalid in TmpNode.FoldAction) and (i < Nest.Count) do - begin - inc(i); - TmpNode := Nest.HLNode[i]; - end; - if not (sfaInvalid in TmpNode.FoldAction) then - AddVerticalLine(TmpNode); - - //inc(i); - dec(i); - end; -end; - -procedure TSynEditMarkupFoldColors.PrepareMarkupForRow(aRow: Integer); -begin - CurrentY := aRow; - SetLength(FHighlights,0); //reset needed to prevent using of invalid area - - if not (TCustomSynEdit(self.SynEdit).Highlighter is TSynCustomFoldHighlighter) then - exit; - - DoMarkupFoldAtRow(aRow); - DoMarkupParentFoldAtRow(aRow); - - FHighlights := SortLeftMostFI(FHighlights); -end; - -function TSynEditMarkupFoldColors.GetFoldHighLighter: TSynCustomFoldHighlighter; -begin - result := TCustomSynEdit(self.SynEdit).Highlighter as TSynCustomFoldHighlighter; -end; - -{.$define debug_FC_line_changed} -procedure TSynEditMarkupFoldColors.DoTextChanged(StartLine, EndLine, - ACountDiff: Integer); -{$ifdef debug_FC_line_changed} -var F : TCustomForm; -begin - F := GetParentForm(self.SynEdit); - if F <> nil then - //F.Caption := Format('Start:%d Endline:%d Diff:%d',[StartLine, EndLIne, ACountDiff]); - F.Caption := F.Caption + Caret.LineText -{$else} - - - - function GetPairCloseFold(aRow, X : integer ): Integer; - var - y,i,LCnt : integer; - HL: TSynCustomFoldHighlighter; - NodeList: TLazSynFoldNodeInfoList; - TmpNode, CloseNode: TSynFoldNodeInfo; - - function FindEndNode(StartNode: TSynFoldNodeInfo; - {var} YIndex, NIndex: Integer): TSynFoldNodeInfo; - function SearchLine(ALineIdx: Integer; var ANodeIdx: Integer): TSynFoldNodeInfo; - begin - NodeList.Line := ALineIdx; - repeat - inc(ANodeIdx); - Result := NodeList[ANodeIdx]; - until (sfaInvalid in Result.FoldAction) - or (Result.NestLvlEnd <= StartNode.NestLvlStart); - end; - - begin - Result := SearchLine(YIndex, NIndex); - if not (sfaInvalid in Result.FoldAction) then - exit; - - inc(YIndex); - while (YIndex < LCnt) and - (HL.FoldBlockMinLevel(YIndex, StartNode.FoldGroup, [sfbIncludeDisabled]) - > StartNode.NestLvlStart) - do - inc(YIndex); - if YIndex = LCnt then - exit; - - NIndex := -1; - Result := SearchLine(YIndex, NIndex); - - if (Result.LogXEnd = 0) or (sfaLastLineClose in Result.FoldAction) then - Result.FoldAction := [sfaInvalid]; // LastLine closed Node(maybe force-closed?) - end; - - begin - Result := -1; - y := aRow -1; - - HL := TCustomSynEdit(self.SynEdit).Highlighter as TSynCustomFoldHighlighter; - HL.CurrentLines := Lines; - LCnt := Lines.Count; - HL.FoldNodeInfo[y].ClearFilter; // only needed once, in case the line was already used - - NodeList := HL.FoldNodeInfo[y]; - NodeList.AddReference; - try - NodeList.ActionFilter := [sfaOpen]; - i := 0; - repeat - TmpNode := NodeList[i]; - - if TmpNode.LogXStart < X-1 then - begin - inc(i); - continue; - end; - - //find till valid - while (sfaInvalid in TmpNode.FoldAction) and (i < NodeList.Count) do - begin - inc(i); - TmpNode := NodeList[i]; - end; - if not (sfaInvalid in TmpNode.FoldAction) then - begin - CloseNode := FindEndNode(TmpNode, y, i); - //AddHighlight(TmpNode); - Result := CloseNode.LineIndex; - exit; - end; - - inc(i); - until i >= NodeList.Count; - - finally - NodeList.ReleaseReference; - end; - end; - - - function IsFoldMoved( aRow: Integer ): integer; - var S : string; - i,n : integer; - begin - Result := -1; - n := -1; - - S := Caret.LineText; - for i := 1 to Min(Length(S), Length(FPrevCaretText)) do - begin - if S[i] <> FPrevCaretText[i] then - begin - n := i; - break; - end; - end; - - if n < 0 then exit; - - Result := GetPairCloseFold(aRow, n); - //limit to screen bottom - if Result > 0 then - begin - inc(Result);//because sometime 'end' has trailing vertical line - with TCustomSynEdit(SynEdit) do - Result := min(Result, TopLine +LinesInWindow);// . .RowToScreenRow(i); - end; - - end; -var - EndFoldLine,y : integer; -begin - if EndLine < 0 then exit; //already refreshed by syn - - y := Caret.LineBytePos.y; - EndFoldLine := IsFoldMoved(y); - if EndFoldLine > 0 then - begin - InvalidateSynLines(y+1, EndFoldLine); - end; - - FPrevCaretText := Caret.LineText; - // I found that almost anything has been repaint by the SynEdit, - // except the trailing space editing: we should repaint them here. -{$endif} -end; - -procedure TSynEditMarkupFoldColors.DoCaretChanged(Sender: TObject); -var Y : integer; -begin - Y := Caret.LineBytePos.y; - if Y = FCaretY then exit; - - FCaretY := Y; - FPrevCaretText := Caret.LineText; - {$ifdef debug_FC_line_changed} - with GetParentForm(self.SynEdit) do - Caption:= Caret.LineText; - {$endif} -end; - - - -end. - diff --git a/src/ce_editoroptions.pas b/src/ce_editoroptions.pas index 178dac4c..1cc474f8 100644 --- a/src/ce_editoroptions.pas +++ b/src/ce_editoroptions.pas @@ -52,21 +52,24 @@ type fCompletionMenuCaseCare: boolean; fCompletionMenuWidth: integer; fCompletionMenuHeight: integer; + fCompletionMenuLines: Byte; // - procedure setFont(aValue: TFont); - procedure setSelCol(aValue: TSynSelectedColor); - procedure setFoldedColor(aValue: TSynSelectedColor); - procedure setMouseLinkColor(aValue: TSynSelectedColor); - procedure setBracketMatchColor(aValue: TSynSelectedColor); - procedure setD2Syn(aValue: TPersistent); - procedure setTxtSyn(aValue: TPersistent); - procedure setShortcuts(aValue: TCollection); - procedure setDDocDelay(aValue: Integer); - procedure setAutoDotDelay(aValue: Integer); + procedure setFont(value: TFont); + procedure setSelCol(value: TSynSelectedColor); + procedure setFoldedColor(value: TSynSelectedColor); + procedure setMouseLinkColor(value: TSynSelectedColor); + procedure setBracketMatchColor(value: TSynSelectedColor); + procedure setD2Syn(value: TPersistent); + procedure setTxtSyn(value: TPersistent); + procedure setShortcuts(value: TCollection); + procedure setDDocDelay(value: Integer); + procedure setAutoDotDelay(value: Integer); + procedure setCompletionMenuLines(value: byte); published property completionMenuCaseCare: boolean read fCompletionMenuCaseCare write fCompletionMenuCaseCare; property completionMenuWidth: integer read fCompletionMenuWidth write fCompletionMenuWidth; - property completionMenuHeight: integer read fCompletionMenuHeight write fCompletionMenuHeight; + property completionMenuHeight: integer read fCompletionMenuHeight write fCompletionMenuHeight stored false; + property completionMenuLines: byte read fCompletionMenuLines write setCompletionMenuLines; property autoDotDelay: integer read fAutoDotDelay write SetautoDotDelay; property hintDelay: Integer read fDDocDelay write setDDocDelay stored false; deprecated; property ddocDelay: Integer read fDDocDelay write setDDocDelay; @@ -178,6 +181,7 @@ begin // fCompletionMenuHeight:= 260; fCompletionMenuWidth:= 160; + fCompletionMenuLines:= 15; // rightEdge := 80; tabulationWidth := 4; @@ -231,6 +235,7 @@ begin // fCompletionMenuWidth:=srcopt.fCompletionMenuWidth; fCompletionMenuHeight:=srcopt.fCompletionMenuHeight; + fCompletionMenuLines:=srcopt.fCompletionMenuLines; fCompletionMenuCaseCare:=srcopt.fCompletionMenuCaseCare; fAutoDotDelay:=srcopt.fAutoDotDelay; fDDocDelay:=srcopt.fDDocDelay; @@ -257,58 +262,65 @@ begin inherited; end; -procedure TCEEditorOptionsBase.setDDocDelay(aValue: Integer); +procedure TCEEditorOptionsBase.setDDocDelay(value: Integer); begin - if aValue > 2000 then aValue := 2000 - else if aValue < 20 then aValue := 20; - fDDocDelay:=aValue; + if value > 2000 then value := 2000 + else if value < 20 then value := 20; + fDDocDelay:=value; end; -procedure TCEEditorOptionsBase.setAutoDotDelay(aValue: Integer); +procedure TCEEditorOptionsBase.setAutoDotDelay(value: Integer); begin - if aValue > 2000 then aValue := 2000 - else if aValue < 0 then aValue := 0; - fAutoDotDelay:=aValue; + if value > 2000 then value := 2000 + else if value < 0 then value := 0; + fAutoDotDelay:=value; end; -procedure TCEEditorOptionsBase.setShortcuts(aValue: TCollection); +procedure TCEEditorOptionsBase.setCompletionMenuLines(value: byte); begin - fShortCuts.Assign(aValue); + if value < 5 then value := 5 + else if value > 64 then value := 64; + fCompletionMenuLines := value; end; -procedure TCEEditorOptionsBase.setFont(aValue: TFont); +procedure TCEEditorOptionsBase.setShortcuts(value: TCollection); begin - fFont.Assign(aValue); + fShortCuts.Assign(value); end; -procedure TCEEditorOptionsBase.setSelCol(aValue: TSynSelectedColor); +procedure TCEEditorOptionsBase.setFont(value: TFont); begin - fSelCol.Assign(aValue); + fFont.Assign(value); end; -procedure TCEEditorOptionsBase.setFoldedColor(aValue: TSynSelectedColor); +procedure TCEEditorOptionsBase.setSelCol(value: TSynSelectedColor); begin - fFoldedColor.Assign(aValue); + fSelCol.Assign(value); end; -procedure TCEEditorOptionsBase.setMouseLinkColor(aValue: TSynSelectedColor); +procedure TCEEditorOptionsBase.setFoldedColor(value: TSynSelectedColor); begin - fMouseLinkColor.Assign(aValue); + fFoldedColor.Assign(value); end; -procedure TCEEditorOptionsBase.setBracketMatchColor(aValue: TSynSelectedColor); +procedure TCEEditorOptionsBase.setMouseLinkColor(value: TSynSelectedColor); begin - fBracketMatchColor.Assign(aValue); + fMouseLinkColor.Assign(value); end; -procedure TCEEditorOptionsBase.setD2Syn(aValue: TPersistent); +procedure TCEEditorOptionsBase.setBracketMatchColor(value: TSynSelectedColor); begin - D2Syn.Assign(aValue); + fBracketMatchColor.Assign(value); end; -procedure TCEEditorOptionsBase.setTxtSyn(aValue: TPersistent); +procedure TCEEditorOptionsBase.setD2Syn(value: TPersistent); begin - TxtSyn.Assign(aValue); + D2Syn.Assign(value); +end; + +procedure TCEEditorOptionsBase.setTxtSyn(value: TPersistent); +begin + TxtSyn.Assign(value); end; constructor TCEEditorOptions.Create(AOwner: TComponent); @@ -404,6 +416,7 @@ procedure TCEEditorOptions.docClosing(aDoc: TCESynMemo); begin fCompletionMenuHeight:=aDoc.completionMenu.TheForm.Height; fCompletionMenuWidth:=aDoc.completionMenu.TheForm.Width; + fCompletionMenuLines:=aDoc.completionMenu.LinesInWindow; end; {$ENDREGION} @@ -537,6 +550,7 @@ begin anEditor.completionMenu.TheForm.Height := fCompletionMenuHeight; anEditor.completionMenu.TheForm.Width := fCompletionMenuWidth; + anEditor.completionMenu.LinesInWindow := fCompletionMenuLines; anEditor.completionMenu.CaseSensitive := fCompletionMenuCaseCare; anEditor.SelectedColor.Assign(fSelCol); diff --git a/src/ce_synmemo.pas b/src/ce_synmemo.pas index 389b91ef..7df4f79d 100644 --- a/src/ce_synmemo.pas +++ b/src/ce_synmemo.pas @@ -470,6 +470,7 @@ begin fCompletion.LongLineHintType:=sclpNone; fCompletion.TheForm.ShowInTaskBar:=stNever; fCompletion.ShortCut:=0; + fCompletion.LinesInWindow:=15; // MouseLinkColor.Style:= [fsUnderline]; with MouseActions.Add do begin @@ -495,16 +496,6 @@ begin fPositions := TCESynMemoPositions.create(self); fMultiDocSubject := TCEMultiDocSubject.create; // - - (*fMarkupIndent:= TSynEditMarkupFoldColors.Create(self); - fMarkupIndent.Lines := TextBuffer; - fMarkupIndent.Enabled:=true; - fMarkupIndent.DefaultGroup:=0; - if (GetMarkupMgr <> nil) then - begin - TSynEditMarkupManager(GetMarkupMgr).AddMarkUp(fMarkupIndent, true); - end; *) - // subjDocNew(TCEMultiDocSubject(fMultiDocSubject), self); end; @@ -998,7 +989,7 @@ begin AddKey(ecSynPSyncroEdStart, ord('E'), [ssCtrl], 0, []); AddKey(ecSynPSyncroEdEscape, ord('E'), [ssCtrl, ssShift], 0, []); AddKey(ecCompletionMenu, ord(' '), [ssCtrl], 0, []); - AddKey(ecJumpToDefinition, VK_UP, [ssCtrl,ssShift], 0, []); // goto def + AddKey(ecJumpToDefinition, VK_UP, [ssCtrl,ssShift], 0, []); end; end;