synedit.pas
来自「一个mwEdit控件原码,比mwCuuEdit0.92a功能先进.」· PAS 代码 · 共 1,671 行 · 第 1/5 页
PAS
1,671 行
{$IFDEF SYN_CLX}
{$ELSE}
DoubleBuffered := false;
{$ENDIF}
{$ENDIF}
fActiveLineColor := clNone;
fSelectedColor := TSynSelectedColor.Create;
fSelectedColor.OnChange := SelectedColorsChanged;
fBookMarkOpt := TSynBookMarkOpt.Create(Self);
fBookMarkOpt.OnChange := BookMarkOptionsChanged;
// fRightEdge has to be set before FontChanged is called for the first time
fRightEdge := 80;
fGutter := TSynGutter.Create;
fGutter.OnChange := GutterChanged;
fGutterWidth := fGutter.Width;
fWordWrapGlyph := TSynGlyph.Create(HINSTANCE, 'SynEditWrapped', clLime);
fWordWrapGlyph.OnChange := WordWrapGlyphChange;
fTextOffset := fGutterWidth + 2;
{$IFDEF SYN_COMPILER_7_UP}
{$IFNDEF SYN_CLX}
ControlStyle := ControlStyle + [csOpaque, csSetCaption, csNeedsBorderPaint];
{$ELSE}
ControlStyle := ControlStyle + [csOpaque, csSetCaption];
{$ENDIF}
{$ELSE}
ControlStyle := ControlStyle + [csOpaque, csSetCaption];
{$ENDIF}
Height := 150;
Width := 200;
Cursor := crIBeam;
Color := clWindow;
{$IFDEF SYN_WIN32}
fFontDummy.Name := 'Courier New';
fFontDummy.Size := 10;
{$ENDIF}
{$IFDEF SYN_KYLIX}
fFontDummy.Name := 'adobe-courier';
if fFontDummy.Name = 'adobe-courier' then
fFontDummy.Size := 12
else begin
fFontDummy.Name := 'terminal';
fFontDummy.Size := 14;
end;
{$ENDIF}
{$IFDEF SYN_COMPILER_3_UP}
fFontDummy.CharSet := DEFAULT_CHARSET;
{$ENDIF}
fShowSpecChar := False; //Fiala 2001-12-17
fTextDrawer := TheTextDrawer.Create([fsBold], fFontDummy);
Font.Assign(fFontDummy);
Font.OnChange := SynFontChanged;
ParentFont := False;
ParentColor := False;
TabStop := True;
fInserting := True;
fMaxScrollWidth := 1024;
fScrollBars := ssBoth;
fBorderStyle := bsSingle;
fInsertCaret := ctVerticalLine;
fOverwriteCaret := ctBlock;
FSelectionMode := smNormal;
fFocusList := TList.Create;
fKbdHandler := TSynEditKbdHandler.Create;
fKeystrokes := TSynEditKeyStrokes.Create(Self);
fMarkList := TSynEditMarkList.Create(self);
fMarkList.OnChange := MarkListChange;
SetDefaultKeystrokes;
fRightEdgeColor := clSilver;
{$IFDEF SYN_MBCSSUPPORT}
fImeCount := 0;
fMBCSStepAside := False;
{$ENDIF}
fWantReturns := True;
fWantTabs := False;
fTabWidth := 8;
fLeftChar := 1;
fTopLine := 1;
fCaretX := 1;
fLastCaretX := 1; //mh 2000-10-19
fCaretY := 1;
fBlockBegin.Char := 1;
fBlockBegin.Line := 1;
fBlockEnd := fBlockBegin;
fOptions := SYNEDIT_DEFAULT_OPTIONS;
fScrollTimer := TTimer.Create(Self);
fScrollTimer.Enabled := False;
fScrollTimer.Interval := 100;
fScrollTimer.OnTimer := ScrollTimerHandler;
{$IFDEF SYN_CLX}
InputKeys := [ikAll];
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;
FIsScrolling := False; //ddh 2002-06-22
fChainedEditor := nil; //ddh 2002-7-15
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; //ddh 2002-7-15
fOrigRedoList.Free; //ddh 2002-7-15
fGutter.Free;
fWordWrapGlyph.Free;
fTextDrawer.Free;
fInternalImage.Free;
fFontDummy.Free;
fOrigLines.Free; //ddh 2002-7-15
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 (fSelectionMode <> smColumn));
end;
function TCustomSynEdit.GetSelTabBlock: Boolean;
begin
Result := (fBlockBegin.Line <> fBlockEnd.Line) and (fSelectionMode <> 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;
const
sLineBreak = #$0D#$0A;
var
First, Last, TotalLen: Integer;
ColF
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?