3055 lines
103 KiB
ObjectPascal
Raw Permalink Normal View History

2011-10-06 20:53:09 +02:00
unit ScintEdit;
{
Inno Setup
2024-03-29 08:20:50 +01:00
Copyright (C) 1997-2024 Jordan Russell
2011-10-06 20:53:09 +02:00
Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT.
TScintEdit component: a VCL wrapper for Scintilla
}
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Generics.Collections, ScintInt;
2011-10-06 20:53:09 +02:00
const
StyleNumbers = 32; { The syntax highlighting can use up to 32 styles }
StyleNumberBits = 5; { 5 bits are needed to store 32 values }
StyleNumberMask = StyleNumbers-1; { To get the 5 bits from a byte it needs to be AND-ed with $1F = 31 }
StyleNumberUnusedBits = 8-StyleNumberBits; { 3 bits of a byte are unused }
2011-10-06 20:53:09 +02:00
type
2024-06-17 15:49:37 +02:00
TScintChangeHistory = (schDisabled, schMarkers, schIndicators);
TScintCommand = type NativeInt;
TScintEditAutoCompleteSelectionEvent = TNotifyEvent;
2024-07-26 10:35:31 +02:00
TScintEditCallTipArrowClick = procedure(Sender: TObject; const Up: Boolean) of object;
2011-10-06 20:53:09 +02:00
TScintEditChangeInfo = record
Inserting: Boolean;
StartPos, Length, LinesDelta: Integer;
end;
TScintEditChangeEvent = procedure(Sender: TObject;
const Info: TScintEditChangeInfo) of object;
TScintEditCharAddedEvent = procedure(Sender: TObject; Ch: AnsiChar) of object;
TScintEditDropFilesEvent = procedure(Sender: TObject; X, Y: Integer;
AFiles: TStrings) of object;
2024-03-30 21:07:36 +01:00
TScintHintInfo = Controls.THintInfo;
2011-10-06 20:53:09 +02:00
TScintEditHintShowEvent = procedure(Sender: TObject;
var Info: TScintHintInfo) of object;
TScintEditMarginClickEvent = procedure(Sender: TObject; MarginNumber: Integer;
Line: Integer) of object;
TScintEditUpdate = (suContent, suSelection, suVScroll, suHScroll);
TScintEditUpdates = set of TScintEditUpdate;
TScintEditUpdateUIEvent = procedure(Sender: TObject; Updated: TScintEditUpdates) of object;
TScintFindOption = (sfoMatchCase, sfoWholeWord, sfoRegEx);
2011-10-06 20:53:09 +02:00
TScintFindOptions = set of TScintFindOption;
TScintFoldFlag = (sffLineBeforeExpanded, sffLineBeforeContracted,
sffLineAfterExpanded, sffLineAfterContracted, sffLevelNumbers, sffLineState);
TScintFoldFlags = set of TScintFoldFlag;
2011-10-06 20:53:09 +02:00
TScintIndentationGuides = (sigNone, sigReal, sigLookForward, sigLookBoth);
TScintKeyCode = type Word;
TScintKeyDefinition = type Cardinal;
TScintReplaceMode = (srmNormal, srmMinimal, srmRegEx);
TScintStyleByteIndicatorNumber = 0..1; { Could be increased to 0..StyleNumberUnusedBits-1 }
TScintStyleByteIndicatorNumbers = set of TScintStyleByteIndicatorNumber;
2024-06-12 17:24:55 +02:00
TScintIndicatorNumber = INDICATOR_CONTAINER..INDICATOR_MAX;
2011-10-06 20:53:09 +02:00
TScintLineEndings = (sleCRLF, sleCR, sleLF);
TScintLineState = type Integer;
TScintMarkerNumber = 0..31;
TScintMarkerNumbers = set of TScintMarkerNumber;
TScintRange = record
StartPos, EndPos: Integer;
constructor Create(const AStartPos, AEndPos: Integer);
function Empty: Boolean;
function Overlaps(const ARange: TScintRange): Boolean;
function Within(const ARange: TScintRange): Boolean;
2011-10-06 20:53:09 +02:00
end;
TScintRangeList = class(TList<TScintRange>)
function Overlaps(const ARange: TScintRange;
var AOverlappingRange: TScintRange): Boolean;
end;
2024-06-27 16:57:54 +02:00
TScintCaretAndAnchor = record
CaretPos, AnchorPos: Integer;
constructor Create(const ACaretPos, AAnchorPos: Integer);
function Range: TScintRange;
end;
TScintCaretAndAnchorList = class(TList<TScintCaretAndAnchor>);
2011-10-06 20:53:09 +02:00
TScintRawCharSet = set of AnsiChar;
2024-03-30 21:07:36 +01:00
TScintRawString = type RawByteString;
TScintRectangle = record
Left, Top, Right, Bottom: Integer;
end;
2024-06-15 01:34:41 +02:00
TScintSelectionMode = (ssmStream, ssmRectangular, ssmLines, ssmThinRectangular);
TScintStyleNumber = 0..StyleNumbers-1;
2024-06-11 20:26:25 +02:00
TScintVirtualSpaceOption = (svsRectangularSelection, svsUserAccessible,
svsNoWrapLineStart);
2011-10-06 20:53:09 +02:00
TScintVirtualSpaceOptions = set of TScintVirtualSpaceOption;
PScintRangeToFormat = ^TScintRangeToFormat;
TScintRangeToFormat = record
hdc, hdcTarget: UINT_PTR;
rc, rcPage: TScintRectangle;
chrg: TScintRange;
end;
2011-10-06 20:53:09 +02:00
TScintEditStrings = class;
TScintCustomStyler = class;
2024-06-15 01:34:41 +02:00
EScintEditError = class(Exception);
2011-10-06 20:53:09 +02:00
TScintEdit = class(TWinControl)
private
FAcceptDroppedFiles: Boolean;
FAutoCompleteFontName: String;
FAutoCompleteFontSize: Integer;
FAutoCompleteStyle: Integer;
2024-06-17 15:49:37 +02:00
FChangeHistory: TScintChangeHistory;
2011-10-06 20:53:09 +02:00
FCodePage: Integer;
FDirectPtr: Pointer;
FDirectStatusFunction: SciFnDirectStatus;
2011-10-06 20:53:09 +02:00
FEffectiveCodePage: Integer;
FEffectiveCodePageDBCS: Boolean;
FFillSelectionToEdge: Boolean;
FFoldLevelNumbersOrLineState: Boolean;
2011-10-06 20:53:09 +02:00
FForceModified: Boolean;
FIndentationGuides: TScintIndentationGuides;
FLeadBytes: TScintRawCharSet;
FLineNumbers: Boolean;
2011-10-06 20:53:09 +02:00
FLines: TScintEditStrings;
FOnAutoCompleteSelection: TScintEditAutoCompleteSelectionEvent;
2024-07-26 10:35:31 +02:00
FOnCallTipArrowClick: TScintEditCallTipArrowClick;
2011-10-06 20:53:09 +02:00
FOnChange: TScintEditChangeEvent;
FOnCharAdded: TScintEditCharAddedEvent;
FOnDropFiles: TScintEditDropFilesEvent;
FOnHintShow: TScintEditHintShowEvent;
FOnMarginClick: TScintEditMarginClickEvent;
FOnMarginRightClick: TScintEditMarginClickEvent;
2011-10-06 20:53:09 +02:00
FOnModifiedChange: TNotifyEvent;
FOnUpdateUI: TScintEditUpdateUIEvent;
FOnZoom: TNotifyEvent;
2011-10-06 20:53:09 +02:00
FReportCaretPositionToStyler: Boolean;
FStyler: TScintCustomStyler;
FTabWidth: Integer;
FUseStyleAttributes: Boolean;
FUseTabCharacter: Boolean;
FVirtualSpaceOptions: TScintVirtualSpaceOptions;
2024-06-29 21:51:50 +02:00
FWordChars: AnsiString;
FWordCharsAsSet: TSysCharSet;
2011-10-06 20:53:09 +02:00
FWordWrap: Boolean;
procedure ApplyOptions;
procedure ForwardMessage(const Message: TMessage);
2011-10-06 20:53:09 +02:00
function GetAutoCompleteActive: Boolean;
2024-06-29 21:51:50 +02:00
function GetCallTipActive: Boolean;
2011-10-06 20:53:09 +02:00
function GetCaretColumn: Integer;
2024-05-18 09:03:17 +02:00
function GetCaretColumnExpandedForTabs: Integer;
2011-10-06 20:53:09 +02:00
function GetCaretLine: Integer;
2024-06-30 15:25:14 +02:00
function GetCaretLineText: String;
2011-10-06 20:53:09 +02:00
function GetCaretPosition: Integer;
2024-06-30 15:25:14 +02:00
function GetCaretPositionInLine: Integer;
2011-10-06 20:53:09 +02:00
function GetCaretVirtualSpace: Integer;
function GetInsertMode: Boolean;
function GetLineEndings: TScintLineEndings;
function GetLineEndingString: TScintRawString;
function GetLineHeight: Integer;
function GetLinesInWindow: Integer;
function GetMainSelText: String;
2011-10-06 20:53:09 +02:00
function GetModified: Boolean;
2024-06-30 15:25:14 +02:00
function GetRawCaretLineText: TScintRawString;
function GetRawMainSelText: TScintRawString;
2011-10-06 20:53:09 +02:00
function GetRawSelText: TScintRawString;
function GetRawText: TScintRawString;
function GetReadOnly: Boolean;
class function GetReplaceTargetMessage(const ReplaceMode: TScintReplaceMode): Cardinal;
class function GetSearchFlags(const Options: TScintFindOptions): Integer;
2011-10-06 20:53:09 +02:00
function GetSelection: TScintRange;
2024-06-06 09:32:39 +02:00
function GetSelectionAnchorPosition(Selection: Integer): Integer;
function GetSelectionAnchorVirtualSpace(Selection: Integer): Integer;
2024-06-06 09:32:39 +02:00
function GetSelectionCaretPosition(Selection: Integer): Integer;
function GetSelectionCaretVirtualSpace(Selection: Integer): Integer;
function GetSelectionEndPosition(Selection: Integer): Integer;
2024-06-06 09:30:47 +02:00
function GetSelectionCount: Integer;
2024-06-15 01:34:41 +02:00
function GetSelectionMode: TScintSelectionMode;
function GetSelectionStartPosition(Selection: Integer): Integer;
2011-10-06 20:53:09 +02:00
function GetSelText: String;
function GetTopLine: Integer;
function GetZoom: Integer;
procedure SetAcceptDroppedFiles(const Value: Boolean);
procedure SetAutoCompleteFontName(const Value: String);
procedure SetAutoCompleteFontSize(const Value: Integer);
procedure SetCodePage(const Value: Integer);
procedure SetCaretColumn(const Value: Integer);
procedure SetCaretLine(const Value: Integer);
procedure SetCaretPosition(const Value: Integer);
2024-06-26 22:07:19 +02:00
procedure SetCaretPositionWithSelectFromAnchor(const Value: Integer);
2011-10-06 20:53:09 +02:00
procedure SetCaretVirtualSpace(const Value: Integer);
2024-06-17 15:49:37 +02:00
procedure SetChangeHistory(const Value: TScintChangeHistory);
2011-10-06 20:53:09 +02:00
procedure SetFillSelectionToEdge(const Value: Boolean);
2024-06-30 15:25:47 +02:00
procedure SetFoldFlags(const Value: TScintFoldFlags);
2011-10-06 20:53:09 +02:00
procedure SetIndentationGuides(const Value: TScintIndentationGuides);
procedure SetLineNumbers(const Value: Boolean);
procedure SetMainSelection(const Value: Integer);
procedure SetMainSelText(const Value: String);
procedure SetRawMainSelText(const Value: TScintRawString);
2011-10-06 20:53:09 +02:00
procedure SetRawSelText(const Value: TScintRawString);
procedure SetRawText(const Value: TScintRawString);
procedure SetReadOnly(const Value: Boolean);
procedure SetSelection(const Value: TScintRange);
procedure SetSelectionAnchorPosition(Selection: Integer; const Value: Integer);
procedure SetSelectionAnchorVirtualSpace(Selection: Integer;
const Value: Integer);
procedure SetSelectionCaretPosition(Selection: Integer; const Value: Integer);
procedure SetSelectionCaretVirtualSpace(Selection: Integer;
const Value: Integer);
2024-06-15 01:34:41 +02:00
procedure SetSelectionMode(const Value: TScintSelectionMode);
2011-10-06 20:53:09 +02:00
procedure SetSelText(const Value: String);
procedure SetStyler(const Value: TScintCustomStyler);
procedure SetTabWidth(const Value: Integer);
procedure SetTopLine(const Value: Integer);
procedure SetUseStyleAttributes(const Value: Boolean);
procedure SetUseTabCharacter(const Value: Boolean);
procedure SetVirtualSpaceOptions(const Value: TScintVirtualSpaceOptions);
procedure SetWordWrap(const Value: Boolean);
procedure SetZoom(const Value: Integer);
procedure UpdateCodePage;
procedure UpdateLineNumbersWidth;
2011-10-06 20:53:09 +02:00
procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED;
procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
procedure CMHintShow(var Message: TCMHintShow); message CM_HINTSHOW;
procedure CMSysColorChange(var Message: TMessage); message CM_SYSCOLORCHANGE;
procedure CNNotify(var Message: TWMNotify); message CN_NOTIFY;
procedure WMDestroy(var Message: TWMDestroy); message WM_DESTROY;
procedure WMDropFiles(var Message: TWMDropFiles); message WM_DROPFILES;
procedure WMEraseBkgnd(var Message: TMessage); message WM_ERASEBKGND;
procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
procedure WMMouseWheel(var Message: TMessage); message WM_MOUSEWHEEL;
protected
procedure Change(const AInserting: Boolean; const AStartPos, ALength,
ALinesDelta: Integer); virtual;
procedure CheckPosRange(const StartPos, EndPos: Integer);
procedure CreateParams(var Params: TCreateParams); override;
procedure CreateWnd; override;
2024-06-15 01:34:41 +02:00
class function GetErrorException(const S: String): EScintEditError;
class procedure Error(const S: String); overload;
2011-10-06 20:53:09 +02:00
class procedure ErrorFmt(const S: String; const Args: array of const);
function GetMainSelection: Integer;
function GetTarget: TScintRange;
procedure InitRawString(var S: TScintRawString; const Len: Integer);
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
procedure Notify(const N: TSCNotification); virtual;
procedure SetTarget(const StartPos, EndPos: Integer);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure AddMarker(const Line: Integer; const Marker: TScintMarkerNumber);
procedure AddSelection(const CaretPos, AnchorPos: Integer);
procedure AssignCmdKey(const Key: AnsiChar; const Shift: TShiftState;
const Command: TScintCommand); overload;
procedure AssignCmdKey(const KeyCode: TScintKeyCode; const Shift: TShiftState;
const Command: TScintCommand); overload;
2011-10-06 20:53:09 +02:00
procedure BeginUndoAction;
function Call(Msg: Cardinal; WParam: Longint; LParam: Longint): Longint; overload;
function Call(Msg: Cardinal; WParam: Longint; LParam: Longint; out WarnStatus: Integer): Longint; overload;
function Call(Msg: Cardinal; WParam: Longint; const LParamStr: TScintRawString): Longint; overload;
function Call(Msg: Cardinal; WParam: Longint; const LParamStr: TScintRawString; out WarnStatus: Integer): Longint; overload;
2011-10-06 20:53:09 +02:00
procedure CancelAutoComplete;
procedure CancelAutoCompleteAndCallTip;
2024-06-29 21:51:50 +02:00
procedure CancelCallTip;
2024-10-11 13:18:42 +02:00
function CanPaste: Boolean;
2011-10-06 20:53:09 +02:00
function CanRedo: Boolean;
function CanUndo: Boolean;
procedure ChooseCaretX;
procedure ClearAll;
procedure ClearCmdKey(const Key: AnsiChar; const Shift: TShiftState); overload;
procedure ClearCmdKey(const KeyCode: TScintKeyCode; const Shift: TShiftState); overload;
procedure ClearIndicators(const IndicatorNumber: TScintIndicatorNumber);
2011-10-06 20:53:09 +02:00
procedure ClearSelection;
procedure ClearUndo(const ClearChangeHistory: Boolean = True);
2011-10-06 20:53:09 +02:00
function ConvertRawStringToString(const S: TScintRawString): String;
function ConvertPCharToRawString(const Text: PChar;
const TextLen: Integer): TScintRawString;
function ConvertStringToRawString(const S: String): TScintRawString;
procedure CopyToClipboard;
procedure CutToClipboard;
procedure DeleteAllMarkersOnLine(const Line: Integer);
procedure DeleteMarker(const Line: Integer; const Marker: TScintMarkerNumber);
procedure DPIChanged(const Message: TMessage);
2011-10-06 20:53:09 +02:00
procedure EndUndoAction;
procedure EnsureLineVisible(const Line: Integer);
2011-10-06 20:53:09 +02:00
function FindRawText(const StartPos, EndPos: Integer; const S: TScintRawString;
const Options: TScintFindOptions; out MatchRange: TScintRange): Boolean;
function FindText(const StartPos, EndPos: Integer; const S: String;
const Options: TScintFindOptions; out MatchRange: TScintRange): Boolean;
procedure FoldLine(const Line: Integer; const Fold: Boolean);
function FormatRange(const Draw: Boolean;
const RangeToFormat: PScintRangeToFormat): Integer;
2011-10-06 20:53:09 +02:00
procedure ForceModifiedState;
2024-06-28 06:54:40 +02:00
function GetByteAtPosition(const Pos: Integer): AnsiChar;
function GetCharacterCount(const StartPos, EndPos: Integer): Integer;
2011-10-06 20:53:09 +02:00
function GetColumnFromPosition(const Pos: Integer): Integer;
function GetDefaultWordChars: AnsiString;
2011-10-06 20:53:09 +02:00
function GetDocLineFromVisibleLine(const VisibleLine: Integer): Integer;
function GetIndicatorAtPosition(const IndicatorNumber: TScintIndicatorNumber;
const Pos: Integer): Boolean;
2011-10-06 20:53:09 +02:00
function GetLineEndPosition(const Line: Integer): Integer;
function GetLineFromPosition(const Pos: Integer): Integer;
function GetLineIndentation(const Line: Integer): Integer;
function GetLineIndentPosition(const Line: Integer): Integer;
function GetMarkers(const Line: Integer): TScintMarkerNumbers;
function GetPointFromPosition(const Pos: Integer): TPoint;
function GetPositionAfter(const Pos: Integer): Integer;
function GetPositionBefore(const Pos: Integer): Integer;
function GetPositionFromLine(const Line: Integer): Integer;
function GetPositionFromLineColumn(const Line, Column: Integer): Integer;
function GetPositionFromLineExpandedColumn(const Line, ExpandedColumn: Integer): Integer;
function GetPositionFromPoint(const P: TPoint;
const CharPosition, CloseOnly: Boolean): Integer;
function GetPositionOfMatchingBrace(const Pos: Integer): Integer;
2024-06-28 06:54:40 +02:00
function GetPositionRelative(const Pos, CharacterCount: Integer): Integer;
function GetRawTextLength: Integer;
2011-10-06 20:53:09 +02:00
function GetRawTextRange(const StartPos, EndPos: Integer): TScintRawString;
2024-06-27 16:57:54 +02:00
procedure GetSelections(const RangeList: TScintRangeList); overload;
procedure GetSelections(const CaretAndAnchorList: TScintCaretAndAnchorList); overload;
procedure GetSelections(const CaretAndAnchorList, VirtualSpacesList: TScintCaretAndAnchorList); overload;
2011-10-06 20:53:09 +02:00
function GetStyleAtPosition(const Pos: Integer): TScintStyleNumber;
function GetTextRange(const StartPos, EndPos: Integer): String;
function GetVisibleLineFromDocLine(const DocLine: Integer): Integer;
function GetWordEndPosition(const Pos: Integer; const OnlyWordChars: Boolean): Integer;
function GetWordStartPosition(const Pos: Integer; const OnlyWordChars: Boolean): Integer;
function IsPositionInViewVertically(const Pos: Integer): Boolean;
class function KeyCodeAndShiftToKeyDefinition(const KeyCode: TScintKeyCode;
Shift: TShiftState): TScintKeyDefinition;
function MainSelTextEquals(const S: String;
const Options: TScintFindOptions): Boolean;
class function KeyToKeyCode(const Key: AnsiChar): TScintKeyCode;
2011-10-06 20:53:09 +02:00
procedure PasteFromClipboard;
function RawMainSelTextEquals(const S: TScintRawString;
const Options: TScintFindOptions): Boolean;
2024-06-17 15:49:37 +02:00
class function RawStringIsBlank(const S: TScintRawString): Boolean;
2011-10-06 20:53:09 +02:00
procedure Redo;
procedure RemoveAdditionalSelections;
function ReplaceMainSelText(const S: String;
2024-07-27 15:48:08 +02:00
const ReplaceMode: TScintReplaceMode = srmNormal): TScintRange;
function ReplaceRawMainSelText(const S: TScintRawString;
2024-07-27 15:48:08 +02:00
const ReplaceMode: TScintReplaceMode = srmNormal): TScintRange;
2011-10-06 20:53:09 +02:00
function ReplaceRawTextRange(const StartPos, EndPos: Integer;
2024-07-27 15:48:08 +02:00
const S: TScintRawString; const ReplaceMode: TScintReplaceMode = srmNormal): TScintRange;
function ReplaceTextRange(const StartPos, EndPos: Integer; const S: String;
2024-07-27 15:48:08 +02:00
const ReplaceMode: TScintReplaceMode = srmNormal): TScintRange;
2011-10-06 20:53:09 +02:00
procedure RestyleLine(const Line: Integer);
procedure ScrollCaretIntoView;
procedure SelectAll;
2024-06-11 08:29:04 +02:00
procedure SelectAllOccurrences(const Options: TScintFindOptions);
procedure SelectAndEnsureVisible(const Range: TScintRange);
2024-06-11 08:29:04 +02:00
procedure SelectNextOccurrence(const Options: TScintFindOptions);
function SelEmpty: Boolean;
function SelNotEmpty(out Sel: TScintRange): Boolean;
2011-10-06 20:53:09 +02:00
procedure SetAutoCompleteFillupChars(const FillupChars: AnsiString);
procedure SetAutoCompleteSeparators(const Separator, TypeSeparator: AnsiChar);
2011-10-06 20:53:09 +02:00
procedure SetAutoCompleteSelectedItem(const S: TScintRawString);
procedure SetAutoCompleteStopChars(const StopChars: AnsiString);
procedure SetBraceBadHighlighting(const Pos: Integer);
2011-10-06 20:53:09 +02:00
procedure SetBraceHighlighting(const Pos1, Pos2: Integer);
procedure SetCursorID(const CursorID: Integer);
2024-06-29 21:51:50 +02:00
procedure SetCallTipHighlight(HighlightStart, HighlightEnd: Integer);
procedure SetDefaultWordChars;
2024-06-08 10:01:42 +02:00
procedure SetEmptySelection;
procedure SetEmptySelections;
procedure SetIndicators(const StartPos, EndPos: Integer;
const IndicatorNumber: TScintIndicatorNumber; const Value: Boolean);
2011-10-06 20:53:09 +02:00
procedure SetLineIndentation(const Line, Indentation: Integer);
procedure SetSavePoint;
procedure SetSingleSelection(const CaretPos, AnchorPos: Integer);
procedure SettingChange(const Message: TMessage);
2020-10-13 22:03:31 +02:00
procedure SetWordChars(const S: AnsiString);
2011-10-06 20:53:09 +02:00
procedure ShowAutoComplete(const CharsEntered: Integer; const WordList: AnsiString);
2024-06-29 21:51:50 +02:00
procedure ShowCallTip(const Pos: Integer; const Definition: AnsiString);
procedure StyleNeeded(const EndPos: Integer);
2024-06-15 17:09:13 +02:00
procedure SysColorChange(const Message: TMessage);
function TestRegularExpression(const S: String): Boolean;
function TestRawRegularExpression(const S: TScintRawString): Boolean;
2011-10-06 20:53:09 +02:00
procedure Undo;
procedure UpdateStyleAttributes;
2024-11-14 23:41:22 +01:00
function WordAtCaret: String;
function WordAtCaretRange: TScintRange;
2011-10-06 20:53:09 +02:00
procedure ZoomIn;
procedure ZoomOut;
property AutoCompleteActive: Boolean read GetAutoCompleteActive;
2024-06-29 21:51:50 +02:00
property CallTipActive: Boolean read GetCallTipActive;
2011-10-06 20:53:09 +02:00
property CaretColumn: Integer read GetCaretColumn write SetCaretColumn;
2024-05-18 09:03:17 +02:00
property CaretColumnExpandedForTabs: Integer read GetCaretColumnExpandedForTabs;
2011-10-06 20:53:09 +02:00
property CaretLine: Integer read GetCaretLine write SetCaretLine;
2024-06-30 15:25:14 +02:00
property CaretLineText: String read GetCaretLineText;
2011-10-06 20:53:09 +02:00
property CaretPosition: Integer read GetCaretPosition write SetCaretPosition;
2024-06-30 15:25:14 +02:00
property CaretPositionInLine: Integer read GetCaretPositionInLine;
2024-06-26 22:07:19 +02:00
property CaretPositionWithSelectFromAnchor: Integer write SetCaretPositionWithSelectFromAnchor;
2011-10-06 20:53:09 +02:00
property CaretVirtualSpace: Integer read GetCaretVirtualSpace write SetCaretVirtualSpace;
property EffectiveCodePage: Integer read FEffectiveCodePage;
property FoldFlags: TScintFoldFlags write SetFoldFlags;
2011-10-06 20:53:09 +02:00
property InsertMode: Boolean read GetInsertMode;
property LineEndings: TScintLineEndings read GetLineEndings;
property LineEndingString: TScintRawString read GetLineEndingString;
property LineHeight: Integer read GetLineHeight;
property Lines: TScintEditStrings read FLines;
property LinesInWindow: Integer read GetLinesInWindow;
property MainSelection: Integer read GetMainSelection write SetMainSelection;
property MainSelText: String read GetMainSelText write SetMainSelText;
2011-10-06 20:53:09 +02:00
property Modified: Boolean read GetModified;
2024-06-30 15:25:14 +02:00
property RawCaretLineText: TScintRawString read GetRawCaretLineText;
property RawMainSelText: TScintRawString read GetRawMainSelText write SetRawMainSelText;
2011-10-06 20:53:09 +02:00
property RawSelText: TScintRawString read GetRawSelText write SetRawSelText;
property RawText: TScintRawString read GetRawText write SetRawText;
property RawTextLength: Integer read GetRawTextLength;
property ReadOnly: Boolean read GetReadOnly write SetReadOnly;
property Selection: TScintRange read GetSelection write SetSelection;
2024-06-06 09:32:39 +02:00
property SelectionAnchorPosition[Selection: Integer]: Integer read GetSelectionAnchorPosition write SetSelectionAnchorPosition;
property SelectionAnchorVirtualSpace[Selection: Integer]: Integer read GetSelectionAnchorVirtualSpace write SetSelectionAnchorVirtualSpace;
2024-06-06 09:32:39 +02:00
property SelectionCaretPosition[Selection: Integer]: Integer read GetSelectionCaretPosition write SetSelectionCaretPosition;
property SelectionCaretVirtualSpace[Selection: Integer]: Integer read GetSelectionCaretVirtualSpace write SetSelectionCaretVirtualSpace;
2024-06-06 09:30:47 +02:00
property SelectionCount: Integer read GetSelectionCount;
property SelectionEndPosition[Selection: Integer]: Integer read GetSelectionEndPosition;
2024-06-15 01:34:41 +02:00
property SelectionMode: TScintSelectionMode read GetSelectionMode write SetSelectionMode;
property SelectionStartPosition[Selection: Integer]: Integer read GetSelectionStartPosition;
2011-10-06 20:53:09 +02:00
property SelText: String read GetSelText write SetSelText;
property Styler: TScintCustomStyler read FStyler write SetStyler;
property Target: TScintRange read GetTarget;
2011-10-06 20:53:09 +02:00
property TopLine: Integer read GetTopLine write SetTopLine;
2024-07-07 16:31:05 +02:00
property WordChars: AnsiString read FWordChars;
property WordCharsAsSet: TSysCharSet read FWordCharsAsSet;
2011-10-06 20:53:09 +02:00
published
property AcceptDroppedFiles: Boolean read FAcceptDroppedFiles write SetAcceptDroppedFiles
default False;
property AutoCompleteFontName: String read FAutoCompleteFontName
write SetAutoCompleteFontName;
property AutoCompleteFontSize: Integer read FAutoCompleteFontSize
write SetAutoCompleteFontSize default 0;
2024-06-17 15:49:37 +02:00
property ChangeHistory: TScintChangeHistory read FChangeHistory write SetChangeHistory default schDisabled;
2024-06-12 08:15:30 +02:00
property CodePage: Integer read FCodePage write SetCodePage default CP_UTF8;
property Color;
2011-10-06 20:53:09 +02:00
property FillSelectionToEdge: Boolean read FFillSelectionToEdge write SetFillSelectionToEdge
default False;
property Font;
property IndentationGuides: TScintIndentationGuides read FIndentationGuides
write SetIndentationGuides default sigNone;
property LineNumbers: Boolean read FLineNumbers write SetLineNumbers default False;
2011-10-06 20:53:09 +02:00
property ParentFont;
property PopupMenu;
property ReportCaretPositionToStyler: Boolean read FReportCaretPositionToStyler
write FReportCaretPositionToStyler;
property TabStop default True;
property TabWidth: Integer read FTabWidth write SetTabWidth default 8;
property UseStyleAttributes: Boolean read FUseStyleAttributes write SetUseStyleAttributes
default True;
property UseTabCharacter: Boolean read FUseTabCharacter write SetUseTabCharacter
default True;
property VirtualSpaceOptions: TScintVirtualSpaceOptions read FVirtualSpaceOptions
write SetVirtualSpaceOptions default [];
property WordWrap: Boolean read FWordWrap write SetWordWrap default False;
property Zoom: Integer read GetZoom write SetZoom default 0;
property OnAutoCompleteSelection: TScintEditAutoCompleteSelectionEvent read FOnAutoCompleteSelection write FOnAutoCompleteSelection;
2024-07-26 10:35:31 +02:00
property OnCallTipArrowClick: TScintEditCallTipArrowClick read FOnCallTipArrowClick write FOnCallTipArrowClick;
2011-10-06 20:53:09 +02:00
property OnChange: TScintEditChangeEvent read FOnChange write FOnChange;
property OnCharAdded: TScintEditCharAddedEvent read FOnCharAdded write FOnCharAdded;
property OnDropFiles: TScintEditDropFilesEvent read FOnDropFiles write FOnDropFiles;
property OnHintShow: TScintEditHintShowEvent read FOnHintShow write FOnHintShow;
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
property OnMarginClick: TScintEditMarginClickEvent read FOnMarginClick write FOnMarginClick;
property OnMarginRightClick: TScintEditMarginClickEvent read FOnMarginRightClick write FOnMarginRightClick;
2011-10-06 20:53:09 +02:00
property OnModifiedChange: TNotifyEvent read FOnModifiedChange write FOnModifiedChange;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property OnUpdateUI: TScintEditUpdateUIEvent read FOnUpdateUI write FOnUpdateUI;
property OnZoom: TNotifyEvent read FOnZoom write FOnZoom;
2011-10-06 20:53:09 +02:00
end;
TScintEditStrings = class(TStrings)
private
FEdit: TScintEdit;
function GetLineEndingLength(const Index: Integer): Integer;
function GetRawLine(Index: Integer): TScintRawString;
function GetRawLineWithEnding(Index: Integer): TScintRawString;
function GetRawLineLength(Index: Integer): Integer;
function GetRawLineLengthWithEnding(Index: Integer): Integer;
function GetState(Index: Integer): TScintLineState;
procedure PutRawLine(Index: Integer; const S: TScintRawString);
protected
procedure CheckIndexRange(const Index: Integer);
procedure CheckIndexRangePlusOne(const Index: Integer);
function Get(Index: Integer): String; override;
function GetCount: Integer; override;
function GetTextStr: String; override;
procedure Put(Index: Integer; const S: String); override;
procedure SetTextStr(const Value: String); override;
public
procedure Clear; override;
procedure Delete(Index: Integer); override;
procedure Insert(Index: Integer; const S: String); override;
procedure InsertRawLine(Index: Integer; const S: TScintRawString);
procedure SetText(Text: PChar); override;
property RawLineLengths[Index: Integer]: Integer read GetRawLineLength;
property RawLineLengthsWithEnding[Index: Integer]: Integer read GetRawLineLengthWithEnding;
property RawLines[Index: Integer]: TScintRawString read GetRawLine write PutRawLine;
property RawLinesWithEnding[Index: Integer]: TScintRawString read GetRawLineWithEnding;
property State[Index: Integer]: TScintLineState read GetState;
end;
TScintStyleAttributes = record
FontName: String;
FontSize: Integer;
FontStyle: TFontStyles;
FontCharset: TFontCharset;
ForeColor: TColor;
BackColor: TColor;
end;
TScintCustomStyler = class(TComponent)
private
FCaretIndex: Integer;
FCurIndex: Integer;
FLineState: TScintLineState;
FStyleStartIndex: Integer;
FStyleStr: AnsiString;
FText: TScintRawString;
FTextLen: Integer;
function GetCurChar: AnsiChar;
function GetEndOfLine: Boolean;
protected
procedure ApplyStyleByteIndicators(const Indicators: TScintStyleByteIndicatorNumbers;
2011-10-06 20:53:09 +02:00
StartIndex, EndIndex: Integer);
procedure ApplyStyle(const Style: TScintStyleNumber;
StartIndex, EndIndex: Integer);
procedure CommitStyle(const Style: TScintStyleNumber);
function ConsumeAllRemaining: Boolean;
function ConsumeChar(const C: AnsiChar): Boolean;
function ConsumeCharIn(const Chars: TScintRawCharSet): Boolean;
2011-10-06 20:53:09 +02:00
function ConsumeChars(const Chars: TScintRawCharSet): Boolean;
function ConsumeCharsNot(const Chars: TScintRawCharSet): Boolean;
function ConsumeString(const Chars: TScintRawCharSet): TScintRawString;
function CurCharIn(const Chars: TScintRawCharSet): Boolean;
function CurCharIs(const C: AnsiChar): Boolean;
procedure GetFoldLevel(const LineState, PreviousLineState: TScintLineState;
var Level: Integer; var Header, EnableHeaderOnPrevious: Boolean); virtual; abstract;
2011-10-06 20:53:09 +02:00
procedure GetStyleAttributes(const Style: Integer;
var Attributes: TScintStyleAttributes); virtual; abstract;
function LineTextSpans(const S: TScintRawString): Boolean; virtual;
function NextCharIs(const C: AnsiChar): Boolean;
function PreviousCharIn(const Chars: TScintRawCharSet): Boolean;
procedure ResetCurIndexTo(Index: Integer);
2011-10-06 20:53:09 +02:00
procedure ReplaceText(StartIndex, EndIndex: Integer; const C: AnsiChar);
procedure StyleNeeded; virtual; abstract;
property CaretIndex: Integer read FCaretIndex;
property CurChar: AnsiChar read GetCurChar;
property CurIndex: Integer read FCurIndex;
property EndOfLine: Boolean read GetEndOfLine;
property LineState: TScintLineState read FLineState write FLineState;
property StyleStartIndex: Integer read FStyleStartIndex;
property Text: TScintRawString read FText;
property TextLength: Integer read FTextLen;
end;
2024-05-04 17:24:37 +02:00
TScintPixmap = class
private
type
TPixmap = array of AnsiString;
class var
ColorCodes: String;
var
FPixmap: TPixmap;
class constructor Create;
2024-05-04 17:24:37 +02:00
function GetPixmap: Pointer;
public
procedure InitializeFromBitmap(const ABitmap: TBitmap; const TransparentColor: TColorRef);
2024-05-04 17:24:37 +02:00
property Pixmap: Pointer read GetPixmap;
end;
2011-10-06 20:53:09 +02:00
implementation
uses
2024-08-04 10:41:34 +02:00
ShellAPI, RTLConsts, UITypes, GraphUtil;
2011-10-06 20:53:09 +02:00
{ TScintEdit }
const
AUTOCSETSEPARATOR = #9;
2011-10-06 20:53:09 +02:00
constructor TScintEdit.Create(AOwner: TComponent);
begin
inherited;
2024-06-12 08:15:30 +02:00
FCodePage := CP_UTF8;
2011-10-06 20:53:09 +02:00
FLines := TScintEditStrings.Create;
FLines.FEdit := Self;
FTabWidth := 8;
FUseStyleAttributes := True;
FUseTabCharacter := True;
SetBounds(0, 0, 257, 193);
ParentColor := False;
TabStop := True;
end;
destructor TScintEdit.Destroy;
begin
SetStyler(nil);
FLines.Free;
FLines := nil;
inherited;
end;
procedure TScintEdit.AddMarker(const Line: Integer;
const Marker: TScintMarkerNumber);
begin
FLines.CheckIndexRange(Line);
Call(SCI_MARKERADD, Line, Marker);
end;
procedure TScintEdit.AddSelection(const CaretPos, AnchorPos: Integer);
{ Adds a new selection as the main selection retaining all other selections as
additional selections without scrolling the caret into view. The first
selection should be added with SetSingleSelection. }
begin
Call(SCI_ADDSELECTION, CaretPos, AnchorPos);
end;
2011-10-06 20:53:09 +02:00
procedure TScintEdit.ApplyOptions;
const
IndentationGuides: array [TScintIndentationGuides] of Integer = (SC_IV_NONE, SC_IV_REAL,
SC_IV_LOOKFORWARD, SC_IV_LOOKBOTH);
var
Flags: Integer;
begin
if not HandleAllocated then
Exit;
Call(SCI_SETSELEOLFILLED, Ord(FFillSelectionToEdge), 0);
Call(SCI_SETTABWIDTH, FTabWidth, 0);
Call(SCI_SETUSETABS, Ord(FUseTabCharacter), 0);
Flags := 0;
if svsRectangularSelection in VirtualSpaceOptions then
Flags := Flags or SCVS_RECTANGULARSELECTION;
if svsUserAccessible in VirtualSpaceOptions then
Flags := Flags or SCVS_USERACCESSIBLE;
2024-06-11 20:26:25 +02:00
if svsNoWrapLineStart in VirtualSpaceOptions then
Flags := Flags or SCVS_NOWRAPLINESTART;
2011-10-06 20:53:09 +02:00
Call(SCI_SETVIRTUALSPACEOPTIONS, Flags, 0);
Call(SCI_SETWRAPMODE, Ord(FWordWrap), 0);
Call(SCI_SETINDENTATIONGUIDES, IndentationGuides[FIndentationGuides], 0);
2024-06-17 15:49:37 +02:00
{ If FChangeHistory is not schDisabled then next call to ClearUndo will enable
change history and else we should disable it now }
if FChangeHistory = schDisabled then
2024-06-15 16:30:07 +02:00
Call(SCI_SETCHANGEHISTORY, SC_CHANGE_HISTORY_DISABLED, 0);
2011-10-06 20:53:09 +02:00
end;
procedure TScintEdit.AssignCmdKey(const Key: AnsiChar; const Shift: TShiftState;
const Command: TScintCommand);
begin
AssignCmdKey(KeyToKeyCode(Key), Shift, Command);
end;
procedure TScintEdit.AssignCmdKey(const KeyCode: TScintKeyCode;
const Shift: TShiftState; const Command: TScintCommand);
begin
Call(SCI_ASSIGNCMDKEY, KeyCodeAndShiftToKeyDefinition(KeyCode, Shift), Command);
end;
2011-10-06 20:53:09 +02:00
procedure TScintEdit.BeginUndoAction;
begin
Call(SCI_BEGINUNDOACTION, 0, 0);
end;
function TScintEdit.Call(Msg: Cardinal; WParam: Longint; LParam: Longint): Longint;
begin
2024-07-28 17:16:53 +02:00
var Dummy: Integer;
Result := Call(Msg, WParam, LParam, Dummy);
end;
function TScintEdit.Call(Msg: Cardinal; WParam: Longint; LParam: Longint;
out WarnStatus: Integer): Longint;
2011-10-06 20:53:09 +02:00
begin
HandleNeeded;
if FDirectPtr = nil then
Error('Call: FDirectPtr is nil');
if not Assigned(FDirectStatusFunction) then
Error('Call: FDirectStatusFunction is nil');
var ErrorStatus: Integer;
Result := FDirectStatusFunction(FDirectPtr, Msg, WParam, LParam, ErrorStatus);
2011-10-06 20:53:09 +02:00
if ErrorStatus <> 0 then begin
2024-06-14 07:40:45 +02:00
var Dummy: Integer;
FDirectStatusFunction(FDirectPtr, SCI_SETSTATUS, 0, 0, Dummy);
if ErrorStatus < SC_STATUS_WARN_START then
ErrorFmt('Error status %d returned after Call(%u, %d, %d) = %d',
[ErrorStatus, Msg, WParam, LParam, Result]);
2011-10-06 20:53:09 +02:00
end;
WarnStatus := ErrorStatus;
2011-10-06 20:53:09 +02:00
end;
function TScintEdit.Call(Msg: Cardinal; WParam: Longint;
2011-10-06 20:53:09 +02:00
const LParamStr: TScintRawString): Longint;
begin
2024-07-28 17:16:53 +02:00
var Dummy: Integer;
Result := Call(Msg, WParam, LParamStr, Dummy);
end;
function TScintEdit.Call(Msg: Cardinal; WParam: Longint;
const LParamStr: TScintRawString; out WarnStatus: Integer): Longint;
begin
Result := Call(Msg, WParam, LPARAM(PAnsiChar(LParamStr)), WarnStatus);
2011-10-06 20:53:09 +02:00
end;
procedure TScintEdit.CancelAutoComplete;
begin
Call(SCI_AUTOCCANCEL, 0, 0);
end;
procedure TScintEdit.CancelAutoCompleteAndCallTip;
begin
CancelAutoComplete;
CancelCallTip;
end;
2024-06-29 21:51:50 +02:00
procedure TScintEdit.CancelCallTip;
begin
Call(SCI_CALLTIPCANCEL, 0, 0);
end;
2024-10-11 13:18:42 +02:00
function TScintEdit.CanPaste: Boolean;
begin
Result := Call(SCI_CANPASTE, 0, 0) <> 0;
end;
2011-10-06 20:53:09 +02:00
function TScintEdit.CanRedo: Boolean;
begin
Result := Call(SCI_CANREDO, 0, 0) <> 0;
end;
function TScintEdit.CanUndo: Boolean;
begin
Result := Call(SCI_CANUNDO, 0, 0) <> 0;
end;
procedure TScintEdit.Change(const AInserting: Boolean;
const AStartPos, ALength, ALinesDelta: Integer);
var
Info: TScintEditChangeInfo;
begin
inherited Changed;
if Assigned(FOnChange) then begin
Info.Inserting := AInserting;
Info.StartPos := AStartPos;
Info.Length := ALength;
Info.LinesDelta := ALinesDelta;
FOnChange(Self, Info);
end;
end;
procedure TScintEdit.CheckPosRange(const StartPos, EndPos: Integer);
begin
if (StartPos < 0) or (StartPos > EndPos) or (EndPos > GetRawTextLength) then
ErrorFmt('CheckPosRange: Invalid range (%d, %d)', [StartPos, EndPos]);
end;
procedure TScintEdit.ChooseCaretX;
begin
Call(SCI_CHOOSECARETX, 0, 0);
end;
procedure TScintEdit.ClearAll;
begin
Call(SCI_CLEARALL, 0, 0);
ChooseCaretX;
end;
procedure TScintEdit.ClearCmdKey(const Key: AnsiChar; const Shift: TShiftState);
begin
ClearCmdKey(KeyToKeyCode(Key), Shift);
end;
procedure TScintEdit.ClearCmdKey(const KeyCode: TScintKeyCode; const Shift: TShiftState);
begin
Call(SCI_CLEARCMDKEY, KeyCodeAndShiftToKeyDefinition(KeyCode, Shift), 0);
end;
procedure TScintEdit.ClearIndicators(
const IndicatorNumber: TScintIndicatorNumber);
begin
Call(SCI_SETINDICATORCURRENT, IndicatorNumber, 0);
Call(SCI_INDICATORCLEARRANGE, 0, RawTextLength);
end;
2011-10-06 20:53:09 +02:00
procedure TScintEdit.ClearSelection;
begin
Call(SCI_CLEAR, 0, 0);
end;
procedure TScintEdit.ClearUndo(const ClearChangeHistory: Boolean);
2011-10-06 20:53:09 +02:00
begin
{ SCI_EMPTYUNDOBUFFER resets the save point but doesn't send a
SCN_SAVEPOINTREACHED notification. Call SetSavePoint manually to get
that. SetSavePoint additionally resets FForceModified. }
SetSavePoint;
Call(SCI_EMPTYUNDOBUFFER, 0, 0);
2024-06-17 15:49:37 +02:00
if ClearChangeHistory and (FChangeHistory <> schDisabled) then begin
Call(SCI_SETCHANGEHISTORY, SC_CHANGE_HISTORY_DISABLED, 0);
2024-06-17 15:49:37 +02:00
var Flags := SC_CHANGE_HISTORY_ENABLED;
if FChangeHistory = schMarkers then
Flags := Flags or SC_CHANGE_HISTORY_MARKERS
else
Flags := Flags or SC_CHANGE_HISTORY_INDICATORS;
Call(SCI_SETCHANGEHISTORY, Flags, 0);
end;
2011-10-06 20:53:09 +02:00
end;
function TScintEdit.ConvertRawStringToString(const S: TScintRawString): String;
var
SrcLen, DestLen: Integer;
DestStr: UnicodeString;
begin
SrcLen := Length(S);
if SrcLen > 0 then begin
DestLen := MultiByteToWideChar(FCodePage, 0, PAnsiChar(S), SrcLen, nil, 0);
if DestLen <= 0 then
Error('MultiByteToWideChar failed');
SetString(DestStr, nil, DestLen);
if MultiByteToWideChar(FCodePage, 0, PAnsiChar(S), SrcLen, @DestStr[1],
Length(DestStr)) <> DestLen then
Error('Unexpected result from MultiByteToWideChar');
end;
Result := DestStr;
end;
function TScintEdit.ConvertPCharToRawString(const Text: PChar;
const TextLen: Integer): TScintRawString;
var
DestLen: Integer;
DestStr: TScintRawString;
begin
if TextLen > 0 then begin
DestLen := WideCharToMultiByte(FCodePage, 0, Text, TextLen, nil, 0, nil, nil);
if DestLen <= 0 then
Error('WideCharToMultiByte failed');
InitRawString(DestStr, DestLen);
if WideCharToMultiByte(FCodePage, 0, Text, TextLen, @DestStr[1], Length(DestStr),
nil, nil) <> DestLen then
Error('Unexpected result from WideCharToMultiByte');
end;
Result := DestStr;
end;
function TScintEdit.ConvertStringToRawString(const S: String): TScintRawString;
begin
Result := ConvertPCharToRawString(PChar(S), Length(S));
end;
procedure TScintEdit.CopyToClipboard;
begin
Call(SCI_COPY, 0, 0);
end;
procedure TScintEdit.CreateParams(var Params: TCreateParams);
begin
inherited;
CreateSubClass(Params, 'Scintilla');
//Params.ExStyle := Params.ExStyle or WS_EX_CLIENTEDGE;
2011-10-06 20:53:09 +02:00
Params.WindowClass.style := Params.WindowClass.style and
not (CS_HREDRAW or CS_VREDRAW);
end;
procedure TScintEdit.CreateWnd;
begin
if IsscintLibrary = 0 then
Error('CreateWnd: IsscintLibrary is 0');
2011-10-06 20:53:09 +02:00
inherited;
FDirectPtr := Pointer(SendMessage(Handle, SCI_GETDIRECTPOINTER, 0, 0));
if FDirectPtr = nil then
Error('CreateWnd: FDirectPtr is nil');
2024-06-14 08:03:32 +02:00
FDirectStatusFunction := SciFnDirectStatus(SendMessage(Handle, SCI_GETDIRECTSTATUSFUNCTION, 0, 0));
if not Assigned(FDirectStatusFunction) then
Error('CreateWnd: FDirectStatusFunction is nil');
2011-10-06 20:53:09 +02:00
UpdateCodePage;
2024-06-12 17:24:55 +02:00
Call(SCI_SETCOMMANDEVENTS, 0, 0);
Call(SCI_SETMODEVENTMASK, SC_MOD_INSERTTEXT or SC_MOD_DELETETEXT, 0);
2011-10-06 20:53:09 +02:00
Call(SCI_SETCARETPERIOD, GetCaretBlinkTime, 0);
Call(SCI_SETSCROLLWIDTHTRACKING, 1, 0);
2024-06-17 15:49:37 +02:00
{ The default popup menu conflicts with the VCL's PopupMenu }
2011-10-06 20:53:09 +02:00
Call(SCI_USEPOPUP, 0, 0);
SetDefaultWordChars;
2011-10-06 20:53:09 +02:00
ApplyOptions;
UpdateStyleAttributes;
if FAcceptDroppedFiles then
DragAcceptFiles(Handle, True);
end;
procedure TScintEdit.CutToClipboard;
begin
Call(SCI_CUT, 0, 0);
end;
procedure TScintEdit.DeleteAllMarkersOnLine(const Line: Integer);
begin
FLines.CheckIndexRange(Line);
Call(SCI_MARKERDELETE, Line, -1);
end;
procedure TScintEdit.DeleteMarker(const Line: Integer;
const Marker: TScintMarkerNumber);
begin
FLines.CheckIndexRange(Line);
Call(SCI_MARKERDELETE, Line, Marker);
end;
procedure TScintEdit.EndUndoAction;
begin
Call(SCI_ENDUNDOACTION, 0, 0);
end;
procedure TScintEdit.EnsureLineVisible(const Line: Integer);
begin
2024-06-17 07:54:36 +02:00
FLines.CheckIndexRange(Line);
Call(SCI_ENSUREVISIBLE, Line, 0);
end;
2024-06-15 01:34:41 +02:00
class function TScintEdit.GetErrorException(const S: String): EScintEditError;
2024-07-26 16:42:53 +02:00
{ Can be used when just calling Error would cause a compiler warning because it doesn't realize Error always raises }
2024-06-15 01:34:41 +02:00
begin
Result := EScintEditError.Create('TScintEdit error: ' + S);
end;
2011-10-06 20:53:09 +02:00
class procedure TScintEdit.Error(const S: String);
begin
2024-06-15 01:34:41 +02:00
raise GetErrorException(S);
2011-10-06 20:53:09 +02:00
end;
class procedure TScintEdit.ErrorFmt(const S: String; const Args: array of const);
begin
Error(Format(S, Args));
end;
function TScintEdit.FindRawText(const StartPos, EndPos: Integer;
const S: TScintRawString; const Options: TScintFindOptions;
out MatchRange: TScintRange): Boolean;
begin
SetTarget(StartPos, EndPos);
2024-06-11 08:18:08 +02:00
Call(SCI_SETSEARCHFLAGS, GetSearchFlags(Options), 0);
Result := Call(SCI_SEARCHINTARGET, Length(S), S) >= 0;
2011-10-06 20:53:09 +02:00
if Result then
MatchRange := GetTarget;
end;
function TScintEdit.FindText(const StartPos, EndPos: Integer; const S: String;
const Options: TScintFindOptions; out MatchRange: TScintRange): Boolean;
begin
Result := FindRawText(StartPos, EndPos, ConvertStringToRawString(S),
Options, MatchRange);
end;
procedure TScintEdit.FoldLine(const Line: Integer; const Fold: Boolean);
begin
FLines.CheckIndexRange(Line);
{ If the line is not part of a fold the following will return False }
var Folded := Call(SCI_GETFOLDEXPANDED, Line, 0) = 0;
if Fold <> Folded then begin
{ If the line is not part of a fold the following will do nothing
and else if the line is not the header Scintilla will lookup the
header for us }
Call(SCI_TOGGLEFOLD, Line, 0);
end;
end;
2011-10-06 20:53:09 +02:00
procedure TScintEdit.ForceModifiedState;
begin
if not FForceModified then begin
FForceModified := True;
if Assigned(FOnModifiedChange) then
FOnModifiedChange(Self);
end;
end;
function TScintEdit.FormatRange(const Draw: Boolean;
const RangeToFormat: PScintRangeToFormat): Integer;
begin
Result := Call(SCI_FORMATRANGE, Ord(Draw), LPARAM(RangeToFormat));
end;
procedure TScintEdit.ForwardMessage(const Message: TMessage);
begin
if HandleAllocated then
2024-06-17 15:49:37 +02:00
CallWindowProc(DefWndProc, Handle, Message.Msg, Message.WParam, Message.LParam);
end;
2011-10-06 20:53:09 +02:00
function TScintEdit.GetAutoCompleteActive: Boolean;
begin
Result := Call(SCI_AUTOCACTIVE, 0, 0) <> 0;
end;
2024-06-28 06:54:40 +02:00
function TScintEdit.GetByteAtPosition(const Pos: Integer): AnsiChar;
begin
Result := AnsiChar(Call(SCI_GETCHARAT, Pos, 0));
end;
2024-06-29 21:51:50 +02:00
function TScintEdit.GetCallTipActive: Boolean;
begin
Result := Call(SCI_CALLTIPACTIVE, 0, 0) <> 0;
end;
2011-10-06 20:53:09 +02:00
function TScintEdit.GetCaretColumn: Integer;
begin
Result := GetColumnFromPosition(GetCaretPosition);
end;
2024-05-18 09:03:17 +02:00
function TScintEdit.GetCaretColumnExpandedForTabs: Integer;
2011-10-06 20:53:09 +02:00
begin
Result := Call(SCI_GETCOLUMN, GetCaretPosition, 0);
Inc(Result, GetCaretVirtualSpace);
end;
function TScintEdit.GetCaretLine: Integer;
begin
Result := GetLineFromPosition(GetCaretPosition);
end;
2024-06-30 15:25:14 +02:00
function TScintEdit.GetCaretLineText: String;
begin
Result := ConvertRawStringToString(GetRawCaretLineText);
end;
2011-10-06 20:53:09 +02:00
function TScintEdit.GetCaretPosition: Integer;
begin
Result := Call(SCI_GETCURRENTPOS, 0, 0);
end;
2024-06-30 15:25:14 +02:00
function TScintEdit.GetCaretPositionInLine: Integer;
begin
var Caret := CaretPosition;
var LineStart := GetPositionFromLine(GetLineFromPosition(Caret));
Result := Caret - LineStart;
end;
2011-10-06 20:53:09 +02:00
function TScintEdit.GetCaretVirtualSpace: Integer;
begin
2024-06-28 07:42:33 +02:00
Result := GetSelectionCaretVirtualSpace(GetMainSelection);
2011-10-06 20:53:09 +02:00
end;
2024-06-28 06:54:40 +02:00
function TScintEdit.GetCharacterCount(const StartPos, EndPos: Integer): Integer;
2011-10-06 20:53:09 +02:00
begin
2024-06-28 06:54:40 +02:00
CheckPosRange(StartPos, EndPos);
Result := Call(SCI_COUNTCHARACTERS, StartPos, EndPos);
2011-10-06 20:53:09 +02:00
end;
function TScintEdit.GetColumnFromPosition(const Pos: Integer): Integer;
var
Line: Integer;
begin
Line := GetLineFromPosition(Pos);
Result := Pos - GetPositionFromLine(Line);
end;
function TScintEdit.GetDefaultWordChars: AnsiString;
begin
Result := 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_';
end;
2011-10-06 20:53:09 +02:00
function TScintEdit.GetDocLineFromVisibleLine(const VisibleLine: Integer): Integer;
begin
Result := Call(SCI_DOCLINEFROMVISIBLE, VisibleLine, 0);
end;
function TScintEdit.GetIndicatorAtPosition(
const IndicatorNumber: TScintIndicatorNumber; const Pos: Integer): Boolean;
2011-10-06 20:53:09 +02:00
begin
Result := Call(SCI_INDICATORVALUEAT, IndicatorNumber, Pos) <> 0;
2011-10-06 20:53:09 +02:00
end;
function TScintEdit.GetInsertMode: Boolean;
begin
Result := Call(SCI_GETOVERTYPE, 0, 0) = 0;
end;
function TScintEdit.GetLineEndings: TScintLineEndings;
begin
case Call(SCI_GETEOLMODE, 0, 0) of
SC_EOL_CR: Result := sleCR;
SC_EOL_LF: Result := sleLF;
2024-06-15 01:34:41 +02:00
SC_EOL_CRLF: Result := sleCRLF;
2011-10-06 20:53:09 +02:00
else
2024-06-15 01:34:41 +02:00
raise GetErrorException('Unexpected SCI_GETEOLMODE result');
2011-10-06 20:53:09 +02:00
end;
end;
function TScintEdit.GetLineEndingString: TScintRawString;
const
EndingStrs: array[TScintLineEndings] of TScintRawString =
(#13#10, #13, #10);
begin
Result := EndingStrs[LineEndings];
end;
function TScintEdit.GetLineEndPosition(const Line: Integer): Integer;
2024-06-26 22:07:19 +02:00
{ Returns the position at the end of the line, before any line end characters. }
2011-10-06 20:53:09 +02:00
begin
FLines.CheckIndexRange(Line);
Result := Call(SCI_GETLINEENDPOSITION, Line, 0);
end;
function TScintEdit.GetLineFromPosition(const Pos: Integer): Integer;
begin
Result := Call(SCI_LINEFROMPOSITION, Pos, 0);
end;
function TScintEdit.GetLineHeight: Integer;
begin
Result := Call(SCI_TEXTHEIGHT, 0, 0);
end;
function TScintEdit.GetLineIndentation(const Line: Integer): Integer;
begin
FLines.CheckIndexRange(Line);
Result := Call(SCI_GETLINEINDENTATION, Line, 0);
end;
function TScintEdit.GetLineIndentPosition(const Line: Integer): Integer;
begin
FLines.CheckIndexRange(Line);
Result := Call(SCI_GETLINEINDENTPOSITION, Line, 0);
end;
function TScintEdit.GetLinesInWindow: Integer;
begin
Result := Call(SCI_LINESONSCREEN, 0, 0);
end;
function TScintEdit.GetMainSelection: Integer;
begin
Result := Call(SCI_GETMAINSELECTION, 0, 0);
end;
function TScintEdit.GetMainSelText: String;
begin
Result := ConvertRawStringToString(GetRawMainSelText);
end;
2011-10-06 20:53:09 +02:00
function TScintEdit.GetMarkers(const Line: Integer): TScintMarkerNumbers;
begin
FLines.CheckIndexRange(Line);
Integer(Result) := Call(SCI_MARKERGET, Line, 0);
end;
function TScintEdit.GetModified: Boolean;
begin
Result := FForceModified or (Call(SCI_GETMODIFY, 0, 0) <> 0);
end;
function TScintEdit.GetPointFromPosition(const Pos: Integer): TPoint;
begin
Result.X := Call(SCI_POINTXFROMPOSITION, 0, Pos);
Result.Y := Call(SCI_POINTYFROMPOSITION, 0, Pos);
end;
function TScintEdit.GetPositionAfter(const Pos: Integer): Integer;
begin
Result := Call(SCI_POSITIONAFTER, Pos, 0);
end;
function TScintEdit.GetPositionBefore(const Pos: Integer): Integer;
begin
Result := Call(SCI_POSITIONBEFORE, Pos, 0);
end;
function TScintEdit.GetPositionFromLine(const Line: Integer): Integer;
begin
FLines.CheckIndexRangePlusOne(Line);
Result := Call(SCI_POSITIONFROMLINE, Line, 0);
end;
function TScintEdit.GetPositionFromLineColumn(const Line, Column: Integer): Integer;
var
Col, Len: Integer;
begin
Col := Column;
Result := GetPositionFromLine(Line);
Len := GetLineEndPosition(Line) - Result;
if Col > Len then
Col := Len;
if Col > 0 then
Inc(Result, Col);
end;
function TScintEdit.GetPositionFromLineExpandedColumn(const Line,
ExpandedColumn: Integer): Integer;
begin
FLines.CheckIndexRange(Line);
Result := Call(SCI_FINDCOLUMN, Line, ExpandedColumn);
end;
function TScintEdit.GetPositionFromPoint(const P: TPoint;
const CharPosition, CloseOnly: Boolean): Integer;
begin
if CharPosition then begin
if CloseOnly then
Result := Call(SCI_CHARPOSITIONFROMPOINTCLOSE, P.X, P.Y)
else
Result := Call(SCI_CHARPOSITIONFROMPOINT, P.X, P.Y);
end
else begin
if CloseOnly then
Result := Call(SCI_POSITIONFROMPOINTCLOSE, P.X, P.Y)
else
Result := Call(SCI_POSITIONFROMPOINT, P.X, P.Y);
end;
end;
function TScintEdit.GetPositionOfMatchingBrace(const Pos: Integer): Integer;
begin
Result := Call(SCI_BRACEMATCH, Pos, 0);
end;
2024-06-28 06:54:40 +02:00
function TScintEdit.GetPositionRelative(const Pos,
CharacterCount: Integer): Integer;
begin
Result := Call(SCI_POSITIONRELATIVE, Pos, CharacterCount);
end;
2024-06-30 15:25:14 +02:00
function TScintEdit.GetRawCaretLineText: TScintRawString;
begin
var Line := CaretLine;
Result := GetRawTextRange(GetPositionFromLine(Line), GetPositionFromLine(Line+1));
end;
function TScintEdit.GetRawMainSelText: TScintRawString;
begin
var MainSel := MainSelection;
var CaretPos := SelectionCaretPosition[MainSel];
var AnchorPos := SelectionAnchorPosition[MainSel];
if AnchorPos < CaretPos then
Result := GetRawTextRange(AnchorPos, CaretPos)
else
Result := GetRawTextRange(CaretPos, AnchorPos);
end;
2011-10-06 20:53:09 +02:00
function TScintEdit.GetRawSelText: TScintRawString;
{ Gets the combined text of *all* selections }
2011-10-06 20:53:09 +02:00
var
Len: Integer;
S: TScintRawString;
begin
Len := Call(SCI_GETSELTEXT, 0, 0);
2011-10-06 20:53:09 +02:00
if Len > 0 then begin
InitRawString(S, Len);
Call(SCI_GETSELTEXT, 0, LPARAM(PAnsiChar(@S[1])));
end;
Result := S;
end;
function TScintEdit.GetRawText: TScintRawString;
begin
Result := GetRawTextRange(0, GetRawTextLength);
end;
function TScintEdit.GetRawTextLength: Integer;
begin
Result := Call(SCI_GETLENGTH, 0, 0);
end;
function TScintEdit.GetRawTextRange(const StartPos, EndPos: Integer): TScintRawString;
var
S: TScintRawString;
Range: TSci_TextRange;
begin
CheckPosRange(StartPos, EndPos);
if EndPos > StartPos then begin
InitRawString(S, EndPos - StartPos);
Range.chrg.cpMin := StartPos;
Range.chrg.cpMax := EndPos;
Range.lpstrText := @S[1];
if Call(SCI_GETTEXTRANGE, 0, LPARAM(@Range)) <> EndPos - StartPos then
Error('Unexpected result from SCI_GETTEXTRANGE');
end;
Result := S;
end;
function TScintEdit.GetReadOnly: Boolean;
begin
Result := Call(SCI_GETREADONLY, 0, 0) <> 0;
end;
class function TScintEdit.GetReplaceTargetMessage(
const ReplaceMode: TScintReplaceMode): Cardinal;
begin
case ReplaceMode of
srmNormal: Result := SCI_REPLACETARGET;
srmMinimal: Result := SCI_REPLACETARGETMINIMAL;
srmRegEx: Result := SCI_REPLACETARGETRE;
else
raise GetErrorException('Unknown ReplaceMode');
end;
end;
2024-06-20 15:50:14 +02:00
class function TScintEdit.GetSearchFlags(const Options: TScintFindOptions): Integer;
2024-06-11 08:18:08 +02:00
begin
{ Note: Scintilla ignores SCFIND_WHOLEWORD when SCFIND_REGEXP is set }
2024-06-11 08:18:08 +02:00
Result := 0;
if sfoMatchCase in Options then
Result := Result or SCFIND_MATCHCASE;
if sfoWholeWord in Options then
Result := Result or SCFIND_WHOLEWORD;
if sfoRegEx in Options then
Result := Result or (SCFIND_REGEXP or SCFIND_CXX11REGEX);
2024-06-11 08:18:08 +02:00
end;
2011-10-06 20:53:09 +02:00
function TScintEdit.GetSelection: TScintRange;
begin
Result.StartPos := Call(SCI_GETSELECTIONSTART, 0, 0);
Result.EndPos := Call(SCI_GETSELECTIONEND, 0, 0);
end;
procedure TScintEdit.GetSelections(const RangeList: TScintRangeList);
begin
RangeList.Clear;
for var I := 0 to SelectionCount-1 do begin
var StartPos := GetSelectionStartPosition(I);
var EndPos := GetSelectionEndPosition(I);
RangeList.Add(TScintRange.Create(StartPos, EndPos));
end;
end;
2024-06-27 16:57:54 +02:00
procedure TScintEdit.GetSelections(const CaretAndAnchorList: TScintCaretAndAnchorList);
begin
CaretAndAnchorList.Clear;
for var I := 0 to SelectionCount-1 do begin
2024-06-28 07:42:33 +02:00
var CaretPos := GetSelectionCaretPosition(I);
var AnchorPos := GetSelectionAnchorPosition(I);
2024-06-27 16:57:54 +02:00
CaretAndAnchorList.Add(TScintCaretAndAnchor.Create(CaretPos, AnchorPos));
end;
end;
procedure TScintEdit.GetSelections(const CaretAndAnchorList, VirtualSpacesList: TScintCaretAndAnchorList);
begin
GetSelections(CaretAndAnchorList);
VirtualSpacesList.Clear;
for var I := 0 to SelectionCount-1 do begin
var CaretPos := GetSelectionCaretVirtualSpace(I);
var AnchorPos := GetSelectionAnchorVirtualSpace(I);
VirtualSpacesList.Add(TScintCaretAndAnchor.Create(CaretPos, AnchorPos));
end;
end;
2024-06-06 09:32:39 +02:00
function TScintEdit.GetSelectionAnchorPosition(Selection: Integer): Integer;
begin
Result := Call(SCI_GETSELECTIONNANCHOR, Selection, 0);
end;
function TScintEdit.GetSelectionAnchorVirtualSpace(Selection: Integer): Integer;
begin
Result := Call(SCI_GETSELECTIONNANCHORVIRTUALSPACE, Selection, 0);
end;
2024-06-06 09:32:39 +02:00
function TScintEdit.GetSelectionCaretPosition(Selection: Integer): Integer;
begin
Result := Call(SCI_GETSELECTIONNCARET, Selection, 0);
end;
function TScintEdit.GetSelectionCaretVirtualSpace(Selection: Integer): Integer;
begin
Result := Call(SCI_GETSELECTIONNCARETVIRTUALSPACE, Selection, 0);
end;
2024-06-06 09:30:47 +02:00
function TScintEdit.GetSelectionCount: Integer;
{ Returns the number of selections currently active. Rectangular selections are
handled (and returned) as multiple selections, one for each line. }
begin
Result := Call(SCI_GETSELECTIONS, 0, 0);
end;
function TScintEdit.GetSelectionEndPosition(Selection: Integer): Integer;
begin
Result := Call(SCI_GETSELECTIONNEND, Selection, 0)
end;
2024-06-15 01:34:41 +02:00
function TScintEdit.GetSelectionMode: TScintSelectionMode;
begin
case Call(SCI_GETSELECTIONMODE, 0, 0) of
SC_SEL_STREAM: Result := ssmStream;
SC_SEL_RECTANGLE: Result := ssmRectangular;
SC_SEL_LINES: Result := ssmLines;
SC_SEL_THIN: Result := ssmThinRectangular;
else
raise GetErrorException('Unexpected SCI_GETSELECTIONMODE result');
end;
end;
function TScintEdit.GetSelectionStartPosition(Selection: Integer): Integer;
begin
Result := Call(SCI_GETSELECTIONNSTART, Selection, 0);
end;
2011-10-06 20:53:09 +02:00
function TScintEdit.GetSelText: String;
begin
Result := ConvertRawStringToString(GetRawSelText);
end;
function TScintEdit.GetStyleAtPosition(const Pos: Integer): TScintStyleNumber;
begin
Result := Call(SCI_GETSTYLEAT, Pos, 0);
2011-10-06 20:53:09 +02:00
end;
function TScintEdit.GetTarget: TScintRange;
begin
Result.StartPos := Call(SCI_GETTARGETSTART, 0, 0);
Result.EndPos := Call(SCI_GETTARGETEND, 0, 0);
end;
function TScintEdit.GetTextRange(const StartPos, EndPos: Integer): String;
begin
Result := ConvertRawStringToString(GetRawTextRange(StartPos, EndPos));
end;
function TScintEdit.GetTopLine: Integer;
begin
Result := Call(SCI_GETFIRSTVISIBLELINE, 0, 0);
end;
function TScintEdit.GetVisibleLineFromDocLine(const DocLine: Integer): Integer;
begin
FLines.CheckIndexRange(DocLine);
Result := Call(SCI_VISIBLEFROMDOCLINE, DocLine, 0);
end;
function TScintEdit.GetWordEndPosition(const Pos: Integer;
const OnlyWordChars: Boolean): Integer;
begin
Result := Call(SCI_WORDENDPOSITION, Pos, Ord(OnlyWordChars));
end;
function TScintEdit.GetWordStartPosition(const Pos: Integer;
const OnlyWordChars: Boolean): Integer;
begin
Result := Call(SCI_WORDSTARTPOSITION, Pos, Ord(OnlyWordChars));
end;
function TScintEdit.GetZoom: Integer;
begin
Result := Call(SCI_GETZOOM, 0, 0);
end;
procedure TScintEdit.InitRawString(var S: TScintRawString; const Len: Integer);
begin
SetString(S, nil, Len);
//experimental, dont need this ATM:
if FCodePage <> 0 then
System.SetCodePage(RawByteString(S), FCodePage, False);
end;
function TScintEdit.IsPositionInViewVertically(const Pos: Integer): Boolean;
var
P: TPoint;
begin
P := GetPointFromPosition(Pos);
Result := (P.Y >= 0) and (P.Y + GetLineHeight <= ClientHeight);
end;
class function TScintEdit.KeyCodeAndShiftToKeyDefinition(
const KeyCode: TScintKeyCode; Shift: TShiftState): TScintKeyDefinition;
begin
Result := KeyCode;
if ssShift in Shift then
Result := Result or (SCMOD_SHIFT shl 16);
if ssAlt in Shift then
Result := Result or (SCMOD_ALT shl 16);
if ssCtrl in Shift then
Result := Result or (SCMOD_CTRL shl 16);
end;
class function TScintEdit.KeyToKeyCode(const Key: AnsiChar): TScintKeyCode;
begin
Result := Ord(UpCase(Key));
end;
function TScintEdit.MainSelTextEquals(const S: String;
const Options: TScintFindOptions): Boolean;
begin
Result := RawMainSelTextEquals(ConvertStringToRawString(S), Options);
end;
2011-10-06 20:53:09 +02:00
procedure TScintEdit.Notification(AComponent: TComponent; Operation: TOperation);
begin
inherited;
if Operation = opRemove then
if AComponent = FStyler then
SetStyler(nil);
end;
procedure TScintEdit.Notify(const N: TSCNotification);
begin
case N.nmhdr.code of
SCN_AUTOCSELECTION:
begin
if Assigned(FOnAutoCompleteSelection) then
FOnAutoCompleteSelection(Self);
end;
2024-07-26 10:35:31 +02:00
SCN_CALLTIPCLICK:
begin
if (N.position in [1, 2]) and Assigned(FOnCallTipArrowClick) then
FOnCallTipArrowClick(Self, N.position = 1);
end;
2011-10-06 20:53:09 +02:00
SCN_CHARADDED:
begin
if Assigned(FOnCharAdded) then
FOnCharAdded(Self, AnsiChar(N.ch));
end;
SCN_MARGINCLICK:
begin
if Assigned(FOnMarginClick) then
FOnMarginClick(Self, N.margin, GetLineFromPosition(N.position));
end;
SCN_MARGINRIGHTCLICK:
begin
if Assigned(FOnMarginRightClick) then
FOnMarginRightClick(Self, N.margin, GetLineFromPosition(N.position));
end;
2011-10-06 20:53:09 +02:00
SCN_MODIFIED:
begin
{ CreateWnd limits SCN_MODIFIED to INSERTTEXT and DELETETEXT }
2011-10-06 20:53:09 +02:00
if N.modificationType and SC_MOD_INSERTTEXT <> 0 then
Change(True, N.position, N.length, N.linesAdded)
else if N.modificationType and SC_MOD_DELETETEXT <> 0 then
Change(False, N.position, N.length, N.linesAdded);
if (N.linesAdded > 0) and FLineNumbers then
UpdateLineNumbersWidth;
2011-10-06 20:53:09 +02:00
end;
SCN_SAVEPOINTLEFT,
SCN_SAVEPOINTREACHED:
begin
if Assigned(FOnModifiedChange) then
FOnModifiedChange(Self);
end;
SCN_STYLENEEDED: StyleNeeded(N.position);
SCN_UPDATEUI:
begin
if Assigned(FOnUpdateUI) then
FOnUpdateUI(Self, TScintEditUpdates(Byte(N.updated)));
2011-10-06 20:53:09 +02:00
end;
SCN_ZOOM:
begin
if Assigned(FOnZoom) then
FOnZoom(Self);
if FLineNumbers then
UpdateLineNumbersWidth;
end;
2011-10-06 20:53:09 +02:00
end;
end;
procedure TScintEdit.PasteFromClipboard;
begin
Call(SCI_PASTE, 0, 0);
end;
function TScintEdit.RawMainSelTextEquals(const S: TScintRawString;
const Options: TScintFindOptions): Boolean;
2011-10-06 20:53:09 +02:00
begin
Call(SCI_TARGETFROMSELECTION, 0, 0);
Call(SCI_SETSEARCHFLAGS, GetSearchFlags(Options), 0);
2011-10-06 20:53:09 +02:00
Result := False;
if Call(SCI_SEARCHINTARGET, Length(S), S) >= 0 then begin
var Target := GetTarget;
var Sel := GetSelection;
2011-10-06 20:53:09 +02:00
if (Target.StartPos = Sel.StartPos) and (Target.EndPos = Sel.EndPos) then
Result := True;
end;
end;
2024-06-17 15:49:37 +02:00
class function TScintEdit.RawStringIsBlank(const S: TScintRawString): Boolean;
begin
for var I := 1 to Length(S) do
if not(S[I] in [#9, ' ']) then
Exit(False);
Result := True;
end;
2011-10-06 20:53:09 +02:00
procedure TScintEdit.Redo;
begin
Call(SCI_REDO, 0, 0);
end;
procedure TScintEdit.RemoveAdditionalSelections;
{ Removes additional selections without scrolling the caret into view }
begin
2024-06-06 09:32:39 +02:00
var MainSel := MainSelection;
var CaretPos := SelectionCaretPosition[MainSel];
var AnchorPos := SelectionAnchorPosition[MainSel];
SetSingleSelection(CaretPos, AnchorPos);
end;
function TScintEdit.ReplaceMainSelText(const S: String;
const ReplaceMode: TScintReplaceMode): TScintRange;
begin
ReplaceRawMainSelText(ConvertStringToRawString(S), ReplaceMode);
end;
function TScintEdit.ReplaceRawMainSelText(const S: TScintRawString;
const ReplaceMode: TScintReplaceMode): TScintRange;
{ Replaces the main selection just like SetRawSelText/SCI_REPLACESEL but
without removing additional selections }
begin
{ First replace the selection }
Call(SCI_TARGETFROMSELECTION, 0, 0);
Call(GetReplaceTargetMessage(ReplaceMode), Length(S), S);
{ Then make the main selection an empty selection at the end of the inserted
text, just like SCI_REPLACESEL }
var Pos := GetTarget.EndPos; { SCI_REPLACETARGET* updates the target }
var MainSel := MainSelection;
SetSelectionCaretPosition(MainSel, Pos);
SetSelectionAnchorPosition(MainSel, Pos);
{ Finally call Editor::SetLastXChosen and scroll caret into view, also just
like SCI_REPLACESEL }
ChooseCaretX;
ScrollCaretIntoView;
end;
2011-10-06 20:53:09 +02:00
function TScintEdit.ReplaceRawTextRange(const StartPos, EndPos: Integer;
const S: TScintRawString; const ReplaceMode: TScintReplaceMode): TScintRange;
2011-10-06 20:53:09 +02:00
begin
CheckPosRange(StartPos, EndPos);
SetTarget(StartPos, EndPos);
Call(GetReplaceTargetMessage(ReplaceMode), Length(S), S);
2011-10-06 20:53:09 +02:00
Result := GetTarget;
end;
function TScintEdit.ReplaceTextRange(const StartPos, EndPos: Integer;
const S: String; const ReplaceMode: TScintReplaceMode): TScintRange;
2011-10-06 20:53:09 +02:00
begin
Result := ReplaceRawTextRange(StartPos, EndPos, ConvertStringToRawString(S), ReplaceMode);
2011-10-06 20:53:09 +02:00
end;
procedure TScintEdit.RestyleLine(const Line: Integer);
begin
2024-06-16 19:50:38 +02:00
var StartPos := GetPositionFromLine(Line);
var EndPos := GetPositionFromLine(Line + 1);
{ Back up the 'last styled position' if necessary using SCI_STARTSTYLINE
(SCI_SETENDSTYLED would have been a clearer name because setting the
'last styled position' is all it does) }
if StartPos < Call(SCI_GETENDSTYLED, 0, 0) then
2011-10-06 20:53:09 +02:00
Call(SCI_STARTSTYLING, StartPos, 0);
StyleNeeded(EndPos);
end;
procedure TScintEdit.ScrollCaretIntoView;
begin
Call(SCI_SCROLLCARET, 0, 0);
end;
2024-06-11 08:29:04 +02:00
procedure TScintEdit.SelectAllOccurrences(const Options: TScintFindOptions);
2024-06-16 19:56:21 +02:00
{ At the moment this does not automatically expand folds, unlike VSCode. Also
see SelectNextOccurrence. }
begin
Call(SCI_TARGETWHOLEDOCUMENT, 0, 0);
2024-06-11 08:29:04 +02:00
Call(SCI_SETSEARCHFLAGS, GetSearchFlags(Options), 0);
Call(SCI_MULTIPLESELECTADDEACH, 0, 0);
end;
procedure TScintEdit.SelectAndEnsureVisible(const Range: TScintRange);
begin
CheckPosRange(Range.StartPos, Range.EndPos);
2024-06-16 19:56:21 +02:00
2024-06-17 07:54:36 +02:00
{ If the range is in a contracted section, expand it }
var StartLine := GetLineFromPosition(Range.StartPos);
var EndLine := GetLineFromPosition(Range.EndPos);
2024-06-16 09:10:41 +02:00
for var Line := StartLine to EndLine do
EnsureLineVisible(Line);
2024-06-16 19:56:21 +02:00
{ Select }
Selection := Range;
end;
2024-06-11 08:29:04 +02:00
procedure TScintEdit.SelectNextOccurrence(const Options: TScintFindOptions);
2024-06-16 19:56:21 +02:00
{ At the moment this does not automatically expand folds, unlike VSCode. Also
see SelectAllOccurrences. }
begin
Call(SCI_TARGETWHOLEDOCUMENT, 0, 0);
2024-06-11 08:29:04 +02:00
Call(SCI_SETSEARCHFLAGS, GetSearchFlags(Options), 0);
Call(SCI_MULTIPLESELECTADDNEXT, 0, 0);
end;
function TScintEdit.SelEmpty: Boolean;
{ Returns True if the main selection is empty even if there are additional
selections. }
begin
var Sel: TScintRange;
Result := not SelNotEmpty(Sel);
end;
function TScintEdit.SelNotEmpty(out Sel: TScintRange): Boolean;
2011-10-06 20:53:09 +02:00
begin
Sel := GetSelection;
Result := Sel.EndPos > Sel.StartPos;
2011-10-06 20:53:09 +02:00
end;
procedure TScintEdit.SelectAll;
begin
Call(SCI_SELECTALL, 0, 0);
end;
procedure TScintEdit.SetAcceptDroppedFiles(const Value: Boolean);
begin
if FAcceptDroppedFiles <> Value then begin
FAcceptDroppedFiles := Value;
if HandleAllocated then
DragAcceptFiles(Handle, Value);
end;
end;
procedure TScintEdit.SetAutoCompleteFillupChars(const FillupChars: AnsiString);
begin
Call(SCI_AUTOCSETFILLUPS, 0, FillupChars);
2011-10-06 20:53:09 +02:00
end;
procedure TScintEdit.SetAutoCompleteFontName(const Value: String);
begin
if FAutoCompleteFontName <> Value then begin
FAutoCompleteFontName := Value;
UpdateStyleAttributes;
end;
end;
procedure TScintEdit.SetAutoCompleteFontSize(const Value: Integer);
begin
if FAutoCompleteFontSize <> Value then begin
FAutoCompleteFontSize := Value;
UpdateStyleAttributes;
end;
end;
procedure TScintEdit.SetAutoCompleteSelectedItem(const S: TScintRawString);
begin
Call(SCI_AUTOCSELECT, 0, S);
2011-10-06 20:53:09 +02:00
end;
procedure TScintEdit.SetAutoCompleteSeparators(const Separator, TypeSeparator: AnsiChar);
begin
Call(SCI_AUTOCSETSEPARATOR, WParam(Separator), 0);
Call(SCI_AUTOCSETTYPESEPARATOR, WParam(TypeSeparator), 0);
end;
2011-10-06 20:53:09 +02:00
procedure TScintEdit.SetAutoCompleteStopChars(const StopChars: AnsiString);
begin
Call(SCI_AUTOCSTOPS, 0, StopChars);
2011-10-06 20:53:09 +02:00
end;
procedure TScintEdit.SetBraceBadHighlighting(const Pos: Integer);
begin
Call(SCI_BRACEBADLIGHT, Pos, 0);
end;
2011-10-06 20:53:09 +02:00
procedure TScintEdit.SetBraceHighlighting(const Pos1, Pos2: Integer);
begin
Call(SCI_BRACEHIGHLIGHT, Pos1, Pos2);
end;
2024-06-29 21:51:50 +02:00
procedure TScintEdit.SetCallTipHighlight(HighlightStart, HighlightEnd: Integer);
begin
Call(SCI_CALLTIPSETHLT, HighlightStart, HighlightEnd);
end;
2011-10-06 20:53:09 +02:00
procedure TScintEdit.SetCaretColumn(const Value: Integer);
begin
SetCaretPosition(GetPositionFromLineColumn(GetCaretLine, Value));
end;
procedure TScintEdit.SetCaretLine(const Value: Integer);
begin
Call(SCI_GOTOLINE, Value, 0);
ChooseCaretX;
end;
procedure TScintEdit.SetCaretPosition(const Value: Integer);
begin
Call(SCI_GOTOPOS, Value, 0);
ChooseCaretX;
end;
2024-06-26 22:07:19 +02:00
procedure TScintEdit.SetCaretPositionWithSelectFromAnchor(const Value: Integer);
{ Sets the caret position and creates a selection between the anchor and the
caret position without scrolling the caret into view. }
begin
Call(SCI_SETCURRENTPOS, Value, 0);
end;
2011-10-06 20:53:09 +02:00
procedure TScintEdit.SetCaretVirtualSpace(const Value: Integer);
2024-06-28 07:42:33 +02:00
{ Also sets the anchor's virtual space! }
2011-10-06 20:53:09 +02:00
var
Pos, LineEndPos, MainSel: Integer;
begin
{ Weird things happen if a non-zero virtual space is set when the caret
isn't at the end of a line, so don't allow it }
Pos := GetCaretPosition;
LineEndPos := GetLineEndPosition(GetLineFromPosition(Pos));
if (Pos = LineEndPos) or (Value = 0) then begin
MainSel := GetMainSelection;
2024-06-29 07:23:38 +02:00
SetSelectionAnchorVirtualSpace(MainSel, Value);
SetSelectionCaretVirtualSpace(MainSel, Value);
2011-10-06 20:53:09 +02:00
ChooseCaretX;
end;
end;
2024-06-17 15:49:37 +02:00
procedure TScintEdit.SetChangeHistory(const Value: TScintChangeHistory);
begin
if FChangeHistory <> Value then begin
FChangeHistory := Value;
2024-06-15 16:30:07 +02:00
ApplyOptions;
end;
end;
2011-10-06 20:53:09 +02:00
procedure TScintEdit.SetCodePage(const Value: Integer);
begin
if FCodePage <> Value then begin
FCodePage := Value;
UpdateCodePage;
end;
end;
procedure TScintEdit.SetCursorID(const CursorID: Integer);
begin
Call(SCI_SETCURSOR, CursorID, 0);
end;
procedure TScintEdit.SetDefaultWordChars;
begin
SetWordChars(GetDefaultWordChars);
end;
2024-06-08 10:01:42 +02:00
procedure TScintEdit.SetEmptySelection;
{ Make the main selection empty and removes additional selections without
scrolling the caret into view }
2024-06-08 10:01:42 +02:00
begin
Call(SCI_SETEMPTYSELECTION, GetCaretPosition, 0);
end;
procedure TScintEdit.SetEmptySelections;
{ Makes all selections empty without scrolling the caret into view }
2011-10-06 20:53:09 +02:00
begin
2024-06-06 09:30:47 +02:00
for var Selection := 0 to SelectionCount-1 do begin
2024-06-06 09:32:39 +02:00
var Pos := SelectionCaretPosition[Selection];
SelectionAnchorPosition[Selection] := Pos;
end;
2011-10-06 20:53:09 +02:00
end;
procedure TScintEdit.SetFillSelectionToEdge(const Value: Boolean);
begin
if FFillSelectionToEdge <> Value then begin
FFillSelectionToEdge := Value;
ApplyOptions;
end;
end;
procedure TScintEdit.SetFoldFlags(const Value: TScintFoldFlags);
begin
var Flags := 0;
if sffLineBeforeExpanded in Value then
Flags := Flags or SC_FOLDFLAG_LINEBEFORE_EXPANDED;
if sffLineBeforeContracted in Value then
Flags := Flags or SC_FOLDFLAG_LINEBEFORE_CONTRACTED;
if sffLineAfterExpanded in Value then
Flags := Flags or SC_FOLDFLAG_LINEAFTER_EXPANDED;
if sffLineAfterContracted in Value then
Flags := Flags or SC_FOLDFLAG_LINEAFTER_CONTRACTED;
if sffLevelNumbers in Value then
Flags := Flags or SC_FOLDFLAG_LEVELNUMBERS
else if sffLineState in Value then
Flags := Flags or SC_FOLDFLAG_LINESTATE;
Call(SCI_SETFOLDFLAGS, Flags, 0);
var FoldLevelNumbersOrLineState := Value * [sffLevelNumbers, sffLineState] <> [];
if FoldLevelNumbersOrLineState <> FFoldLevelNumbersOrLineState then begin
FFoldLevelNumbersOrLineState := FoldLevelNumbersOrLineState;
UpdateLineNumbersWidth;
end;
end;
procedure TScintEdit.SetIndicators(const StartPos, EndPos: Integer;
const IndicatorNumber: TScintIndicatorNumber; const Value: Boolean);
begin
CheckPosRange(StartPos, EndPos);
Call(SCI_SETINDICATORCURRENT, IndicatorNumber, 0);
if Value then begin
Call(SCI_SETINDICATORVALUE, IndicatorNumber, 1);
Call(SCI_INDICATORFILLRANGE, StartPos, EndPos - StartPos);
end else
Call(SCI_INDICATORCLEARRANGE, StartPos, EndPos - StartPos);
end;
2011-10-06 20:53:09 +02:00
procedure TScintEdit.SetLineIndentation(const Line, Indentation: Integer);
begin
FLines.CheckIndexRange(Line);
Call(SCI_SETLINEINDENTATION, Line, Indentation);
end;
procedure TScintEdit.SetIndentationGuides(const Value: TScintIndentationGuides);
begin
if FIndentationGuides <> Value then begin
FIndentationGuides := Value;
ApplyOptions;
end;
end;
procedure TScintEdit.SetLineNumbers(const Value: Boolean);
begin
if FLineNumbers <> Value then begin
FLineNumbers := Value;
UpdateLineNumbersWidth;
end;
end;
procedure TScintEdit.SetMainSelection(const Value: Integer);
begin
Call(SCI_SETMAINSELECTION, Value, 0);
end;
procedure TScintEdit.SetMainSelText(const Value: String);
begin
SetRawMainSelText(ConvertStringToRawString(Value));
end;
procedure TScintEdit.SetRawMainSelText(const Value: TScintRawString);
begin
ReplaceRawMainSelText(Value, srmMinimal);
end;
2011-10-06 20:53:09 +02:00
procedure TScintEdit.SetRawSelText(const Value: TScintRawString);
{ Replaces the main selection's text and *clears* additional selections }
2011-10-06 20:53:09 +02:00
begin
Call(SCI_REPLACESEL, 0, Value);
2011-10-06 20:53:09 +02:00
end;
procedure TScintEdit.SetRawText(const Value: TScintRawString);
begin
{ Workaround: Without this call, if the caret is on line 0 and out in
virtual space, it'll remain in virtual space after the replacement }
Call(SCI_CLEARSELECTIONS, 0, 0);
{ Using ReplaceRawTextRange instead of SCI_SETTEXT for embedded null support }
2024-07-27 15:48:08 +02:00
ReplaceRawTextRange(0, GetRawTextLength, Value);
2011-10-06 20:53:09 +02:00
ChooseCaretX;
end;
procedure TScintEdit.SetReadOnly(const Value: Boolean);
begin
Call(SCI_SETREADONLY, Ord(Value), 0);
end;
procedure TScintEdit.SetSavePoint;
begin
if FForceModified then begin
FForceModified := False;
if Assigned(FOnModifiedChange) then
FOnModifiedChange(Self);
end;
Call(SCI_SETSAVEPOINT, 0, 0);
end;
procedure TScintEdit.SetSelection(const Value: TScintRange);
{ Sets the main selection and removes additional selections. Very similar
to SetSingleSelection, not sure why both messages exist and are slightly
different }
2011-10-06 20:53:09 +02:00
begin
Call(SCI_SETSEL, Value.StartPos, Value.EndPos);
end;
2024-06-06 09:32:39 +02:00
procedure TScintEdit.SetSelectionAnchorPosition(Selection: Integer;
const Value: Integer);
{ Also sets anchors's virtual space to 0 }
begin
Call(SCI_SETSELECTIONNANCHOR, Selection, Value);
end;
procedure TScintEdit.SetSelectionAnchorVirtualSpace(Selection: Integer;
const Value: Integer);
begin
Call(SCI_SETSELECTIONNANCHORVIRTUALSPACE, Selection, Value);
end;
2024-06-06 09:32:39 +02:00
procedure TScintEdit.SetSelectionCaretPosition(Selection: Integer;
const Value: Integer);
{ Also sets caret's virtual space to 0 }
begin
Call(SCI_SETSELECTIONNCARET, Selection, Value);
end;
procedure TScintEdit.SetSelectionCaretVirtualSpace(Selection: Integer;
const Value: Integer);
begin
Call(SCI_SETSELECTIONNCARETVIRTUALSPACE, Selection, Value);
end;
2024-06-15 01:34:41 +02:00
procedure TScintEdit.SetSelectionMode(const Value: TScintSelectionMode);
begin
var Mode: Integer;
if Value = ssmStream then
Mode := SC_SEL_STREAM
else if Value = ssmRectangular then
Mode := SC_SEL_RECTANGLE
else if Value = ssmLines then
Mode := SC_SEL_LINES
else
Mode := SC_SEL_THIN;
{ Note this uses *CHANGE* and not *SET* }
Call(SCI_CHANGESELECTIONMODE, Mode, 0);
end;
2011-10-06 20:53:09 +02:00
procedure TScintEdit.SetSelText(const Value: String);
begin
SetRawSelText(ConvertStringToRawString(Value));
end;
procedure TScintEdit.SetSingleSelection(const CaretPos, AnchorPos: Integer);
{ Sets the main selection and removes additional selections without scrolling
the caret into view }
begin
Call(SCI_SETSELECTION, CaretPos, AnchorPos);
end;
2011-10-06 20:53:09 +02:00
procedure TScintEdit.SetStyler(const Value: TScintCustomStyler);
begin
if FStyler <> Value then begin
if Assigned(Value) then
Value.FreeNotification(Self);
FStyler := Value;
if HandleAllocated then begin
Call(SCI_CLEARDOCUMENTSTYLE, 0, 0);
Call(SCI_STARTSTYLING, 0, 0);
UpdateStyleAttributes;
end;
end;
end;
procedure TScintEdit.SetTabWidth(const Value: Integer);
begin
if (FTabWidth <> Value) and (Value > 0) and (Value < 100) then begin
FTabWidth := Value;
ApplyOptions;
end;
end;
procedure TScintEdit.SetTarget(const StartPos, EndPos: Integer);
begin
Call(SCI_SETTARGETSTART, StartPos, 0);
Call(SCI_SETTARGETEND, EndPos, 0);
end;
procedure TScintEdit.SetTopLine(const Value: Integer);
begin
Call(SCI_SETFIRSTVISIBLELINE, Value, 0);
end;
procedure TScintEdit.SetUseStyleAttributes(const Value: Boolean);
begin
if FUseStyleAttributes <> Value then begin
FUseStyleAttributes := Value;
UpdateStyleAttributes;
end;
end;
procedure TScintEdit.SetUseTabCharacter(const Value: Boolean);
begin
if FUseTabCharacter <> Value then begin
FUseTabCharacter := Value;
ApplyOptions;
end;
end;
procedure TScintEdit.SetVirtualSpaceOptions(const Value: TScintVirtualSpaceOptions);
begin
if FVirtualSpaceOptions <> Value then begin
FVirtualSpaceOptions := Value;
ApplyOptions;
end;
end;
2020-10-13 22:03:31 +02:00
procedure TScintEdit.SetWordChars(const S: AnsiString);
begin
2024-06-29 21:51:50 +02:00
FWordChars := S;
FWordCharsAsSet := [];
for var C in S do
Include(FWordCharsAsSet, C);
Call(SCI_SETWORDCHARS, 0, S);
2020-10-13 22:03:31 +02:00
end;
2011-10-06 20:53:09 +02:00
procedure TScintEdit.SetWordWrap(const Value: Boolean);
begin
if FWordWrap <> Value then begin
FWordWrap := Value;
ApplyOptions;
end;
end;
procedure TScintEdit.SetZoom(const Value: Integer);
begin
Call(SCI_SETZOOM, Value, 0);
end;
procedure TScintEdit.ShowAutoComplete(const CharsEntered: Integer;
const WordList: AnsiString);
begin
Call(SCI_AUTOCSHOW, CharsEntered, WordList);
2011-10-06 20:53:09 +02:00
end;
2024-06-29 21:51:50 +02:00
procedure TScintEdit.ShowCallTip(const Pos: Integer;
const Definition: AnsiString);
begin
Call(SCI_CALLTIPSHOW, Pos, Definition);
2024-06-29 21:51:50 +02:00
end;
2011-10-06 20:53:09 +02:00
procedure TScintEdit.StyleNeeded(const EndPos: Integer);
function CalcCaretIndex(const FirstLine, LastLine: Integer): Integer;
var
CaretPos, StartPos, EndPos: Integer;
begin
Result := 0;
if FReportCaretPositionToStyler then begin
CaretPos := GetCaretPosition;
StartPos := GetPositionFromLine(FirstLine);
EndPos := GetLineEndPosition(LastLine);
if (CaretPos >= StartPos) and (CaretPos <= EndPos) then
Result := CaretPos - StartPos + 1;
end;
end;
procedure MaskDoubleByteCharacters(var S: TScintRawString);
var
Len, I: Integer;
begin
{ This replaces all lead and trail bytes in S with #$80 and #$81 to
ensure that stylers do not mistake trail bytes for single-byte ASCII
characters (e.g. #131'A' is a valid combination on CP 932). }
if not FEffectiveCodePageDBCS then
Exit;
Len := Length(S);
I := 1;
while I <= Len do begin
if S[I] in FLeadBytes then begin
S[I] := #$80;
if I < Len then begin
Inc(I);
S[I] := #$81;
end;
end;
Inc(I);
end;
end;
function LineSpans(const Line: Integer): Boolean;
var
S: TScintRawString;
begin
S := FLines.RawLines[Line];
MaskDoubleByteCharacters(S);
Result := FStyler.LineTextSpans(S);
end;
function StyleLine(const FirstLine: Integer; const StartStylingPos: Integer): Integer;
2011-10-06 20:53:09 +02:00
begin
{ Find final line in series of spanned lines }
var LastLine := FirstLine;
2011-10-06 20:53:09 +02:00
while (LastLine < Lines.Count - 1) and LineSpans(LastLine) do
Inc(LastLine);
{ We don't pass line endings to the styler, because when the style of a
line ending changes, Scintilla assumes it must be a 'hanging' style and
immediately repaints all subsequent lines. (To see this in the IS IDE,
insert and remove a ';' character before a [Setup] directive, i.e.
toggle comment styling.) }
FStyler.FCaretIndex := CalcCaretIndex(FirstLine, LastLine);
FStyler.FCurIndex := 1;
FStyler.FStyleStartIndex := 1;
FStyler.FLineState := 0;
if FirstLine > 0 then
FStyler.FLineState := FLines.GetState(FirstLine-1);
FStyler.FText := GetRawTextRange(GetPositionFromLine(FirstLine),
GetLineEndPosition(LastLine));
MaskDoubleByteCharacters(FStyler.FText);
FStyler.FTextLen := Length(FStyler.FText);
FStyler.FStyleStr := StringOfChar(AnsiChar(0), FStyler.FTextLen +
FLines.GetLineEndingLength(LastLine));
var PreviousLineState := FStyler.LineState;
2011-10-06 20:53:09 +02:00
FStyler.StyleNeeded;
2024-06-08 11:33:26 +02:00
var N := Length(FStyler.FStyleStr);
if N > 0 then begin
var HadStyleByteIndicators := False;
2024-06-12 17:24:55 +02:00
{ Apply style byte indicators. Add first as INDICATOR_CONTAINER and so on. }
for var Indicator := 0 to High(TScintStyleByteIndicatorNumber) do begin
2024-06-10 19:33:53 +02:00
var PrevI := 1;
var PrevValue := Indicator in TScintStyleByteIndicatorNumbers(Byte(Ord(FStyler.FStyleStr[1]) shr StyleNumberBits));
for var CurI := 2 to N do begin
var CurValue := Indicator in TScintStyleByteIndicatorNumbers(Byte(Ord(FStyler.FStyleStr[CurI]) shr StyleNumberBits));
if CurValue <> PrevValue then begin
2024-06-12 17:24:55 +02:00
SetIndicators(StartStylingPos+PrevI-1, StartStylingPos+CurI-1, Ord(Indicator)+INDICATOR_CONTAINER, PrevValue);
HadStyleByteIndicators := HadStyleByteIndicators or PrevValue;
PrevI := CurI;
PrevValue := CurValue;
end;
end;
2024-06-12 17:24:55 +02:00
SetIndicators(StartStylingPos+PrevI-1, StartStylingPos+N, Ord(Indicator)+INDICATOR_CONTAINER, PrevValue);
HadStyleByteIndicators := HadStyleByteIndicators or PrevValue;
end;
2011-10-06 20:53:09 +02:00
{ Apply styles after removing any style byte indicators }
if HadStyleByteIndicators then
2024-06-10 19:33:53 +02:00
for var I := 1 to N do
FStyler.FStyleStr[I] := AnsiChar(Ord(FStyler.FStyleStr[I]) and StyleNumberMask);
Call(SCI_SETSTYLINGEX, Length(FStyler.FStyleStr), FStyler.FStyleStr);
2011-10-06 20:53:09 +02:00
FStyler.FStyleStr := '';
FStyler.FText := '';
end;
{ Get fold level }
var LineState := FStyler.LineState;
var FoldLevel: Integer;
var FoldHeader, EnableFoldHeaderOnPrevious: Boolean;
FStyler.GetFoldLevel(LineState, PreviousLineState, FoldLevel, FoldHeader, EnableFoldHeaderOnPrevious);
Inc(FoldLevel, SC_FOLDLEVELBASE);
if FoldHeader then
FoldLevel := FoldLevel or SC_FOLDLEVELHEADERFLAG;
{ Apply line state and fold level }
for var I := FirstLine to LastLine do begin
var OldState := FLines.GetState(I);
2011-10-06 20:53:09 +02:00
if FStyler.FLineState <> OldState then
Call(SCI_SETLINESTATE, I, FStyler.FLineState);
var OldLevel := Call(SCI_GETFOLDLEVEL, I, 0);
var NewLevel := FoldLevel;
{ Setting SC_FOLDLEVELWHITEFLAG on empty lines causes a problem: when
Scintilla auto expands a contracted section (for example after removing ']'
from a section header) all the empty lines stay invisible, even any which
are in the middle of the section. See https://sourceforge.net/p/scintilla/bugs/2442/ }
//if FLines.GetRawLineLength(I) = 0 then
// NewLevel := NewLevel or SC_FOLDLEVELWHITEFLAG;
if NewLevel <> OldLevel then
Call(SCI_SETFOLDLEVEL, I, NewLevel);
end;
{ Retroactively set header on previous line if requested to do so. Must be
*after* the loop above. Not sure why. Problem reproduction: move code above
the loop, run it, open Debug.iss, change [Setup] to [Set up] and notice
styling of the [Languages] section below it is now broken. If you turn on
sffLevelNumbers you will also see that the first entry in that section got
a header flag. }
if (FirstLine > 0) and EnableFoldHeaderOnPrevious then begin
var PreviousLine := FirstLine-1;
var OldLevel := Call(SCI_GETFOLDLEVEL, PreviousLine, 0);
var NewLevel := OldLevel or SC_FOLDLEVELHEADERFLAG;
if NewLevel <> OldLevel then
Call(SCI_SETFOLDLEVEL, PreviousLine, NewLevel);
2011-10-06 20:53:09 +02:00
end;
Result := LastLine;
end;
procedure DefaultStyleLine(const Line: Integer);
var
StyleStr: AnsiString;
begin
{ Note: Using SCI_SETSTYLINGEX because it only redraws the part of the
range that changed, whereas SCI_SETSTYLING redraws the entire range. }
StyleStr := StringOfChar(AnsiChar(0), FLines.GetRawLineLengthWithEnding(Line));
Call(SCI_SETSTYLINGEX, Length(StyleStr), StyleStr);
2011-10-06 20:53:09 +02:00
end;
var
StartPos, StartLine, EndLine, Line: Integer;
begin
StartPos := Call(SCI_GETENDSTYLED, 0, 0);
StartLine := GetLineFromPosition(StartPos);
{ EndPos (always?) points to the position *after* the last character of the
last line needing styling (usually an LF), so subtract 1 to avoid
restyling one extra line unnecessarily.
But don't do this if we're being asked to style all the way to the end.
When the document's last line is empty, 'EndPos - 1' will point to the
line preceding the last line, so StyleLine() will never be called on the
last line, and it will never be assigned a LINESTATE. This causes IS's
autocompletion to think the last line's section is scNone. }
if EndPos < GetRawTextLength then
EndLine := GetLineFromPosition(EndPos - 1)
else
EndLine := GetLineFromPosition(EndPos);
//outputdebugstring('-----');
//outputdebugstring(pchar(format('StyleNeeded poses: %d, %d', [StartPos, EndPos])));
//outputdebugstring(pchar(format('StyleNeeded lines: %d, %d', [StartLine, EndLine])));
{ If StartLine is within a series of spanned lines, back up }
if Assigned(FStyler) then
while (StartLine > 0) and (LineSpans(StartLine - 1)) do
Dec(StartLine);
Line := StartLine;
while Line <= EndLine do begin
var StartStylingPos := GetPositionFromLine(Line);
Call(SCI_STARTSTYLING, StartStylingPos, 0);
2011-10-06 20:53:09 +02:00
if Assigned(FStyler) then
Line := StyleLine(Line, StartStylingPos)
2011-10-06 20:53:09 +02:00
else
DefaultStyleLine(Line);
Inc(Line);
end;
end;
2024-06-15 17:09:13 +02:00
procedure TScintEdit.SysColorChange(const Message: TMessage);
begin
ForwardMessage(Message);
end;
function TScintEdit.TestRawRegularExpression(const S: TScintRawString): Boolean;
{ Example invalid regular expression: ( }
begin
Call(SCI_SETTARGETRANGE, 0, 0);
Call(SCI_SETSEARCHFLAGS, GetSearchFlags([sfoRegEx]), 0);
var WarnStatus: Integer;
var Res := Call(SCI_SEARCHINTARGET, Length(S), S, WarnStatus);
Result := not ((Res = -1) and (WarnStatus = SC_STATUS_WARN_REGEX));
end;
function TScintEdit.TestRegularExpression(const S: String): Boolean;
begin
Result := TestRawRegularExpression(ConvertStringToRawString(S));
end;
2011-10-06 20:53:09 +02:00
procedure TScintEdit.Undo;
begin
Call(SCI_UNDO, 0, 0);
end;
procedure TScintEdit.UpdateCodePage;
procedure InitLeadBytes;
var
Info: TCPInfo;
I: Integer;
J: Byte;
begin
FLeadBytes := [];
if FEffectiveCodePageDBCS and GetCPInfo(FEffectiveCodePage, Info) then begin
I := 0;
while (I < MAX_LEADBYTES) and ((Info.LeadByte[I] or Info.LeadByte[I+1]) <> 0) do begin
for J := Info.LeadByte[I] to Info.LeadByte[I+1] do
Include(FLeadBytes, AnsiChar(J));
Inc(I, 2);
end;
end;
end;
var
CP: Integer;
begin
if HandleAllocated then begin
{ To Scintilla, code page 0 does not mean the current ANSI code page, but
an unspecified single byte code page. So that DBCS support is properly
enabled when running on a DBCS ANSI code page, replace 0 with GetACP. }
CP := FCodePage;
if CP = 0 then
CP := GetACP;
Call(SCI_SETCODEPAGE, CP, 0);
{ Scintilla ignores attempts to set a code page it has no special support
for. But the editor could currently be set for UTF-8 or DBCS, so get it
out of that mode by setting the code page to 0 (a value it does
recognize). }
if Call(SCI_GETCODEPAGE, 0, 0) <> CP then
Call(SCI_SETCODEPAGE, 0, 0);
FEffectiveCodePage := Call(SCI_GETCODEPAGE, 0, 0);
FEffectiveCodePageDBCS := (FEffectiveCodePage <> 0) and
(FEffectiveCodePage <> SC_CP_UTF8);
InitLeadBytes;
end;
end;
procedure TScintEdit.UpdateLineNumbersWidth;
var
LineCount, PixelWidth: Integer;
Nines: String;
begin
if FLineNumbers or FFoldLevelNumbersOrLineState then begin
{ Note: Based on SciTE's SciTEBase::SetLineNumberWidth. }
if FFoldLevelNumbersOrLineState then
Nines := StringOfChar('9', 12)
else begin
LineCount := Call(SCI_GETLINECOUNT, 0, 0);
Nines := '9';
while LineCount >= 10 do begin
LineCount := LineCount div 10;
Nines := Nines + '9';
end;
end;
PixelWidth := 4 + Call(SCI_TEXTWIDTH, STYLE_LINENUMBER, AnsiString(Nines));
end else
PixelWidth := 0;
Call(SCI_SETMARGINWIDTHN, 0, PixelWidth);
end;
2011-10-06 20:53:09 +02:00
procedure TScintEdit.UpdateStyleAttributes;
var
DefaultAttr: TScintStyleAttributes;
procedure SetStyleAttr(const StyleNumber: Integer;
const Attr: TScintStyleAttributes; const Force: Boolean);
begin
if Force or (Attr.FontName <> DefaultAttr.FontName) then
Call(SCI_STYLESETFONT, StyleNumber, AnsiString(Attr.FontName));
2011-10-06 20:53:09 +02:00
if Force or (Attr.FontSize <> DefaultAttr.FontSize) then
{ Note: Scintilla doesn't support negative point sizes like the VCL }
Call(SCI_STYLESETSIZE, StyleNumber, Abs(Attr.FontSize));
if Force or (Attr.FontCharset <> DefaultAttr.FontCharset) then
Call(SCI_STYLESETCHARACTERSET, StyleNumber, Attr.FontCharset);
if Force or (Attr.FontStyle <> DefaultAttr.FontStyle) then begin
Call(SCI_STYLESETBOLD, StyleNumber, Ord(fsBold in Attr.FontStyle));
Call(SCI_STYLESETITALIC, StyleNumber, Ord(fsItalic in Attr.FontStyle));
Call(SCI_STYLESETUNDERLINE, StyleNumber, Ord(fsUnderline in Attr.FontStyle));
end;
if Force or (Attr.ForeColor <> DefaultAttr.ForeColor) then
Call(SCI_STYLESETFORE, StyleNumber, ColorToRGB(Attr.ForeColor));
if Force or (Attr.BackColor <> DefaultAttr.BackColor) then
Call(SCI_STYLESETBACK, StyleNumber, ColorToRGB(Attr.BackColor));
end;
procedure SetStyleAttrFromStyler(const StyleNumber: Integer);
var
Attr: TScintStyleAttributes;
begin
Attr := DefaultAttr;
FStyler.GetStyleAttributes(StyleNumber, Attr);
SetStyleAttr(StyleNumber, Attr, False);
end;
var
I: Integer;
begin
if not HandleAllocated then
Exit;
Call(SCI_SETCARETFORE, ColorToRGB(Font.Color), 0);
DefaultAttr.FontName := Font.Name;
DefaultAttr.FontSize := Font.Size;
DefaultAttr.FontStyle := Font.Style;
DefaultAttr.FontCharset := Font.Charset;
DefaultAttr.ForeColor := Font.Color;
DefaultAttr.BackColor := Color;
Call(SCI_STYLERESETDEFAULT, 0, 0);
SetStyleAttr(STYLE_DEFAULT, DefaultAttr, True);
Call(SCI_STYLECLEARALL, 0, 0);
if Assigned(FStyler) then begin
2024-06-15 03:21:58 +02:00
if FUseStyleAttributes then begin
for I := 0 to StyleNumbers-1 do
SetStyleAttrFromStyler(I);
SetStyleAttrFromStyler(STYLE_BRACEBAD);
SetStyleAttrFromStyler(STYLE_BRACELIGHT);
SetStyleAttrFromStyler(STYLE_INDENTGUIDE);
end;
SetStyleAttrFromStyler(STYLE_LINENUMBER);
2011-10-06 20:53:09 +02:00
end;
if (AutoCompleteFontName <> '') or (AutoCompleteFontSize > 0) then begin
if AutoCompleteFontName <> '' then
DefaultAttr.FontName := AutoCompleteFontName;
if AutoCompleteFontSize > 0 then
2011-10-06 20:53:09 +02:00
DefaultAttr.FontSize := AutoCompleteFontSize;
DefaultAttr.FontStyle := [];
{ Note: Scintilla doesn't actually use the colors set here }
DefaultAttr.ForeColor := clWindowText;
DefaultAttr.BackColor := clWindow;
if FAutoCompleteStyle = 0 then
FAutoCompleteStyle := Call(SCI_ALLOCATEEXTENDEDSTYLES, 1, 0);
SetStyleAttr(FAutoCompleteStyle, DefaultAttr, True);
Call(SCI_AUTOCSETSTYLE, FAutoCompleteStyle, 0);
end else
Call(SCI_AUTOCSETSTYLE, 0, 0);
2011-10-06 20:53:09 +02:00
end;
2024-11-14 23:41:22 +01:00
function TScintEdit.WordAtCaret: String;
2011-10-06 20:53:09 +02:00
begin
2024-11-14 23:41:22 +01:00
var Range := WordAtCaretRange;
Result := GetTextRange(Range.StartPos, Range.EndPos);
end;
2024-11-14 23:41:22 +01:00
function TScintEdit.WordAtCaretRange: TScintRange;
begin
var Pos := GetCaretPosition;
Result.StartPos := GetWordStartPosition(Pos, True);
Result.EndPos := GetWordEndPosition(Pos, True);
2011-10-06 20:53:09 +02:00
end;
procedure TScintEdit.ZoomIn;
begin
Call(SCI_ZOOMIN, 0, 0);
end;
procedure TScintEdit.ZoomOut;
begin
Call(SCI_ZOOMOUT, 0, 0);
end;
procedure TScintEdit.CMColorChanged(var Message: TMessage);
begin
inherited;
UpdateStyleAttributes;
end;
procedure TScintEdit.CMFontChanged(var Message: TMessage);
begin
inherited;
UpdateStyleAttributes;
end;
procedure TScintEdit.CMHintShow(var Message: TCMHintShow);
begin
inherited;
if Assigned(FOnHintShow) then
FOnHintShow(Self, Message.HintInfo^);
end;
procedure TScintEdit.CMSysColorChange(var Message: TMessage);
begin
inherited;
UpdateStyleAttributes;
end;
procedure TScintEdit.CNNotify(var Message: TWMNotify);
begin
Notify(PSCNotification(Message.NMHdr)^);
end;
procedure TScintEdit.WMDestroy(var Message: TWMDestroy);
begin
FDirectPtr := nil;
FDirectStatusFunction := nil;
2011-10-06 20:53:09 +02:00
inherited;
end;
procedure TScintEdit.DpiChanged(const Message: TMessage);
begin
ForwardMessage(Message);
end;
2011-10-06 20:53:09 +02:00
procedure TScintEdit.WMDropFiles(var Message: TWMDropFiles);
var
FileList: TStringList;
NumFiles, I: Integer;
Filename: array[0..MAX_PATH-1] of Char;
P: TPoint;
begin
FileList := nil;
try
if FAcceptDroppedFiles and Assigned(FOnDropFiles) then begin
FileList := TStringList.Create;
NumFiles := DragQueryFile(Message.Drop, UINT(-1), nil, 0);
for I := 0 to NumFiles-1 do
if DragQueryFile(Message.Drop, I, Filename,
SizeOf(Filename) div SizeOf(Filename[0])) <> 0 then
FileList.Add(Filename);
if FileList.Count > 0 then begin
if not DragQueryPoint(Message.Drop, P) then begin
P.X := -1;
P.Y := -1;
end;
FOnDropFiles(Self, P.X, P.Y, FileList);
end;
end;
finally
FileList.Free;
DragFinish(Message.Drop);
Message.Drop := 0;
end;
end;
procedure TScintEdit.WMEraseBkgnd(var Message: TMessage);
begin
{ Bypass the VCL's WM_ERASEBKGND handler; it causes flicker when selecting +
scrolling downward using the mouse }
Message.Result := CallWindowProc(DefWndProc, Handle, Message.Msg,
Message.WParam, Message.LParam);
end;
procedure TScintEdit.WMGetDlgCode(var Message: TWMGetDlgCode);
begin
inherited;
Message.Result := Message.Result or (DLGC_WANTARROWS or DLGC_WANTTAB);
end;
procedure TScintEdit.WMMouseWheel(var Message: TMessage);
begin
{ Bypass TControl's broken WM_MOUSEWHEEL handler: it translates WParamLo
from a combination of MK_* values to a TShiftState -- which is only
meaningful to the VCL -- but it doesn't restore the original value before
passing an unhandled WM_MOUSEWHEEL message up to DefWndProc. This causes
Scintilla to see Ctrl+wheel as Shift+wheel, breaking zoom. (Observed on
2024-06-08 11:46:12 +02:00
Delphi 2009 and still needed in Delphi 11.3.) }
2011-10-06 20:53:09 +02:00
Message.Result := CallWindowProc(DefWndProc, Handle, Message.Msg,
Message.WParam, Message.LParam);
end;
procedure TScintEdit.SettingChange(const Message: TMessage);
begin
ForwardMessage(Message);
end;
2011-10-06 20:53:09 +02:00
{ TScintEditStrings }
procedure TScintEditStrings.CheckIndexRange(const Index: Integer);
begin
if (Index < 0) or (Index >= GetCount) then
Error(@SListIndexError, Index);
end;
procedure TScintEditStrings.CheckIndexRangePlusOne(const Index: Integer);
begin
if (Index < 0) or (Index > GetCount) then
Error(@SListIndexError, Index);
end;
procedure TScintEditStrings.Clear;
begin
FEdit.SetRawText('');
end;
procedure TScintEditStrings.Delete(Index: Integer);
var
StartPos, EndPos: Integer;
begin
CheckIndexRange(Index);
StartPos := FEdit.GetPositionFromLine(Index);
EndPos := FEdit.GetPositionFromLine(Index + 1);
2024-07-27 15:48:08 +02:00
FEdit.ReplaceRawTextRange(StartPos, EndPos, '');
2011-10-06 20:53:09 +02:00
end;
function TScintEditStrings.Get(Index: Integer): String;
begin
Result := FEdit.ConvertRawStringToString(GetRawLine(Index));
end;
function TScintEditStrings.GetCount: Integer;
begin
Result := FEdit.Call(SCI_GETLINECOUNT, 0, 0);
end;
function TScintEditStrings.GetLineEndingLength(const Index: Integer): Integer;
var
StartPos, EndPos: Integer;
begin
CheckIndexRange(Index);
StartPos := FEdit.GetLineEndPosition(Index);
EndPos := FEdit.GetPositionFromLine(Index + 1);
Result := EndPos - StartPos;
end;
function TScintEditStrings.GetRawLine(Index: Integer): TScintRawString;
var
StartPos, EndPos: Integer;
begin
CheckIndexRange(Index);
StartPos := FEdit.GetPositionFromLine(Index);
EndPos := FEdit.GetLineEndPosition(Index);
Result := FEdit.GetRawTextRange(StartPos, EndPos);
end;
function TScintEditStrings.GetRawLineLength(Index: Integer): Integer;
var
StartPos, EndPos: Integer;
begin
CheckIndexRange(Index);
StartPos := FEdit.GetPositionFromLine(Index);
EndPos := FEdit.GetLineEndPosition(Index);
Result := EndPos - StartPos;
end;
function TScintEditStrings.GetRawLineLengthWithEnding(Index: Integer): Integer;
var
StartPos, EndPos: Integer;
begin
CheckIndexRange(Index);
StartPos := FEdit.GetPositionFromLine(Index);
EndPos := FEdit.GetPositionFromLine(Index + 1);
Result := EndPos - StartPos;
end;
function TScintEditStrings.GetRawLineWithEnding(Index: Integer): TScintRawString;
var
StartPos, EndPos: Integer;
begin
CheckIndexRange(Index);
StartPos := FEdit.GetPositionFromLine(Index);
EndPos := FEdit.GetPositionFromLine(Index + 1);
Result := FEdit.GetRawTextRange(StartPos, EndPos);
end;
function TScintEditStrings.GetState(Index: Integer): TScintLineState;
begin
CheckIndexRange(Index);
Result := FEdit.Call(SCI_GETLINESTATE, Index, 0);
end;
function TScintEditStrings.GetTextStr: String;
begin
Result := FEdit.ConvertRawStringToString(FEdit.GetRawText);
end;
procedure TScintEditStrings.Insert(Index: Integer; const S: String);
begin
InsertRawLine(Index, FEdit.ConvertStringToRawString(S));
end;
procedure TScintEditStrings.InsertRawLine(Index: Integer; const S: TScintRawString);
var
Pos: Integer;
EndingStr, InsertStr: TScintRawString;
begin
CheckIndexRangePlusOne(Index);
EndingStr := FEdit.GetLineEndingString;
Pos := FEdit.GetPositionFromLine(Index);
if (Index = GetCount) and (Pos <> FEdit.GetPositionFromLine(Index - 1)) then
InsertStr := EndingStr + S + EndingStr
else
InsertStr := S + EndingStr;
{ Using ReplaceRawTextRange instead of SCI_INSERTTEXT for embedded null support }
2024-07-27 15:48:08 +02:00
FEdit.ReplaceRawTextRange(Pos, Pos, InsertStr);
2011-10-06 20:53:09 +02:00
end;
procedure TScintEditStrings.Put(Index: Integer; const S: String);
begin
PutRawLine(Index, FEdit.ConvertStringToRawString(S));
end;
procedure TScintEditStrings.PutRawLine(Index: Integer; const S: TScintRawString);
var
StartPos, EndPos: Integer;
begin
CheckIndexRange(Index);
StartPos := FEdit.GetPositionFromLine(Index);
EndPos := FEdit.GetLineEndPosition(Index);
2024-07-27 15:48:08 +02:00
FEdit.ReplaceRawTextRange(StartPos, EndPos, S, srmMinimal);
2011-10-06 20:53:09 +02:00
end;
procedure TScintEditStrings.SetText(Text: PChar);
begin
FEdit.SetRawText(FEdit.ConvertPCharToRawString(Text, StrLen(Text)));
end;
procedure TScintEditStrings.SetTextStr(const Value: String);
begin
FEdit.SetRawText(FEdit.ConvertStringToRawString(Value));
end;
{ TScintCustomStyler }
procedure TScintCustomStyler.ApplyStyleByteIndicators(const Indicators: TScintStyleByteIndicatorNumbers;
2011-10-06 20:53:09 +02:00
StartIndex, EndIndex: Integer);
begin
2024-06-10 19:33:53 +02:00
var IndByte := Byte(Indicators) shl StyleNumberBits;
2011-10-06 20:53:09 +02:00
if IndByte <> 0 then begin
if StartIndex < 1 then
StartIndex := 1;
if EndIndex > FTextLen then
EndIndex := FTextLen;
2024-06-10 19:33:53 +02:00
for var I := StartIndex to EndIndex do
FStyleStr[I] := AnsiChar(Ord(FStyleStr[I]) or IndByte);
2011-10-06 20:53:09 +02:00
end;
end;
procedure TScintCustomStyler.ApplyStyle(const Style: TScintStyleNumber;
StartIndex, EndIndex: Integer);
begin
if StartIndex < 1 then
StartIndex := 1;
if EndIndex > FTextLen then
EndIndex := FTextLen;
2024-06-10 19:33:53 +02:00
for var I := StartIndex to EndIndex do
if Ord(FStyleStr[I]) and StyleNumberMask = 0 then
FStyleStr[I] := AnsiChar(Style or (Ord(FStyleStr[I]) and not StyleNumberMask));
2011-10-06 20:53:09 +02:00
end;
procedure TScintCustomStyler.CommitStyle(const Style: TScintStyleNumber);
begin
ApplyStyle(Style, FStyleStartIndex, FCurIndex - 1);
FStyleStartIndex := FCurIndex;
end;
function TScintCustomStyler.ConsumeAllRemaining: Boolean;
begin
Result := FCurIndex <= FTextLen;
2011-10-06 20:53:09 +02:00
if Result then
FCurIndex := FTextLen + 1;
end;
function TScintCustomStyler.ConsumeChar(const C: AnsiChar): Boolean;
begin
Result := (FCurIndex <= FTextLen) and (FText[FCurIndex] = C);
if Result then
Inc(FCurIndex);
end;
function TScintCustomStyler.ConsumeCharIn(const Chars: TScintRawCharSet): Boolean;
begin
Result := (FCurIndex <= FTextLen) and (FText[FCurIndex] in Chars);
if Result then
Inc(FCurIndex);
end;
2011-10-06 20:53:09 +02:00
function TScintCustomStyler.ConsumeChars(const Chars: TScintRawCharSet): Boolean;
begin
Result := False;
while FCurIndex <= FTextLen do begin
if not(FText[FCurIndex] in Chars) then
Break;
Result := True;
Inc(FCurIndex);
end;
end;
function TScintCustomStyler.ConsumeCharsNot(const Chars: TScintRawCharSet): Boolean;
begin
Result := False;
while FCurIndex <= FTextLen do begin
if FText[FCurIndex] in Chars then
Break;
Result := True;
Inc(FCurIndex);
end;
end;
function TScintCustomStyler.ConsumeString(const Chars: TScintRawCharSet): TScintRawString;
var
StartIndex: Integer;
begin
StartIndex := FCurIndex;
ConsumeChars(Chars);
Result := Copy(FText, StartIndex, FCurIndex - StartIndex);
end;
function TScintCustomStyler.CurCharIn(const Chars: TScintRawCharSet): Boolean;
begin
Result := (FCurIndex <= FTextLen) and (FText[FCurIndex] in Chars);
end;
function TScintCustomStyler.CurCharIs(const C: AnsiChar): Boolean;
begin
Result := (FCurIndex <= FTextLen) and (FText[FCurIndex] = C);
end;
function TScintCustomStyler.GetCurChar: AnsiChar;
begin
Result := #0;
if FCurIndex <= FTextLen then
Result := FText[FCurIndex];
end;
function TScintCustomStyler.GetEndOfLine: Boolean;
begin
Result := FCurIndex > FTextLen;
2011-10-06 20:53:09 +02:00
end;
function TScintCustomStyler.LineTextSpans(const S: TScintRawString): Boolean;
begin
Result := False;
end;
function TScintCustomStyler.NextCharIs(const C: AnsiChar): Boolean;
begin
Result := (FCurIndex < FTextLen) and (FText[FCurIndex+1] = C);
end;
function TScintCustomStyler.PreviousCharIn(const Chars: TScintRawCharSet): Boolean;
begin
Result := (FCurIndex > 1) and (FCurIndex-1 <= FTextLen) and
(FText[FCurIndex-1] in Chars);
end;
procedure TScintCustomStyler.ReplaceText(StartIndex, EndIndex: Integer;
const C: AnsiChar);
var
P: PAnsiChar;
I: Integer;
begin
if StartIndex < 1 then
StartIndex := 1;
if EndIndex > FTextLen then
EndIndex := FTextLen;
P := @FText[1];
for I := StartIndex to EndIndex do
P[I-1] := C;
end;
procedure TScintCustomStyler.ResetCurIndexTo(Index: Integer);
2016-07-02 20:12:09 +08:00
begin
FCurIndex := Index;
FStyleStartIndex := Index;
2016-07-02 20:12:09 +08:00
end;
2024-05-04 17:24:37 +02:00
{ TScintPixmap }
const
XPMTransparentChar = ' ';
XPMTerminatorChar = '"';
class constructor TScintPixmap.Create;
begin
2024-05-07 18:14:29 +02:00
{ Chars 128-255 are supported below but don't work in Scintilla }
for var C := #1 to #127 do
if (C <> XPMTransparentChar) and (C <> XPMTerminatorChar) then
ColorCodes := ColorCodes + C;
end;
2024-05-04 17:24:37 +02:00
function TScintPixmap.GetPixmap: Pointer;
begin
Result := FPixmap;
end;
type
2024-05-07 18:14:29 +02:00
TRGBTripleArray = array[0..MaxInt div SizeOf(TRGBTriple) - 1] of TRGBTriple;
2024-05-04 20:47:03 +02:00
PRGBTripleArray = ^TRGBTripleArray;
2024-05-04 17:24:37 +02:00
procedure TScintPixmap.InitializeFromBitmap(const ABitmap: TBitmap;
2024-05-07 18:14:29 +02:00
const TransparentColor: TColorRef);
2024-05-04 17:24:37 +02:00
procedure SetNextPixmapLine(const Pixmap: TPixmap; var Index: Integer; const Line: String);
2024-05-04 17:24:37 +02:00
begin
2024-05-07 00:58:30 -05:00
if Index > High(Pixmap) then
TScintEdit.Error('SetNextPixmapLine: Index out of range');
{ Convert Line to an AnsiString, but copy the exact ordinal values;
i.e. don't do any translation of 128-255 }
var AnsiLine: AnsiString;
SetLength(AnsiLine, Length(Line));
for var I := 1 to Length(AnsiLine) do
AnsiLine[I] := AnsiChar(Ord(Line[I]));
Pixmap[Index] := AnsiLine;
2024-05-04 17:24:37 +02:00
Inc(Index);
end;
begin
2024-05-04 20:47:03 +02:00
if ABitmap.PixelFormat <> pf24bit then
TScintEdit.Error('Invalid PixelFormat');
var Colors := TDictionary<Integer, TPair<Char, String>>.Create; { RGB -> Code & WebColor }
2024-05-04 17:24:37 +02:00
try
{ Build colors list }
for var Y := 0 to ABitmap.Height-1 do begin
var Pixels: PRGBTripleArray := ABitmap.ScanLine[Y];
for var X := 0 to ABitmap.Width-1 do begin
var Color := RGB(Pixels[X].rgbtRed, Pixels[X].rgbtGreen, Pixels[X].rgbtBlue);
if (Color <> TransparentColor) and not Colors.ContainsKey(Color) then begin
var ColorCodeIndex := Colors.Count+1;
if ColorCodeIndex > Length(ColorCodes) then
2024-05-04 20:47:03 +02:00
TScintEdit.Error('Too many colors');
Colors.Add(Color, TPair<Char, String>.Create(ColorCodes[ColorCodeIndex], RGBToWebColorStr(Color)))
2024-05-04 17:24:37 +02:00
end;
end;
end;
{ Build pixmap }
var Line: String;
2024-05-07 18:14:29 +02:00
SetLength(FPixmap, 0); { Not really needed but makes things clearer while debugging }
2024-05-07 00:58:30 -05:00
SetLength(FPixmap, 1 + Colors.Count + ABitmap.Height + 1);
Line := Format('%d %d %d 1', [ABitmap.Width, ABitmap.Height, Colors.Count]);
2024-05-04 17:24:37 +02:00
var Index := 0;
SetNextPixmapLine(FPixmap, Index, Line);
for var Color in Colors do begin
Line := Format('%s c %s', [Color.Value.Key, Color.Value.Value]);
2024-05-04 17:24:37 +02:00
SetNextPixmapLine(FPixmap, Index, Line);
end;
for var Y := 0 to ABitmap.Height-1 do begin
Line := '';
var Pixels: PRGBTripleArray := ABitmap.ScanLine[Y];
for var X := 0 to ABitmap.Width-1 do begin
var Color := RGB(Pixels[X].rgbtRed, Pixels[X].rgbtGreen, Pixels[X].rgbtBlue);
if Color = TransparentColor then
Line := Line + XPMTransparentChar
else
Line := Line + Colors[Color].Key;
2024-05-04 17:24:37 +02:00
end;
SetNextPixmapLine(FPixmap, Index, Line);
end;
2024-05-07 18:14:29 +02:00
{ Add terminating nil pointer - Scintilla doesnt really need it but setting it anyway }
SetNextPixmapLine(FPixmap, Index, '');
2024-05-04 17:24:37 +02:00
finally
Colors.Free;
end;
end;
{ TScintRange }
constructor TScintRange.Create(const AStartPos, AEndPos: Integer);
begin
StartPos := AStartPos;
EndPos := AEndPos;
end;
function TScintRange.Overlaps(const ARange: TScintRange): Boolean;
begin
Result := not ARange.Empty and (StartPos <= ARange.EndPos) and (EndPos >= ARange.StartPos);
end;
function TScintRange.Empty: Boolean;
begin
Result := StartPos = EndPos;
end;
function TScintRange.Within(const ARange: TScintRange): Boolean;
begin
Result := (StartPos >= ARange.StartPos) and (EndPos <= ARange.EndPos);
end;
{ TScintRangeList }
function TScintRangeList.Overlaps(const ARange: TScintRange;
var AOverlappingRange: TScintRange): Boolean;
begin
for var Item in Self do begin
if Item.Overlaps(ARange) then begin
AOverlappingRange := Item;
Exit(True);
end;
end;
Result := False;
end;
2024-06-27 16:57:54 +02:00
{ TScintCaretAndAnchor }
constructor TScintCaretAndAnchor.Create(const ACaretPos, AAnchorPos: Integer);
begin
CaretPos := ACaretPos;
AnchorPos := AAnchorPos;
end;
function TScintCaretAndAnchor.Range: TScintRange;
begin
if CaretPos <= AnchorPos then begin
Result.StartPos := CaretPos;
Result.EndPos := AnchorPos;
end else begin
Result.StartPos := AnchorPos;
Result.EndPos := CaretPos;
end;
end;
2011-10-06 20:53:09 +02:00
end.