4434 lines
130 KiB
ObjectPascal
4434 lines
130 KiB
ObjectPascal
{
|
|
Copyright (C) Alexey Torgashin, uvviewsoft.com
|
|
License: MPL 2.0 or LGPL
|
|
}
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
//{$define test_markedrange}
|
|
//{$define test_attribs}
|
|
//{$define beep_wrapinfo}
|
|
//{$define debug_findwrapindex}
|
|
//{$define beep_cached_update}
|
|
//{$define test_foldlist}
|
|
//{$define allow_proc_msg}
|
|
{$define fix_horzscroll} //workaround for gtk2 widgetset unstable: it freezes app
|
|
//when horz-scroll hides/shows/hides/...
|
|
//ok also for win32
|
|
|
|
unit ATSynEdit;
|
|
|
|
interface
|
|
|
|
uses
|
|
{$ifdef Windows}
|
|
windows, imm, messages,
|
|
{$endif}
|
|
Classes, SysUtils, Graphics,
|
|
Controls, ExtCtrls, Menus, Forms,
|
|
LMessages, LCLType,
|
|
ATStringProc,
|
|
ATStrings,
|
|
ATSynEdit_Colors,
|
|
ATSynEdit_Keymap,
|
|
ATSynEdit_CanvasProc,
|
|
ATSynEdit_Carets,
|
|
ATSynEdit_Markers,
|
|
ATSynEdit_Gutter,
|
|
ATSynEdit_WrapInfo,
|
|
ATSynEdit_Ranges,
|
|
ATSynEdit_Adapters;
|
|
|
|
type
|
|
TATDirection = (
|
|
cDirNone,
|
|
cDirLeft,
|
|
cDirRight,
|
|
cDirUp,
|
|
cDirDown
|
|
);
|
|
|
|
TATSelectColumnDirection = (
|
|
cDirColumnLeft,
|
|
cDirColumnRight,
|
|
cDirColumnUp,
|
|
cDirColumnDown,
|
|
cDirColumnPageUp,
|
|
cDirColumnPageDown
|
|
);
|
|
|
|
TATCaseConvert = (
|
|
cCaseLower,
|
|
cCaseUpper,
|
|
cCaseTitle,
|
|
cCaseInvert,
|
|
cCaseSentence
|
|
);
|
|
|
|
TATCommandResult = (
|
|
cResultText,
|
|
cResultCaretAny,
|
|
cResultCaretLeft,
|
|
cResultCaretTop,
|
|
cResultCaretRight,
|
|
cResultCaretBottom,
|
|
cResultKeepColumnSel,
|
|
cResultScroll,
|
|
cResultState
|
|
);
|
|
TATCommandResults = set of TATCommandResult;
|
|
|
|
TATFoldStyle = ( //affects folding of blocks without "text hint" passed from adapter
|
|
cFoldHereWithDots, //show "..." from fold-pos
|
|
cFoldHereWithTruncatedText, //show truncated line instead of "..."
|
|
cFoldFromEndOfLine, //looks like Lazarus: show "..." after line, bad with 2 blocks starting at the same line
|
|
cFoldFromNextLine //looks like SynWrite: don't show "...", show separator line
|
|
);
|
|
|
|
type
|
|
TATAutoIndentKind = (
|
|
cIndentAsIs,
|
|
cIndentSpaces,
|
|
cIndentTabsSpaces,
|
|
cIndentTabsOnly
|
|
);
|
|
|
|
TATPageUpDownSize = (
|
|
cPageSizeFull,
|
|
cPageSizeFullMinus1,
|
|
cPageSizeHalf
|
|
);
|
|
|
|
TATSynWrapMode = (
|
|
cWrapOff,
|
|
cWrapOn,
|
|
cWrapAtMargin
|
|
);
|
|
|
|
TATSynNumbersStyle = (
|
|
cNumbersAll,
|
|
cNumbersNone,
|
|
cNumbersEach10th,
|
|
cNumbersEach5th
|
|
);
|
|
|
|
TATSynPaintFlag = (
|
|
cPaintUpdateBitmap,
|
|
cPaintUpdateCaretsCoords,
|
|
cPaintUpdateScrollbars
|
|
);
|
|
TATSynPaintFlags = set of TATSynPaintFlag;
|
|
|
|
TATSynScrollInfo = record
|
|
NMin,
|
|
NMax,
|
|
NPage,
|
|
NPos,
|
|
NPosLast: integer;
|
|
end;
|
|
|
|
TATSynCaretShape = (
|
|
cCaretShapeFull,
|
|
cCaretShapeVertPixels1,
|
|
cCaretShapeVertPixels2,
|
|
cCaretShapeVertPixels3,
|
|
cCaretShapeVertPixels4,
|
|
cCaretShapeVertPercents10,
|
|
cCaretShapeVertPercents15,
|
|
cCaretShapeVertPercents20,
|
|
cCaretShapeVertPercents25,
|
|
cCaretShapeVertPercents30,
|
|
cCaretShapeVertPercents35,
|
|
cCaretShapeVertPercents40,
|
|
cCaretShapeVertPercents50,
|
|
cCaretShapeHorzPixels1,
|
|
cCaretShapeHorzPixels2,
|
|
cCaretShapeHorzPixels3,
|
|
cCaretShapeHorzPixels4,
|
|
cCaretShapeHorzPixels5,
|
|
cCaretShapeHorzPercents10,
|
|
cCaretShapeHorzPercents15,
|
|
cCaretShapeHorzPercents20,
|
|
cCaretShapeHorzPercents25,
|
|
cCaretShapeHorzPercents30,
|
|
cCaretShapeHorzPercents35,
|
|
cCaretShapeHorzPercents40,
|
|
cCaretShapeHorzPercents50,
|
|
cCaretShapeFrameFull
|
|
);
|
|
|
|
const
|
|
cInitCaretShapeIns = cCaretShapeVertPixels1;
|
|
cInitCaretShapeOvr = cCaretShapeFull;
|
|
cInitCaretShapeRO = cCaretShapeHorzPixels1;
|
|
cInitTextOffsetFromLine = {$ifdef windows} 0 {$else} 1 {$endif};
|
|
cInitSpacingText = 1;
|
|
cInitTimerBlink = 600;
|
|
cInitTimerAutoScroll = 80;
|
|
cInitTimerNiceScroll = 200;
|
|
cInitMinimapVisible = false;
|
|
cInitMicromapVisible = false;
|
|
cInitMarginRight = 80;
|
|
cInitTabSize = 8;
|
|
cInitMicromapWidth = 30;
|
|
cInitMinimapWidth = 160;
|
|
cInitNumbersStyle = cNumbersEach5th;
|
|
cInitBitmapWidth = 1000;
|
|
cInitBitmapHeight = 800;
|
|
cInitGutterPlusSize = 4;
|
|
cInitFoldStyle = cFoldHereWithTruncatedText;
|
|
|
|
cGutterBands = 6;
|
|
cGutterSizeBm = 16;
|
|
cGutterSizeNum = 10;
|
|
cGutterSizeFold = 14;
|
|
cGutterSizeState = 3;
|
|
cGutterSizeSep = 1;
|
|
cGutterSizeEmpty = 2;
|
|
|
|
const
|
|
cFoldedLenOfEmptyHint = 50;
|
|
cFoldedMarkIndentInner = 2;
|
|
cFoldedMarkIndentOuter = 0;
|
|
cScrollKeepHorz = 1; //keep char, allow handy clicking after eol of longest line
|
|
cScrollIndentCaretHorz = 10; //offsets for caret-moving: if caret goes out of control
|
|
cScrollIndentCaretVert = 0; //must be 0, >0 gives jumps on move-down
|
|
cScrollIndentGotoHorz = 10; //offsets for "goto" command: if caret goes out of control
|
|
cScrollIndentGotoVert = 3;
|
|
cSpeedScrollAutoHorz = 10; //auto-scroll (drag out of control): speed x
|
|
cSpeedScrollAutoVert = 1; //... speed y
|
|
cSpeedScrollNiceHorz = 4; //browser-scroll (middle-click): speed x
|
|
cSpeedScrollNiceVert = 1; //... speed y
|
|
cResizeBitmapStep = 200; //resize bitmap by N pixels step
|
|
cSizeGutterFoldLineDx = 3;
|
|
cSizeRulerHeight = 20;
|
|
cSizeRulerMarkSmall = 3;
|
|
cSizeRulerMarkBig = 7;
|
|
cMinFontSize = 6;
|
|
cMinTabSize = 1;
|
|
cMaxTabSize = 64;
|
|
cMinMinimapWidth = 30;
|
|
cMaxCharsForOutput = 1000; //don't paint more chars in line
|
|
cMinWrapColumn = 20; //too small width won't give smaller wrap-column
|
|
cMinWrapColumnAbs = 4; //absolute min of wrap-column (leave n chars on line anyway)
|
|
cMinMarginRt = 20;
|
|
cMinCaretTime = 300;
|
|
cMaxCaretTime = 2000;
|
|
cMinCharsAfterAnyIndent = 20; //if indent is too big, leave 20 chrs in wrapped-parts anyway
|
|
cMaxLinesForOldWrapUpdate = 100; //if less lines, force old wrapinfo update (fast)
|
|
cHintScrollPrefix: string = 'Line';
|
|
cHintScrollDx = 5;
|
|
cStrMenuItemFoldAll: string = 'Fold all';
|
|
cStrMenuItemUnfoldAll: string = 'Unfold all';
|
|
cStrMenuItemFoldLevel: string = 'Fold level';
|
|
|
|
var
|
|
cRectEmpty: TRect = (Left: 0; Top: 0; Right: 0; Bottom: 0);
|
|
cATClipboardFormatId: integer = 0; //must be inited
|
|
cATClipboardSignatureColBlock: integer = $1000;
|
|
|
|
type
|
|
TATSynEditClickEvent = procedure(Sender: TObject; var AHandled: boolean) of object;
|
|
TATSynEditClickMoveCaretEvent = procedure(Sender: TObject; APrevPnt, ANewPnt: TPoint) of object;
|
|
TATSynEditCommandEvent = procedure(Sender: TObject; ACommand: integer; const AText: string; var AHandled: boolean) of object;
|
|
TATSynEditClickGutterEvent = procedure(Sender: TObject; ABand: integer; ALineNum: integer) of object;
|
|
TATSynEditClickMicromapEvent = procedure(Sender: TObject; AX, AY: integer) of object;
|
|
TATSynEditDrawBookmarkEvent = procedure(Sender: TObject; C: TCanvas; ALineNum: integer; const ARect: TRect) of object;
|
|
TATSynEditDrawRectEvent = procedure(Sender: TObject; C: TCanvas; const ARect: TRect) of object;
|
|
TATSynEditCalcBookmarkColorEvent = procedure(Sender: TObject; ABookmarkKind: integer; out AColor: TColor) of object;
|
|
TATSynEditCalcStapleEvent = procedure(Sender: TObject; ALine, AIndent: integer; var AStapleColor: TColor) of object;
|
|
TATSynEditCalcHiliteEvent = procedure(Sender: TObject; var AParts: TATLineParts;
|
|
ALineIndex, ACharIndex, ALineLen: integer; var AColorAfterEol: TColor) of object;
|
|
|
|
|
|
type
|
|
{ TATSynEdit }
|
|
|
|
TATSynEdit = class(TCustomControl)
|
|
private
|
|
FTimerBlink: TTimer;
|
|
FTimerScroll: TTimer;
|
|
FTimerNiceScroll: TTimer;
|
|
FPaintStatic: boolean;
|
|
FPaintFlags: TATSynPaintFlags;
|
|
FPaintLocked: integer;
|
|
FBitmap: TBitmap;
|
|
FKeymap: TATKeymap;
|
|
FWantTabs: boolean;
|
|
FEditorIndex: integer;
|
|
FMarginRight: integer;
|
|
FMarginList: TList;
|
|
FStringsInt,
|
|
FStringsExternal: TATStrings;
|
|
FAdapterHilite: TATAdapterHilite;
|
|
FFold: TATSynRanges;
|
|
FFoldImageList: TImageList;
|
|
FFoldStyle: TATFoldStyle;
|
|
FCursorText,
|
|
FCursorBm: TCursor;
|
|
FTextOffset: TPoint;
|
|
FTextLocked: string;
|
|
FTextHint: string;
|
|
FTextHintFontStyle: TFontStyles;
|
|
FTextHintCenter: boolean;
|
|
FSelRect: TRect;
|
|
FSelRectBegin,
|
|
FSelRectEnd: TPoint;
|
|
FCarets: TATCarets;
|
|
FCaretBlinkEnabled: boolean;
|
|
FCaretShapeIns,
|
|
FCaretShapeOvr,
|
|
FCaretShapeRO: TATSynCaretShape;
|
|
FCaretShown: boolean;
|
|
FCaretVirtual: boolean;
|
|
FCaretSpecPos: boolean;
|
|
FCaretStopUnfocused: boolean;
|
|
FMarkers: TATMarkers;
|
|
FAttribs: TATMarkers;
|
|
FMarkedRange: TATMarkers;
|
|
FMenuStd,
|
|
FMenuText,
|
|
FMenuGutterBm,
|
|
FMenuGutterNum,
|
|
FMenuGutterFold,
|
|
FMenuGutterFoldStd,
|
|
FMenuMinimap,
|
|
FMenuMicromap,
|
|
FMenuRuler: TPopupMenu;
|
|
FOverwrite: boolean;
|
|
FHintWnd: THintWindow;
|
|
FMouseDownPnt: TPoint;
|
|
FMouseDownNumber: integer;
|
|
FMouseDownDouble: boolean;
|
|
FMouseDownRight: boolean;
|
|
FMouseNiceScrollPos: TPoint;
|
|
FMouseDragDropping: boolean;
|
|
FMouseDragMinimap: boolean;
|
|
FMouseAutoScroll: TATDirection;
|
|
FLastTextCmd: integer;
|
|
FLastTextCmdText: atString;
|
|
FCursorOnMinimap: boolean;
|
|
FCursorOnGutter: boolean;
|
|
FOnBeforeCalcHilite: TNotifyEvent;
|
|
FOnClickDbl,
|
|
FOnClickTriple,
|
|
FOnClickMiddle: TATSynEditClickEvent;
|
|
FOnClickMoveCaret: TATSynEditClickMoveCaretEvent;
|
|
FOnClickEndSelect: TATSynEditClickMoveCaretEvent;
|
|
FOnChangeCaretPos: TNotifyEvent;
|
|
FOnChange: TNotifyEvent;
|
|
FOnScroll: TNotifyEvent;
|
|
FOnClickGutter: TATSynEditClickGutterEvent;
|
|
FOnClickMicromap: TATSynEditClickMicromapEvent;
|
|
FOnDrawBookmarkIcon: TATSynEditDrawBookmarkEvent;
|
|
FOnDrawLine: TATSynEditDrawLineEvent;
|
|
FOnDrawMicromap: TATSynEditDrawRectEvent;
|
|
FOnDrawEditor: TATSynEditDrawRectEvent;
|
|
FOnDrawRuler: TATSynEditDrawRectEvent;
|
|
FOnChangeState: TNotifyEvent;
|
|
FOnCommand: TATSynEditCommandEvent;
|
|
FOnCalcHilite: TATSynEditCalcHiliteEvent;
|
|
FOnCalcStaple: TATSynEditCalcStapleEvent;
|
|
FOnCalcBookmarkColor: TATSynEditCalcBookmarkColorEvent;
|
|
FWrapInfo: TATSynWrapInfo;
|
|
//FWrapProgress: integer;
|
|
FWrapColumn: integer;
|
|
FWrapMode: TATSynWrapMode;
|
|
FWrapUpdateNeeded: boolean;
|
|
FWrapIndented: boolean;
|
|
FUnprintedVisible,
|
|
FUnprintedSpaces,
|
|
FUnprintedEnds,
|
|
FUnprintedEndsDetails,
|
|
FUnprintedReplaceSpec: boolean;
|
|
FPrevVisibleColumns: integer;
|
|
FCharSize: TPoint;
|
|
FCharSizeMinimap: TPoint;
|
|
FCharSpacingText: TPoint;
|
|
FTabSize: integer;
|
|
FGutter: TATGutter;
|
|
FGutterBandBm,
|
|
FGutterBandNum,
|
|
FGutterBandState,
|
|
FGutterBandFold,
|
|
FGutterBandSep,
|
|
FGutterBandEmpty: integer;
|
|
FColors: TATSynEditColors;
|
|
FRectMain,
|
|
FRectMinimap,
|
|
FRectMicromap,
|
|
FRectGutter,
|
|
FRectRuler: TRect;
|
|
FLineBottom: integer;
|
|
FScrollVert,
|
|
FScrollHorz: TATSynScrollInfo;
|
|
FScrollVertMinimap,
|
|
FScrollHorzMinimap: TATSynScrollInfo;
|
|
FPrevHorz,
|
|
FPrevVert: TATSynScrollInfo;
|
|
FMinimapWidth: integer;
|
|
FMinimapCharWidth: integer;
|
|
FMinimapVisible: boolean;
|
|
FMinimapShowSelBorder: boolean;
|
|
FMinimapShowSelAlways: boolean;
|
|
FMicromapWidth: integer;
|
|
FMicromapVisible: boolean;
|
|
FOptMaxLinesToCountUnindent: integer;
|
|
FOptShowStapleStyle: TATLineStyle;
|
|
FOptShowStapleIndent: integer;
|
|
FOptShowStapleWidthPercent: integer;
|
|
FOptMouseEnableNormalSelection: boolean;
|
|
FOptMouseEnableColumnSelection: boolean;
|
|
FOptMouseDownForPopup: boolean;
|
|
FOptCaretPreferLeftSide: boolean;
|
|
FOptMarkersSize: integer;
|
|
FOptShowScrollHint: boolean;
|
|
FOptTextOffsetTop: integer;
|
|
FOptTextOffsetFromLine: integer;
|
|
FOptSavingForceFinalEol: boolean;
|
|
FOptSavingTrimSpaces: boolean;
|
|
FOptUndoGrouped: boolean;
|
|
FOptIndentSize: integer;
|
|
FOptIndentKeepsAlign: boolean;
|
|
FOptRulerVisible: boolean;
|
|
FOptRulerSize: integer;
|
|
FOptRulerFontSize: integer;
|
|
FOptRulerMarkSizeSmall: integer;
|
|
FOptRulerMarkSizeBig: integer;
|
|
FOptRulerTextIndent: integer;
|
|
FOptGutterVisible: boolean;
|
|
FOptGutterPlusSize: integer;
|
|
FOptGutterShowFoldAlways: boolean;
|
|
FOptGutterShowFoldLines: boolean;
|
|
FOptGutterShowFoldLinesAll: boolean;
|
|
FOptNumbersAutosize: boolean;
|
|
FOptNumbersAlignment: TAlignment;
|
|
FOptNumbersFontSize: integer;
|
|
FOptNumbersStyle: TATSynNumbersStyle;
|
|
FOptNumbersShowFirst,
|
|
FOptNumbersShowCarets: boolean;
|
|
FOptNumbersSkippedChar: atString;
|
|
FOptNumbersIndentLeft,
|
|
FOptNumbersIndentRight: integer;
|
|
FOptWordChars: atString;
|
|
FOptAutoIndent: boolean;
|
|
FOptAutoIndentKind: TATAutoIndentKind;
|
|
FOptTabSpaces: boolean;
|
|
FOptLastLineOnTop: boolean;
|
|
FOptOverwriteSel: boolean;
|
|
FOptOverwriteAllowedOnPaste: boolean;
|
|
FOptKeyBackspaceUnindent: boolean;
|
|
FOptKeyPageKeepsRelativePos: boolean;
|
|
FOptKeyUpDownNavigateWrapped: boolean;
|
|
FOptKeyHomeEndNavigateWrapped: boolean;
|
|
FOptKeyUpDownKeepColumn: boolean;
|
|
FOptCopyLinesIfNoSel: boolean;
|
|
FOptCutLinesIfNoSel: boolean;
|
|
FOptShowFullSel: boolean;
|
|
FOptShowFullHilite: boolean;
|
|
FOptShowCurLine: boolean;
|
|
FOptShowCurLineMinimal: boolean;
|
|
FOptShowCurColumn: boolean;
|
|
FOptMouseHideCursor: boolean;
|
|
FOptMouse2ClickSelectsLine: boolean;
|
|
FOptMouse3ClickSelectsLine: boolean;
|
|
FOptMouse2ClickDragSelectsWords: boolean;
|
|
FOptMouseDragDrop: boolean;
|
|
FOptMouseRightClickMovesCaret: boolean;
|
|
FOptMouseGutterClickSelectsLine: boolean;
|
|
FOptMouseNiceScroll: boolean;
|
|
FOptKeyPageUpDownSize: TATPageUpDownSize;
|
|
FOptKeyLeftRightSwapSel: boolean;
|
|
FOptKeyLeftRightSwapSelAndSelect: boolean;
|
|
FOptKeyHomeToNonSpace: boolean;
|
|
FOptKeyEndToNonSpace: boolean;
|
|
FOptKeyTabIndents: boolean;
|
|
FOptShowIndentLines: boolean;
|
|
FOptShowGutterCaretBG: boolean;
|
|
FOptAllowScrollbarVert: boolean;
|
|
FOptAllowScrollbarHorz: boolean;
|
|
FOptAllowZooming: boolean;
|
|
FOptAllowReadOnly: boolean;
|
|
|
|
//
|
|
procedure DebugFindWrapIndex;
|
|
function DoCalcIndentCharsFromPrevLines(AX, AY: integer): integer;
|
|
procedure DoCalcPosColor(AX, AY: integer; var AColor: TColor);
|
|
procedure DoCalcLineEntireColor(ALine: integer; ACoordTop: integer;
|
|
ALineWithCaret: boolean; out AColor: TColor; out AColorForced: boolean);
|
|
procedure DoCaretsAssign(NewCarets: TATCarets);
|
|
procedure DoCaretsShift_CaretItem(Caret: TATCaretItem; APosX, APosY, AShiftX,
|
|
AShiftY, AShiftBelowX: integer);
|
|
procedure DoCaretsShift_MarkerItem(Mark: TATMarkerItem; APosX, APosY, AShiftX,
|
|
AShiftY, AShiftBelowX: integer; APosAfter: TPoint);
|
|
procedure DoDebugAddAttribs;
|
|
procedure DoDropText;
|
|
procedure DoFoldbarClick(ALine: integer);
|
|
procedure DoFoldForLevel(ALevel: integer);
|
|
procedure DoFoldForLevelAndLines(ALineFrom, ALineTo: integer; ALevel: integer;
|
|
AForThisRange: TATSynRange);
|
|
procedure DoHandleRightClick(X, Y: integer);
|
|
function DoHandleClickEvent(AEvent: TATSynEditClickEvent): boolean;
|
|
procedure DoHintShow;
|
|
procedure DoHintHide;
|
|
procedure DoMenuGutterFold_AddDynamicItems(Menu: TPopupMenu);
|
|
procedure DoMenuGutterFold;
|
|
procedure DoMenuText;
|
|
procedure DoMinimapClick(APosY: integer);
|
|
procedure DoMinimapDrag(APosY: integer);
|
|
procedure DoPaintMarkersTo(C: TCanvas);
|
|
procedure DoSelectionDeleteColumnBlock;
|
|
procedure DoSelect_NormalSelToColumnSel(out ABegin, AEnd: TPoint);
|
|
function GetColorTextBG: TColor;
|
|
function GetColorTextFont: TColor;
|
|
function GetMinimapActualHeight: integer;
|
|
function GetMinimapSelTop: integer;
|
|
function GetMinimapSelTop_PixelsToWrapIndex(APixels: integer): integer;
|
|
function GetRectMinimapSel: TRect;
|
|
procedure InitResourcesFoldbar;
|
|
function IsFoldLineNeededBeforeWrapitem(N: integer): boolean;
|
|
procedure MenuFoldFoldAllClick(Sender: TObject);
|
|
procedure MenuFoldLevelClick(Sender: TObject);
|
|
procedure MenuFoldUnfoldAllClick(Sender: TObject);
|
|
procedure MenuFoldPlusMinusClick(Sender: TObject);
|
|
procedure PaintEx(ALine: integer);
|
|
procedure DoPaintGutterFolding(C: TCanvas; AWrapItemIndex: integer; ACoordX1,
|
|
ACoordX2, ACoordY1, ACoordY2: integer);
|
|
procedure DoPaintGutterBandBG(C: TCanvas; ABand: integer; AColor: TColor; ATop,
|
|
ABottom: integer);
|
|
procedure DoPaintLockedWarning(C: TCanvas);
|
|
procedure DoPaintStaple(C: TCanvas; const R: TRect; AColor: TColor);
|
|
procedure DoPaintStaples(C: TCanvas; const ARect: TRect; ACharSize: TPoint;
|
|
const AScrollHorz: TATSynScrollInfo);
|
|
procedure DoPaintTextHintTo(C: TCanvas);
|
|
procedure DoPartCalc_ApplyOver(var AParts: TATLineParts; AOffsetMax,
|
|
ALineIndex, ACharIndex: integer);
|
|
procedure DoPartCalc_CreateNew(var AParts: TATLineParts; AOffsetMax,
|
|
ALineIndex, ACharIndex: integer; AColorBG: TColor);
|
|
procedure DoPartCalc_ApplyAttribsOver(var AParts: TATLineParts; AOffsetMax,
|
|
ALineIndex, ACharIndex: integer);
|
|
function GetAutoIndentString(APosX, APosY: integer): atString;
|
|
function GetFirstUnfoldedLineNumber: integer;
|
|
function GetFoldedMarkText(ALine: integer): string;
|
|
function GetLastUnfoldedLineNumber: integer;
|
|
function GetModified: boolean;
|
|
function GetNextUnfoldedLineNumber(ALine: integer; ADown: boolean): integer;
|
|
function GetOneLine: boolean;
|
|
function GetRedoCount: integer;
|
|
function GetLinesFromTop: integer;
|
|
function GetText: atString;
|
|
function GetUndoAfterSave: boolean;
|
|
function GetUndoCount: integer;
|
|
function GetUndoLimit: integer;
|
|
procedure DoInitPopupMenu;
|
|
function IsCaretBlocked: boolean;
|
|
function IsLineFoldedFull(ALine: integer): boolean;
|
|
function IsLinePartWithCaret(ALine: integer; ACoordY: integer): boolean;
|
|
procedure MenuClick(Sender: TObject);
|
|
procedure MenuPopup(Sender: TObject);
|
|
procedure DoCalcWrapInfos(ALine: integer; AIndentMaximal: integer; AItems: TList);
|
|
procedure DoCalcLineHilite(const AItem: TATSynWrapItem;
|
|
var AParts: TATLineParts; ACharsSkipped, ACharsMax: integer;
|
|
AColorBG: TColor; AColorForced: boolean; var AColorAfter: TColor);
|
|
//select
|
|
procedure DoSelectionDeleteOrReset;
|
|
procedure DoSelect_ExtendSelectionByLine;
|
|
procedure DoSelect_CharRange(ACaretIndex: integer; Pnt: TPoint);
|
|
procedure DoSelect_WordRange(ACaretIndex: integer; P1, P2: TPoint);
|
|
procedure DoSelect_Word_ByClick;
|
|
procedure DoSelect_Line_ByClick;
|
|
//paint
|
|
function DoPaint(AFlags: TATSynPaintFlags; ALineFrom: integer): boolean;
|
|
procedure DoPaintNiceScroll(C: TCanvas);
|
|
procedure DoPaintMarginLineTo(C: TCanvas; AX: integer; AColor: TColor);
|
|
procedure DoPaintTo(C: TCanvas; ALineFrom: integer);
|
|
procedure DoPaintRulerTo(C: TCanvas);
|
|
procedure DoPaintTextTo(C: TCanvas; const ARect: TRect;
|
|
const ACharSize: TPoint; AWithGutter, AMainText: boolean;
|
|
var AScrollHorz, AScrollVert: TATSynScrollInfo; ALineFrom: integer);
|
|
procedure DoPaintLineIndent(C: TCanvas; const ARect: TRect; ACharSize: TPoint;
|
|
ACoordY: integer; AIndentSize: integer; AColorBG: TColor;
|
|
AScrollPos: integer; AIndentLines: boolean);
|
|
procedure DoPaintMinimapSelTo(C: TCanvas);
|
|
procedure DoPaintMinimapTo(C: TCanvas);
|
|
procedure DoPaintMicromapTo(C: TCanvas);
|
|
procedure DoPaintMarginsTo(C: TCanvas);
|
|
procedure DoPaintFoldedMark(C: TCanvas; APos: TPoint; ACoord: TPoint;
|
|
const AMarkText: string);
|
|
procedure DoPaintCarets(C: TCanvas; AWithInvalidate: boolean);
|
|
procedure DoPaintModeStatic;
|
|
procedure DoPaintModeBlinking;
|
|
procedure DoPaintSelectedLineBG(C: TCanvas; ACharSize: TPoint;
|
|
const AVisRect: TRect; APointLeft: TPoint; APointText: TPoint;
|
|
ALineIndex: integer; AEolSelected: boolean;
|
|
const AScrollHorz: TATSynScrollInfo);
|
|
//carets
|
|
procedure DoCaretsExtend(ADown: boolean; ALines: integer);
|
|
function GetCaretManyAllowed: boolean;
|
|
function GetCaretSelectionIndex(P: TPoint): integer;
|
|
function GetCaretBlinkTime: integer;
|
|
function DoCaretSwapEdge(AMoveLeft: boolean): boolean;
|
|
procedure DoCaretsSort;
|
|
//events
|
|
procedure DoEventBeforeCalcHilite;
|
|
procedure DoEventClickMicromap(AX, AY: integer);
|
|
procedure DoEventClickGutter(ABandIndex, ALineNumber: integer);
|
|
function DoEventCommand(ACommand: integer; const AText: string): boolean;
|
|
procedure DoEventDrawBookmarkIcon(C: TCanvas; ALineNumber: integer; const ARect: TRect);
|
|
//
|
|
function GetCharSpacingX: integer;
|
|
function GetCharSpacingY: integer;
|
|
function GetEndOfFilePos: TPoint;
|
|
function GetMarginString: string;
|
|
function GetReadOnly: boolean;
|
|
function GetLineTop: integer;
|
|
function GetTextForClipboard: string;
|
|
function GetWrapInfoIndex(AMousePos: TPoint): integer;
|
|
function GetStrings: TATStrings;
|
|
function GetMouseNiceScroll: boolean;
|
|
procedure SetCaretShapeRO(AValue: TATSynCaretShape);
|
|
procedure SetCaretBlinkEnabled(AValue: boolean);
|
|
procedure SetMouseNiceScroll(AValue: boolean);
|
|
procedure SetCaretManyAllowed(AValue: boolean);
|
|
procedure SetCaretBlinkTime(AValue: integer);
|
|
procedure SetCaretShapeIns(AValue: TATSynCaretShape);
|
|
procedure SetCaretShapeOvr(AValue: TATSynCaretShape);
|
|
procedure SetCharSpacingX(AValue: integer);
|
|
procedure SetCharSpacingY(AValue: integer);
|
|
procedure SetMarginString(AValue: string);
|
|
procedure SetMicromapVisible(AValue: boolean);
|
|
procedure SetMinimapVisible(AValue: boolean);
|
|
procedure SetOneLine(AValue: boolean);
|
|
procedure SetReadOnly(AValue: boolean);
|
|
procedure SetLineTop(AValue: integer);
|
|
procedure SetLinesFromTop(AValue: integer);
|
|
procedure SetStrings(Obj: TATStrings);
|
|
function GetRectMain: TRect;
|
|
function GetRectMinimap: TRect;
|
|
function GetRectMicromap: TRect;
|
|
function GetRectGutter: TRect;
|
|
function GetRectRuler: TRect;
|
|
function GetTextOffset: TPoint;
|
|
function GetGutterNumbersWidth(C: TCanvas): integer;
|
|
function GetPageLines: integer;
|
|
function GetVisibleLines: integer;
|
|
function GetVisibleColumns: integer;
|
|
function GetVisibleLinesMinimap: integer;
|
|
function GetMinimapScrollPos: integer;
|
|
procedure SetTabSize(AValue: integer);
|
|
procedure SetText(AValue: atString);
|
|
procedure SetUndoAfterSave(AValue: boolean);
|
|
procedure SetUndoLimit(AValue: integer);
|
|
procedure SetWrapMode(AValue: TATSynWrapMode);
|
|
procedure SetWrapIndented(AValue: boolean);
|
|
procedure UpdateCursor;
|
|
procedure UpdateGutterAutosize(C: TCanvas);
|
|
procedure UpdateMinimapAutosize(C: TCanvas);
|
|
function DoFormatLineNumber(N: integer): atString;
|
|
function UpdateScrollInfoFromMessage(const Msg: TLMScroll;
|
|
var Info: TATSynScrollInfo): boolean;
|
|
procedure UpdateWrapInfo;
|
|
function UpdateScrollbars: boolean;
|
|
procedure UpdateScrollbarVert;
|
|
procedure UpdateScrollbarHorz;
|
|
procedure UpdateCaretsCoords(AOnlyLast: boolean = false);
|
|
function GetCharSize(C: TCanvas; ACharSpacing: TPoint): TPoint;
|
|
function GetScrollbarVisible(bVertical: boolean): boolean;
|
|
procedure SetMarginRight(AValue: integer);
|
|
procedure TimerBlinkTick(Sender: TObject);
|
|
procedure TimerScrollTick(Sender: TObject);
|
|
procedure TimerNiceScrollTick(Sender: TObject);
|
|
|
|
//carets
|
|
procedure DoCaretAddToPoint(AX, AY: integer);
|
|
procedure DoCaretsColumnToPoint(AX, AY: integer);
|
|
procedure DoCaretsShift(APosX, APosY: integer; AShiftX, AShiftY: integer;
|
|
APosAfter: TPoint; AShiftBelowX: integer = 0);
|
|
procedure DoCaretsDeleteOnSameLines;
|
|
|
|
//editing
|
|
procedure DoCommandResults(Res: TATCommandResults);
|
|
function DoCommand_FoldLevel(ALevel: integer): TATCommandResults;
|
|
function DoCommand_FoldUnfoldAll(ADoFold: boolean): TATCommandResults;
|
|
function DoCommand_TextTrimSpaces(AMode: TATTrimSpaces): TATCommandResults;
|
|
function DoCommand_TextChangeCase(AMode: TATCaseConvert): TATCommandResults;
|
|
function DoCommand_SizeChange(AIncrease: boolean): TATCommandResults;
|
|
function DoCommand_MoveSelectionUpDown(ADown: boolean): TATCommandResults;
|
|
function DoCommand_TextInsertEmptyAboveBelow(ADown: boolean): TATCommandResults;
|
|
function DoCommand_SelectColumn(ADir: TATSelectColumnDirection
|
|
): TATCommandResults;
|
|
function DoCommand_SelectColumnToLineEdge(AToEnd: boolean): TATCommandResults;
|
|
function DoCommand_TextInsertColumnBlockOnce(const AText: atString; AKeepCaret: boolean): TATCommandResults;
|
|
function DoCommand_CaretsExtend(ADown: boolean; ALines: integer): TATCommandResults;
|
|
function DoCommand_Undo: TATCommandResults;
|
|
function DoCommand_Redo: TATCommandResults;
|
|
function DoCommand_TextIndentUnindent(ARight: boolean): TATCommandResults;
|
|
function DoCommand_SelectWords: TATCommandResults;
|
|
function DoCommand_SelectLines: TATCommandResults;
|
|
function DoCommand_SelectAll: TATCommandResults;
|
|
function DoCommand_SelectInverted: TATCommandResults;
|
|
function DoCommand_SelectSplitToLines: TATCommandResults;
|
|
function DoCommand_SelectExtendByLine: TATCommandResults;
|
|
function DoCommand_Cancel: TATCommandResults;
|
|
function DoCommand_ToggleReadOnly: TATCommandResults;
|
|
function DoCommand_ToggleOverwrite: TATCommandResults;
|
|
function DoCommand_ToggleWordWrap: TATCommandResults;
|
|
function DoCommand_ToggleUnprinted: TATCommandResults;
|
|
function DoCommand_ToggleUnprintedSpaces: TATCommandResults;
|
|
function DoCommand_ToggleUnprintedEnds: TATCommandResults;
|
|
function DoCommand_ToggleUnprintedEndDetails: TATCommandResults;
|
|
function DoCommand_ToggleLineNums: TATCommandResults;
|
|
function DoCommand_ToggleFolding: TATCommandResults;
|
|
function DoCommand_ToggleRuler: TATCommandResults;
|
|
function DoCommand_ToggleMinimap: TATCommandResults;
|
|
function DoCommand_GotoWord(ANext: boolean): TATCommandResults;
|
|
function DoCommand_ScrollVert(ALines: integer): TATCommandResults;
|
|
function DoCommand_TextInsertAtCarets(const AText: atString; AKeepCaret,
|
|
AOvrMode, ASelectThen: boolean): TATCommandResults;
|
|
function DoCommand_TextInsertTabSpacesAtCarets(AOvrMode: boolean): TATCommandResults;
|
|
function DoCommand_TextTabulation: TATCommandResults;
|
|
function DoCommand_KeyHome: TATCommandResults;
|
|
function DoCommand_KeyEnd: TATCommandResults;
|
|
function DoCommand_KeyLeft(ASelCommand: boolean): TATCommandResults;
|
|
function DoCommand_KeyRight(ASelCommand: boolean): TATCommandResults;
|
|
function DoCommand_KeyUpDown(ADown: boolean; ALines: integer; AKeepRelativePos: boolean): TATCommandResults;
|
|
function DoCommand_KeyUpDown_NextLine(ADown: boolean; ALines: integer): TATCommandResults;
|
|
function DoCommand_KeyUpDown_Wrapped(ADown: boolean; ALines: integer): TATCommandResults;
|
|
function DoCommand_TextBackspace: TATCommandResults;
|
|
function DoCommand_TextDelete: TATCommandResults;
|
|
function DoCommand_TextDeleteSelection: TATCommandResults;
|
|
function DoCommand_TextDeleteLeft(ALen: integer; AAllowUnindent: boolean): TATCommandResults;
|
|
function DoCommand_TextDeleteRight(ALen: integer): TATCommandResults;
|
|
function DoCommand_TextInsertEol(AKeepCaret: boolean): TATCommandResults;
|
|
function DoCommand_TextDeleteLines: TATCommandResults;
|
|
function DoCommand_TextDuplicateLine: TATCommandResults;
|
|
function DoCommand_TextDeleteToLineBegin: TATCommandResults;
|
|
function DoCommand_TextDeleteToLineEnd: TATCommandResults;
|
|
function DoCommand_TextDeleteWord(ANext: boolean): TATCommandResults;
|
|
function DoCommand_TextDeleteToFileEnd: TATCommandResults;
|
|
function DoCommand_GotoTextBegin: TATCommandResults;
|
|
function DoCommand_GotoTextEnd: TATCommandResults;
|
|
function DoCommand_ClipboardPaste(AKeepCaret, ASelectThen: boolean): TATCommandResults;
|
|
function DoCommand_ClipboardPasteColumnBlock(AKeepCaret: boolean): TATCommandResults;
|
|
function DoCommand_ClipboardCopy(Append: boolean = false): TATCommandResults;
|
|
function DoCommand_ClipboardCut: TATCommandResults;
|
|
//
|
|
function GetCommandFromKey(var Key: Word; Shift: TShiftState): integer;
|
|
function DoMouseWheelAction(Shift: TShiftState; AUp: boolean): boolean;
|
|
function GetCaretsArray: TATPointArray;
|
|
procedure SetCaretsArray(const L: TATPointArray);
|
|
property MouseNiceScroll: boolean read GetMouseNiceScroll write SetMouseNiceScroll;
|
|
procedure DoDebugInitFoldList;
|
|
|
|
procedure OnCanvasFontChanged(Sender:TObject);
|
|
protected
|
|
procedure DoSendShowHideToInterface; override;
|
|
public
|
|
//overrides
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
procedure SetFocus; override;
|
|
//updates
|
|
procedure Invalidate; override;
|
|
procedure Update(AUpdateWrapInfo: boolean = false; AUpdateCaretsCoords: boolean = true); reintroduce;
|
|
procedure UpdateIncorrectCaretPositions;
|
|
procedure UpdateFoldedFromLinesHidden;
|
|
procedure DoEventCarets;
|
|
procedure DoEventScroll;
|
|
procedure DoEventChange;
|
|
procedure DoEventState;
|
|
//general
|
|
property Strings: TATStrings read GetStrings write SetStrings;
|
|
property Fold: TATSynRanges read FFold;
|
|
property Keymap: TATKeymap read FKeymap write FKeymap;
|
|
property Modified: boolean read GetModified;
|
|
property AdapterHilite: TATAdapterHilite read FAdapterHilite write FAdapterHilite;
|
|
property EditorIndex: integer read FEditorIndex write FEditorIndex;
|
|
property LineTop: integer read GetLineTop write SetLineTop;
|
|
property LineBottom: integer read FLineBottom;
|
|
property LinesFromTop: integer read GetLinesFromTop write SetLinesFromTop;
|
|
property ModeOverwrite: boolean read FOverwrite write FOverwrite;
|
|
property ModeReadOnly: boolean read GetReadOnly write SetReadOnly;
|
|
property ModeOneLine: boolean read GetOneLine write SetOneLine;
|
|
property UndoCount: integer read GetUndoCount;
|
|
property RedoCount: integer read GetRedoCount;
|
|
property Text: atString read GetText write SetText;
|
|
property SelRect: TRect read FSelRect;
|
|
function IsSelRectEmpty: boolean;
|
|
function IsPosSelected(AX, AY: integer): boolean;
|
|
function IsPosFolded(AX, AY: integer): boolean;
|
|
function IsLineFolded(ALine: integer; ADetectPartialFold: boolean = false): boolean;
|
|
function IsCharWord(ch: Widechar): boolean;
|
|
property TextCharSize: TPoint read FCharSize;
|
|
procedure DoUnfoldLine(ALine: integer);
|
|
//gutter
|
|
property Gutter: TATGutter read FGutter;
|
|
property GutterBandBm: integer read FGutterBandBm write FGutterBandBm;
|
|
property GutterBandNum: integer read FGutterBandNum write FGutterBandNum;
|
|
property GutterBandState: integer read FGutterBandState write FGutterBandState;
|
|
property GutterBandFold: integer read FGutterBandFold write FGutterBandFold;
|
|
property GutterBandSep: integer read FGutterBandSep write FGutterBandSep;
|
|
property GutterBandEmpty: integer read FGutterBandEmpty write FGutterBandEmpty;
|
|
//files
|
|
procedure LoadFromFile(const AFilename: string);
|
|
procedure SaveToFile(const AFilename: string);
|
|
//carets
|
|
procedure DoCaretSingle(APosX, APosY, AEndX, AEndY: integer; AUseEndXY: boolean);
|
|
procedure DoCaretSingle(AX, AY: integer; AClearSelection: boolean = true);
|
|
procedure DoCaretSingleAsIs;
|
|
function CaretPosToClientPos(P: TPoint): TPoint;
|
|
function ClientPosToCaretPos(P: TPoint; out AEndOfLinePos: boolean): TPoint;
|
|
property Carets: TATCarets read FCarets;
|
|
property Markers: TATMarkers read FMarkers;
|
|
property Attribs: TATMarkers read FAttribs;
|
|
function IsLineWithCaret(ALine: integer): boolean;
|
|
procedure DoGotoPos(APnt: TPoint; AIndentHorz, AIndentVert: integer);
|
|
procedure DoGotoPos_AndUnfold(APnt: TPoint; AIndentHorz, AIndentVert: integer);
|
|
procedure DoGotoCaret(AEdge: TATCaretEdge);
|
|
//misc
|
|
procedure DoCommand(ACmd: integer; const AText: atString = ''); virtual;
|
|
procedure BeginUpdate;
|
|
procedure EndUpdate;
|
|
function TextSelected: atString;
|
|
function TextCurrentWord: atString;
|
|
procedure DoSelect_All;
|
|
procedure DoSelect_None;
|
|
procedure DoSelect_Inverted;
|
|
procedure DoSelect_SplitSelectionToLines;
|
|
procedure DoSelect_Line(P: TPoint);
|
|
procedure DoSelect_Word(P: TPoint);
|
|
procedure DoSelect_LineRange(ALineFrom: integer; P: TPoint);
|
|
procedure DoSelect_ColumnBlock(P1, P2: TPoint);
|
|
procedure DoRangeFold(ARange: TATSynRange);
|
|
procedure DoRangeUnfold(ARange: TATSynRange);
|
|
procedure DoScrollByDelta(Dx, Dy: integer);
|
|
procedure DoSizeChange(AInc: boolean);
|
|
procedure DoCommentSelectionLines(Act: TATCommentAction;
|
|
const AComment: atString);
|
|
function DoCalcLineHiliteEx(ALineIndex: integer; var AParts: TATLineParts;
|
|
AColorBG: TColor; out AColorAfter: TColor): boolean;
|
|
procedure DoSetMarkedLines(ALine1, ALine2: integer);
|
|
procedure DoGetMarkedLines(out ALine1, ALine2: integer);
|
|
|
|
protected
|
|
procedure Paint; override;
|
|
procedure DoOnResize; override;
|
|
procedure UTF8KeyPress(var UTF8Key: TUTF8Char); override;
|
|
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
|
|
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
|
|
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
|
|
procedure MouseMove(Shift: TShiftState; X,Y: Integer); override;
|
|
function DoMouseWheelDown(Shift: TShiftState; MousePos{%H-}: TPoint): boolean; override;
|
|
function DoMouseWheelUp(Shift: TShiftState; MousePos{%H-}: TPoint): boolean; override;
|
|
procedure DblClick; override;
|
|
procedure TripleClick; override;
|
|
function DoGetTextString: atString; virtual;
|
|
//messages
|
|
procedure WMGetDlgCode(var Msg: TLMNoParams); message LM_GETDLGCODE;
|
|
procedure WMEraseBkgnd(var Msg: TLMEraseBkgnd); message LM_ERASEBKGND;
|
|
procedure WMHScroll(var Msg: TLMHScroll); message LM_HSCROLL;
|
|
procedure WMVScroll(var Msg: TLMVScroll); message LM_VSCROLL;
|
|
// Windows IME Support
|
|
{$ifdef Windows}
|
|
procedure WMIME_STARTCOMPOSITION(var Msg:TMessage); message WM_IME_STARTCOMPOSITION;
|
|
procedure WMIME_COMPOSITION(var Msg:TMessage); message WM_IME_COMPOSITION;
|
|
procedure WMIME_ENDCOMPOSITION(var Msg:TMessage); message WM_IME_ENDCOMPOSITION;
|
|
{$endif}
|
|
published
|
|
property Align;
|
|
property Anchors;
|
|
property BorderSpacing;
|
|
property BorderStyle;
|
|
property Enabled;
|
|
property Font;
|
|
property ParentFont;
|
|
property ParentShowHint;
|
|
property ShowHint;
|
|
property TabOrder;
|
|
property TabStop;
|
|
property Visible;
|
|
//menu
|
|
property PopupTextDefault: TPopupMenu read FMenuStd;
|
|
property PopupText: TPopupMenu read FMenuText write FMenuText;
|
|
property PopupGutterBm: TPopupMenu read FMenuGutterBm write FMenuGutterBm;
|
|
property PopupGutterNum: TPopupMenu read FMenuGutterNum write FMenuGutterNum;
|
|
property PopupGutterFold: TPopupMenu read FMenuGutterFold write FMenuGutterFold;
|
|
property PopupMinimap: TPopupMenu read FMenuMinimap write FMenuMinimap;
|
|
property PopupMicromap: TPopupMenu read FMenuMicromap write FMenuMicromap;
|
|
property PopupRuler: TPopupMenu read FMenuRuler write FMenuRuler;
|
|
//events std
|
|
property OnEnter;
|
|
property OnExit;
|
|
property OnKeyDown;
|
|
property OnKeyPress;
|
|
property OnKeyUp;
|
|
property OnMouseDown;
|
|
property OnMouseEnter;
|
|
property OnMouseLeave;
|
|
property OnMouseMove;
|
|
property OnMouseUp;
|
|
property OnMouseWheel;
|
|
property OnMouseWheelDown;
|
|
property OnMouseWheelUp;
|
|
property OnUTF8KeyPress;
|
|
//events new
|
|
property OnClickDouble: TATSynEditClickEvent read FOnClickDbl write FOnClickDbl;
|
|
property OnClickTriple: TATSynEditClickEvent read FOnClickTriple write FOnClickTriple;
|
|
property OnClickMiddle: TATSynEditClickEvent read FOnClickMiddle write FOnClickMiddle;
|
|
property OnClickGutter: TATSynEditClickGutterEvent read FOnClickGutter write FOnClickGutter;
|
|
property OnClickMicromap: TATSynEditClickMicromapEvent read FOnClickMicromap write FOnClickMicromap;
|
|
property OnClickMoveCaret: TATSynEditClickMoveCaretEvent read FOnClickMoveCaret write FOnClickMoveCaret;
|
|
property OnClickEndSelect: TATSynEditClickMoveCaretEvent read FOnClickEndSelect write FOnClickEndSelect;
|
|
property OnChange: TNotifyEvent read FOnChange write FOnChange;
|
|
property OnChangeState: TNotifyEvent read FOnChangeState write FOnChangeState;
|
|
property OnChangeCaretPos: TNotifyEvent read FOnChangeCaretPos write FOnChangeCaretPos;
|
|
property OnScroll: TNotifyEvent read FOnScroll write FOnScroll;
|
|
property OnCommand: TATSynEditCommandEvent read FOnCommand write FOnCommand;
|
|
property OnDrawBookmarkIcon: TATSynEditDrawBookmarkEvent read FOnDrawBookmarkIcon write FOnDrawBookmarkIcon;
|
|
property OnDrawLine: TATSynEditDrawLineEvent read FOnDrawLine write FOnDrawLine;
|
|
property OnDrawMicromap: TATSynEditDrawRectEvent read FOnDrawMicromap write FOnDrawMicromap;
|
|
property OnDrawEditor: TATSynEditDrawRectEvent read FOnDrawEditor write FOnDrawEditor;
|
|
property OnDrawRuler: TATSynEditDrawRectEvent read FOnDrawRuler write FOnDrawRuler;
|
|
property OnCalcHilite: TATSynEditCalcHiliteEvent read FOnCalcHilite write FOnCalcHilite;
|
|
property OnCalcStaple: TATSynEditCalcStapleEvent read FOnCalcStaple write FOnCalcStaple;
|
|
property OnCalcBookmarkColor: TATSynEditCalcBookmarkColorEvent read FOnCalcBookmarkColor write FOnCalcBookmarkColor;
|
|
property OnBeforeCalcHilite: TNotifyEvent read FOnBeforeCalcHilite write FOnBeforeCalcHilite;
|
|
|
|
//misc
|
|
property CursorText: TCursor read FCursorText write FCursorText;
|
|
property CursorBm: TCursor read FCursorBm write FCursorBm;
|
|
property Colors: TATSynEditColors read FColors write FColors;
|
|
property WantTabs: boolean read FWantTabs write FWantTabs;
|
|
|
|
//options
|
|
property OptTabSpaces: boolean read FOptTabSpaces write FOptTabSpaces;
|
|
property OptTabSize: integer read FTabSize write SetTabSize;
|
|
property OptWordChars: atString read FOptWordChars write FOptWordChars;
|
|
property OptFoldStyle: TATFoldStyle read FFoldStyle write FFoldStyle;
|
|
property OptTextLocked: string read FTextLocked write FTextLocked;
|
|
property OptTextHint: string read FTextHint write FTextHint;
|
|
property OptTextHintFontStyle: TFontStyles read FTextHintFontStyle write FTextHintFontStyle;
|
|
property OptTextHintCenter: boolean read FTextHintCenter write FTextHintCenter;
|
|
property OptTextOffsetTop: integer read FOptTextOffsetTop write FOptTextOffsetTop;
|
|
property OptTextOffsetFromLine: integer read FOptTextOffsetFromLine write FOptTextOffsetFromLine;
|
|
property OptAutoIndent: boolean read FOptAutoIndent write FOptAutoIndent;
|
|
property OptAutoIndentKind: TATAutoIndentKind read FOptAutoIndentKind write FOptAutoIndentKind;
|
|
property OptCopyLinesIfNoSel: boolean read FOptCopyLinesIfNoSel write FOptCopyLinesIfNoSel;
|
|
property OptCutLinesIfNoSel: boolean read FOptCutLinesIfNoSel write FOptCutLinesIfNoSel;
|
|
property OptLastLineOnTop: boolean read FOptLastLineOnTop write FOptLastLineOnTop;
|
|
property OptOverwriteSel: boolean read FOptOverwriteSel write FOptOverwriteSel;
|
|
property OptOverwriteAllowedOnPaste: boolean read FOptOverwriteAllowedOnPaste write FOptOverwriteAllowedOnPaste;
|
|
property OptShowStapleStyle: TATLineStyle read FOptShowStapleStyle write FOptShowStapleStyle;
|
|
property OptShowStapleIndent: integer read FOptShowStapleIndent write FOptShowStapleIndent;
|
|
property OptShowStapleWidthPercent: integer read FOptShowStapleWidthPercent write FOptShowStapleWidthPercent;
|
|
property OptShowFullSel: boolean read FOptShowFullSel write FOptShowFullSel;
|
|
property OptShowFullHilite: boolean read FOptShowFullHilite write FOptShowFullHilite;
|
|
property OptShowCurLine: boolean read FOptShowCurLine write FOptShowCurLine;
|
|
property OptShowCurLineMinimal: boolean read FOptShowCurLineMinimal write FOptShowCurLineMinimal;
|
|
property OptShowScrollHint: boolean read FOptShowScrollHint write FOptShowScrollHint;
|
|
property OptShowCurColumn: boolean read FOptShowCurColumn write FOptShowCurColumn;
|
|
property OptCaretManyAllowed: boolean read GetCaretManyAllowed write SetCaretManyAllowed;
|
|
property OptCaretVirtual: boolean read FCaretVirtual write FCaretVirtual;
|
|
property OptCaretShape: TATSynCaretShape read FCaretShapeIns write SetCaretShapeIns;
|
|
property OptCaretShapeOvr: TATSynCaretShape read FCaretShapeOvr write SetCaretShapeOvr;
|
|
property OptCaretShapeRO: TATSynCaretShape read FCaretShapeRO write SetCaretShapeRO;
|
|
property OptCaretBlinkTime: integer read GetCaretBlinkTime write SetCaretBlinkTime;
|
|
property OptCaretBlinkEnabled: boolean read FCaretBlinkEnabled write SetCaretBlinkEnabled;
|
|
property OptCaretStopUnfocused: boolean read FCaretStopUnfocused write FCaretStopUnfocused;
|
|
property OptCaretPreferLeftSide: boolean read FOptCaretPreferLeftSide write FOptCaretPreferLeftSide;
|
|
property OptMarkersSize: integer read FOptMarkersSize write FOptMarkersSize;
|
|
property OptGutterVisible: boolean read FOptGutterVisible write FOptGutterVisible;
|
|
property OptGutterPlusSize: integer read FOptGutterPlusSize write FOptGutterPlusSize;
|
|
property OptGutterShowFoldAlways: boolean read FOptGutterShowFoldAlways write FOptGutterShowFoldAlways;
|
|
property OptGutterShowFoldLines: boolean read FOptGutterShowFoldLines write FOptGutterShowFoldLines;
|
|
property OptGutterShowFoldLinesAll: boolean read FOptGutterShowFoldLinesAll write FOptGutterShowFoldLinesAll;
|
|
property OptRulerVisible: boolean read FOptRulerVisible write FOptRulerVisible;
|
|
property OptRulerSize: integer read FOptRulerSize write FOptRulerSize;
|
|
property OptRulerFontSize: integer read FOptRulerFontSize write FOptRulerFontSize;
|
|
property OptRulerMarkSizeSmall: integer read FOptRulerMarkSizeSmall write FOptRulerMarkSizeSmall;
|
|
property OptRulerMarkSizeBig: integer read FOptRulerMarkSizeBig write FOptRulerMarkSizeBig;
|
|
property OptRulerTextIndent: integer read FOptRulerTextIndent write FOptRulerTextIndent;
|
|
property OptMinimapVisible: boolean read FMinimapVisible write SetMinimapVisible;
|
|
property OptMinimapCharWidth: integer read FMinimapCharWidth write FMinimapCharWidth;
|
|
property OptMinimapShowSelBorder: boolean read FMinimapShowSelBorder write FMinimapShowSelBorder;
|
|
property OptMinimapShowSelAlways: boolean read FMinimapShowSelAlways write FMinimapShowSelAlways;
|
|
property OptMicromapVisible: boolean read FMicromapVisible write SetMicromapVisible;
|
|
property OptMicromapWidth: integer read FMicromapWidth write FMicromapWidth;
|
|
property OptCharSpacingX: integer read GetCharSpacingX write SetCharSpacingX;
|
|
property OptCharSpacingY: integer read GetCharSpacingY write SetCharSpacingY;
|
|
property OptWrapMode: TATSynWrapMode read FWrapMode write SetWrapMode;
|
|
property OptWrapIndented: boolean read FWrapIndented write SetWrapIndented;
|
|
property OptMarginRight: integer read FMarginRight write SetMarginRight;
|
|
property OptMarginString: string read GetMarginString write SetMarginString;
|
|
property OptNumbersAutosize: boolean read FOptNumbersAutosize write FOptNumbersAutosize;
|
|
property OptNumbersAlignment: TAlignment read FOptNumbersAlignment write FOptNumbersAlignment;
|
|
property OptNumbersFontSize: integer read FOptNumbersFontSize write FOptNumbersFontSize;
|
|
property OptNumbersStyle: TATSynNumbersStyle read FOptNumbersStyle write FOptNumbersStyle;
|
|
property OptNumbersShowFirst: boolean read FOptNumbersShowFirst write FOptNumbersShowFirst;
|
|
property OptNumbersShowCarets: boolean read FOptNumbersShowCarets write FOptNumbersShowCarets;
|
|
property OptNumbersSkippedChar: atString read FOptNumbersSkippedChar write FOptNumbersSkippedChar;
|
|
property OptNumbersIndentLeft: integer read FOptNumbersIndentLeft write FOptNumbersIndentLeft;
|
|
property OptNumbersIndentRight: integer read FOptNumbersIndentRight write FOptNumbersIndentRight;
|
|
property OptUnprintedVisible: boolean read FUnprintedVisible write FUnprintedVisible;
|
|
property OptUnprintedSpaces: boolean read FUnprintedSpaces write FUnprintedSpaces;
|
|
property OptUnprintedEnds: boolean read FUnprintedEnds write FUnprintedEnds;
|
|
property OptUnprintedEndsDetails: boolean read FUnprintedEndsDetails write FUnprintedEndsDetails;
|
|
property OptUnprintedReplaceSpec: boolean read FUnprintedReplaceSpec write FUnprintedReplaceSpec;
|
|
property OptMouseEnableNormalSelection: boolean read FOptMouseEnableNormalSelection write FOptMouseEnableNormalSelection;
|
|
property OptMouseEnableColumnSelection: boolean read FOptMouseEnableColumnSelection write FOptMouseEnableColumnSelection;
|
|
property OptMouseDownForPopup: boolean read FOptMouseDownForPopup write FOptMouseDownForPopup;
|
|
property OptMouseHideCursorOnType: boolean read FOptMouseHideCursor write FOptMouseHideCursor;
|
|
property OptMouse2ClickSelectsLine: boolean read FOptMouse2ClickSelectsLine write FOptMouse2ClickSelectsLine;
|
|
property OptMouse3ClickSelectsLine: boolean read FOptMouse3ClickSelectsLine write FOptMouse3ClickSelectsLine;
|
|
property OptMouse2ClickDragSelectsWords: boolean read FOptMouse2ClickDragSelectsWords write FOptMouse2ClickDragSelectsWords;
|
|
property OptMouseDragDrop: boolean read FOptMouseDragDrop write FOptMouseDragDrop;
|
|
property OptMouseNiceScroll: boolean read FOptMouseNiceScroll write FOptMouseNiceScroll;
|
|
property OptMouseRightClickMovesCaret: boolean read FOptMouseRightClickMovesCaret write FOptMouseRightClickMovesCaret;
|
|
property OptMouseGutterClickSelectsLine: boolean read FOptMouseGutterClickSelectsLine write FOptMouseGutterClickSelectsLine;
|
|
property OptKeyBackspaceUnindent: boolean read FOptKeyBackspaceUnindent write FOptKeyBackspaceUnindent;
|
|
property OptKeyPageKeepsRelativePos: boolean read FOptKeyPageKeepsRelativePos write FOptKeyPageKeepsRelativePos;
|
|
property OptKeyUpDownNavigateWrapped: boolean read FOptKeyUpDownNavigateWrapped write FOptKeyUpDownNavigateWrapped;
|
|
property OptKeyUpDownKeepColumn: boolean read FOptKeyUpDownKeepColumn write FOptKeyUpDownKeepColumn;
|
|
property OptKeyHomeEndNavigateWrapped: boolean read FOptKeyHomeEndNavigateWrapped write FOptKeyHomeEndNavigateWrapped;
|
|
property OptKeyPageUpDownSize: TATPageUpDownSize read FOptKeyPageUpDownSize write FOptKeyPageUpDownSize;
|
|
property OptKeyLeftRightSwapSel: boolean read FOptKeyLeftRightSwapSel write FOptKeyLeftRightSwapSel;
|
|
property OptKeyLeftRightSwapSelAndSelect: boolean read FOptKeyLeftRightSwapSelAndSelect write FOptKeyLeftRightSwapSelAndSelect;
|
|
property OptKeyHomeToNonSpace: boolean read FOptKeyHomeToNonSpace write FOptKeyHomeToNonSpace;
|
|
property OptKeyEndToNonSpace: boolean read FOptKeyEndToNonSpace write FOptKeyEndToNonSpace;
|
|
property OptKeyTabIndents: boolean read FOptKeyTabIndents write FOptKeyTabIndents;
|
|
property OptIndentSize: integer read FOptIndentSize write FOptIndentSize;
|
|
property OptIndentKeepsAlign: boolean read FOptIndentKeepsAlign write FOptIndentKeepsAlign;
|
|
property OptMaxLinesToCountUnindent: integer read FOptMaxLinesToCountUnindent write FOptMaxLinesToCountUnindent;
|
|
property OptShowIndentLines: boolean read FOptShowIndentLines write FOptShowIndentLines;
|
|
property OptShowGutterCaretBG: boolean read FOptShowGutterCaretBG write FOptShowGutterCaretBG;
|
|
property OptAllowScrollbarVert: boolean read FOptAllowScrollbarVert write FOptAllowScrollbarVert;
|
|
property OptAllowScrollbarHorz: boolean read FOptAllowScrollbarHorz write FOptAllowScrollbarHorz;
|
|
property OptAllowZooming: boolean read FOptAllowZooming write FOptAllowZooming;
|
|
property OptAllowReadOnly: boolean read FOptAllowReadOnly write FOptAllowReadOnly;
|
|
property OptUndoLimit: integer read GetUndoLimit write SetUndoLimit;
|
|
property OptUndoGrouped: boolean read FOptUndoGrouped write FOptUndoGrouped;
|
|
property OptUndoAfterSave: boolean read GetUndoAfterSave write SetUndoAfterSave;
|
|
property OptSavingForceFinalEol: boolean read FOptSavingForceFinalEol write FOptSavingForceFinalEol;
|
|
property OptSavingTrimSpaces: boolean read FOptSavingTrimSpaces write FOptSavingTrimSpaces;
|
|
end;
|
|
|
|
|
|
implementation
|
|
|
|
uses
|
|
LCLIntf,
|
|
LCLProc,
|
|
Dialogs,
|
|
Types,
|
|
Math,
|
|
Clipbrd,
|
|
ATSynEdit_Commands,
|
|
ATSynEdit_Keymap_Init,
|
|
ATStringProc_WordJump;
|
|
|
|
{$I atsynedit_proc.inc}
|
|
|
|
|
|
{ TATSynEdit }
|
|
|
|
procedure TATSynEdit.DoPaintRulerTo(C: TCanvas);
|
|
var
|
|
NX, NSize, NPrevSize, NRulerStart, i: integer;
|
|
Str: string;
|
|
begin
|
|
NPrevSize:= C.Font.Size;
|
|
NRulerStart:= FScrollHorz.NPos;
|
|
|
|
if FOptRulerFontSize<>0 then
|
|
C.Font.Size:= FOptRulerFontSize;
|
|
C.Font.Color:= FColors.RulerFont;
|
|
C.Pen.Color:= FColors.RulerFont;
|
|
C.Brush.Color:= FColors.RulerBG;
|
|
|
|
C.FillRect(FRectRuler);
|
|
C.Line(FRectRuler.Left, FRectRuler.Bottom-1,
|
|
FRectRuler.Right, FRectRuler.Bottom-1);
|
|
|
|
for i:= NRulerStart to NRulerStart+GetVisibleColumns+1 do
|
|
begin
|
|
NX:= FTextOffset.X+(i-NRulerStart)*FCharSize.X;
|
|
NSize:= IfThen(i mod 5 = 0, FOptRulerMarkSizeBig, FOptRulerMarkSizeSmall);
|
|
C.Line(NX, FRectRuler.Bottom-1,
|
|
NX, FRectRuler.Bottom-1-NSize);
|
|
|
|
if i mod 10 = 0 then
|
|
begin
|
|
Str:= IntToStr(i);
|
|
C.TextOut(NX - C.TextWidth(Str) div 2, FOptRulerTextIndent, Str);
|
|
end;
|
|
end;
|
|
|
|
C.Font.Size:= NPrevSize;
|
|
end;
|
|
|
|
procedure TATSynEdit.UpdateGutterAutosize(C: TCanvas);
|
|
begin
|
|
FGutter[FGutterBandNum].Size:= GetGutterNumbersWidth(C);
|
|
FGutter.Update;
|
|
end;
|
|
|
|
procedure TATSynEdit.UpdateMinimapAutosize(C: TCanvas);
|
|
{
|
|
Minimap must give same cnt of small chars, as rest width gives for normal chars.
|
|
This gives:
|
|
MapSize / CharWidth_small = (ClientWidth - MapSize) / CharWidth_big
|
|
MapSize = (ClientWidth * CharWidth_small) / (CharWidth_big+CharWidth_small)
|
|
}
|
|
var
|
|
CharSmall, CharBig: integer;
|
|
begin
|
|
CharBig:= FCharSize.X;
|
|
CharSmall:= FCharSizeMinimap.X;
|
|
|
|
if FMinimapCharWidth=0 then
|
|
begin
|
|
FMinimapWidth:= (ClientWidth - IfThen(FMicromapVisible, FMicromapWidth) - FTextOffset.X)
|
|
* CharSmall div (CharSmall+CharBig);
|
|
end
|
|
else
|
|
FMinimapWidth:= CharSmall*FMinimapCharWidth;
|
|
|
|
FMinimapWidth:= Max(cMinMinimapWidth, FMinimapWidth);
|
|
end;
|
|
|
|
function TATSynEdit.DoFormatLineNumber(N: integer): atString;
|
|
begin
|
|
if FOptNumbersShowCarets then
|
|
if IsLineWithCaret(N-1) then
|
|
begin
|
|
Result:= IntToStr(N);
|
|
Exit
|
|
end;
|
|
|
|
if FOptNumbersShowFirst then
|
|
if N=1 then
|
|
begin
|
|
Result:= IntToStr(N);
|
|
Exit
|
|
end;
|
|
|
|
case FOptNumbersStyle of
|
|
cNumbersAll:
|
|
Result:= IntToStr(N);
|
|
cNumbersNone:
|
|
Result:= FOptNumbersSkippedChar;
|
|
cNumbersEach10th:
|
|
begin
|
|
if (N mod 10 = 0) then
|
|
Result:= IntToStr(N)
|
|
else
|
|
if (N mod 5) = 0 then
|
|
Result:= '-'
|
|
else
|
|
Result:= FOptNumbersSkippedChar;
|
|
end;
|
|
cNumbersEach5th:
|
|
begin
|
|
if (N mod 5 = 0) then
|
|
Result:= IntToStr(N)
|
|
else
|
|
Result:= FOptNumbersSkippedChar;
|
|
end;
|
|
else
|
|
raise Exception.Create('Unknown num-style');
|
|
end;
|
|
end;
|
|
|
|
function TATSynEdit.GetScrollbarVisible(bVertical: boolean): boolean;
|
|
const
|
|
cKind: array[boolean] of integer = (SB_HORZ, SB_VERT);
|
|
var
|
|
si: TScrollInfo;
|
|
begin
|
|
FillChar(si{%H-}, SizeOf(si), 0);
|
|
si.cbSize:= SizeOf(si);
|
|
si.fMask:= SIF_ALL;
|
|
GetScrollInfo(Handle, cKind[bVertical], si);
|
|
Result:= Longword(si.nMax) > Longword(si.nPage);
|
|
end;
|
|
|
|
procedure TATSynEdit.SetMarginRight(AValue: integer);
|
|
begin
|
|
if AValue=FMarginRight then Exit;
|
|
FMarginRight:= Max(AValue, cMinMarginRt);
|
|
if FWrapMode=cWrapAtMargin then
|
|
FWrapUpdateNeeded:= true;
|
|
Update;
|
|
end;
|
|
|
|
procedure TATSynEdit.UpdateWrapInfo;
|
|
var
|
|
NNewVisibleColumns: integer;
|
|
NIndentMaximal: integer;
|
|
Items: TList;
|
|
ListNums: TList;
|
|
i, j: integer;
|
|
NLine, NIndexFrom, NIndexTo: integer;
|
|
UseCachedUpdate: boolean;
|
|
begin
|
|
//FWrapProgress:= 0;
|
|
NNewVisibleColumns:= GetVisibleColumns;
|
|
NIndentMaximal:= Max(2, NNewVisibleColumns-cMinCharsAfterAnyIndent); //don't do too big NIndent
|
|
|
|
if (not FWrapUpdateNeeded) and
|
|
(FWrapMode=cWrapOn) and
|
|
(FPrevVisibleColumns<>NNewVisibleColumns) then
|
|
FWrapUpdateNeeded:= true;
|
|
|
|
if not FWrapUpdateNeeded then Exit;
|
|
FWrapUpdateNeeded:= false;
|
|
FPrevVisibleColumns:= NNewVisibleColumns;
|
|
|
|
{$ifdef beep_wrapinfo}
|
|
Beep;
|
|
{$endif}
|
|
|
|
case FWrapMode of
|
|
cWrapOff:
|
|
FWrapColumn:= 0;
|
|
cWrapOn:
|
|
FWrapColumn:= Max(cMinWrapColumn, NNewVisibleColumns-cScrollKeepHorz);
|
|
cWrapAtMargin:
|
|
FWrapColumn:= Max(cMinWrapColumn, FMarginRight);
|
|
end;
|
|
|
|
UseCachedUpdate:=
|
|
(FWrapInfo.Count>0) and
|
|
(Strings.Count>cMaxLinesForOldWrapUpdate) and
|
|
(not Strings.ListUpdatesHard) and
|
|
(Strings.ListUpdates.Count>0);
|
|
//UseCachedUpdate:= false;////to disable
|
|
|
|
Items:= TList.Create;
|
|
ListNums:= TList.Create;
|
|
|
|
try
|
|
if not UseCachedUpdate then
|
|
begin
|
|
FWrapInfo.Clear;
|
|
FWrapInfo.SetCapacity(Strings.Count);
|
|
for i:= 0 to Strings.Count-1 do
|
|
begin
|
|
DoCalcWrapInfos(i, NIndentMaximal, Items);
|
|
for j:= 0 to Items.Count-1 do
|
|
FWrapInfo.Add(TATSynWrapItem(Items[j]));
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
{$ifdef beep_cached_update}
|
|
Beep;
|
|
{$endif}
|
|
|
|
ListNums.Assign(Strings.ListUpdates);
|
|
|
|
for i:= 0 to ListNums.Count-1 do
|
|
begin
|
|
NLine:= NativeInt{%H-}(ListNums[i]);
|
|
DoCalcWrapInfos(NLine, NIndentMaximal, Items);
|
|
if Items.Count=0 then Continue;
|
|
|
|
FWrapInfo.FindIndexesOfLineNumber(NLine, NIndexFrom, NIndexTo);
|
|
if NIndexFrom<0 then
|
|
begin
|
|
//Showmessage('Cant find wrap-index for line '+Inttostr(NLine));
|
|
Continue;
|
|
end;
|
|
|
|
//slow for 100carets, 1M lines, so made method in which
|
|
//we can optimize it (instead of del/ins do assign)
|
|
FWrapInfo.ReplaceItems(NIndexFrom, NIndexTo, Items);
|
|
end;
|
|
end;
|
|
finally
|
|
FreeAndNil(ListNums);
|
|
FreeAndNil(Items);
|
|
end;
|
|
|
|
Strings.ListUpdates.Clear;
|
|
Strings.ListUpdatesHard:= false;
|
|
|
|
{$ifdef debug_findwrapindex}
|
|
DebugFindWrapIndex;
|
|
{$endif}
|
|
end;
|
|
|
|
|
|
procedure TATSynEdit.DoCalcWrapInfos(ALine: integer; AIndentMaximal: integer; AItems: TList);
|
|
var
|
|
NHiddenIndex, NOffset, NLen, NIndent, NVisColumns: integer;
|
|
NFinal: TATSynWrapFinal;
|
|
Str: atString;
|
|
begin
|
|
AItems.Clear;
|
|
|
|
NHiddenIndex:= Strings.LinesHidden[ALine, FEditorIndex];
|
|
if NHiddenIndex<0 then Exit;
|
|
|
|
Str:= Strings.Lines[ALine];
|
|
NLen:= Length(Str);
|
|
NVisColumns:= Max(GetVisibleColumns, cMinWrapColumnAbs);
|
|
|
|
//line collapsed partially?
|
|
if NHiddenIndex>0 then
|
|
begin
|
|
AItems.Add(TATSynWrapItem.Create(ALine, 1, Min(NLen, NHiddenIndex-1), 0, cWrapItemCollapsed));
|
|
Exit;
|
|
end;
|
|
|
|
//wrap not needed?
|
|
if (FWrapColumn<cMinWrapColumnAbs) then
|
|
begin
|
|
AItems.Add(TATSynWrapItem.Create(ALine, 1, NLen, 0, cWrapItemFinal));
|
|
Exit;
|
|
end;
|
|
|
|
NOffset:= 1;
|
|
NIndent:= 0;
|
|
|
|
repeat
|
|
NLen:= SFindWordWrapOffset(
|
|
//very slow to calc for entire line (eg len=70K),
|
|
//calc for first NVisColumns chars
|
|
Copy(Str, 1, NVisColumns),
|
|
Max(FWrapColumn-NIndent, cMinWrapColumnAbs),
|
|
FTabSize,
|
|
FOptWordChars,
|
|
FWrapIndented);
|
|
|
|
if NLen>=Length(Str) then
|
|
NFinal:= cWrapItemFinal
|
|
else
|
|
NFinal:= cWrapItemMiddle;
|
|
AItems.Add(TATSynWrapItem.Create(ALine, NOffset, NLen, NIndent, NFinal));
|
|
|
|
if FWrapIndented then
|
|
if NOffset=1 then
|
|
begin
|
|
NIndent:= SGetIndentExpanded(Str, FTabSize);
|
|
NIndent:= Min(NIndent, AIndentMaximal);
|
|
end;
|
|
|
|
Inc(NOffset, NLen);
|
|
Delete(Str, 1, NLen);
|
|
until Str='';
|
|
end;
|
|
|
|
function TATSynEdit.GetVisibleLines: integer;
|
|
begin
|
|
Result:= (FRectMain.Bottom-FRectMain.Top) div FCharSize.Y;
|
|
end;
|
|
|
|
function TATSynEdit.GetVisibleColumns: integer;
|
|
begin
|
|
Result:= (FRectMain.Right-FRectMain.Left) div FCharSize.X;
|
|
end;
|
|
|
|
function TATSynEdit.GetVisibleLinesMinimap: integer;
|
|
begin
|
|
Result:= (FRectMinimap.Bottom-FRectMinimap.Top) div FCharSizeMinimap.Y - 1;
|
|
end;
|
|
|
|
function TATSynEdit.GetMinimapScrollPos: integer;
|
|
begin
|
|
Result:=
|
|
Int64(FScrollVert.NPos) *
|
|
Max(0, FScrollVert.NMax-GetVisibleLinesMinimap) div
|
|
Max(1, FScrollVert.NMax-FScrollVert.NPage);
|
|
end;
|
|
|
|
procedure TATSynEdit.SetTabSize(AValue: integer);
|
|
begin
|
|
if FTabSize=AValue then Exit;
|
|
FTabSize:= Min(cMaxTabSize, Max(cMinTabSize, AValue));
|
|
FWrapUpdateNeeded:= true;
|
|
end;
|
|
|
|
procedure TATSynEdit.SetText(AValue: atString);
|
|
begin
|
|
Strings.LoadFromString(AValue);
|
|
DoCaretSingle(0, 0);
|
|
Update(true);
|
|
end;
|
|
|
|
procedure TATSynEdit.SetWrapMode(AValue: TATSynWrapMode);
|
|
var
|
|
NLine: integer;
|
|
begin
|
|
if FWrapMode=AValue then Exit;
|
|
|
|
NLine:= LineTop;
|
|
|
|
FWrapMode:= AValue;
|
|
FWrapUpdateNeeded:= true;
|
|
|
|
if FWrapMode<>cWrapOff then
|
|
FScrollHorz.NPos:= 0;
|
|
|
|
Invalidate;
|
|
AppProcessMessages;
|
|
LineTop:= NLine;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TATSynEdit.SetWrapIndented(AValue: boolean);
|
|
begin
|
|
if FWrapIndented=AValue then Exit;
|
|
FWrapIndented:=AValue;
|
|
if FWrapMode<>cWrapOff then
|
|
FWrapUpdateNeeded:= true;
|
|
end;
|
|
|
|
function TATSynEdit.UpdateScrollbars: boolean;
|
|
var
|
|
bVert1, bVert2,
|
|
bHorz1, bHorz2: boolean;
|
|
begin
|
|
Result:= false;
|
|
|
|
with FScrollVert do
|
|
begin
|
|
NPage:= Max(1, GetVisibleLines)-1;
|
|
NMin:= 0;
|
|
if FOptLastLineOnTop then
|
|
NMax:= Max(1, FWrapInfo.Count+NPage-1)
|
|
else
|
|
NMax:= Max(1, FWrapInfo.Count-1);
|
|
NPosLast:= Max(NMin, NMax-NPage);
|
|
end;
|
|
|
|
with FScrollHorz do
|
|
begin
|
|
NPage:= Max(1, GetVisibleColumns);
|
|
NMin:= 0;
|
|
//NMax calculated in DoPaintTextTo
|
|
//hide horz bar for word-wrap:
|
|
if FWrapMode=cWrapOn then
|
|
NMax:= NPage;
|
|
NPosLast:= Max(NMin, NMax-NPage);
|
|
end;
|
|
|
|
bVert1:= GetScrollbarVisible(true);
|
|
bHorz1:= GetScrollbarVisible(false);
|
|
UpdateScrollbarVert;
|
|
UpdateScrollbarHorz;
|
|
bVert2:= GetScrollbarVisible(true);
|
|
bHorz2:= GetScrollbarVisible(false);
|
|
Result:= (bVert1<>bVert2) or (bHorz1<>bHorz2);
|
|
|
|
if not IsEqualScrollInfo(FPrevHorz, FScrollHorz) or
|
|
not IsEqualScrollInfo(FPrevVert, FScrollVert) then
|
|
begin
|
|
FPrevHorz:= FScrollHorz;
|
|
FPrevVert:= FScrollVert;
|
|
DoEventScroll;
|
|
end;
|
|
end;
|
|
|
|
procedure TATSynEdit.UpdateScrollbarVert;
|
|
var
|
|
si: TScrollInfo;
|
|
begin
|
|
if not FOptAllowScrollbarVert then Exit;
|
|
|
|
FillChar(si{%H-}, SizeOf(si), 0);
|
|
si.cbSize:= SizeOf(si);
|
|
si.fMask:= SIF_ALL;// or SIF_DISABLENOSCROLL; //todo -- DisableNoScroll doesnt work(Win)
|
|
si.nMin:= FScrollVert.NMin;
|
|
si.nMax:= FScrollVert.NMax;
|
|
si.nPage:= FScrollVert.NPage;
|
|
si.nPos:= FScrollVert.NPos;
|
|
SetScrollInfo(Handle, SB_VERT, si, True);
|
|
end;
|
|
|
|
procedure TATSynEdit.UpdateScrollbarHorz;
|
|
var
|
|
si: TScrollInfo;
|
|
begin
|
|
if not FOptAllowScrollbarHorz then Exit;
|
|
|
|
FillChar(si{%H-}, SizeOf(si), 0);
|
|
si.cbSize:= SizeOf(si);
|
|
si.fMask:= SIF_ALL; //or SIF_DISABLENOSCROLL; don't work
|
|
si.nMin:= FScrollHorz.NMin;
|
|
si.nMax:= FScrollHorz.NMax;
|
|
si.nPage:= FScrollHorz.NPage;
|
|
si.nPos:= FScrollHorz.NPos;
|
|
SetScrollInfo(Handle, SB_HORZ, si, True);
|
|
end;
|
|
|
|
function TATSynEdit.GetRectMain: TRect;
|
|
begin
|
|
Result.Left:= FTextOffset.X;
|
|
Result.Top:= FTextOffset.Y;
|
|
Result.Right:= ClientWidth
|
|
- IfThen(FMinimapVisible, FMinimapWidth)
|
|
- IfThen(FMicromapVisible, FMicromapWidth);
|
|
Result.Bottom:= ClientHeight;
|
|
end;
|
|
|
|
function TATSynEdit.GetRectMinimap: TRect;
|
|
begin
|
|
if FMinimapVisible then
|
|
begin
|
|
Result.Left:= ClientWidth-FMinimapWidth-IfThen(FMicromapVisible, FMicromapWidth);
|
|
Result.Top:= 0;
|
|
Result.Right:= Result.Left+FMinimapWidth;
|
|
Result.Bottom:= ClientHeight;
|
|
end
|
|
else
|
|
Result:= cRectEmpty;
|
|
end;
|
|
|
|
function TATSynEdit.GetRectMinimapSel: TRect;
|
|
begin
|
|
Result.Left:= FRectMinimap.Left;
|
|
Result.Right:= FRectMinimap.Right;
|
|
Result.Top:= GetMinimapSelTop;
|
|
Result.Bottom:= Result.Top +
|
|
Min(
|
|
(FScrollVert.NPage+1)*FCharSizeMinimap.Y,
|
|
GetMinimapActualHeight
|
|
);
|
|
end;
|
|
|
|
function TATSynEdit.GetRectMicromap: TRect;
|
|
begin
|
|
if FMicromapVisible then
|
|
begin
|
|
Result.Left:= ClientWidth-FMicromapWidth;
|
|
Result.Top:= 0;
|
|
Result.Right:= ClientWidth;
|
|
Result.Bottom:= ClientHeight;
|
|
end
|
|
else
|
|
Result:= cRectEmpty;
|
|
end;
|
|
|
|
function TATSynEdit.GetRectGutter: TRect;
|
|
begin
|
|
if FOptGutterVisible then
|
|
begin
|
|
Result.Left:= 0;
|
|
Result.Top:= IfThen(FOptRulerVisible, FOptRulerSize);
|
|
Result.Right:= FGutter.Width;
|
|
Result.Bottom:= ClientHeight;
|
|
end
|
|
else
|
|
Result:= cRectEmpty;
|
|
end;
|
|
|
|
function TATSynEdit.GetRectRuler: TRect;
|
|
begin
|
|
if FOptRulerVisible then
|
|
begin
|
|
Result.Left:= 0;
|
|
Result.Right:= FRectMain.Right;
|
|
Result.Top:= 0;
|
|
Result.Bottom:= Result.Top+FOptRulerSize;
|
|
end
|
|
else
|
|
Result:= cRectEmpty;
|
|
end;
|
|
|
|
procedure TATSynEdit.DoPaintTo(C: TCanvas; ALineFrom: integer);
|
|
begin
|
|
if csLoading in ComponentState then Exit;
|
|
|
|
C.Brush.Color:= GetColorTextBG;
|
|
C.FillRect(ClientRect);
|
|
|
|
C.Font.Assign(Font);
|
|
FCharSize:= GetCharSize(C, FCharSpacingText);
|
|
|
|
if FOptGutterVisible and FOptNumbersAutosize then
|
|
UpdateGutterAutosize(C);
|
|
if FMinimapVisible then
|
|
UpdateMinimapAutosize(C);
|
|
|
|
FTextOffset:= GetTextOffset; //after gutter autosize
|
|
FRectMinimap:= GetRectMinimap;
|
|
FRectMicromap:= GetRectMicromap;
|
|
FRectGutter:= GetRectGutter;
|
|
FRectMain:= GetRectMain; //after gutter/minimap
|
|
FRectRuler:= GetRectRuler; //after main
|
|
|
|
UpdateWrapInfo;
|
|
|
|
DoPaintTextTo(C, FRectMain, FCharSize, FOptGutterVisible, true, FScrollHorz, FScrollVert, ALineFrom);
|
|
DoPaintMarginsTo(C);
|
|
DoPaintNiceScroll(C);
|
|
|
|
if FOptRulerVisible then
|
|
begin
|
|
DoPaintRulerTo(C);
|
|
if Assigned(FOnDrawRuler) then
|
|
FOnDrawRuler(Self, C, FRectRuler);
|
|
end;
|
|
|
|
if Assigned(FOnDrawEditor) then
|
|
FOnDrawEditor(Self, C, FRectMain);
|
|
|
|
if FMinimapVisible then
|
|
DoPaintMinimapTo(C);
|
|
if FMicromapVisible then
|
|
DoPaintMicromapTo(C);
|
|
end;
|
|
|
|
function TATSynEdit.GetCharSize(C: TCanvas; ACharSpacing: TPoint): TPoint;
|
|
var
|
|
Size: TPoint;
|
|
begin
|
|
Size:= CanvasFontSizes(C);
|
|
Result.X:= Max(1, Size.X + ACharSpacing.X);
|
|
Result.Y:= Max(1, Size.Y + ACharSpacing.Y);
|
|
end;
|
|
|
|
procedure TATSynEdit.DoPaintGutterBandBG(C: TCanvas; ABand: integer; AColor: TColor; ATop, ABottom: integer);
|
|
var
|
|
X1, X2: integer;
|
|
begin
|
|
with FGutter[ABand] do
|
|
begin X1:= Left; X2:= Right; end;
|
|
C.Brush.Color:= AColor;
|
|
if ATop>=0 then
|
|
C.FillRect(X1, ATop, X2, ABottom)
|
|
else
|
|
C.FillRect(X1, FRectGutter.Top, X2, FRectGutter.Bottom)
|
|
end;
|
|
|
|
procedure TATSynEdit.DoPaintTextTo(C: TCanvas;
|
|
const ARect: TRect;
|
|
const ACharSize: TPoint;
|
|
AWithGutter, AMainText: boolean;
|
|
var AScrollHorz, AScrollVert: TATSynScrollInfo;
|
|
ALineFrom: integer);
|
|
var
|
|
NCoordTop, NCoordSep: integer;
|
|
NWrapIndex, NLinesIndex: integer;
|
|
NOutputCharsSkipped, NOutputStrWidth: integer;
|
|
NOutputSpacesSkipped: real;
|
|
WrapItem: TATSynWrapItem;
|
|
NColorEntire, NColorAfter: TColor;
|
|
Str, StrOut, StrOutUncut: atString;
|
|
CurrPoint, CurrPointText, CoordAfterText, CoordNums: TPoint;
|
|
LineSeparator: TATLineSeparator;
|
|
LineWithCaret, LineEolSelected, LineColorForced: boolean;
|
|
Parts: TATLineParts;
|
|
Event: TATSynEditDrawLineEvent;
|
|
StrSize: TSize;
|
|
//
|
|
procedure DoPaintGutterBandState(ATop: integer; AColor: TColor);
|
|
begin
|
|
DoPaintGutterBandBG(C, FGutterBandState, AColor, ATop, ATop+ACharSize.Y);
|
|
end;
|
|
//
|
|
begin
|
|
//wrap turned off can cause bad scrollpos, fix it
|
|
with AScrollVert do
|
|
NPos:= Min(NPos, NPosLast);
|
|
|
|
C.Brush.Color:= GetColorTextBG;
|
|
C.FillRect(ARect);
|
|
|
|
if AWithGutter then
|
|
begin
|
|
C.Brush.Color:= FColors.GutterBG;
|
|
C.FillRect(FRectGutter);
|
|
|
|
//paint some bands, for full height coloring
|
|
if FGutter[FGutterBandFold].Visible then
|
|
DoPaintGutterBandBG(C, FGutterBandFold, FColors.GutterFoldBG, -1, -1);
|
|
if FGutter[FGutterBandSep].Visible then
|
|
DoPaintGutterBandBG(C, FGutterBandSep, FColors.GutterSeparatorBG, -1, -1);
|
|
if FGutter[FGutterBandEmpty].Visible then
|
|
DoPaintGutterBandBG(C, FGutterBandEmpty, GetColorTextBG, -1, -1);
|
|
end;
|
|
|
|
if AMainText and (FTextHint<>'') then
|
|
if (Strings.Count=0) or ((Strings.Count=1) and (Strings.Lines[0]='')) then
|
|
begin
|
|
DoPaintTextHintTo(C);
|
|
Exit
|
|
end;
|
|
|
|
{$ifndef fix_horzscroll}
|
|
AScrollHorz.NMax:= 1;
|
|
{$endif}
|
|
NCoordTop:= ARect.Top;
|
|
|
|
if ALineFrom>=0 then
|
|
begin
|
|
FWrapInfo.FindIndexesOfLineNumber(ALineFrom, NWrapIndex, NColorAfter{dummy});
|
|
AScrollVert.NPos:= NWrapIndex;
|
|
end
|
|
else
|
|
NWrapIndex:= AScrollVert.NPos;
|
|
|
|
DoEventBeforeCalcHilite;
|
|
|
|
repeat
|
|
if NCoordTop>ARect.Bottom then Break;
|
|
if not FWrapInfo.IsIndexValid(NWrapIndex) then Break;
|
|
|
|
WrapItem:= FWrapInfo.Items[NWrapIndex];
|
|
NLinesIndex:= WrapItem.NLineIndex;
|
|
if not Strings.IsIndexValid(NLinesIndex) then Break;
|
|
FLineBottom:= NLinesIndex;
|
|
|
|
if IsFoldLineNeededBeforeWrapitem(NWrapIndex) then
|
|
begin
|
|
NCoordSep:= NCoordTop-1;
|
|
C.Pen.Color:= Colors.CollapseLine;
|
|
C.Line(ARect.Left, NCoordSep, ARect.Right, NCoordSep);
|
|
end;
|
|
|
|
//prepare line
|
|
Str:= Strings.Lines[NLinesIndex];
|
|
Str:= Copy(Str, WrapItem.NCharIndex, WrapItem.NLength);
|
|
|
|
LineSeparator:= Strings.LinesSeparator[NLinesIndex];
|
|
LineWithCaret:= IsLineWithCaret(NLinesIndex);
|
|
LineEolSelected:= IsPosSelected(WrapItem.NCharIndex-1+WrapItem.NLength, WrapItem.NLineIndex);
|
|
|
|
StrOut:= Str;
|
|
StrOutUncut:= StrOut;
|
|
AScrollHorz.NMax:= Max(AScrollHorz.NMax,
|
|
Round(CanvasTextSpaces(StrOutUncut, FTabSize)) + cScrollKeepHorz);
|
|
|
|
CurrPoint.X:= ARect.Left;
|
|
CurrPoint.Y:= NCoordTop;
|
|
|
|
C.Brush.Color:= GetColorTextBG;
|
|
C.Font.Color:= GetColorTextFont;
|
|
|
|
DoCalcLineEntireColor(NLinesIndex, NCoordTop, LineWithCaret, NColorEntire, LineColorForced);
|
|
C.Brush.Color:= NColorEntire;
|
|
C.FillRect(ARect.Left, NCoordTop, ARect.Right, NCoordTop+ACharSize.Y);
|
|
|
|
CurrPointText:= Point(
|
|
Int64(CurrPoint.X) + (Int64(WrapItem.NIndent)-AScrollHorz.NPos)*ACharSize.X,
|
|
CurrPoint.Y);
|
|
NOutputStrWidth:= 0;
|
|
|
|
//paint line
|
|
if StrOut<>'' then
|
|
begin
|
|
NOutputCharsSkipped:= 0;
|
|
NOutputSpacesSkipped:= 0;
|
|
if FWrapInfo.IsItemInitial(NWrapIndex) then
|
|
begin
|
|
SFindOutputSkipOffset(StrOut, FTabSize, AScrollHorz.NPos, NOutputCharsSkipped, NOutputSpacesSkipped);
|
|
Delete(StrOut, 1, NOutputCharsSkipped);
|
|
Delete(StrOut, cMaxCharsForOutput, MaxInt);
|
|
Inc(CurrPointText.X, Trunc(NOutputSpacesSkipped*ACharSize.X));
|
|
end;
|
|
|
|
if WrapItem.NIndent>0 then
|
|
begin
|
|
NColorAfter:= GetColorTextBG;
|
|
DoCalcPosColor(WrapItem.NCharIndex, NLinesIndex, NColorAfter);
|
|
DoPaintLineIndent(C, ARect, ACharSize,
|
|
NCoordTop, WrapItem.NIndent,
|
|
NColorAfter,
|
|
AScrollHorz.NPos, AMainText and FOptShowIndentLines);
|
|
end;
|
|
|
|
NColorAfter:= clNone;
|
|
DoCalcLineHilite(WrapItem, Parts{%H-},
|
|
NOutputCharsSkipped, cMaxCharsForOutput,
|
|
NColorEntire, LineColorForced,
|
|
NColorAfter);
|
|
|
|
//adapter may return ColorAfterEol, paint it
|
|
if FOptShowFullHilite then
|
|
if NColorAfter<>clNone then
|
|
begin
|
|
C.Brush.Color:= NColorAfter;
|
|
C.FillRect(CurrPointText.X, NCoordTop, ARect.Right, NCoordTop+ACharSize.Y);
|
|
end;
|
|
|
|
//paint selection bg, after applying ColorAfterEol
|
|
DoPaintSelectedLineBG(C, ACharSize, ARect,
|
|
CurrPoint,
|
|
CurrPointText,
|
|
NLinesIndex,
|
|
LineEolSelected,
|
|
AScrollHorz);
|
|
|
|
if AWithGutter then
|
|
Event:= FOnDrawLine
|
|
else
|
|
Event:= nil;
|
|
|
|
if FUnprintedReplaceSpec then
|
|
StrOut:= SRemoveAsciiControlChars(StrOut);
|
|
|
|
if AMainText then
|
|
CanvasTextOut(C,
|
|
CurrPointText.X,
|
|
CurrPointText.Y,
|
|
StrOut,
|
|
FTabSize,
|
|
ACharSize,
|
|
AMainText,
|
|
AMainText and FUnprintedVisible and FUnprintedSpaces,
|
|
FColors.UnprintedFont,
|
|
FColors.UnprintedHexFont,
|
|
NOutputStrWidth,
|
|
Trunc(NOutputSpacesSkipped), //todo:
|
|
//needed number of chars of all chars counted as 1.0,
|
|
//while NOutputSpacesSkipped is with cjk counted as 1.7
|
|
@Parts,
|
|
Event,
|
|
FOptTextOffsetFromLine,
|
|
ClientWidth+ACharSize.X*2
|
|
)
|
|
else
|
|
CanvasTextOutMinimap(C,
|
|
StrOut,
|
|
CurrPointText,
|
|
FCharSizeMinimap,
|
|
FTabSize,
|
|
@Parts
|
|
);
|
|
|
|
//restore after textout
|
|
C.Font.Style:= Font.Style;
|
|
end
|
|
else
|
|
//paint empty line bg
|
|
begin
|
|
if FOptShowFullHilite then
|
|
begin
|
|
NColorAfter:= clNone;
|
|
DoCalcPosColor(0, NLinesIndex, NColorAfter);
|
|
if NColorAfter<>clNone then
|
|
begin
|
|
C.Brush.Color:= NColorAfter;
|
|
C.FillRect(ARect.Left, NCoordTop, ARect.Right, NCoordTop+ACharSize.Y);
|
|
end;
|
|
end;
|
|
|
|
DoPaintSelectedLineBG(C, ACharSize, ARect,
|
|
CurrPoint,
|
|
CurrPointText,
|
|
NLinesIndex,
|
|
LineEolSelected,
|
|
AScrollHorz);
|
|
end;
|
|
|
|
CoordAfterText:= Point(
|
|
CurrPointText.X+NOutputStrWidth,
|
|
CurrPointText.Y);
|
|
|
|
if WrapItem.NFinal=cWrapItemFinal then
|
|
begin
|
|
//for OptShowFullSel=false paint eol bg
|
|
if LineEolSelected then
|
|
begin
|
|
C.Brush.Color:= FColors.TextSelBG;
|
|
C.FillRect(
|
|
CoordAfterText.X,
|
|
CoordAfterText.Y,
|
|
CoordAfterText.X+ACharSize.X,
|
|
CoordAfterText.Y+ACharSize.Y);
|
|
end;
|
|
|
|
//paint eol mark
|
|
if AMainText and FUnprintedVisible and FUnprintedEnds then
|
|
DoPaintUnprintedEol(C,
|
|
cLineEndNiceNames[Strings.LinesEnds[WrapItem.NLineIndex]],
|
|
CoordAfterText,
|
|
ACharSize,
|
|
FColors.UnprintedFont,
|
|
FColors.UnprintedBG,
|
|
FUnprintedEndsDetails);
|
|
end;
|
|
|
|
//draw collapsed-mark
|
|
if AMainText then
|
|
if WrapItem.NFinal=cWrapItemCollapsed then
|
|
DoPaintFoldedMark(C,
|
|
Point(Strings.LinesHidden[NLinesIndex, FEditorIndex]-1, NLinesIndex),
|
|
CoordAfterText,
|
|
GetFoldedMarkText(NLinesIndex));
|
|
|
|
//draw separators
|
|
if LineSeparator<>cLineSepNone then
|
|
begin
|
|
if LineSeparator=cLineSepTop then
|
|
NCoordSep:= NCoordTop
|
|
else
|
|
NCoordSep:= NCoordTop+ACharSize.Y-1;
|
|
C.Pen.Color:= Colors.BlockSepLine;
|
|
C.Line(ARect.Left, NCoordSep, ARect.Right, NCoordSep);
|
|
end;
|
|
|
|
//draw gutter
|
|
if AWithGutter then
|
|
begin
|
|
//paint area over scrolled text
|
|
C.Brush.Color:= FColors.GutterBG;
|
|
C.FillRect(FRectGutter.Left, NCoordTop, FRectGutter.Right, NCoordTop+ACharSize.Y);
|
|
|
|
//gutter band: number
|
|
if FGutter[FGutterBandNum].Visible then
|
|
begin
|
|
if LineWithCaret and FOptShowGutterCaretBG then
|
|
DoPaintGutterBandBG(C, FGutterBandNum, FColors.GutterCaretBG, NCoordTop, NCoordTop+ACharSize.Y);
|
|
|
|
if FWrapInfo.IsItemInitial(NWrapIndex) then
|
|
begin
|
|
C.Font.Color:= FColors.GutterFont;
|
|
if FOptNumbersFontSize<>0 then
|
|
C.Font.Size:= FOptNumbersFontSize;
|
|
|
|
Str:= DoFormatLineNumber(NLinesIndex+1);
|
|
StrSize:= C.TextExtent(Str);
|
|
|
|
case FOptNumbersAlignment of
|
|
taLeftJustify: CoordNums.X:= FGutter[FGutterBandNum].Left + FOptNumbersIndentLeft;
|
|
taRightJustify: CoordNums.X:= FGutter[FGutterBandNum].Right - StrSize.cx - FOptNumbersIndentRight;
|
|
taCenter: CoordNums.X:= (FGutter[FGutterBandNum].Left + FGutter[FGutterBandNum].Right - StrSize.cx) div 2;
|
|
end;
|
|
|
|
if FOptNumbersFontSize=0 then
|
|
CoordNums.Y:= NCoordTop
|
|
else
|
|
CoordNums.Y:= NCoordTop + ACharSize.y div 2 - StrSize.cy div 2;
|
|
|
|
C.TextOut(CoordNums.X, CoordNums.Y, Str);
|
|
C.Font.Size:= Font.Size;
|
|
end;
|
|
end;
|
|
|
|
//gutter band: bookmark
|
|
if FGutter[FGutterBandBm].Visible then
|
|
if FWrapInfo.IsItemInitial(NWrapIndex) then
|
|
begin
|
|
if Strings.LinesBm[NLinesIndex]<>0 then
|
|
DoEventDrawBookmarkIcon(C, NLinesIndex,
|
|
Rect(
|
|
FGutter[FGutterBandBm].Left,
|
|
NCoordTop,
|
|
FGutter[FGutterBandBm].Right,
|
|
NCoordTop+ACharSize.Y
|
|
));
|
|
end;
|
|
|
|
//gutter band: fold
|
|
if FGutter[FGutterBandFold].Visible then
|
|
begin
|
|
DoPaintGutterBandBG(C, FGutterBandFold, FColors.GutterFoldBG, NCoordTop, NCoordTop+ACharSize.Y);
|
|
DoPaintGutterFolding(C,
|
|
NWrapIndex,
|
|
FGutter[FGutterBandFold].Left,
|
|
FGutter[FGutterBandFold].Right,
|
|
NCoordTop,
|
|
NCoordTop+ACharSize.Y
|
|
);
|
|
end;
|
|
|
|
//gutter band: state
|
|
if FGutter[FGutterBandState].Visible then
|
|
begin
|
|
case Strings.LinesState[NLinesIndex] of
|
|
cLineStateChanged: DoPaintGutterBandState(NCoordTop, FColors.StateChanged);
|
|
cLineStateAdded: DoPaintGutterBandState(NCoordTop, FColors.StateAdded);
|
|
cLineStateSaved: DoPaintGutterBandState(NCoordTop, FColors.StateSaved);
|
|
end;
|
|
end;
|
|
|
|
//gutter band: separator
|
|
if FGutter[FGutterBandSep].Visible then
|
|
DoPaintGutterBandBG(C, FGutterBandSep, FColors.GutterSeparatorBG, NCoordTop, NCoordTop+ACharSize.Y);
|
|
//gutter band: empty indent
|
|
if FGutter[FGutterBandEmpty].Visible then
|
|
DoPaintGutterBandBG(C, FGutterBandEmpty, GetColorTextBG, NCoordTop, NCoordTop+ACharSize.Y);
|
|
end;
|
|
|
|
//end of painting line
|
|
Inc(NCoordTop, ACharSize.Y);
|
|
Inc(NWrapIndex);
|
|
until false;
|
|
|
|
//staples
|
|
if AMainText then
|
|
DoPaintStaples(C, ARect, ACharSize, AScrollHorz);
|
|
end;
|
|
|
|
function TATSynEdit.GetMinimapSelTop: integer;
|
|
begin
|
|
Result:= FRectMinimap.Top + (FScrollVert.NPos-FScrollVertMinimap.NPos)*FCharSizeMinimap.Y;
|
|
end;
|
|
|
|
function TATSynEdit.GetMinimapActualHeight: integer;
|
|
begin
|
|
Result:=
|
|
Max(2, Min(
|
|
FRectMinimap.Bottom-FRectMinimap.Top,
|
|
FWrapInfo.Count*FCharSizeMinimap.Y
|
|
));
|
|
end;
|
|
|
|
function TATSynEdit.GetMinimapSelTop_PixelsToWrapIndex(APixels: integer): integer;
|
|
var
|
|
Percent: double;
|
|
const
|
|
PercentFix: double = 0.02;
|
|
begin
|
|
{
|
|
1) calculate percent position of mouse
|
|
2) must correct this! we must scroll to 0 if almost at the top;
|
|
must scroll to end if almost at the end - do this by increment n%
|
|
}
|
|
Percent:= (APixels-FRectMinimap.Top) / GetMinimapActualHeight;
|
|
|
|
if Percent<0.1 then Percent:= Max(0.0, Percent-PercentFix) else
|
|
if Percent>0.9 then Percent:= Min(100.0, Percent+PercentFix);
|
|
|
|
Result:= Round(Percent * FWrapInfo.Count);
|
|
end;
|
|
|
|
procedure TATSynEdit.DoPaintMinimapSelTo(C: TCanvas);
|
|
var
|
|
R: TRect;
|
|
begin
|
|
if not FMinimapShowSelAlways then
|
|
if not FCursorOnMinimap then Exit;
|
|
|
|
R:= GetRectMinimapSel;
|
|
if IntersectRect(R, R, FRectMinimap) then
|
|
begin
|
|
CanvasInvertRect(C, R, FColors.MinimapSelBG);
|
|
if FMinimapShowSelBorder then
|
|
begin
|
|
C.Pen.Color:= FColors.MinimapBorder;
|
|
C.Brush.Style:= bsClear;
|
|
C.Rectangle(R);
|
|
C.Brush.Style:= bsSolid;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TATSynEdit.DoPaintMinimapTo(C: TCanvas);
|
|
begin
|
|
DoClearScrollInfo(FScrollHorzMinimap);
|
|
DoClearScrollInfo(FScrollVertMinimap);
|
|
|
|
FScrollVertMinimap.NPos:= GetMinimapScrollPos;
|
|
FScrollVertMinimap.NPosLast:= MaxInt div 2;
|
|
DoPaintTextTo(C, FRectMinimap, FCharSizeMinimap, false, false, FScrollHorzMinimap, FScrollVertMinimap, -1);
|
|
|
|
DoPaintMinimapSelTo(C);
|
|
|
|
if FColors.MinimapBorder<>clNone then
|
|
begin
|
|
C.Pen.Color:= FColors.MinimapBorder;
|
|
C.Line(FRectMinimap.Left-1, FRectMinimap.Top,
|
|
FRectMinimap.Left-1, FRectMinimap.Bottom);
|
|
end;
|
|
end;
|
|
|
|
procedure TATSynEdit.DoPaintMicromapTo(C: TCanvas);
|
|
begin
|
|
if Assigned(FOnDrawMicromap) then
|
|
FOnDrawMicromap(Self, C, FRectMicromap)
|
|
else
|
|
begin
|
|
C.Brush.Color:= clCream;
|
|
C.FillRect(FRectMicromap);
|
|
end;
|
|
end;
|
|
|
|
procedure TATSynEdit.DoPaintMarginLineTo(C: TCanvas; AX: integer; AColor: TColor);
|
|
begin
|
|
if (AX>=FRectMain.Left) and (AX<FRectMain.Right) then
|
|
begin
|
|
C.Pen.Color:= AColor;
|
|
C.Line(AX, FRectMain.Top,
|
|
AX, FRectMain.Bottom);
|
|
end;
|
|
end;
|
|
|
|
procedure TATSynEdit.DoPaintMarginsTo(C: TCanvas);
|
|
//
|
|
function PosX(NMargin: integer): integer;
|
|
begin
|
|
Result:= FRectMain.Left + FCharSize.X*(NMargin-FScrollHorz.NPos);
|
|
end;
|
|
var
|
|
i: integer;
|
|
begin
|
|
if FMarginRight>1 then
|
|
DoPaintMarginLineTo(C, PosX(FMarginRight), FColors.MarginRight);
|
|
for i:= 0 to FMarginList.Count-1 do
|
|
DoPaintMarginLineTo(C, PosX(NativeInt{%H-}(FMarginList[i])), FColors.MarginUser);
|
|
end;
|
|
|
|
|
|
procedure TATSynEdit.DoPaintFoldedMark(C: TCanvas;
|
|
APos: TPoint; ACoord: TPoint; const AMarkText: string);
|
|
var
|
|
NWidth: integer;
|
|
Str: string;
|
|
begin
|
|
Str:= STabsToSpaces(AMarkText, FTabSize);
|
|
Inc(ACoord.X, cFoldedMarkIndentOuter);
|
|
|
|
//set colors:
|
|
//if 1st chars selected, then use selection-color
|
|
if IsPosSelected(APos.X, APos.Y) then
|
|
begin
|
|
C.Font.Color:= Colors.TextSelFont;
|
|
C.Brush.Color:= Colors.TextSelBG;
|
|
end
|
|
else
|
|
begin
|
|
C.Font.Color:= Colors.CollapseMarkFont;
|
|
C.Brush.Color:= Colors.CollapseMarkBG;
|
|
end;
|
|
|
|
//paint text
|
|
C.TextOut(
|
|
ACoord.X+cFoldedMarkIndentInner,
|
|
ACoord.Y+FOptTextOffsetFromLine,
|
|
Str);
|
|
NWidth:= C.TextWidth(Str) + 2*cFoldedMarkIndentInner;
|
|
|
|
//paint frame
|
|
C.Pen.Color:= FColors.CollapseMarkBorder;
|
|
C.Brush.Style:= bsClear;
|
|
C.Rectangle(ACoord.X, ACoord.Y, ACoord.X+NWidth, ACoord.Y+FCharSize.Y);
|
|
C.Brush.Style:= bsSolid;
|
|
end;
|
|
|
|
function TATSynEdit.GetCharSpacingX: integer;
|
|
begin
|
|
Result:= FCharSpacingText.X;
|
|
end;
|
|
|
|
function TATSynEdit.GetCharSpacingY: integer;
|
|
begin
|
|
Result:= FCharSpacingText.Y;
|
|
end;
|
|
|
|
function TATSynEdit.GetMarginString: string;
|
|
var
|
|
i: integer;
|
|
begin
|
|
Result:= '';
|
|
for i:= 0 to FMarginList.Count-1 do
|
|
Result:= Result+IntToStr(NativeInt{%H-}(FMarginList[i]))+' ';
|
|
end;
|
|
|
|
function TATSynEdit.GetReadOnly: boolean;
|
|
begin
|
|
Result:= Strings.ReadOnly;
|
|
end;
|
|
|
|
function TATSynEdit.GetLineTop: integer;
|
|
var
|
|
Item: TATSynWrapItem;
|
|
begin
|
|
Result:= 0;
|
|
Item:= FWrapInfo.Items[FScrollVert.NPos];
|
|
if Assigned(Item) then
|
|
Result:= Item.NLineIndex;
|
|
end;
|
|
|
|
constructor TATSynEdit.Create(AOwner: TComponent);
|
|
var
|
|
i: integer;
|
|
begin
|
|
inherited;
|
|
|
|
Caption:= '';
|
|
ControlStyle:= ControlStyle+[csOpaque, csDoubleClicks, csTripleClicks];
|
|
BorderStyle:= bsNone;
|
|
TabStop:= true;
|
|
|
|
Width:= 300;
|
|
Height:= 200;
|
|
Font.Name:= 'Courier New';
|
|
Font.Size:= {$ifndef darwin} 9 {$else} 14 {$endif};
|
|
|
|
FWantTabs:= true;
|
|
FCharSize:= Point(4, 4); //not nul
|
|
FEditorIndex:= 0;
|
|
|
|
FCarets:= TATCarets.Create;
|
|
FCarets.Add(0, 0);
|
|
FCaretBlinkEnabled:= true;
|
|
FCaretShown:= false;
|
|
FCaretShapeIns:= cInitCaretShapeIns;
|
|
FCaretShapeOvr:= cInitCaretShapeOvr;
|
|
FCaretShapeRO:= cInitCaretShapeRO;
|
|
FCaretVirtual:= true;
|
|
FCaretSpecPos:= false;
|
|
FCaretStopUnfocused:= true;
|
|
|
|
FMarkers:= TATMarkers.Create;
|
|
FAttribs:= TATMarkers.Create;
|
|
FMarkedRange:= TATMarkers.Create;
|
|
|
|
{$ifdef test_markedrange}
|
|
DoSetMarkedRange(1, 3);
|
|
{$endif}
|
|
{$ifdef test_attribs}
|
|
DoDebugAddAttribs;
|
|
{$endif}
|
|
|
|
FPaintLocked:= 0;
|
|
FPaintStatic:= false;
|
|
FPaintFlags:= [cPaintUpdateBitmap, cPaintUpdateScrollbars];
|
|
|
|
FColors:= TATSynEditColors.Create;
|
|
InitDefaultColors(FColors);
|
|
|
|
FCursorText:= crIBeam;
|
|
FCursorBm:= crHandPoint;
|
|
|
|
FTimerBlink:= TTimer.Create(Self);
|
|
FTimerBlink.Interval:= cInitTimerBlink;
|
|
FTimerBlink.OnTimer:= @TimerBlinkTick;
|
|
FTimerBlink.Enabled:= true;
|
|
|
|
FTimerScroll:= TTimer.Create(Self);
|
|
FTimerScroll.Interval:= cInitTimerAutoScroll;
|
|
FTimerScroll.OnTimer:= @TimerScrollTick;
|
|
FTimerScroll.Enabled:= false;
|
|
|
|
FTimerNiceScroll:= TTimer.Create(Self);
|
|
FTimerNiceScroll.Interval:= cInitTimerNiceScroll;
|
|
FTimerNiceScroll.OnTimer:= @TimerNiceScrollTick;
|
|
FTimerNiceScroll.Enabled:= false;
|
|
|
|
FBitmap:= Graphics.TBitmap.Create;
|
|
FBitmap.PixelFormat:= pf24bit;
|
|
FBitmap.Width:= cInitBitmapWidth;
|
|
FBitmap.Height:= cInitBitmapHeight;
|
|
|
|
FStringsExternal:= nil;
|
|
FStringsInt:= TATStrings.Create;
|
|
FStringsInt.OnGetCaretsArray:= @GetCaretsArray;
|
|
FStringsInt.OnSetCaretsArray:= @SetCaretsArray;
|
|
|
|
FFold:= TATSynRanges.Create;
|
|
FFoldStyle:= cInitFoldStyle;
|
|
|
|
FWrapInfo:= TATSynWrapInfo.Create;
|
|
FWrapInfo.OnCheckLineCollapsed:= @IsLineFoldedFull;
|
|
FWrapUpdateNeeded:= true;
|
|
FWrapMode:= cWrapOn;
|
|
FWrapColumn:= cInitMarginRight;
|
|
FWrapIndented:= true;
|
|
//FWrapProgress:= 0;
|
|
|
|
FOverwrite:= false;
|
|
FTabSize:= cInitTabSize;
|
|
FMarginRight:= cInitMarginRight;
|
|
FMarginList:= TList.Create;
|
|
|
|
FUnprintedVisible:= true;
|
|
FUnprintedSpaces:= true;
|
|
FUnprintedEnds:= true;
|
|
FUnprintedEndsDetails:= true;
|
|
FUnprintedReplaceSpec:= true;
|
|
|
|
FTextLocked:= 'wait...';
|
|
FTextHint:= '';
|
|
FTextHintFontStyle:= [fsItalic];
|
|
FTextHintCenter:= false;
|
|
|
|
FGutter:= TATGutter.Create;
|
|
FOptGutterVisible:= true;
|
|
FOptGutterPlusSize:= cInitGutterPlusSize;
|
|
FOptGutterShowFoldAlways:= true;
|
|
FOptGutterShowFoldLines:= true;
|
|
FOptGutterShowFoldLinesAll:= false;
|
|
|
|
FGutterBandBm:= 0;
|
|
FGutterBandNum:= 1;
|
|
FGutterBandState:= 2;
|
|
FGutterBandFold:= 3;
|
|
FGutterBandSep:= 4;
|
|
FGutterBandEmpty:= 5;
|
|
|
|
for i:= 1 to cGutterBands do
|
|
FGutter.Add(10);
|
|
FGutter[FGutterBandBm].Size:= cGutterSizeBm;
|
|
FGutter[FGutterBandNum].Size:= cGutterSizeNum;
|
|
FGutter[FGutterBandState].Size:= cGutterSizeState;
|
|
FGutter[FGutterBandFold].Size:= cGutterSizeFold;
|
|
FGutter[FGutterBandSep].Size:= cGutterSizeSep;
|
|
FGutter[FGutterBandEmpty].Size:= cGutterSizeEmpty;
|
|
FGutter[FGutterBandSep].Visible:= false;
|
|
FGutter.Update;
|
|
|
|
FOptNumbersAutosize:= true;
|
|
FOptNumbersAlignment:= taRightJustify;
|
|
FOptNumbersFontSize:= 0;
|
|
FOptNumbersStyle:= cInitNumbersStyle;
|
|
FOptNumbersShowFirst:= true;
|
|
FOptNumbersShowCarets:= false;
|
|
FOptNumbersSkippedChar:= '.';
|
|
FOptNumbersIndentLeft:= 5;
|
|
FOptNumbersIndentRight:= 5;
|
|
|
|
FOptRulerVisible:= true;
|
|
FOptRulerSize:= cSizeRulerHeight;
|
|
FOptRulerMarkSizeSmall:= cSizeRulerMarkSmall;
|
|
FOptRulerMarkSizeBig:= cSizeRulerMarkBig;
|
|
FOptRulerFontSize:= 8;
|
|
FOptRulerTextIndent:= 0;
|
|
|
|
FMinimapWidth:= cInitMinimapWidth;
|
|
FMinimapCharWidth:= 0;
|
|
FMinimapVisible:= cInitMinimapVisible;
|
|
FMinimapShowSelBorder:= false;
|
|
FMinimapShowSelAlways:= true;
|
|
FMicromapWidth:= cInitMicromapWidth;
|
|
FMicromapVisible:= cInitMicromapVisible;
|
|
|
|
FCharSpacingText:= Point(0, cInitSpacingText);
|
|
FCharSizeMinimap:= Point(1, 2);
|
|
|
|
FOptShowStapleStyle:= cLineStyleSolid;
|
|
FOptShowStapleIndent:= -1;
|
|
FOptShowStapleWidthPercent:= 100;
|
|
|
|
FOptMaxLinesToCountUnindent:= 100;
|
|
FOptTextOffsetTop:= 0;
|
|
FOptTextOffsetFromLine:= cInitTextOffsetFromLine;
|
|
FOptAllowScrollbarVert:= true;
|
|
FOptAllowScrollbarHorz:= true;
|
|
FOptAllowZooming:= true;
|
|
FOptAllowReadOnly:= true;
|
|
FOptKeyBackspaceUnindent:= true;
|
|
FOptKeyPageKeepsRelativePos:= true;
|
|
FOptKeyUpDownNavigateWrapped:= true;
|
|
FOptKeyHomeEndNavigateWrapped:= true;
|
|
FOptKeyUpDownKeepColumn:= true;
|
|
FOptOverwriteAllowedOnPaste:= false;
|
|
FOptWordChars:= '';
|
|
FOptAutoIndent:= true;
|
|
FOptAutoIndentKind:= cIndentAsIs;
|
|
FOptTabSpaces:= false;
|
|
|
|
FOptLastLineOnTop:= false;
|
|
FOptOverwriteSel:= true;
|
|
FOptMouseDragDrop:= true;
|
|
FOptMouseNiceScroll:= true;
|
|
FOptMouseHideCursor:= false;
|
|
FOptMouse2ClickSelectsLine:= false;
|
|
FOptMouse3ClickSelectsLine:= true;
|
|
FOptMouse2ClickDragSelectsWords:= true;
|
|
FOptMouseRightClickMovesCaret:= false;
|
|
FOptMouseGutterClickSelectsLine:= true;
|
|
FOptCopyLinesIfNoSel:= true;
|
|
FOptCutLinesIfNoSel:= false;
|
|
FOptShowFullSel:= false;
|
|
FOptShowFullHilite:= true;
|
|
FOptShowCurLine:= false;
|
|
FOptShowCurLineMinimal:= true;
|
|
FOptShowCurColumn:= false;
|
|
FOptKeyPageUpDownSize:= cPageSizeFullMinus1;
|
|
FOptKeyLeftRightSwapSel:= true;
|
|
FOptKeyLeftRightSwapSelAndSelect:= false;
|
|
FOptKeyHomeToNonSpace:= true;
|
|
FOptKeyEndToNonSpace:= true;
|
|
FOptKeyTabIndents:= true;
|
|
FOptShowIndentLines:= true;
|
|
FOptShowGutterCaretBG:= true;
|
|
FOptIndentSize:= 2;
|
|
FOptIndentKeepsAlign:= true;
|
|
FOptUndoGrouped:= true;
|
|
FOptSavingForceFinalEol:= false;
|
|
FOptSavingTrimSpaces:= false;
|
|
FOptShowScrollHint:= false;
|
|
FOptCaretPreferLeftSide:= true;
|
|
FOptMarkersSize:= 4;
|
|
FOptMouseDownForPopup:= false;
|
|
FOptMouseEnableNormalSelection:= true;
|
|
FOptMouseEnableColumnSelection:= true;
|
|
|
|
FMouseDownPnt:= Point(-1, -1);
|
|
FMouseDownNumber:= -1;
|
|
FMouseDownDouble:= false;
|
|
FMouseDownRight:= false;
|
|
FMouseDragDropping:= false;
|
|
FMouseNiceScrollPos:= Point(0, 0);
|
|
|
|
FSelRect:= cRectEmpty;
|
|
FCursorOnMinimap:= false;
|
|
FCursorOnGutter:= false;
|
|
FLastTextCmd:= 0;
|
|
FLastTextCmdText:= '';
|
|
|
|
DoClearScrollInfo(FScrollHorz);
|
|
DoClearScrollInfo(FScrollVert);
|
|
|
|
FKeymap:= KeymapFull;
|
|
FHintWnd:= THintWindow.Create(Self);
|
|
|
|
FMenuStd:= TPopupMenu.Create(Self);
|
|
FMenuText:= nil;
|
|
FMenuGutterBm:= nil;
|
|
FMenuGutterNum:= nil;
|
|
FMenuGutterFold:= nil;
|
|
FMenuGutterFoldStd:= nil;
|
|
FMenuMinimap:= nil;
|
|
FMenuMicromap:= nil;
|
|
FMenuRuler:= nil;
|
|
|
|
DoInitPopupMenu;
|
|
end;
|
|
|
|
destructor TATSynEdit.Destroy;
|
|
begin
|
|
FreeAndNil(FHintWnd);
|
|
FreeAndNil(FMenuStd);
|
|
DoPaintModeStatic;
|
|
FreeAndNil(FFold);
|
|
FreeAndNil(FTimerNiceScroll);
|
|
FreeAndNil(FTimerScroll);
|
|
FreeAndNil(FTimerBlink);
|
|
FreeAndNil(FCarets);
|
|
FreeAndNil(FMarkedRange);
|
|
FreeAndNil(FMarkers);
|
|
FreeAndNil(FAttribs);
|
|
FreeAndNil(FGutter);
|
|
FreeAndNil(FMarginList);
|
|
FreeAndNil(FWrapInfo);
|
|
FreeAndNil(FStringsInt);
|
|
FreeAndNil(FBitmap);
|
|
FreeAndNil(FColors);
|
|
inherited;
|
|
end;
|
|
|
|
procedure TATSynEdit.Update(
|
|
AUpdateWrapInfo: boolean = false;
|
|
AUpdateCaretsCoords: boolean = true);
|
|
begin
|
|
UpdateCursor;
|
|
if AUpdateWrapInfo then
|
|
FWrapUpdateNeeded:= true;
|
|
Include(FPaintFlags, cPaintUpdateScrollbars);
|
|
if AUpdateCaretsCoords then
|
|
Include(FPaintFlags, cPaintUpdateCaretsCoords);
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TATSynEdit.SetFocus;
|
|
begin
|
|
LCLIntf.SetFocus(Handle);
|
|
end;
|
|
|
|
procedure TATSynEdit.LoadFromFile(const AFilename: string);
|
|
begin
|
|
DoPaintModeStatic;
|
|
|
|
FCarets.Clear;
|
|
FCarets.Add(0, 0);
|
|
|
|
Strings.Clear;
|
|
FWrapInfo.Clear;
|
|
FWrapUpdateNeeded:= true;
|
|
|
|
DoClearScrollInfo(FScrollHorz);
|
|
DoClearScrollInfo(FScrollVert);
|
|
|
|
BeginUpdate;
|
|
//show "wait" text
|
|
Strings.Clear;
|
|
Update(true);
|
|
AppProcessMessages;
|
|
|
|
try
|
|
Strings.LoadFromFile(AFilename);
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
|
|
Update;
|
|
DoPaintModeBlinking;
|
|
DoEventChange;
|
|
DoEventCarets;
|
|
|
|
{$ifdef test_foldlist}
|
|
DoDebugInitFoldList;
|
|
{$endif}
|
|
end;
|
|
|
|
procedure TATSynEdit.SaveToFile(const AFilename: string);
|
|
var
|
|
Change1, Change2: boolean;
|
|
begin
|
|
Change1:= false;
|
|
Change2:= false;
|
|
|
|
if FOptSavingForceFinalEol then
|
|
Change1:= Strings.ActionEnsureFinalEol;
|
|
if FOptSavingTrimSpaces then
|
|
Change2:= Strings.ActionTrimSpaces(cTrimRight);
|
|
if Change1 or Change2 then
|
|
Update(true);
|
|
|
|
Strings.SaveToFile(AFilename);
|
|
DoEventState; //modified
|
|
Update;
|
|
end;
|
|
|
|
|
|
function TATSynEdit.GetStrings: TATStrings;
|
|
begin
|
|
if Assigned(FStringsExternal) then
|
|
Result:= FStringsExternal
|
|
else
|
|
Result:= FStringsInt;
|
|
end;
|
|
|
|
procedure TATSynEdit.SetCaretBlinkTime(AValue: integer);
|
|
begin
|
|
AValue:= Max(AValue, cMinCaretTime);
|
|
AValue:= Min(AValue, cMaxCaretTime);
|
|
FTimerBlink.Interval:= AValue;
|
|
end;
|
|
|
|
procedure TATSynEdit.SetCharSpacingX(AValue: integer);
|
|
begin
|
|
if FCharSpacingText.X=AValue then Exit;
|
|
FCharSpacingText.X:= AValue;
|
|
FWrapUpdateNeeded:= true;
|
|
end;
|
|
|
|
procedure TATSynEdit.SetCharSpacingY(AValue: integer);
|
|
begin
|
|
if FCharSpacingText.Y=AValue then Exit;
|
|
FCharSpacingText.Y:= AValue;
|
|
FWrapUpdateNeeded:= true;
|
|
end;
|
|
|
|
procedure TATSynEdit.SetMarginString(AValue: string);
|
|
var
|
|
S: string;
|
|
N: integer;
|
|
begin
|
|
FMarginList.Clear;
|
|
repeat
|
|
S:= SGetItem(AValue, ' ');
|
|
if S='' then Break;
|
|
N:= StrToIntDef(S, 0);
|
|
if N<2 then Continue;
|
|
FMarginList.Add(pointer{%H-}(N));
|
|
until false;
|
|
end;
|
|
|
|
procedure TATSynEdit.SetMicromapVisible(AValue: boolean);
|
|
begin
|
|
if FMicromapVisible=AValue then Exit;
|
|
FMicromapVisible:= AValue;
|
|
FWrapUpdateNeeded:= true;
|
|
end;
|
|
|
|
procedure TATSynEdit.SetMinimapVisible(AValue: boolean);
|
|
begin
|
|
if FMinimapVisible=AValue then Exit;
|
|
FMinimapVisible:= AValue;
|
|
FWrapUpdateNeeded:= true;
|
|
end;
|
|
|
|
procedure TATSynEdit.SetOneLine(AValue: boolean);
|
|
begin
|
|
Strings.OneLine:= AValue;
|
|
Carets.OneLine:= AValue;
|
|
if AValue then
|
|
begin
|
|
OptGutterVisible:= false;
|
|
OptRulerVisible:= false;
|
|
OptMinimapVisible:= false;
|
|
OptMicromapVisible:= false;
|
|
OptCaretVirtual:= false;
|
|
OptCaretManyAllowed:= false;
|
|
OptUnprintedVisible:= false;
|
|
OptWrapMode:= cWrapOff;
|
|
OptAllowScrollbarVert:= false;
|
|
OptAllowScrollbarHorz:= false;
|
|
OptAllowZooming:= false;
|
|
OptAllowReadOnly:= false;
|
|
OptMouseNiceScroll:= false;
|
|
OptMouseDragDrop:= false;
|
|
OptMarginRight:= 1000;
|
|
OptUndoLimit:= 200;
|
|
end;
|
|
end;
|
|
|
|
procedure TATSynEdit.SetReadOnly(AValue: boolean);
|
|
begin
|
|
if not FOptAllowReadOnly then Exit;
|
|
Strings.ReadOnly:= AValue;
|
|
end;
|
|
|
|
procedure TATSynEdit.SetLineTop(AValue: integer);
|
|
var
|
|
NFrom, NTo, i: integer;
|
|
begin
|
|
//find exact match
|
|
FWrapInfo.FindIndexesOfLineNumber(AValue, NFrom, NTo);
|
|
if NFrom>=0 then
|
|
begin
|
|
FScrollVert.NPos:= NFrom;
|
|
Update;
|
|
Exit
|
|
end;
|
|
|
|
//find approx match
|
|
for i:= 0 to FWrapInfo.Count-1 do
|
|
with FWrapInfo.Items[i] do
|
|
if NLineIndex>=AValue then
|
|
begin
|
|
FScrollVert.NPos:= i;
|
|
Update;
|
|
Exit
|
|
end;
|
|
end;
|
|
|
|
procedure TATSynEdit.SetLinesFromTop(AValue: integer);
|
|
begin
|
|
with FScrollVert do
|
|
NPos:= Max(0, NPos + (GetLinesFromTop - AValue));
|
|
end;
|
|
|
|
procedure TATSynEdit.SetStrings(Obj: TATStrings);
|
|
begin
|
|
FStringsExternal:= Obj;
|
|
end;
|
|
|
|
function TATSynEdit.GetTextOffset: TPoint;
|
|
begin
|
|
Result.X:= 0;
|
|
if FOptGutterVisible then
|
|
Inc(Result.X, FGutter.Width);
|
|
|
|
Result.Y:= FOptTextOffsetTop;
|
|
if FOptRulerVisible then
|
|
Inc(Result.Y, FOptRulerSize);
|
|
end;
|
|
|
|
function TATSynEdit.GetGutterNumbersWidth(C: TCanvas): integer;
|
|
var
|
|
Str: atString;
|
|
CharSize: integer;
|
|
begin
|
|
if FOptNumbersFontSize<>0 then
|
|
C.Font.Size:= FOptNumbersFontSize;
|
|
CharSize:= C.TextWidth('0');
|
|
|
|
Str:= IntToStr(Max(10, Strings.Count));
|
|
Result:=
|
|
Length(Str)*CharSize+
|
|
FOptNumbersIndentLeft+
|
|
FOptNumbersIndentRight;
|
|
|
|
if FOptNumbersFontSize<>0 then
|
|
C.Font.Size:= Font.Size;
|
|
end;
|
|
|
|
function TATSynEdit.GetPageLines: integer;
|
|
begin
|
|
case FOptKeyPageUpDownSize of
|
|
cPageSizeFull: Result:= GetVisibleLines;
|
|
cPageSizeFullMinus1: Result:= GetVisibleLines-1;
|
|
cPageSizeHalf: Result:= GetVisibleLines div 2;
|
|
else
|
|
raise Exception.Create('Unknown pagesize');
|
|
end;
|
|
end;
|
|
|
|
function TATSynEdit.DoPaint(AFlags: TATSynPaintFlags; ALineFrom: integer): boolean;
|
|
var
|
|
ARect: TRect;
|
|
begin
|
|
Result:= false;
|
|
if not Assigned(FBitmap) then Exit;
|
|
|
|
if cPaintUpdateBitmap in AFlags then
|
|
begin
|
|
DoPaintTo(FBitmap.Canvas, ALineFrom);
|
|
|
|
if cPaintUpdateCaretsCoords in AFlags then
|
|
begin
|
|
UpdateCaretsCoords;
|
|
//paint margin
|
|
if FOptShowCurColumn and (Carets.Count>0) then
|
|
DoPaintMarginLineTo(FBitmap.Canvas, Carets[0].CoordX, FColors.MarginCaret);
|
|
end;
|
|
|
|
//paint markers after calc carets
|
|
DoPaintMarkersTo(FBitmap.Canvas);
|
|
|
|
FCaretShown:= false;
|
|
DoPaintCarets(FBitmap.Canvas, false);
|
|
end;
|
|
|
|
ARect:= Canvas.ClipRect;
|
|
Canvas.CopyRect(ARect, FBitmap.Canvas, ARect);
|
|
|
|
if cPaintUpdateScrollbars in AFlags then
|
|
Result:= UpdateScrollbars;
|
|
end;
|
|
|
|
procedure TATSynEdit.DoPaintLockedWarning(C: TCanvas);
|
|
var
|
|
Str: string;
|
|
begin
|
|
C.Brush.Color:= Colors.LockedBG;
|
|
C.FillRect(ClientRect);
|
|
C.Font.Assign(Self.Font);
|
|
Str:= FTextLocked;
|
|
C.TextOut(10, 10, Str);
|
|
end;
|
|
|
|
|
|
procedure TATSynEdit.Paint;
|
|
begin
|
|
PaintEx(-1);
|
|
end;
|
|
|
|
procedure TATSynEdit.PaintEx(ALine: integer);
|
|
begin
|
|
if FPaintLocked>0 then
|
|
begin
|
|
DoPaintLockedWarning(Canvas);
|
|
Exit
|
|
end;
|
|
|
|
//if scrollbars shown, paint again
|
|
if DoPaint(FPaintFlags, ALine) then
|
|
DoPaint(FPaintFlags, ALine);
|
|
|
|
Exclude(FPaintFlags, cPaintUpdateBitmap);
|
|
end;
|
|
|
|
procedure TATSynEdit.DoOnResize;
|
|
var
|
|
SizeX, SizeY: integer;
|
|
begin
|
|
inherited;
|
|
|
|
if Assigned(FBitmap) then
|
|
begin
|
|
SizeX:= (Width div cResizeBitmapStep + 1)*cResizeBitmapStep;
|
|
SizeY:= (Height div cResizeBitmapStep + 1)*cResizeBitmapStep;
|
|
if (SizeX>FBitmap.Width) or (SizeY>FBitmap.Height) then
|
|
begin
|
|
FBitmap.SetSize(SizeX, SizeY);
|
|
FBitmap.FreeImage; //recommended, else seen black bitmap on bigsize
|
|
end;
|
|
end;
|
|
|
|
FWrapUpdateNeeded:= true;
|
|
Include(FPaintFlags, cPaintUpdateScrollbars);
|
|
Include(FPaintFlags, cPaintUpdateCaretsCoords);
|
|
Include(FPaintFlags, cPaintUpdateBitmap);
|
|
PaintEx(LineTop);
|
|
end;
|
|
|
|
//needed to remove flickering on resize and mouse-over
|
|
procedure TATSynEdit.WMEraseBkgnd(var Msg: TLMEraseBkgnd);
|
|
begin
|
|
Msg.Result:= 1;
|
|
end;
|
|
|
|
procedure TATSynEdit.DoHintShow;
|
|
var
|
|
S: string;
|
|
P: TPoint;
|
|
R: TRect;
|
|
begin
|
|
if not FOptShowScrollHint then Exit;
|
|
|
|
S:= cHintScrollPrefix+' '+IntToStr(LineTop+1);
|
|
R:= FHintWnd.CalcHintRect(500, S, nil);
|
|
|
|
P:= ClientToScreen(Point(ClientWidth-(R.Right-R.Left), 0));
|
|
OffsetRect(R, P.X, P.Y);
|
|
OffsetRect(R, -cHintScrollDx, cHintScrollDx);
|
|
|
|
FHintWnd.ActivateHint(R, S);
|
|
FHintWnd.Invalidate; //for Win
|
|
end;
|
|
|
|
procedure TATSynEdit.DoHintHide;
|
|
begin
|
|
if Assigned(FHintWnd) then
|
|
FHintWnd.Hide;
|
|
end;
|
|
|
|
function TATSynEdit.UpdateScrollInfoFromMessage(const Msg: TLMScroll; var Info: TATSynScrollInfo): boolean;
|
|
begin
|
|
{
|
|
application.MainForm.caption:= format('min %d max %d page %d pos %d',
|
|
[info.nmin, info.nmax, info.npage, info.npos]);
|
|
}
|
|
with Info do
|
|
if (NMax-NMin)<NPage then
|
|
begin
|
|
DoClearScrollInfo(Info);
|
|
Exit(true);
|
|
end;
|
|
|
|
case Msg.ScrollCode of
|
|
SB_TOP: Info.NPos:= Info.NMin;
|
|
SB_BOTTOM: Info.NPos:= Info.NPosLast;
|
|
|
|
SB_LINEUP: Info.NPos:= Max(Info.NPos-1, Info.NMin);
|
|
SB_LINEDOWN: Info.NPos:= Min(Info.NPos+1, Info.NPosLast);
|
|
|
|
SB_PAGEUP: Info.NPos:= Max(Info.NPos-Info.NPage, Info.NMin);
|
|
SB_PAGEDOWN: Info.NPos:= Min(Info.NPos+Info.NPage, Info.NPosLast);
|
|
|
|
SB_THUMBPOSITION: Info.NPos:= Msg.Pos;
|
|
SB_THUMBTRACK:
|
|
begin
|
|
Info.NPos:= Msg.Pos;
|
|
if @Info=@FScrollVert then DoHintShow;
|
|
end;
|
|
SB_ENDSCROLL:
|
|
DoHintHide;
|
|
end;
|
|
|
|
Result:= Msg.ScrollCode<>SB_THUMBTRACK;
|
|
end;
|
|
|
|
procedure TATSynEdit.WMVScroll(var Msg: TLMVScroll);
|
|
begin
|
|
Include(FPaintFlags, cPaintUpdateCaretsCoords);
|
|
UpdateScrollInfoFromMessage(Msg, FScrollVert);
|
|
Invalidate;
|
|
end;
|
|
|
|
{ Simple Windows IME support, only tested with Korean }
|
|
{$ifdef Windows}
|
|
procedure TATSynEdit.WMIME_STARTCOMPOSITION(var Msg: TMessage);
|
|
begin
|
|
Msg.Result:=-1;
|
|
end;
|
|
|
|
procedure TATSynEdit.WMIME_COMPOSITION(var Msg: TMessage);
|
|
var
|
|
IMC:HIMC;
|
|
imeCode, len:Integer;
|
|
p:PWideChar;
|
|
res:TATCommandResults;
|
|
begin
|
|
if not ModeReadOnly then
|
|
begin
|
|
{ work with GCS_COMPSTR and GCS_RESULTSTR }
|
|
if Msg.lParam and GCS_COMPSTR <> 0 then
|
|
imeCode := GCS_COMPSTR
|
|
else if Msg.lParam and GCS_RESULTSTR <> 0 then
|
|
imeCode := GCS_RESULTSTR
|
|
else
|
|
imeCode := 0;
|
|
{ check compositon state }
|
|
if imeCode<>0 then
|
|
begin
|
|
IMC := ImmGetContext(Handle);
|
|
try
|
|
{ Get Result string length }
|
|
len := ImmGetCompositionStringW(IMC,imeCode,nil,0);
|
|
GetMem(p,len+2);
|
|
try
|
|
{ get compositon string }
|
|
ImmGetCompositionStringW(IMC,imeCode,p,len);
|
|
len := len shr 1;
|
|
p[len]:=#0;
|
|
{ Insert text and
|
|
select text if it is not GCS_RESULTSTR }
|
|
res:=DoCommand_TextInsertAtCarets(p, False,
|
|
(imeCode=GCS_RESULTSTR) and FOverwrite,
|
|
(imeCode<>GCS_RESULTSTR) and (Len>0));
|
|
DoCommandResults(res);
|
|
finally
|
|
FreeMem(p);
|
|
end;
|
|
finally
|
|
ImmReleaseContext(Handle,IMC);
|
|
end;
|
|
end;
|
|
end;
|
|
Msg.Result:=-1;
|
|
end;
|
|
|
|
procedure TATSynEdit.WMIME_ENDCOMPOSITION(var Msg: TMessage);
|
|
begin
|
|
Msg.Result:=-1;
|
|
end;
|
|
{$endif}
|
|
|
|
procedure TATSynEdit.WMHScroll(var Msg: TLMHScroll);
|
|
begin
|
|
Include(FPaintFlags, cPaintUpdateCaretsCoords);
|
|
UpdateScrollInfoFromMessage(Msg, FScrollHorz);
|
|
Invalidate;
|
|
end;
|
|
|
|
|
|
procedure TATSynEdit.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
var
|
|
PCaret: TPoint;
|
|
EolPos: boolean;
|
|
Index: integer;
|
|
begin
|
|
inherited;
|
|
SetFocus;
|
|
|
|
PCaret:= ClientPosToCaretPos(Point(X, Y), EolPos);
|
|
FCaretSpecPos:= false;
|
|
FMouseDownNumber:= -1;
|
|
FMouseDragDropping:= false;
|
|
FMouseDownRight:= Shift=[ssRight];
|
|
|
|
if MouseNiceScroll then
|
|
begin
|
|
MouseNiceScroll:= false;
|
|
Exit
|
|
end;
|
|
|
|
if FMinimapVisible and PtInRect(FRectMinimap, Point(X, Y)) then
|
|
begin
|
|
if PtInRect(GetRectMinimapSel, Point(X, Y)) then
|
|
FMouseDragMinimap:= true;
|
|
if Shift=[ssLeft] then
|
|
begin
|
|
DoMinimapClick(Y);
|
|
Exit
|
|
end;
|
|
end;
|
|
|
|
if PtInRect(FRectMain, Point(X, Y)) then
|
|
begin
|
|
FMouseDownPnt:= PCaret;
|
|
|
|
if Shift=[ssMiddle] then
|
|
begin
|
|
if DoHandleClickEvent(FOnClickMiddle) then Exit;
|
|
if FOptMouseNiceScroll then
|
|
begin
|
|
FMouseNiceScrollPos:= Point(X, Y);
|
|
MouseNiceScroll:= true;
|
|
end;
|
|
Exit
|
|
end;
|
|
|
|
if Shift=[ssLeft] then
|
|
begin
|
|
FSelRect:= cRectEmpty;
|
|
Strings.SetGroupMark;
|
|
DoCaretSingleAsIs;
|
|
|
|
if FOptMouseDragDrop and (GetCaretSelectionIndex(FMouseDownPnt)>=0) and not ModeReadOnly then
|
|
begin
|
|
FMouseDragDropping:= true;
|
|
UpdateCursor;
|
|
end
|
|
else
|
|
begin
|
|
if Assigned(FOnClickMoveCaret) then
|
|
FOnClickMoveCaret(Self, Point(Carets[0].PosX, Carets[0].PosY), FMouseDownPnt);
|
|
|
|
DoCaretSingle(FMouseDownPnt.X, FMouseDownPnt.Y);
|
|
DoSelect_None;
|
|
end;
|
|
end;
|
|
|
|
if Shift=[ssLeft, ssShift] then
|
|
begin
|
|
FSelRect:= cRectEmpty;
|
|
DoCaretSingleAsIs;
|
|
Carets[0].SelectToPoint(FMouseDownPnt.X, FMouseDownPnt.Y);
|
|
end;
|
|
|
|
if Shift=[ssLeft, ssXControl] then
|
|
begin
|
|
FSelRect:= cRectEmpty;
|
|
DoCaretAddToPoint(FMouseDownPnt.X, FMouseDownPnt.Y);
|
|
end;
|
|
|
|
if Shift=[ssLeft, ssXControl, ssShift] then
|
|
begin
|
|
FSelRect:= cRectEmpty;
|
|
DoCaretsColumnToPoint(FMouseDownPnt.X, FMouseDownPnt.Y);
|
|
end;
|
|
|
|
if Shift=[ssRight] then
|
|
begin
|
|
if FOptMouseRightClickMovesCaret then
|
|
if GetCaretSelectionIndex(FMouseDownPnt)<0 then
|
|
begin
|
|
DoCaretSingle(FMouseDownPnt.X, FMouseDownPnt.Y);
|
|
DoSelect_None;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
if Shift=[ssRight] then
|
|
if FOptMouseDownForPopup then
|
|
DoHandleRightClick(X, Y);
|
|
|
|
if FOptGutterVisible and PtInRect(FRectGutter, Point(X, Y)) then
|
|
begin
|
|
if Shift=[ssLeft] then
|
|
begin
|
|
Index:= FGutter.IndexAt(X);
|
|
if Index=FGutterBandNum then
|
|
begin
|
|
if FOptMouseGutterClickSelectsLine then
|
|
begin
|
|
FSelRect:= cRectEmpty;
|
|
FMouseDownNumber:= PCaret.Y;
|
|
DoSelect_Line(PCaret);
|
|
end;
|
|
end
|
|
else
|
|
if Index=FGutterBandFold then
|
|
begin
|
|
DoFoldbarClick(PCaret.Y);
|
|
end
|
|
else
|
|
//click on other bands- event
|
|
DoEventClickGutter(FGutter.IndexAt(X), PCaret.Y);
|
|
end;
|
|
end;
|
|
|
|
if FMicromapVisible and PtInRect(FRectMicromap, Point(X, Y)) then
|
|
if Shift=[ssLeft] then
|
|
begin
|
|
DoEventClickMicromap(X-FRectMicromap.Left, Y-FRectMicromap.Top);
|
|
Exit
|
|
end;
|
|
|
|
DoCaretsSort;
|
|
DoEventCarets;
|
|
Update;
|
|
end;
|
|
|
|
procedure TATSynEdit.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
inherited;
|
|
|
|
if FMouseDragDropping then
|
|
begin
|
|
DoDropText;
|
|
Update;
|
|
end;
|
|
|
|
FMouseDownPnt:= Point(-1, -1);
|
|
FMouseDownNumber:= -1;
|
|
FMouseDownDouble:= false;
|
|
FMouseDragDropping:= false;
|
|
FMouseDragMinimap:= false;
|
|
FTimerScroll.Enabled:= false;
|
|
|
|
//popup menu
|
|
if FMouseDownRight then
|
|
begin
|
|
FMouseDownRight:= false;
|
|
if not FOptMouseDownForPopup then
|
|
DoHandleRightClick(X, Y);
|
|
end;
|
|
|
|
if Carets.Count=1 then
|
|
with Carets[0] do
|
|
if EndY>=0 then
|
|
if Assigned(FOnClickEndSelect) then
|
|
FOnClickEndSelect(Self, Point(EndX, EndY), Point(PosX, PosY));
|
|
end;
|
|
|
|
|
|
procedure TATSynEdit.DoHandleRightClick(X, Y: integer);
|
|
var
|
|
Index: integer;
|
|
begin
|
|
if PtInRect(FRectMain, Point(X, Y)) then
|
|
begin
|
|
if Assigned(FMenuText) then
|
|
FMenuText.PopUp
|
|
else
|
|
FMenuStd.PopUp;
|
|
end
|
|
else
|
|
if FOptGutterVisible and PtInRect(FRectGutter, Point(X, Y)) then
|
|
begin
|
|
Index:= FGutter.IndexAt(X);
|
|
if Index=FGutterBandBm then
|
|
if Assigned(FMenuGutterBm) then FMenuGutterBm.PopUp;
|
|
if Index=FGutterBandNum then
|
|
if Assigned(FMenuGutterNum) then FMenuGutterNum.PopUp;
|
|
if Index=FGutterBandFold then
|
|
if Assigned(FMenuGutterFold) then FMenuGutterFold.PopUp else DoMenuGutterFold;
|
|
end
|
|
else
|
|
if FMinimapVisible and PtInRect(FRectMinimap, Point(X, Y)) then
|
|
begin
|
|
if Assigned(FMenuMinimap) then FMenuMinimap.PopUp;
|
|
end
|
|
else
|
|
if FMicromapVisible and PtInRect(FRectMicromap, Point(X, Y)) then
|
|
begin
|
|
if Assigned(FMenuMicromap) then FMenuMicromap.PopUp;
|
|
end
|
|
else
|
|
if FOptRulerVisible and PtInRect(FRectRuler, Point(X, Y)) then
|
|
begin
|
|
if Assigned(FMenuRuler) then FMenuRuler.PopUp;
|
|
end;
|
|
end;
|
|
|
|
procedure TATSynEdit.UpdateCursor;
|
|
var
|
|
P: TPoint;
|
|
RectBm: TRect;
|
|
begin
|
|
if MouseNiceScroll then Exit;
|
|
P:= ScreenToClient(Mouse.CursorPos);
|
|
|
|
RectBm.Left:= FGutter[FGutterBandBm].Left;
|
|
RectBm.Right:= FGutter[FGutterBandBm].Right;
|
|
RectBm.Top:= FRectMain.Top;
|
|
RectBm.Bottom:= FRectMain.Bottom;
|
|
|
|
if FMouseDragDropping then
|
|
Cursor:= crDrag
|
|
else
|
|
//if FMouseDragMinimap then
|
|
// Cursor:= crSizeNS
|
|
//else
|
|
if PtInRect(FRectMain, P) then
|
|
Cursor:= FCursorText
|
|
else
|
|
if PtInRect(RectBm, P) then
|
|
Cursor:= FCursorBm
|
|
else
|
|
Cursor:= crDefault;
|
|
end;
|
|
|
|
procedure TATSynEdit.MouseMove(Shift: TShiftState; X, Y: Integer);
|
|
var
|
|
P: TPoint;
|
|
RectNums: TRect;
|
|
nIndex: integer;
|
|
bOnMinimap, bOnGutter, bEolPos: boolean;
|
|
begin
|
|
inherited;
|
|
|
|
P:= Point(X, Y);
|
|
UpdateCursor;
|
|
|
|
//detect cursor on minimap
|
|
if FMinimapVisible then
|
|
begin
|
|
bOnMinimap:= PtInRect(FRectMinimap, P);
|
|
if not FMinimapShowSelAlways then
|
|
if bOnMinimap<>FCursorOnMinimap then
|
|
Invalidate;
|
|
FCursorOnMinimap:= bOnMinimap;
|
|
end;
|
|
|
|
//detect cursor on gutter
|
|
if FOptGutterVisible then
|
|
begin
|
|
bOnGutter:= PtInRect(FRectGutter, P);
|
|
if not FOptGutterShowFoldAlways then
|
|
if bOnGutter<>FCursorOnGutter then
|
|
Invalidate;
|
|
FCursorOnGutter:= bOnGutter;
|
|
end;
|
|
|
|
//numbers
|
|
RectNums.Left:= FGutter[FGutterBandNum].Left;
|
|
RectNums.Right:= FGutter[FGutterBandNum].Right;
|
|
RectNums.Top:= FRectMain.Top;
|
|
RectNums.Bottom:= FRectMain.Bottom;
|
|
|
|
//start scroll timer
|
|
FTimerScroll.Enabled:=
|
|
(ssLeft in Shift) and
|
|
(not PtInRect(ClientRect, P) or FCursorOnGutter);
|
|
FMouseAutoScroll:= cDirNone;
|
|
if P.Y<FRectMain.Top then FMouseAutoScroll:= cDirUp else
|
|
if P.Y>=FRectMain.Bottom then FMouseAutoScroll:= cDirDown else
|
|
if P.X<FRectMain.Left then FMouseAutoScroll:= cDirLeft else
|
|
if P.X>=FRectMain.Right then FMouseAutoScroll:= cDirRight;
|
|
|
|
//mouse dragged on numbers
|
|
if PtInRect(RectNums, P) then
|
|
begin
|
|
if Shift=[ssLeft] then
|
|
begin
|
|
P:= ClientPosToCaretPos(P, bEolPos);
|
|
if (P.Y>=0) and (P.X>=0) then
|
|
if FMouseDownNumber>=0 then
|
|
begin
|
|
DoSelect_LineRange(FMouseDownNumber, P);
|
|
DoCaretsSort;
|
|
DoEventCarets;
|
|
Update;
|
|
end;
|
|
end;
|
|
Exit
|
|
end;
|
|
|
|
//mouse dragged on text
|
|
if (not FMouseDragDropping) and (FMouseDownPnt.X>=0) then
|
|
if PtInRect(FRectMain, P) then
|
|
begin
|
|
if ssLeft in Shift then
|
|
if Carets.Count>0 then
|
|
begin
|
|
P:= ClientPosToCaretPos(P, bEolPos);
|
|
if P.Y>=0 then
|
|
begin
|
|
//drag w/out button pressed: single selection
|
|
if FOptMouseEnableNormalSelection then
|
|
if [ssXControl, ssShift, ssAlt]*Shift=[] then
|
|
begin
|
|
DoCaretSingleAsIs;
|
|
if FMouseDownDouble and FOptMouse2ClickDragSelectsWords then
|
|
DoSelect_WordRange(0, FMouseDownPnt, P)
|
|
else
|
|
DoSelect_CharRange(0, P);
|
|
end;
|
|
|
|
//drag with Ctrl pressed: add selection
|
|
if Shift=[ssXControl, ssLeft] then
|
|
begin
|
|
nIndex:= Carets.IndexOfPosXY(FMouseDownPnt.X, FMouseDownPnt.Y, true);
|
|
DoSelect_CharRange(nIndex, P);
|
|
end;
|
|
|
|
//drag with Alt pressed
|
|
if FOptMouseEnableColumnSelection then
|
|
if Shift=[ssAlt, ssLeft] then
|
|
begin
|
|
DoCaretSingle(FMouseDownPnt.X, FMouseDownPnt.Y);
|
|
DoSelect_None;
|
|
DoSelect_ColumnBlock(FMouseDownPnt, P);
|
|
end;
|
|
|
|
DoCaretsSort;
|
|
DoEventCarets;
|
|
Update;
|
|
end;
|
|
end;
|
|
Exit;
|
|
end;
|
|
|
|
//mouse dragged on minimap
|
|
if PtInRect(FRectMinimap, P) then
|
|
if FMouseDragMinimap then
|
|
begin
|
|
if Shift=[ssLeft] then
|
|
DoMinimapDrag(Y);
|
|
Exit
|
|
end;
|
|
end;
|
|
|
|
function TATSynEdit.DoMouseWheelDown(Shift: TShiftState; MousePos: TPoint): boolean;
|
|
begin
|
|
Result:= DoMouseWheelAction(Shift, false);
|
|
end;
|
|
|
|
function TATSynEdit.DoMouseWheelUp(Shift: TShiftState; MousePos: TPoint): boolean;
|
|
begin
|
|
Result:= DoMouseWheelAction(Shift, true);
|
|
end;
|
|
|
|
function TATSynEdit.DoMouseWheelAction(Shift: TShiftState; AUp: boolean): boolean;
|
|
begin
|
|
if Shift=[ssCtrl] then
|
|
begin
|
|
DoSizeChange(AUp);
|
|
Result:= true;
|
|
end
|
|
else
|
|
Result:= false;
|
|
end;
|
|
|
|
function TATSynEdit.DoHandleClickEvent(AEvent: TATSynEditClickEvent): boolean;
|
|
begin
|
|
Result:= false;
|
|
if Assigned(AEvent) then
|
|
AEvent(Self, Result);
|
|
end;
|
|
|
|
procedure TATSynEdit.DblClick;
|
|
begin
|
|
inherited;
|
|
|
|
if DoHandleClickEvent(FOnClickDbl) then Exit;
|
|
|
|
if FOptMouse2ClickSelectsLine then
|
|
DoSelect_Line_ByClick
|
|
else
|
|
begin
|
|
FMouseDownDouble:= true;
|
|
DoSelect_Word_ByClick;
|
|
end;
|
|
|
|
DoEventCarets;
|
|
end;
|
|
|
|
procedure TATSynEdit.TripleClick;
|
|
begin
|
|
inherited;
|
|
|
|
if DoHandleClickEvent(FOnClickTriple) then Exit;
|
|
|
|
if FOptMouse3ClickSelectsLine then
|
|
DoSelect_Line_ByClick;
|
|
end;
|
|
|
|
|
|
procedure TATSynEdit.DoSelect_Word_ByClick;
|
|
var
|
|
P: TPoint;
|
|
EolPos: boolean;
|
|
begin
|
|
P:= ScreenToClient(Mouse.CursorPos);
|
|
if PtInRect(FRectMain, P) then
|
|
begin
|
|
P:= ClientPosToCaretPos(P, EolPos);
|
|
if P.Y<0 then Exit;
|
|
DoSelect_Word(P);
|
|
Update;
|
|
end;
|
|
end;
|
|
|
|
function TATSynEdit.GetCaretManyAllowed: boolean;
|
|
begin
|
|
Result:= Carets.ManyAllowed;
|
|
end;
|
|
|
|
procedure TATSynEdit.SetCaretManyAllowed(AValue: boolean);
|
|
begin
|
|
Carets.ManyAllowed:= AValue;
|
|
if not AValue then
|
|
DoCaretSingleAsIs;
|
|
end;
|
|
|
|
|
|
procedure TATSynEdit.DoSelect_Line_ByClick;
|
|
var
|
|
P: TPoint;
|
|
EolPos: boolean;
|
|
begin
|
|
P:= ScreenToClient(Mouse.CursorPos);
|
|
if PtInRect(FRectMain, P) then
|
|
begin
|
|
P:= ClientPosToCaretPos(P, EolPos);
|
|
if P.Y<0 then Exit;
|
|
DoSelect_Line(P);
|
|
Update;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TATSynEdit.Invalidate;
|
|
begin
|
|
Include(FPaintFlags, cPaintUpdateBitmap);
|
|
inherited;
|
|
end;
|
|
|
|
procedure TATSynEdit.TimerBlinkTick(Sender: TObject);
|
|
begin
|
|
DoPaintCarets(FBitmap.Canvas, true);
|
|
end;
|
|
|
|
procedure TATSynEdit.TimerScrollTick(Sender: TObject);
|
|
var
|
|
nIndex: integer;
|
|
PClient, PCaret: TPoint;
|
|
EolPos: boolean;
|
|
begin
|
|
PClient:= ScreenToClient(Mouse.CursorPos);
|
|
PClient.X:= Max(FRectMain.Left, PClient.X);
|
|
PClient.Y:= Max(FRectMain.Top, PClient.Y);
|
|
PClient.X:= Min(FRectMain.Right, PClient.X);
|
|
PClient.Y:= Min(FRectMain.Bottom, PClient.Y);
|
|
|
|
case FMouseAutoScroll of
|
|
cDirUp: DoScrollByDelta(0, -cSpeedScrollAutoVert);
|
|
cDirDown: DoScrollByDelta(0, cSpeedScrollAutoVert);
|
|
cDirLeft: DoScrollByDelta(-cSpeedScrollAutoHorz, 0);
|
|
cDirRight: DoScrollByDelta(cSpeedScrollAutoHorz, 0);
|
|
else Exit;
|
|
end;
|
|
|
|
PCaret:= ClientPosToCaretPos(PClient, EolPos);
|
|
if (PCaret.X>=0) and (PCaret.Y>=0) then
|
|
if FMouseDownNumber>=0 then
|
|
begin
|
|
DoSelect_LineRange(FMouseDownNumber, PCaret);
|
|
end
|
|
else
|
|
begin
|
|
nIndex:= Carets.IndexOfPosXY(FMouseDownPnt.X, FMouseDownPnt.Y, true);
|
|
if nIndex>=0 then
|
|
Carets[nIndex].SelectToPoint(PCaret.X, PCaret.Y);
|
|
end;
|
|
|
|
DoCaretsSort;
|
|
DoEventCarets;
|
|
DoEventScroll;
|
|
Update;
|
|
end;
|
|
|
|
procedure TATSynEdit.TimerNiceScrollTick(Sender: TObject);
|
|
var
|
|
Pnt: TPoint;
|
|
Dx, Dy: integer;
|
|
Dir: TATDirection;
|
|
begin
|
|
Pnt:= ScreenToClient(Mouse.CursorPos);
|
|
if not PtInRect(FRectMain, Pnt) then Exit;
|
|
|
|
//delta in pixels
|
|
Dx:= Pnt.X-FMouseNiceScrollPos.X;
|
|
Dy:= Pnt.Y-FMouseNiceScrollPos.Y;
|
|
|
|
if (Abs(Dx)<=cBitmapNiceScrollRadius) and
|
|
(Abs(Dy)<=cBitmapNiceScrollRadius) then
|
|
begin
|
|
Cursor:= crNiceScrollNone;
|
|
Exit;
|
|
end;
|
|
|
|
if (Dy<0) and (Abs(Dy)>Abs(Dx)) then Dir:= cDirUp else
|
|
if (Dy>0) and (Abs(Dy)>Abs(Dx)) then Dir:= cDirDown else
|
|
if Dx<0 then Dir:= cDirLeft else
|
|
Dir:= cDirRight;
|
|
|
|
case Dir of
|
|
cDirLeft: Cursor:= crNiceScrollLeft;
|
|
cDirRight: Cursor:= crNiceScrollRight;
|
|
cDirUp: Cursor:= crNiceScrollUp;
|
|
cDirDown: Cursor:= crNiceScrollDown;
|
|
end;
|
|
|
|
//delta in chars
|
|
Dx:= Sign(Dx)*((Abs(Dx)-cBitmapNiceScrollRadius) div FCharSize.X + 1)*cSpeedScrollNiceHorz;
|
|
Dy:= Sign(Dy)*((Abs(Dy)-cBitmapNiceScrollRadius) div FCharSize.Y + 1)*cSpeedScrollNiceVert;
|
|
|
|
if Dir in [cDirLeft, cDirRight] then
|
|
DoScrollByDelta(Dx, 0)
|
|
else
|
|
DoScrollByDelta(0, Dy);
|
|
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TATSynEdit.DoPaintCarets(C: TCanvas; AWithInvalidate: boolean);
|
|
var
|
|
R: TRect;
|
|
i: integer;
|
|
Item: TATCaretItem;
|
|
Shape: TATSynCaretShape;
|
|
begin
|
|
if IsCaretBlocked then
|
|
begin
|
|
if not FCaretShown then Exit;
|
|
end;
|
|
FCaretShown:= not FCaretShown;
|
|
|
|
if ModeReadOnly then
|
|
Shape:= FCaretShapeRO
|
|
else
|
|
if ModeOverwrite then
|
|
Shape:= FCaretShapeOvr
|
|
else
|
|
Shape:= FCaretShapeIns;
|
|
|
|
for i:= 0 to FCarets.Count-1 do
|
|
begin
|
|
Item:= FCarets[i];
|
|
R.Left:= Item.CoordX;
|
|
R.Top:= Item.CoordY;
|
|
R.Right:= R.Left+FCharSize.X;
|
|
R.Bottom:= R.Top+FCharSize.Y;
|
|
|
|
//caret not visible
|
|
if R.Left<0 then Continue;
|
|
if R.Top<0 then Continue;
|
|
|
|
case Shape of
|
|
cCaretShapeVertPixels1: begin R.Right:= R.Left+1; end;
|
|
cCaretShapeVertPixels2: begin R.Right:= R.Left+2; end;
|
|
cCaretShapeVertPixels3: begin R.Right:= R.Left+3; end;
|
|
cCaretShapeVertPixels4: begin R.Right:= R.Left+4; end;
|
|
cCaretShapeVertPercents10: begin R.Right:= R.Left+Trunc(FCharSize.X*0.10); end;
|
|
cCaretShapeVertPercents15: begin R.Right:= R.Left+Trunc(FCharSize.X*0.15); end;
|
|
cCaretShapeVertPercents20: begin R.Right:= R.Left+Trunc(FCharSize.X*0.20); end;
|
|
cCaretShapeVertPercents25: begin R.Right:= R.Left+Trunc(FCharSize.X*0.25); end;
|
|
cCaretShapeVertPercents30: begin R.Right:= R.Left+Trunc(FCharSize.X*0.30); end;
|
|
cCaretShapeVertPercents35: begin R.Right:= R.Left+Trunc(FCharSize.X*0.35); end;
|
|
cCaretShapeVertPercents40: begin R.Right:= R.Left+Trunc(FCharSize.X*0.40); end;
|
|
cCaretShapeVertPercents50: begin R.Right:= R.Left+FCharSize.X div 2; end;
|
|
cCaretShapeHorzPixels1: begin R.Top:= R.Bottom-1; end;
|
|
cCaretShapeHorzPixels2: begin R.Top:= R.Bottom-2; end;
|
|
cCaretShapeHorzPixels3: begin R.Top:= R.Bottom-3; end;
|
|
cCaretShapeHorzPixels4: begin R.Top:= R.Bottom-4; end;
|
|
cCaretShapeHorzPixels5: begin R.Top:= R.Bottom-5; end;
|
|
cCaretShapeHorzPercents10: begin R.Top:= R.Bottom-Trunc(FCharSize.Y*0.10); end;
|
|
cCaretShapeHorzPercents15: begin R.Top:= R.Bottom-Trunc(FCharSize.Y*0.15); end;
|
|
cCaretShapeHorzPercents20: begin R.Top:= R.Bottom-Trunc(FCharSize.Y*0.20); end;
|
|
cCaretShapeHorzPercents25: begin R.Top:= R.Bottom-Trunc(FCharSize.Y*0.25); end;
|
|
cCaretShapeHorzPercents30: begin R.Top:= R.Bottom-Trunc(FCharSize.Y*0.30); end;
|
|
cCaretShapeHorzPercents35: begin R.Top:= R.Bottom-Trunc(FCharSize.Y*0.35); end;
|
|
cCaretShapeHorzPercents40: begin R.Top:= R.Bottom-Trunc(FCharSize.Y*0.40); end;
|
|
cCaretShapeHorzPercents50: begin R.Top:= R.Bottom-FCharSize.Y div 2; end;
|
|
end;
|
|
|
|
if IntersectRect(R, R, FRectMain) then
|
|
begin
|
|
CanvasInvertRect(C, R, FColors.Caret);
|
|
|
|
//frame-shape: invert second time inner area
|
|
if Shape=cCaretShapeFrameFull then
|
|
CanvasInvertRect(C, Rect(R.Left+1, R.Top+1, R.Right-1, R.Bottom-1), FColors.Caret);
|
|
|
|
if AWithInvalidate then
|
|
InvalidateRect(Handle, @R, false);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TATSynEdit.DoPaintModeStatic;
|
|
begin
|
|
FPaintStatic:= true;
|
|
FTimerBlink.Enabled:= false;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TATSynEdit.DoPaintModeBlinking;
|
|
begin
|
|
FPaintStatic:= false;
|
|
if Assigned(FTimerBlink) then
|
|
begin
|
|
FTimerBlink.Enabled:= false;
|
|
FTimerBlink.Enabled:= FCaretBlinkEnabled;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TATSynEdit.DoPaintLineIndent(C: TCanvas;
|
|
const ARect: TRect;
|
|
ACharSize: TPoint;
|
|
ACoordY: integer;
|
|
AIndentSize: integer;
|
|
AColorBG: TColor;
|
|
AScrollPos: integer;
|
|
AIndentLines: boolean);
|
|
var
|
|
i: integer;
|
|
RBack: TRect;
|
|
begin
|
|
if AIndentSize=0 then Exit;
|
|
|
|
RBack:= Rect(0, 0, AIndentSize*ACharSize.X, ACharSize.Y);
|
|
OffsetRect(RBack, ARect.Left-AScrollPos*ACharSize.X, ACoordY);
|
|
|
|
C.Brush.Color:= AColorBG;
|
|
C.FillRect(RBack);
|
|
|
|
if AIndentLines then
|
|
for i:= 0 to AIndentSize-1 do
|
|
if i mod FTabSize = 0 then
|
|
CanvasDottedVertLine_Alt(C,
|
|
FColors.IndentVertLines,
|
|
ARect.Left + (i-AScrollPos)*ACharSize.X,
|
|
ACoordY,
|
|
ACoordY+ACharSize.Y);
|
|
end;
|
|
|
|
procedure TATSynEdit.DoPaintSelectedLineBG(C: TCanvas;
|
|
ACharSize: TPoint;
|
|
const AVisRect: TRect;
|
|
APointLeft: TPoint;
|
|
APointText: TPoint;
|
|
ALineIndex: integer;
|
|
AEolSelected: boolean;
|
|
const AScrollHorz: TATSynScrollInfo);
|
|
var
|
|
NLeft, NRight: integer;
|
|
begin
|
|
if not IsSelRectEmpty then
|
|
begin
|
|
if (ALineIndex>=FSelRect.Top) and (ALineIndex<=FSelRect.Bottom) then
|
|
begin
|
|
NLeft:= APointLeft.X+ACharSize.X*(FSelRect.Left-AScrollHorz.NPos);
|
|
NRight:= NLeft+ACharSize.X*(FSelRect.Right-FSelRect.Left);
|
|
C.Brush.Color:= FColors.TextSelBG;
|
|
C.FillRect(
|
|
NLeft,
|
|
APointLeft.Y,
|
|
NRight,
|
|
APointLeft.Y+ACharSize.Y);
|
|
end;
|
|
end
|
|
else
|
|
if FOptShowFullSel then
|
|
if AEolSelected then
|
|
begin
|
|
C.Brush.Color:= FColors.TextSelBG;
|
|
C.FillRect(
|
|
APointText.X,
|
|
APointText.Y,
|
|
AVisRect.Right,
|
|
APointText.Y+ACharSize.Y);
|
|
end;
|
|
end;
|
|
|
|
procedure TATSynEdit.DoPaintNiceScroll(C: TCanvas);
|
|
begin
|
|
if MouseNiceScroll then
|
|
C.Draw(
|
|
FMouseNiceScrollPos.X - cBitmapNiceScrollRadius,
|
|
FMouseNiceScrollPos.Y - cBitmapNiceScrollRadius,
|
|
cBitmapNiceScroll);
|
|
end;
|
|
|
|
|
|
function TATSynEdit.DoEventCommand(ACommand: integer; const AText: string): boolean;
|
|
begin
|
|
Result:= false;
|
|
if Assigned(FOnCommand) then
|
|
FOnCommand(Self, ACommand, AText, Result);
|
|
end;
|
|
|
|
function TATSynEdit.GetCaretBlinkTime: integer;
|
|
begin
|
|
Result:= FTimerBlink.Interval;
|
|
end;
|
|
|
|
function TATSynEdit.GetWrapInfoIndex(AMousePos: TPoint): integer;
|
|
var
|
|
NPixels: integer;
|
|
begin
|
|
Result:= -1;
|
|
NPixels:= AMousePos.Y - FRectMain.Top;
|
|
Result:= FScrollVert.NPos + NPixels div FCharSize.Y;
|
|
if not FWrapInfo.IsIndexValid(Result) then
|
|
Result:= -1;
|
|
end;
|
|
|
|
procedure TATSynEdit.DoEventCarets;
|
|
begin
|
|
if Assigned(FAdapterHilite) then
|
|
FAdapterHilite.OnEditorCaretMove(Self);
|
|
|
|
if Assigned(FOnChangeCaretPos) then
|
|
FOnChangeCaretPos(Self);
|
|
end;
|
|
|
|
procedure TATSynEdit.DoEventScroll;
|
|
begin
|
|
if Assigned(FAdapterHilite) then
|
|
FAdapterHilite.OnEditorScroll(Self);
|
|
|
|
if Assigned(FOnScroll) then
|
|
FOnScroll(Self);
|
|
end;
|
|
|
|
procedure TATSynEdit.DoEventChange;
|
|
begin
|
|
if Assigned(FAdapterHilite) then
|
|
FAdapterHilite.OnEditorChange(Self);
|
|
|
|
if Assigned(FOnChange) then
|
|
FOnChange(Self);
|
|
end;
|
|
|
|
procedure TATSynEdit.DoEventState;
|
|
begin
|
|
if Assigned(FOnChangeState) then
|
|
FOnChangeState(Self);
|
|
end;
|
|
|
|
procedure TATSynEdit.DoEventClickGutter(ABandIndex, ALineNumber: integer);
|
|
begin
|
|
if Assigned(FOnClickGutter) then
|
|
FOnClickGutter(Self, ABandIndex, ALineNumber);
|
|
end;
|
|
|
|
procedure TATSynEdit.DoEventClickMicromap(AX, AY: integer);
|
|
begin
|
|
if Assigned(FOnClickMicromap) then
|
|
FOnClickMicromap(Self, AX, AY);
|
|
end;
|
|
|
|
procedure TATSynEdit.DoEventDrawBookmarkIcon(C: TCanvas; ALineNumber: integer; const ARect: TRect);
|
|
begin
|
|
if Assigned(FOnDrawBookmarkIcon) then
|
|
FOnDrawBookmarkIcon(Self, C, ALineNumber, ARect);
|
|
end;
|
|
|
|
procedure TATSynEdit.DoEventBeforeCalcHilite;
|
|
begin
|
|
if Assigned(FAdapterHilite) then
|
|
FAdapterHilite.OnEditorBeforeCalcHilite(Self);
|
|
|
|
if Assigned(FOnBeforeCalcHilite) then
|
|
FOnBeforeCalcHilite(Self);
|
|
end;
|
|
|
|
|
|
procedure TATSynEdit.OnCanvasFontChanged(Sender: TObject);
|
|
const
|
|
cCodeM: Widechar = #$4d; //half-width M
|
|
cCodeFullM: Widechar = #$ff2d; //full-width M
|
|
{$ifdef windows}
|
|
var
|
|
sizeSmall, sizeFull: single;
|
|
a: ABCFLOAT;
|
|
{$endif}
|
|
begin
|
|
ATStringProc.cCharScaleFullwidth:= ATStringProc.cCharScaleFullwidth_Default;
|
|
if assigned(Parent) then
|
|
begin
|
|
{$ifdef windows}
|
|
//half width
|
|
if GetCharABCWidthsFloatW(Canvas.Handle, Ord(cCodeM), Ord(cCodeM), a) then
|
|
sizeSmall:= Max(1.0, a.abcfA+a.abcfB+a.abcfC)
|
|
else
|
|
sizeSmall:= 1;
|
|
//full width
|
|
if GetCharABCWidthsFloatW(Canvas.Handle, Ord(cCodeFullM), Ord(cCodeFullM), a) then
|
|
sizeFull:= a.abcfA+a.abcfB+a.abcfC
|
|
else
|
|
sizeFull:= 1;
|
|
ATStringProc.cCharScaleFullwidth:= sizeFull/sizeSmall;
|
|
{$else}
|
|
ATStringProc.cCharScaleFullwidth:=
|
|
Canvas.TextWidth(Utf8Encode(cCodeFullM)) /
|
|
Canvas.TextWidth(Utf8Encode(cCodeM));
|
|
{$endif}
|
|
end;
|
|
end;
|
|
|
|
procedure TATSynEdit.DoSendShowHideToInterface;
|
|
begin
|
|
inherited DoSendShowHideToInterface;
|
|
Canvas.Font.OnChange:=@OnCanvasFontChanged;
|
|
OnCanvasFontChanged(Canvas.Font);
|
|
end;
|
|
|
|
procedure TATSynEdit.DoScrollByDelta(Dx, Dy: integer);
|
|
begin
|
|
with FScrollHorz do
|
|
NPos:= Max(0, Min(NPosLast, NPos+Dx));
|
|
with FScrollVert do
|
|
NPos:= Max(0, Min(NPosLast, NPos+Dy));
|
|
end;
|
|
|
|
procedure TATSynEdit.MenuClick(Sender: TObject);
|
|
var
|
|
Cmd: integer;
|
|
begin
|
|
Cmd:= (Sender as TMenuItem).Tag;
|
|
if Cmd>0 then
|
|
begin
|
|
DoCommand(Cmd);
|
|
Update;
|
|
end;
|
|
end;
|
|
|
|
procedure TATSynEdit.MenuPopup(Sender: TObject);
|
|
var
|
|
i: integer;
|
|
begin
|
|
for i:= 0 to FMenuStd.Items.Count-1 do
|
|
with FMenuStd.Items[i] do
|
|
begin
|
|
if Assigned(FKeymap) then
|
|
ShortCut:= FKeymap.GetShortcutFromCommand(Tag);
|
|
|
|
//separator items: hide if read-only, nicer menu
|
|
if Caption='-' then
|
|
Visible:= not ModeReadOnly;
|
|
|
|
case Tag of
|
|
cCommand_ClipboardCut:
|
|
begin
|
|
Enabled:= not ModeReadOnly;
|
|
Visible:= not ModeReadOnly;
|
|
end;
|
|
cCommand_ClipboardPaste:
|
|
begin
|
|
Enabled:= not ModeReadOnly and Clipboard.HasFormat(CF_Text);
|
|
Visible:= not ModeReadOnly;
|
|
end;
|
|
cCommand_TextDeleteSelection:
|
|
begin
|
|
Enabled:= not ModeReadOnly and Carets.IsSelection;
|
|
Visible:= not ModeReadOnly;
|
|
end;
|
|
cCommand_Undo:
|
|
begin
|
|
Enabled:= not ModeReadOnly and (UndoCount>0);
|
|
Visible:= not ModeReadOnly;
|
|
end;
|
|
cCommand_Redo:
|
|
begin
|
|
Enabled:= not ModeReadOnly and (RedoCount>0);
|
|
Visible:= not ModeReadOnly;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TATSynEdit.DoInitPopupMenu;
|
|
//
|
|
procedure Add(const SName: string; Cmd: integer);
|
|
var
|
|
MI: TMenuItem;
|
|
begin
|
|
MI:= TMenuItem.Create(FMenuStd);
|
|
MI.Caption:= SName;
|
|
MI.Tag:= Cmd;
|
|
MI.OnClick:= @MenuClick;
|
|
FMenuStd.Items.Add(MI);
|
|
end;
|
|
//
|
|
begin
|
|
FMenuStd.OnPopup:= @MenuPopup;
|
|
|
|
Add('Undo', cCommand_Undo);
|
|
Add('Redo', cCommand_Redo);
|
|
Add('-', 0);
|
|
Add('Cut', cCommand_ClipboardCut);
|
|
Add('Copy', cCommand_ClipboardCopy);
|
|
Add('Paste', cCommand_ClipboardPaste);
|
|
Add('Delete', cCommand_TextDeleteSelection);
|
|
Add('-', 0);
|
|
Add('Select all', cCommand_SelectAll);
|
|
end;
|
|
|
|
//drop selection of 1st caret into mouse-pos
|
|
procedure TATSynEdit.DoDropText;
|
|
var
|
|
P, PosAfter, Shift: TPoint;
|
|
X1, Y1, X2, Y2: integer;
|
|
bSel, bEolPos: boolean;
|
|
Str: atString;
|
|
Relation: TATPosRelation;
|
|
begin
|
|
if Carets.Count<>1 then Exit; //allow only 1 caret
|
|
Carets[0].GetRange(X1, Y1, X2, Y2, bSel);
|
|
if not bSel then Exit;
|
|
|
|
DoSelect_None;
|
|
|
|
//calc insert-pos
|
|
P:= ScreenToClient(Mouse.CursorPos);
|
|
P:= ClientPosToCaretPos(P, bEolPos);
|
|
if P.Y<0 then
|
|
begin Beep; Exit end;
|
|
|
|
//can't drop into selection
|
|
Relation:= IsPosInRange(P.X, P.Y, X1, Y1, X2, Y2);
|
|
if Relation=cRelateInside then
|
|
begin Beep; Exit end;
|
|
|
|
Str:= Strings.TextSubstring(X1, Y1, X2, Y2);
|
|
if Str='' then
|
|
begin Beep; Exit end;
|
|
|
|
//insert before selection?
|
|
if Relation=cRelateBefore then
|
|
begin
|
|
Strings.TextDeleteRange(X1, Y1, X2, Y2, Shift, PosAfter);
|
|
Strings.TextInsert(P.X, P.Y, Str, false, Shift, PosAfter);
|
|
|
|
//select moved text
|
|
DoCaretSingle(0, 0);
|
|
with Carets[0] do
|
|
begin
|
|
PosX:= PosAfter.X;
|
|
PosY:= PosAfter.Y;
|
|
EndX:= P.X;
|
|
EndY:= P.Y;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
Strings.TextInsert(P.X, P.Y, Str, false, Shift, PosAfter);
|
|
|
|
//select moved text
|
|
DoCaretSingle(0, 0);
|
|
with Carets[0] do
|
|
begin
|
|
PosX:= PosAfter.X;
|
|
PosY:= PosAfter.Y;
|
|
EndX:= P.X;
|
|
EndY:= P.Y;
|
|
end;
|
|
|
|
Strings.TextDeleteRange(X1, Y1, X2, Y2, Shift, PosAfter);
|
|
DoCaretsShift(X1, Y1, Shift.X, Shift.Y, PosAfter);
|
|
end;
|
|
|
|
Update(true);
|
|
end;
|
|
|
|
function TATSynEdit.GetAutoIndentString(APosX, APosY: integer): atString;
|
|
var
|
|
Str: atString;
|
|
NChars, NSpaces: integer;
|
|
begin
|
|
if not FOptAutoIndent then
|
|
begin Result:= ''; Exit end;
|
|
|
|
Str:= Strings.Lines[APosY];
|
|
NChars:= SGetIndentChars(Str); //count of chars in indent
|
|
NChars:= Min(APosX, NChars); //limit indent by x-pos
|
|
|
|
Str:= Copy(Str, 1, NChars);
|
|
NSpaces:= Length(STabsToSpaces(Str, FTabSize));
|
|
|
|
case FOptAutoIndentKind of
|
|
cIndentAsIs:
|
|
Result:= Str;
|
|
cIndentSpaces:
|
|
Result:= StringOfChar(' ', NSpaces);
|
|
cIndentTabsOnly:
|
|
Result:= StringOfChar(#9, NSpaces div FTabSize);
|
|
cIndentTabsSpaces:
|
|
Result:= StringOfChar(#9, NSpaces div FTabSize) + StringOfChar(' ', NSpaces mod FTabSize);
|
|
else
|
|
raise Exception.Create('Unknown autoindent-kind');
|
|
end;
|
|
end;
|
|
|
|
function TATSynEdit.GetModified: boolean;
|
|
begin
|
|
Result:= Strings.Modified;
|
|
end;
|
|
|
|
function TATSynEdit.GetOneLine: boolean;
|
|
begin
|
|
Result:= Strings.OneLine;
|
|
end;
|
|
|
|
function TATSynEdit.GetRedoCount: integer;
|
|
begin
|
|
Result:= Strings.RedoCount;
|
|
end;
|
|
|
|
function TATSynEdit.GetLinesFromTop: integer;
|
|
var
|
|
P: TPoint;
|
|
begin
|
|
if Carets.Count=0 then
|
|
begin Result:= 0; Exit end;
|
|
with Carets[0] do
|
|
P:= Point(PosX, PosY);
|
|
P:= CaretPosToClientPos(P);
|
|
Result:= (P.Y-FRectMain.Top) div FCharSize.Y;
|
|
end;
|
|
|
|
function TATSynEdit.GetText: atString;
|
|
begin
|
|
Result:= DoGetTextString;
|
|
end;
|
|
|
|
function TATSynEdit.DoGetTextString: atString;
|
|
begin
|
|
//TATEdit overrides it
|
|
Result:= Strings.TextString;
|
|
end;
|
|
|
|
procedure TATSynEdit.DoMinimapClick(APosY: integer);
|
|
var
|
|
NItem: integer;
|
|
begin
|
|
NItem:= (APosY-FRectMinimap.Top) div FCharSizeMinimap.Y + FScrollVertMinimap.NPos;
|
|
if FWrapInfo.IsIndexValid(NItem) then
|
|
begin
|
|
NItem:= Max(0, NItem - GetVisibleLines div 2);
|
|
FScrollVert.NPos:= Min(NItem, FScrollVert.NMax);
|
|
Update;
|
|
end;
|
|
end;
|
|
|
|
procedure TATSynEdit.DoMinimapDrag(APosY: integer);
|
|
var
|
|
NIndex: integer;
|
|
begin
|
|
NIndex:= GetMinimapSelTop_PixelsToWrapIndex(APosY);
|
|
FScrollVert.NPos:= Max(0, Min(NIndex, FScrollVert.NMax));
|
|
Update;
|
|
end;
|
|
|
|
function TATSynEdit.GetUndoLimit: integer;
|
|
begin
|
|
Result:= Strings.UndoLimit;
|
|
end;
|
|
|
|
procedure TATSynEdit.SetUndoLimit(AValue: integer);
|
|
begin
|
|
Strings.UndoLimit:= AValue;
|
|
end;
|
|
|
|
function TATSynEdit.GetUndoAfterSave: boolean;
|
|
begin
|
|
Result:= Strings.UndoAfterSave;
|
|
end;
|
|
|
|
function TATSynEdit.GetUndoCount: integer;
|
|
begin
|
|
Result:= Strings.UndoCount;
|
|
end;
|
|
|
|
procedure TATSynEdit.SetUndoAfterSave(AValue: boolean);
|
|
begin
|
|
Strings.UndoAfterSave:= AValue;
|
|
end;
|
|
|
|
procedure TATSynEdit.DoSizeChange(AInc: boolean);
|
|
var
|
|
NTop: integer;
|
|
begin
|
|
if not FOptAllowZooming then Exit;
|
|
if not AInc then
|
|
if Font.Size<=cMinFontSize then Exit;
|
|
|
|
NTop:= LineTop;
|
|
Font.Size:= Font.Size+BoolToPlusMinusOne(AInc);
|
|
Update;
|
|
AppProcessMessages;
|
|
|
|
LineTop:= NTop;
|
|
Update;
|
|
end;
|
|
|
|
procedure TATSynEdit.BeginUpdate;
|
|
begin
|
|
Inc(FPaintLocked);
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TATSynEdit.EndUpdate;
|
|
begin
|
|
Dec(FPaintLocked);
|
|
if FPaintLocked=0 then
|
|
Invalidate;
|
|
end;
|
|
|
|
function TATSynEdit.TextSelected: atString;
|
|
var
|
|
X1, Y1, X2, Y2: integer;
|
|
bSel: boolean;
|
|
begin
|
|
Result:= '';
|
|
if Carets.Count=0 then Exit;
|
|
Carets[0].GetRange(X1, Y1, X2, Y2, bSel);
|
|
if bSel then
|
|
Result:= Strings.TextSubstring(X1, Y1, X2, Y2);
|
|
end;
|
|
|
|
function TATSynEdit.TextCurrentWord: atString;
|
|
var
|
|
Str: atString;
|
|
Caret: TATCaretItem;
|
|
N1, N2: integer;
|
|
begin
|
|
Result:= '';
|
|
if Carets.Count=0 then Exit;
|
|
Caret:= Carets[0];
|
|
Str:= Strings.Lines[Caret.PosY];
|
|
SFindWordBounds(Str, Caret.PosX, N1, N2, OptWordChars);
|
|
if N2>N1 then
|
|
Result:= Copy(Str, N1+1, N2-N1);
|
|
end;
|
|
|
|
function TATSynEdit.GetMouseNiceScroll: boolean;
|
|
begin
|
|
Result:= FTimerNiceScroll.Enabled;
|
|
end;
|
|
|
|
procedure TATSynEdit.SetMouseNiceScroll(AValue: boolean);
|
|
begin
|
|
FTimerNiceScroll.Enabled:= AValue;
|
|
if not AValue then
|
|
UpdateCursor;
|
|
Invalidate;
|
|
end;
|
|
|
|
function TATSynEdit.GetEndOfFilePos: TPoint;
|
|
begin
|
|
Result.X:= 0;
|
|
Result.Y:= 0;
|
|
if Strings.Count>0 then
|
|
begin
|
|
Result.Y:= Strings.Count-1;
|
|
Result.X:= Length(Strings.Lines[Result.Y]);
|
|
if Strings.LinesEnds[Result.Y]<>cEndNone then
|
|
Inc(Result.X);
|
|
end;
|
|
end;
|
|
|
|
procedure TATSynEdit.DoPaintGutterFolding(C: TCanvas;
|
|
AWrapItemIndex: integer;
|
|
ACoordX1, ACoordX2, ACoordY1, ACoordY2: integer);
|
|
var
|
|
List: TATIntArray;
|
|
State: (cFoldbarNone, cFoldbarBegin, cFoldbarEnd, cFoldbarMiddle);
|
|
CoordXM, CoordYM: integer;
|
|
WrapItem: TATSynWrapItem;
|
|
LineIndex: integer;
|
|
IsPlus, IsLineUp, IsLineDown: boolean;
|
|
i: integer;
|
|
//
|
|
procedure DrawUp;
|
|
begin
|
|
if IsLineUp then
|
|
C.Line(
|
|
CoordXM,
|
|
ACoordY1,
|
|
CoordXM,
|
|
CoordYM
|
|
);
|
|
end;
|
|
procedure DrawDown;
|
|
begin
|
|
if IsLineDown then
|
|
C.Line(
|
|
CoordXM,
|
|
CoordYM,
|
|
CoordXM,
|
|
ACoordY2
|
|
);
|
|
end;
|
|
//
|
|
begin
|
|
if not FOptGutterShowFoldAlways then
|
|
if not FCursorOnGutter then Exit;
|
|
|
|
WrapItem:= FWrapInfo[AWrapItemIndex];
|
|
LineIndex:= WrapItem.NLineIndex;
|
|
|
|
List:= FFold.FindRangesContainingLines(LineIndex, LineIndex, nil,
|
|
false{OnlyFolded}, false{TopLevelOnly}, cRngHasAllLines);
|
|
if Length(List)=0 then Exit;
|
|
|
|
//calc state
|
|
State:= cFoldbarNone;
|
|
IsPlus:= false;
|
|
IsLineUp:= false;
|
|
IsLineDown:= false;
|
|
|
|
for i:= Low(List) to High(List) do
|
|
with FFold[List[i]] do
|
|
begin
|
|
if Y<LineIndex then IsLineUp:= true;
|
|
if Y2>LineIndex then IsLineDown:= true;
|
|
if Y=LineIndex then
|
|
begin
|
|
State:= cFoldbarBegin;
|
|
//don't override found [+], 2 blocks can start at same pos
|
|
if not IsPlus then IsPlus:= Folded;
|
|
end;
|
|
if Y2=LineIndex then
|
|
if State<>cFoldbarBegin then
|
|
State:= cFoldbarEnd;
|
|
end;
|
|
|
|
//correct state for wrapped line
|
|
if State=cFoldbarBegin then
|
|
if not FWrapInfo.IsItemInitial(AWrapItemIndex) then
|
|
State:= cFoldbarMiddle;
|
|
|
|
//correct state for wrapped line
|
|
if State=cFoldbarEnd then
|
|
if WrapItem.NFinal=cWrapItemMiddle then
|
|
State:= cFoldbarMiddle;
|
|
|
|
C.Pen.Color:= IfThen(FOptGutterShowFoldLines,
|
|
FColors.GutterFoldLine,
|
|
FColors.GutterFoldBG);
|
|
|
|
CoordXM:= (ACoordX1+ACoordX2) div 2;
|
|
CoordYM:= (ACoordY1+ACoordY2) div 2;
|
|
|
|
case State of
|
|
cFoldbarBegin:
|
|
begin
|
|
if FOptGutterShowFoldLinesAll then
|
|
begin DrawUp; DrawDown; end;
|
|
|
|
if not IsPlus then
|
|
DrawDown;
|
|
|
|
CanvasPaintPlusMinus(C,
|
|
FColors.GutterPlusBorder,
|
|
FColors.GutterPlusBG,
|
|
Point(CoordXM, CoordYM),
|
|
FOptGutterPlusSize,
|
|
IsPlus);
|
|
end;
|
|
cFoldbarEnd:
|
|
begin
|
|
if FOptGutterShowFoldLinesAll then
|
|
begin DrawUp; DrawDown; end;
|
|
|
|
Dec(ACoordY2, cSizeGutterFoldLineDx);
|
|
C.Line(
|
|
CoordXM,
|
|
ACoordY1,
|
|
CoordXM,
|
|
ACoordY2
|
|
);
|
|
C.Line(
|
|
CoordXM,
|
|
ACoordY2,
|
|
CoordXM + FOptGutterPlusSize,
|
|
ACoordY2
|
|
);
|
|
end;
|
|
cFoldbarMiddle:
|
|
begin
|
|
C.Line(
|
|
CoordXM,
|
|
ACoordY1,
|
|
CoordXM,
|
|
ACoordY2
|
|
);
|
|
end;
|
|
else
|
|
begin
|
|
DrawUp;
|
|
DrawDown;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TATSynEdit.DoPaintTextHintTo(C: TCanvas);
|
|
var
|
|
Size: TSize;
|
|
Pos: TPoint;
|
|
begin
|
|
C.Brush.Color:= GetColorTextBG;
|
|
C.Font.Color:= FColors.TextHintFont;
|
|
C.Font.Style:= FTextHintFontStyle;
|
|
|
|
Size:= C.TextExtent(FTextHint);
|
|
if FTextHintCenter then
|
|
begin
|
|
Pos:= CenterPoint(FRectMain);
|
|
Dec(Pos.X, Size.cx div 2);
|
|
Dec(Pos.Y, Size.cy div 2);
|
|
end
|
|
else
|
|
begin
|
|
Pos:= FTextOffset;
|
|
end;
|
|
|
|
C.TextOut(Pos.X, Pos.Y, FTextHint);
|
|
end;
|
|
|
|
|
|
procedure TATSynEdit.WMGetDlgCode(var Msg: TLMNoParams);
|
|
begin
|
|
inherited;
|
|
Msg.Result:= DLGC_WANTARROWS or DLGC_WANTCHARS or DLGC_WANTALLKEYS;
|
|
if FWantTabs and (GetKeyState(VK_CONTROL) >= 0) then
|
|
Msg.Result:= Msg.Result or DLGC_WANTTAB;
|
|
end;
|
|
|
|
procedure TATSynEdit.DoPaintStaple(C: TCanvas; const R: TRect; AColor: TColor);
|
|
begin
|
|
if FOptShowStapleStyle=cLineStyleNone then Exit;
|
|
CanvasLineEx(C, AColor, FOptShowStapleStyle, Point(R.Left, R.Top), Point(R.Right, R.Top), false);
|
|
CanvasLineEx(C, AColor, FOptShowStapleStyle, Point(R.Left, R.Top), Point(R.Left, R.Bottom), false);
|
|
CanvasLineEx(C, AColor, FOptShowStapleStyle, Point(R.Left, R.Bottom), Point(R.Right, R.Bottom), true);
|
|
end;
|
|
|
|
procedure TATSynEdit.DoPaintStaples(C: TCanvas; const ARect: TRect;
|
|
ACharSize: TPoint; const AScrollHorz: TATSynScrollInfo);
|
|
var
|
|
nLineFrom, nLineTo, nIndent: integer;
|
|
Indexes: TATIntArray;
|
|
Range: TATSynRange;
|
|
P1, P2: TPoint;
|
|
i: integer;
|
|
RSt: TRect;
|
|
NColor: TColor;
|
|
begin
|
|
if FOptShowStapleStyle=cLineStyleNone then Exit;
|
|
nLineFrom:= LineTop;
|
|
nLineTo:= LineBottom;
|
|
Indexes:= FFold.FindRangesContainingLines(nLineFrom, nLineTo, nil,
|
|
false{OnlyFolded}, false{TopLevelOnly}, cRngHasAnyOfLines);
|
|
|
|
//c.font.color:= clblue;
|
|
//c.textout(arect.right-150, arect.top, format('staples vis %d', [length(indexes)]));
|
|
|
|
for i:= 0 to High(Indexes) do
|
|
begin
|
|
Range:= FFold[Indexes[i]];
|
|
if not Range.Staple then Continue;
|
|
if Range.Folded then Continue;
|
|
|
|
if IsLineFolded(Range.Y, true) then Continue;
|
|
if IsLineFolded(Range.Y2, true) then Continue;
|
|
|
|
P1:= CaretPosToClientPos(Point(0, Range.Y));
|
|
P2:= CaretPosToClientPos(Point(0, Range.Y2));
|
|
if (P1.Y<0) and (Range.Y>=nLineFrom) then Continue;
|
|
if (P2.Y<0) and (Range.Y2>=nLineFrom) then Continue;
|
|
|
|
NIndent:= SGetIndentExpanded(Strings.Lines[Range.Y], FTabSize);
|
|
Inc(P1.X, NIndent*ACharSize.X);
|
|
Inc(P2.X, NIndent*ACharSize.X);
|
|
|
|
RSt.Left:= P1.X + FOptShowStapleIndent;
|
|
RSt.Top:= P1.Y;
|
|
RSt.Right:= RSt.Left+ (ACharSize.X * FOptShowStapleWidthPercent div 100);
|
|
RSt.Bottom:= P2.Y + ACharSize.Y-1;
|
|
|
|
if (RSt.Left>=ARect.Left) and
|
|
(RSt.Left<ARect.Right) then
|
|
begin
|
|
NColor:= Colors.BlockStaple;
|
|
if Assigned(FOnCalcStaple) then
|
|
FOnCalcStaple(Self, Range.Y, NIndent, NColor);
|
|
DoPaintStaple(C, RSt, NColor);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
function TATSynEdit.IsCharWord(ch: Widechar): boolean;
|
|
begin
|
|
Result:= ATStringProc.IsCharWord(ch, OptWordChars);
|
|
end;
|
|
|
|
function TATSynEdit.GetColorTextBG: TColor;
|
|
begin
|
|
if Enabled then
|
|
Result:= Colors.TextBG
|
|
else
|
|
Result:= Colors.TextDisabledBG;
|
|
end;
|
|
|
|
function TATSynEdit.GetColorTextFont: TColor;
|
|
begin
|
|
if Enabled then
|
|
Result:= Colors.TextFont
|
|
else
|
|
Result:= Colors.TextDisabledFont;
|
|
end;
|
|
|
|
procedure TATSynEdit.DoPaintMarkersTo(C: TCanvas);
|
|
var
|
|
M: TATMarkerItem;
|
|
i: integer;
|
|
begin
|
|
for i:= 0 to Markers.Count-1 do
|
|
begin
|
|
M:= Markers[i];
|
|
if M.CoordX<0 then Continue;
|
|
if M.CoordY<0 then Continue;
|
|
if not PtInRect(FRectMain, Point(M.CoordX, M.CoordY)) then Continue;
|
|
|
|
C.Brush.Color:= Colors.Markers;
|
|
C.Pen.Color:= Colors.Markers;
|
|
C.Polygon([
|
|
Point(M.CoordX, M.CoordY+FCharSize.Y-FOptMarkersSize-1),
|
|
Point(M.CoordX-FOptMarkersSize, M.CoordY+FCharSize.Y-1),
|
|
Point(M.CoordX+FOptMarkersSize, M.CoordY+FCharSize.Y-1) ]);
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TATSynEdit.DoDebugAddAttribs;
|
|
var
|
|
p1, p2, p3: TATLinePartClass;
|
|
begin
|
|
p1:= TATLinePartClass.Create;
|
|
p2:= TATLinePartClass.Create;
|
|
p3:= TATLinePartClass.Create;
|
|
|
|
p1.Data.ColorBG:= clgreen;
|
|
p1.Data.ColorFont:= clwhite;
|
|
p1.data.BorderDown:= cLineStyleDotted;
|
|
Attribs.Add(1,1, 0, 4, p1);
|
|
|
|
p2.Data.ColorBG:= clYellow;
|
|
p2.Data.ColorFont:= clBlue;
|
|
p2.data.BorderDown:= cLineStyleSolid;
|
|
Attribs.Add(2,2, 0, 4, p2);
|
|
|
|
p3.Data.ColorBG:= clRed;
|
|
p3.Data.ColorFont:= clYellow;
|
|
Attribs.Add(3,3, 0, 4, p3);
|
|
end;
|
|
|
|
procedure TATSynEdit.DoSetMarkedLines(ALine1, ALine2: integer);
|
|
begin
|
|
FMarkedRange.Clear;
|
|
if (ALine1>=0) and (ALine2>=ALine1) then
|
|
begin
|
|
FMarkedRange.Add(0, ALine1);
|
|
FMarkedRange.Add(0, ALine2);
|
|
end;
|
|
end;
|
|
|
|
procedure TATSynEdit.DoGetMarkedLines(out ALine1, ALine2: integer);
|
|
begin
|
|
ALine1:= -1;
|
|
ALine2:= -1;
|
|
if FMarkedRange.Count=2 then
|
|
begin
|
|
ALine1:= FMarkedRange.Items[0].PosY;
|
|
ALine2:= FMarkedRange.Items[1].PosY;
|
|
end;
|
|
end;
|
|
|
|
|
|
{$I atsynedit_carets.inc}
|
|
{$I atsynedit_hilite.inc}
|
|
{$I atsynedit_sel.inc}
|
|
{$I atsynedit_fold.inc}
|
|
{$I atsynedit_debug.inc}
|
|
{$R res/nicescroll.res}
|
|
{$R res/foldbar.res}
|
|
|
|
{$I atsynedit_cmd_handler.inc}
|
|
{$I atsynedit_cmd_keys.inc}
|
|
{$I atsynedit_cmd_sel.inc}
|
|
{$I atsynedit_cmd_editing.inc}
|
|
{$I atsynedit_cmd_clipboard.inc}
|
|
{$I atsynedit_cmd_misc.inc}
|
|
|
|
|
|
initialization
|
|
InitClipboardFormat;
|
|
InitResourcesNicescroll;
|
|
|
|
finalization
|
|
FreeResources;
|
|
|
|
end.
|
|
|