📄 synedit.pas
字号:
{$IFDEF SYN_CLX}
InputKeys := [ikArrows, ikChars, ikReturns, ikEdit, ikNav, ikEsc];
FHScrollBar := TSynEditScrollbar.Create(self);
FHScrollBar.Kind := sbHorizontal;
FHScrollBar.Height := CYHSCROLL;
FHScrollBar.OnScroll := ScrollEvent;
FVScrollBar := TSynEditScrollbar.Create(self);
FVScrollBar.Kind := sbVertical;
FVScrollBar.Width := CXVSCROLL;
FVScrollBar.OnScroll := ScrollEvent;
// Set parent after BOTH scrollbars are created.
FHScrollBar.Parent := Self;
FHScrollBar.Color := clScrollBar;
FVScrollBar.Parent := Self;
FVScrollBar.Color := clScrollBar;
{$ENDIF}
fScrollHintColor := clInfoBk;
fScrollHintFormat := shfTopLineOnly;
SynFontChanged(nil);
end;
{$IFDEF SYN_CLX}
{$ELSE}
procedure TCustomSynEdit.CreateParams(var Params: TCreateParams);
const
BorderStyles: array[TBorderStyle] of DWORD = (0, WS_BORDER);
ClassStylesOff = CS_VREDRAW or CS_HREDRAW;
begin
inherited CreateParams(Params);
with Params do
begin
WindowClass.Style := WindowClass.Style and not ClassStylesOff;
Style := Style or BorderStyles[fBorderStyle] or WS_CLIPCHILDREN;
if NewStyleControls and Ctl3D and (fBorderStyle = bsSingle) then
begin
Style := Style and not WS_BORDER;
ExStyle := ExStyle or WS_EX_CLIENTEDGE;
end;
end;
end;
{$ENDIF}
procedure TCustomSynEdit.DecPaintLock;
var
vAuxPos: TDisplayCoord;
begin
Dec(fPaintLock);
if (fPaintLock = 0) and HandleAllocated then
begin
if sfScrollbarChanged in fStateFlags then
UpdateScrollbars;
// Locks the caret inside the visible area
if WordWrap and ([scCaretX,scCaretY] * fStatusChanges <> []) then
begin
vAuxPos := DisplayXY;
// This may happen in the last row of a line or in rows which length is
// greater than CharsInWindow (Tabs and Spaces are allowed beyond
// CharsInWindow while wrapping the lines)
if (vAuxPos.Column > CharsInWindow +1) and (CharsInWindow > 0) then
begin
if fCaretAtEOL then
fCaretAtEOL := False
else begin
vAuxPos.Column := CharsInWindow +1;
fCaretX := DisplayToBufferPos( vAuxPos ).Char;
Include(fStatusChanges,scCaretX);
end;
UpdateLastCaretX;
Include(fStateFlags, sfCaretChanged);
end;
end;
if sfCaretChanged in fStateFlags then
UpdateCaret;
if fStatusChanges <> [] then
DoOnStatusChange(fStatusChanges);
end;
end;
destructor TCustomSynEdit.Destroy;
var
i: integer;
begin
Highlighter := nil;
if (fChainedEditor <> nil) or (fLines <> fOrigLines) then
RemoveLinesPointer;
inherited Destroy;
// free listeners while other fields are still valid
if Assigned(fHookedCommandHandlers) then
begin
for i := 0 to fHookedCommandHandlers.Count - 1 do
THookedCommandHandlerEntry(fHookedCommandHandlers[i]).Free;
FreeAndNil(fHookedCommandHandlers);
end;
if fPlugins <> nil then
begin
for i := fPlugins.Count - 1 downto 0 do
TSynEditPlugin(fPlugins[i]).Free;
fPlugins.Free;
end;
fMarkList.Free;
fBookMarkOpt.Free;
fKeyStrokes.Free;
fKbdHandler.Free;
fFocusList.Free;
fSelectedColor.Free;
fOrigUndoList.Free;
fOrigRedoList.Free;
fGutter.Free;
fWordWrapGlyph.Free;
fTextDrawer.Free;
fInternalImage.Free;
fFontDummy.Free;
fOrigLines.Free;
end;
function TCustomSynEdit.GetBlockBegin: TBufferCoord;
begin
if (fBlockEnd.Line < fBlockBegin.Line)
or ((fBlockEnd.Line = fBlockBegin.Line) and (fBlockEnd.Char < fBlockBegin.Char))
then
Result := fBlockEnd
else
Result := fBlockBegin;
end;
function TCustomSynEdit.GetBlockEnd: TBufferCoord;
begin
if (fBlockEnd.Line < fBlockBegin.Line)
or ((fBlockEnd.Line = fBlockBegin.Line) and (fBlockEnd.Char < fBlockBegin.Char))
then
Result := fBlockBegin
else
Result := fBlockEnd;
end;
procedure TCustomSynEdit.SynFontChanged(Sender: TObject);
begin
RecalcCharExtent;
SizeOrFontChanged(TRUE);
end;
function TCustomSynEdit.GetFont: TFont;
begin
Result := inherited Font;
end;
function TCustomSynEdit.GetLineText: string;
begin
if (CaretY >= 1) and (CaretY <= Lines.Count) then
Result := Lines[CaretY - 1]
else
Result := '';
end;
function TCustomSynEdit.GetSelAvail: Boolean;
begin
Result := (fBlockBegin.Char <> fBlockEnd.Char) or
((fBlockBegin.Line <> fBlockEnd.Line) and (fActiveSelectionMode <> smColumn));
end;
function TCustomSynEdit.GetSelTabBlock: Boolean;
begin
Result := (fBlockBegin.Line <> fBlockEnd.Line) and (fActiveSelectionMode <> smColumn);
end;
function TCustomSynEdit.GetSelTabLine: Boolean;
begin
Result := (BlockBegin.Char <= 1) and (BlockEnd.Char > length(Lines[CaretY - 1])) and SelAvail;
end;
function TCustomSynEdit.GetSelText: string;
function CopyPadded(const S: string; Index, Count: integer): string;
var
SrcLen: Integer;
DstLen: integer;
P: PChar;
begin
SrcLen := Length(S);
DstLen := Index + Count;
if SrcLen >= DstLen then
Result := Copy(S, Index, Count)
else begin
SetLength(Result, DstLen);
P := PChar(Result);
StrPCopy(P, Copy(S, Index, Count));
Inc(P, Length(S));
FillChar(P^, DstLen - Srclen, $20);
end;
end;
procedure CopyAndForward(const S: string; Index, Count: Integer; var P:
PChar);
var
pSrc: PChar;
SrcLen: Integer;
DstLen: Integer;
begin
SrcLen := Length(S);
if (Index <= SrcLen) and (Count > 0) then
begin
Dec(Index);
pSrc := PChar(S) + Index;
DstLen := Min(SrcLen - Index, Count);
Move(pSrc^, P^, DstLen);
Inc(P, DstLen);
P^ := #0;
end;
end;
function CopyPaddedAndForward(const S: string; Index, Count: Integer;
var P: PChar): Integer;
var
OldP: PChar;
Len: Integer;
begin
Result := 0;
OldP := P;
CopyAndForward(S, Index, Count, P);
Len := Count - (P - OldP);
if not (eoTrimTrailingSpaces in Options) then
begin
FillChar(P^, Len, #$20);
Inc(P, Len);
end
else
Result:= Len;
end;
var
First, Last, TotalLen: Integer;
ColFrom, ColTo: Integer;
I: Integer;
{$IFDEF SYN_MBCSSUPPORT}
l, r: Integer;
s: string;
{$ELSE}
ColLen: integer;
{$ENDIF}
P: PChar;
begin
if not SelAvail then
Result := ''
else begin
ColFrom := BlockBegin.Char;
First := BlockBegin.Line - 1;
//
ColTo := BlockEnd.Char;
Last := BlockEnd.Line - 1;
//
TotalLen := 0;
case fActiveSelectionMode of
smNormal:
if (First = Last) then
Result := Copy(Lines[First], ColFrom, ColTo - ColFrom)
else begin
// step1: calclate total length of result string
TotalLen := Max(0, Length(Lines[First]) - ColFrom + 1);
for i := First + 1 to Last - 1 do
Inc(TotalLen, Length(Lines[i]));
Inc(TotalLen, ColTo - 1);
Inc(TotalLen, Length(sLineBreak) * (Last - First));
// step2: build up result string
SetLength(Result, TotalLen);
P := PChar(Result);
CopyAndForward(Lines[First], ColFrom, MaxInt, P);
CopyAndForward(sLineBreak, 1, MaxInt, P);
for i := First + 1 to Last - 1 do
begin
CopyAndForward(Lines[i], 1, MaxInt, P);
CopyAndForward(sLineBreak, 1, MaxInt, P);
end;
CopyAndForward(Lines[Last], 1, ColTo - 1, P);
end;
smColumn:
begin
if ColFrom > ColTo then
SwapInt(ColFrom, ColTo);
// step1: calclate total length of result string
{$IFNDEF SYN_MBCSSUPPORT}
ColLen := ColTo - ColFrom;
TotalLen := ColLen + (ColLen + Length(sLineBreak)) * (Last - First);
// step2: build up result string
SetLength(Result, TotalLen);
P := PChar(Result);
for i := First to Last - 1 do
begin
TotalLen:= TotalLen - CopyPaddedAndForward(Lines[i], ColFrom, ColLen, P);
CopyAndForward(sLineBreak, 1, MaxInt, P);
end;
TotalLen:= TotalLen - CopyPaddedAndForward(Lines[Last], ColFrom, ColLen, P);
SetLength(Result, TotalLen);
{$ELSE} //SYN_MBCSSUPPORT
for i := First to Last do
begin
s := Lines[i];
l := ColFrom;
r := ColTo;
MBCSGetSelRangeInLineWhenColumnSelectionMode(s, l, r);
Inc(TotalLen, r - l);
end;
Inc(TotalLen, Length(sLineBreak) * (Last - First));
// step2: build up result string
SetLength(Result, TotalLen);
P := PChar(Result);
for i := First to Last - 1 do
begin
s := Lines[i];
l := ColFrom;
r := ColTo;
MBCSGetSelRangeInLineWhenColumnSelectionMode(s, l, r);
TotalLen:= TotalLen - CopyPaddedAndForward(s, l, r - l, P);
CopyAndForward(sLineBreak, 1, MaxInt, P);
end;
s := Lines[Last];
l := ColFrom;
r := ColTo;
MBCSGetSelRangeInLineWhenColumnSelectionMode(s, l, r);
TotalLen := TotalLen - CopyPaddedAndForward(Lines[Last], l, r - l, P);
SetLength(Result, TotalLen);
{$ENDIF}
end;
smLine:
begin
// If block selection includes LastLine,
// line break code(s) of the last line will not be added.
// step1: calclate total length of result string
for i := First to Last do
Inc(TotalLen, Length(Lines[i]) + Length(sLineBreak));
if Last = Lines.Count then
Dec(TotalLen, Length(sLineBreak));
// step2: build up result string
SetLength(Result, TotalLen);
P := PChar(Result);
for i := First to Last - 1 do
begin
CopyAndForward(Lines[i], 1, MaxInt, P);
CopyAndForward(sLineBreak, 1, MaxInt, P);
end;
CopyAndForward(Lines[Last], 1, MaxInt
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -