ScintEdit.pas 103 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054
  1. unit ScintEdit;
  2. {
  3. Inno Setup
  4. Copyright (C) 1997-2024 Jordan Russell
  5. Portions by Martijn Laan
  6. For conditions of distribution and use, see LICENSE.TXT.
  7. TScintEdit component: a VCL wrapper for Scintilla
  8. }
  9. interface
  10. uses
  11. Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Generics.Collections, ScintInt;
  12. const
  13. StyleNumbers = 32; { The syntax highlighting can use up to 32 styles }
  14. StyleNumberBits = 5; { 5 bits are needed to store 32 values }
  15. StyleNumberMask = StyleNumbers-1; { To get the 5 bits from a byte it needs to be AND-ed with $1F = 31 }
  16. StyleNumberUnusedBits = 8-StyleNumberBits; { 3 bits of a byte are unused }
  17. type
  18. TScintChangeHistory = (schDisabled, schMarkers, schIndicators);
  19. TScintCommand = type NativeInt;
  20. TScintEditAutoCompleteSelectionEvent = TNotifyEvent;
  21. TScintEditCallTipArrowClick = procedure(Sender: TObject; const Up: Boolean) of object;
  22. TScintEditChangeInfo = record
  23. Inserting: Boolean;
  24. StartPos, Length, LinesDelta: Integer;
  25. end;
  26. TScintEditChangeEvent = procedure(Sender: TObject;
  27. const Info: TScintEditChangeInfo) of object;
  28. TScintEditCharAddedEvent = procedure(Sender: TObject; Ch: AnsiChar) of object;
  29. TScintEditDropFilesEvent = procedure(Sender: TObject; X, Y: Integer;
  30. AFiles: TStrings) of object;
  31. TScintHintInfo = Controls.THintInfo;
  32. TScintEditHintShowEvent = procedure(Sender: TObject;
  33. var Info: TScintHintInfo) of object;
  34. TScintEditMarginClickEvent = procedure(Sender: TObject; MarginNumber: Integer;
  35. Line: Integer) of object;
  36. TScintEditUpdate = (suContent, suSelection, suVScroll, suHScroll);
  37. TScintEditUpdates = set of TScintEditUpdate;
  38. TScintEditUpdateUIEvent = procedure(Sender: TObject; Updated: TScintEditUpdates) of object;
  39. TScintFindOption = (sfoMatchCase, sfoWholeWord, sfoRegEx);
  40. TScintFindOptions = set of TScintFindOption;
  41. TScintFoldFlag = (sffLineBeforeExpanded, sffLineBeforeContracted,
  42. sffLineAfterExpanded, sffLineAfterContracted, sffLevelNumbers, sffLineState);
  43. TScintFoldFlags = set of TScintFoldFlag;
  44. TScintIndentationGuides = (sigNone, sigReal, sigLookForward, sigLookBoth);
  45. TScintKeyCode = type Word;
  46. TScintKeyDefinition = type Cardinal;
  47. TScintReplaceMode = (srmNormal, srmMinimal, srmRegEx);
  48. TScintStyleByteIndicatorNumber = 0..1; { Could be increased to 0..StyleNumberUnusedBits-1 }
  49. TScintStyleByteIndicatorNumbers = set of TScintStyleByteIndicatorNumber;
  50. TScintIndicatorNumber = INDICATOR_CONTAINER..INDICATOR_MAX;
  51. TScintLineEndings = (sleCRLF, sleCR, sleLF);
  52. TScintLineState = type Integer;
  53. TScintMarkerNumber = 0..31;
  54. TScintMarkerNumbers = set of TScintMarkerNumber;
  55. TScintRange = record
  56. StartPos, EndPos: Integer;
  57. constructor Create(const AStartPos, AEndPos: Integer);
  58. function Empty: Boolean;
  59. function Overlaps(const ARange: TScintRange): Boolean;
  60. function Within(const ARange: TScintRange): Boolean;
  61. end;
  62. TScintRangeList = class(TList<TScintRange>)
  63. function Overlaps(const ARange: TScintRange;
  64. var AOverlappingRange: TScintRange): Boolean;
  65. end;
  66. TScintCaretAndAnchor = record
  67. CaretPos, AnchorPos: Integer;
  68. constructor Create(const ACaretPos, AAnchorPos: Integer);
  69. function Range: TScintRange;
  70. end;
  71. TScintCaretAndAnchorList = class(TList<TScintCaretAndAnchor>);
  72. TScintRawCharSet = set of AnsiChar;
  73. TScintRawString = type RawByteString;
  74. TScintRectangle = record
  75. Left, Top, Right, Bottom: Integer;
  76. end;
  77. TScintSelectionMode = (ssmStream, ssmRectangular, ssmLines, ssmThinRectangular);
  78. TScintStyleNumber = 0..StyleNumbers-1;
  79. TScintVirtualSpaceOption = (svsRectangularSelection, svsUserAccessible,
  80. svsNoWrapLineStart);
  81. TScintVirtualSpaceOptions = set of TScintVirtualSpaceOption;
  82. PScintRangeToFormat = ^TScintRangeToFormat;
  83. TScintRangeToFormat = record
  84. hdc, hdcTarget: UINT_PTR;
  85. rc, rcPage: TScintRectangle;
  86. chrg: TScintRange;
  87. end;
  88. TScintEditStrings = class;
  89. TScintCustomStyler = class;
  90. EScintEditError = class(Exception);
  91. TScintEdit = class(TWinControl)
  92. private
  93. FAcceptDroppedFiles: Boolean;
  94. FAutoCompleteFontName: String;
  95. FAutoCompleteFontSize: Integer;
  96. FAutoCompleteStyle: Integer;
  97. FChangeHistory: TScintChangeHistory;
  98. FCodePage: Integer;
  99. FDirectPtr: Pointer;
  100. FDirectStatusFunction: SciFnDirectStatus;
  101. FEffectiveCodePage: Integer;
  102. FEffectiveCodePageDBCS: Boolean;
  103. FFillSelectionToEdge: Boolean;
  104. FFoldLevelNumbersOrLineState: Boolean;
  105. FForceModified: Boolean;
  106. FIndentationGuides: TScintIndentationGuides;
  107. FLeadBytes: TScintRawCharSet;
  108. FLineNumbers: Boolean;
  109. FLines: TScintEditStrings;
  110. FOnAutoCompleteSelection: TScintEditAutoCompleteSelectionEvent;
  111. FOnCallTipArrowClick: TScintEditCallTipArrowClick;
  112. FOnChange: TScintEditChangeEvent;
  113. FOnCharAdded: TScintEditCharAddedEvent;
  114. FOnDropFiles: TScintEditDropFilesEvent;
  115. FOnHintShow: TScintEditHintShowEvent;
  116. FOnMarginClick: TScintEditMarginClickEvent;
  117. FOnMarginRightClick: TScintEditMarginClickEvent;
  118. FOnModifiedChange: TNotifyEvent;
  119. FOnUpdateUI: TScintEditUpdateUIEvent;
  120. FOnZoom: TNotifyEvent;
  121. FReportCaretPositionToStyler: Boolean;
  122. FStyler: TScintCustomStyler;
  123. FTabWidth: Integer;
  124. FUseStyleAttributes: Boolean;
  125. FUseTabCharacter: Boolean;
  126. FVirtualSpaceOptions: TScintVirtualSpaceOptions;
  127. FWordChars: AnsiString;
  128. FWordCharsAsSet: TSysCharSet;
  129. FWordWrap: Boolean;
  130. procedure ApplyOptions;
  131. procedure ForwardMessage(const Message: TMessage);
  132. function GetAutoCompleteActive: Boolean;
  133. function GetCallTipActive: Boolean;
  134. function GetCaretColumn: Integer;
  135. function GetCaretColumnExpandedForTabs: Integer;
  136. function GetCaretLine: Integer;
  137. function GetCaretLineText: String;
  138. function GetCaretPosition: Integer;
  139. function GetCaretPositionInLine: Integer;
  140. function GetCaretVirtualSpace: Integer;
  141. function GetInsertMode: Boolean;
  142. function GetLineEndings: TScintLineEndings;
  143. function GetLineEndingString: TScintRawString;
  144. function GetLineHeight: Integer;
  145. function GetLinesInWindow: Integer;
  146. function GetMainSelText: String;
  147. function GetModified: Boolean;
  148. function GetRawCaretLineText: TScintRawString;
  149. function GetRawMainSelText: TScintRawString;
  150. function GetRawSelText: TScintRawString;
  151. function GetRawText: TScintRawString;
  152. function GetReadOnly: Boolean;
  153. class function GetReplaceTargetMessage(const ReplaceMode: TScintReplaceMode): Cardinal;
  154. class function GetSearchFlags(const Options: TScintFindOptions): Integer;
  155. function GetSelection: TScintRange;
  156. function GetSelectionAnchorPosition(Selection: Integer): Integer;
  157. function GetSelectionAnchorVirtualSpace(Selection: Integer): Integer;
  158. function GetSelectionCaretPosition(Selection: Integer): Integer;
  159. function GetSelectionCaretVirtualSpace(Selection: Integer): Integer;
  160. function GetSelectionEndPosition(Selection: Integer): Integer;
  161. function GetSelectionCount: Integer;
  162. function GetSelectionMode: TScintSelectionMode;
  163. function GetSelectionStartPosition(Selection: Integer): Integer;
  164. function GetSelText: String;
  165. function GetTopLine: Integer;
  166. function GetZoom: Integer;
  167. procedure SetAcceptDroppedFiles(const Value: Boolean);
  168. procedure SetAutoCompleteFontName(const Value: String);
  169. procedure SetAutoCompleteFontSize(const Value: Integer);
  170. procedure SetCodePage(const Value: Integer);
  171. procedure SetCaretColumn(const Value: Integer);
  172. procedure SetCaretLine(const Value: Integer);
  173. procedure SetCaretPosition(const Value: Integer);
  174. procedure SetCaretPositionWithSelectFromAnchor(const Value: Integer);
  175. procedure SetCaretVirtualSpace(const Value: Integer);
  176. procedure SetChangeHistory(const Value: TScintChangeHistory);
  177. procedure SetFillSelectionToEdge(const Value: Boolean);
  178. procedure SetFoldFlags(const Value: TScintFoldFlags);
  179. procedure SetIndentationGuides(const Value: TScintIndentationGuides);
  180. procedure SetLineNumbers(const Value: Boolean);
  181. procedure SetMainSelection(const Value: Integer);
  182. procedure SetMainSelText(const Value: String);
  183. procedure SetRawMainSelText(const Value: TScintRawString);
  184. procedure SetRawSelText(const Value: TScintRawString);
  185. procedure SetRawText(const Value: TScintRawString);
  186. procedure SetReadOnly(const Value: Boolean);
  187. procedure SetSelection(const Value: TScintRange);
  188. procedure SetSelectionAnchorPosition(Selection: Integer; const Value: Integer);
  189. procedure SetSelectionAnchorVirtualSpace(Selection: Integer;
  190. const Value: Integer);
  191. procedure SetSelectionCaretPosition(Selection: Integer; const Value: Integer);
  192. procedure SetSelectionCaretVirtualSpace(Selection: Integer;
  193. const Value: Integer);
  194. procedure SetSelectionMode(const Value: TScintSelectionMode);
  195. procedure SetSelText(const Value: String);
  196. procedure SetStyler(const Value: TScintCustomStyler);
  197. procedure SetTabWidth(const Value: Integer);
  198. procedure SetTopLine(const Value: Integer);
  199. procedure SetUseStyleAttributes(const Value: Boolean);
  200. procedure SetUseTabCharacter(const Value: Boolean);
  201. procedure SetVirtualSpaceOptions(const Value: TScintVirtualSpaceOptions);
  202. procedure SetWordWrap(const Value: Boolean);
  203. procedure SetZoom(const Value: Integer);
  204. procedure UpdateCodePage;
  205. procedure UpdateLineNumbersWidth;
  206. procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED;
  207. procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
  208. procedure CMHintShow(var Message: TCMHintShow); message CM_HINTSHOW;
  209. procedure CMSysColorChange(var Message: TMessage); message CM_SYSCOLORCHANGE;
  210. procedure CNNotify(var Message: TWMNotify); message CN_NOTIFY;
  211. procedure WMDestroy(var Message: TWMDestroy); message WM_DESTROY;
  212. procedure WMDropFiles(var Message: TWMDropFiles); message WM_DROPFILES;
  213. procedure WMEraseBkgnd(var Message: TMessage); message WM_ERASEBKGND;
  214. procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
  215. procedure WMMouseWheel(var Message: TMessage); message WM_MOUSEWHEEL;
  216. protected
  217. procedure Change(const AInserting: Boolean; const AStartPos, ALength,
  218. ALinesDelta: Integer); virtual;
  219. procedure CheckPosRange(const StartPos, EndPos: Integer);
  220. procedure CreateParams(var Params: TCreateParams); override;
  221. procedure CreateWnd; override;
  222. class function GetErrorException(const S: String): EScintEditError;
  223. class procedure Error(const S: String); overload;
  224. class procedure ErrorFmt(const S: String; const Args: array of const);
  225. function GetMainSelection: Integer;
  226. function GetTarget: TScintRange;
  227. procedure InitRawString(var S: TScintRawString; const Len: Integer);
  228. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  229. procedure Notify(const N: TSCNotification); virtual;
  230. procedure SetTarget(const StartPos, EndPos: Integer);
  231. public
  232. constructor Create(AOwner: TComponent); override;
  233. destructor Destroy; override;
  234. procedure AddMarker(const Line: Integer; const Marker: TScintMarkerNumber);
  235. procedure AddSelection(const CaretPos, AnchorPos: Integer);
  236. procedure AssignCmdKey(const Key: AnsiChar; const Shift: TShiftState;
  237. const Command: TScintCommand); overload;
  238. procedure AssignCmdKey(const KeyCode: TScintKeyCode; const Shift: TShiftState;
  239. const Command: TScintCommand); overload;
  240. procedure BeginUndoAction;
  241. function Call(Msg: Cardinal; WParam: Longint; LParam: Longint): Longint; overload;
  242. function Call(Msg: Cardinal; WParam: Longint; LParam: Longint; out WarnStatus: Integer): Longint; overload;
  243. function Call(Msg: Cardinal; WParam: Longint; const LParamStr: TScintRawString): Longint; overload;
  244. function Call(Msg: Cardinal; WParam: Longint; const LParamStr: TScintRawString; out WarnStatus: Integer): Longint; overload;
  245. procedure CancelAutoComplete;
  246. procedure CancelAutoCompleteAndCallTip;
  247. procedure CancelCallTip;
  248. function CanPaste: Boolean;
  249. function CanRedo: Boolean;
  250. function CanUndo: Boolean;
  251. procedure ChooseCaretX;
  252. procedure ClearAll;
  253. procedure ClearCmdKey(const Key: AnsiChar; const Shift: TShiftState); overload;
  254. procedure ClearCmdKey(const KeyCode: TScintKeyCode; const Shift: TShiftState); overload;
  255. procedure ClearIndicators(const IndicatorNumber: TScintIndicatorNumber);
  256. procedure ClearSelection;
  257. procedure ClearUndo(const ClearChangeHistory: Boolean = True);
  258. function ConvertRawStringToString(const S: TScintRawString): String;
  259. function ConvertPCharToRawString(const Text: PChar;
  260. const TextLen: Integer): TScintRawString;
  261. function ConvertStringToRawString(const S: String): TScintRawString;
  262. procedure CopyToClipboard;
  263. procedure CutToClipboard;
  264. procedure DeleteAllMarkersOnLine(const Line: Integer);
  265. procedure DeleteMarker(const Line: Integer; const Marker: TScintMarkerNumber);
  266. procedure DPIChanged(const Message: TMessage);
  267. procedure EndUndoAction;
  268. procedure EnsureLineVisible(const Line: Integer);
  269. function FindRawText(const StartPos, EndPos: Integer; const S: TScintRawString;
  270. const Options: TScintFindOptions; out MatchRange: TScintRange): Boolean;
  271. function FindText(const StartPos, EndPos: Integer; const S: String;
  272. const Options: TScintFindOptions; out MatchRange: TScintRange): Boolean;
  273. procedure FoldLine(const Line: Integer; const Fold: Boolean);
  274. function FormatRange(const Draw: Boolean;
  275. const RangeToFormat: PScintRangeToFormat): Integer;
  276. procedure ForceModifiedState;
  277. function GetByteAtPosition(const Pos: Integer): AnsiChar;
  278. function GetCharacterCount(const StartPos, EndPos: Integer): Integer;
  279. function GetColumnFromPosition(const Pos: Integer): Integer;
  280. function GetDefaultWordChars: AnsiString;
  281. function GetDocLineFromVisibleLine(const VisibleLine: Integer): Integer;
  282. function GetIndicatorAtPosition(const IndicatorNumber: TScintIndicatorNumber;
  283. const Pos: Integer): Boolean;
  284. function GetLineEndPosition(const Line: Integer): Integer;
  285. function GetLineFromPosition(const Pos: Integer): Integer;
  286. function GetLineIndentation(const Line: Integer): Integer;
  287. function GetLineIndentPosition(const Line: Integer): Integer;
  288. function GetMarkers(const Line: Integer): TScintMarkerNumbers;
  289. function GetPointFromPosition(const Pos: Integer): TPoint;
  290. function GetPositionAfter(const Pos: Integer): Integer;
  291. function GetPositionBefore(const Pos: Integer): Integer;
  292. function GetPositionFromLine(const Line: Integer): Integer;
  293. function GetPositionFromLineColumn(const Line, Column: Integer): Integer;
  294. function GetPositionFromLineExpandedColumn(const Line, ExpandedColumn: Integer): Integer;
  295. function GetPositionFromPoint(const P: TPoint;
  296. const CharPosition, CloseOnly: Boolean): Integer;
  297. function GetPositionOfMatchingBrace(const Pos: Integer): Integer;
  298. function GetPositionRelative(const Pos, CharacterCount: Integer): Integer;
  299. function GetRawTextLength: Integer;
  300. function GetRawTextRange(const StartPos, EndPos: Integer): TScintRawString;
  301. procedure GetSelections(const RangeList: TScintRangeList); overload;
  302. procedure GetSelections(const CaretAndAnchorList: TScintCaretAndAnchorList); overload;
  303. procedure GetSelections(const CaretAndAnchorList, VirtualSpacesList: TScintCaretAndAnchorList); overload;
  304. function GetStyleAtPosition(const Pos: Integer): TScintStyleNumber;
  305. function GetTextRange(const StartPos, EndPos: Integer): String;
  306. function GetVisibleLineFromDocLine(const DocLine: Integer): Integer;
  307. function GetWordEndPosition(const Pos: Integer; const OnlyWordChars: Boolean): Integer;
  308. function GetWordStartPosition(const Pos: Integer; const OnlyWordChars: Boolean): Integer;
  309. function IsPositionInViewVertically(const Pos: Integer): Boolean;
  310. class function KeyCodeAndShiftToKeyDefinition(const KeyCode: TScintKeyCode;
  311. Shift: TShiftState): TScintKeyDefinition;
  312. function MainSelTextEquals(const S: String;
  313. const Options: TScintFindOptions): Boolean;
  314. class function KeyToKeyCode(const Key: AnsiChar): TScintKeyCode;
  315. procedure PasteFromClipboard;
  316. function RawMainSelTextEquals(const S: TScintRawString;
  317. const Options: TScintFindOptions): Boolean;
  318. class function RawStringIsBlank(const S: TScintRawString): Boolean;
  319. procedure Redo;
  320. procedure RemoveAdditionalSelections;
  321. function ReplaceMainSelText(const S: String;
  322. const ReplaceMode: TScintReplaceMode = srmNormal): TScintRange;
  323. function ReplaceRawMainSelText(const S: TScintRawString;
  324. const ReplaceMode: TScintReplaceMode = srmNormal): TScintRange;
  325. function ReplaceRawTextRange(const StartPos, EndPos: Integer;
  326. const S: TScintRawString; const ReplaceMode: TScintReplaceMode = srmNormal): TScintRange;
  327. function ReplaceTextRange(const StartPos, EndPos: Integer; const S: String;
  328. const ReplaceMode: TScintReplaceMode = srmNormal): TScintRange;
  329. procedure RestyleLine(const Line: Integer);
  330. procedure ScrollCaretIntoView;
  331. procedure SelectAll;
  332. procedure SelectAllOccurrences(const Options: TScintFindOptions);
  333. procedure SelectAndEnsureVisible(const Range: TScintRange);
  334. procedure SelectNextOccurrence(const Options: TScintFindOptions);
  335. function SelEmpty: Boolean;
  336. function SelNotEmpty(out Sel: TScintRange): Boolean;
  337. procedure SetAutoCompleteFillupChars(const FillupChars: AnsiString);
  338. procedure SetAutoCompleteSeparators(const Separator, TypeSeparator: AnsiChar);
  339. procedure SetAutoCompleteSelectedItem(const S: TScintRawString);
  340. procedure SetAutoCompleteStopChars(const StopChars: AnsiString);
  341. procedure SetBraceBadHighlighting(const Pos: Integer);
  342. procedure SetBraceHighlighting(const Pos1, Pos2: Integer);
  343. procedure SetCursorID(const CursorID: Integer);
  344. procedure SetCallTipHighlight(HighlightStart, HighlightEnd: Integer);
  345. procedure SetDefaultWordChars;
  346. procedure SetEmptySelection;
  347. procedure SetEmptySelections;
  348. procedure SetIndicators(const StartPos, EndPos: Integer;
  349. const IndicatorNumber: TScintIndicatorNumber; const Value: Boolean);
  350. procedure SetLineIndentation(const Line, Indentation: Integer);
  351. procedure SetSavePoint;
  352. procedure SetSingleSelection(const CaretPos, AnchorPos: Integer);
  353. procedure SettingChange(const Message: TMessage);
  354. procedure SetWordChars(const S: AnsiString);
  355. procedure ShowAutoComplete(const CharsEntered: Integer; const WordList: AnsiString);
  356. procedure ShowCallTip(const Pos: Integer; const Definition: AnsiString);
  357. procedure StyleNeeded(const EndPos: Integer);
  358. procedure SysColorChange(const Message: TMessage);
  359. function TestRegularExpression(const S: String): Boolean;
  360. function TestRawRegularExpression(const S: TScintRawString): Boolean;
  361. procedure Undo;
  362. procedure UpdateStyleAttributes;
  363. function WordAtCaret: String;
  364. function WordAtCaretRange: TScintRange;
  365. procedure ZoomIn;
  366. procedure ZoomOut;
  367. property AutoCompleteActive: Boolean read GetAutoCompleteActive;
  368. property CallTipActive: Boolean read GetCallTipActive;
  369. property CaretColumn: Integer read GetCaretColumn write SetCaretColumn;
  370. property CaretColumnExpandedForTabs: Integer read GetCaretColumnExpandedForTabs;
  371. property CaretLine: Integer read GetCaretLine write SetCaretLine;
  372. property CaretLineText: String read GetCaretLineText;
  373. property CaretPosition: Integer read GetCaretPosition write SetCaretPosition;
  374. property CaretPositionInLine: Integer read GetCaretPositionInLine;
  375. property CaretPositionWithSelectFromAnchor: Integer write SetCaretPositionWithSelectFromAnchor;
  376. property CaretVirtualSpace: Integer read GetCaretVirtualSpace write SetCaretVirtualSpace;
  377. property EffectiveCodePage: Integer read FEffectiveCodePage;
  378. property FoldFlags: TScintFoldFlags write SetFoldFlags;
  379. property InsertMode: Boolean read GetInsertMode;
  380. property LineEndings: TScintLineEndings read GetLineEndings;
  381. property LineEndingString: TScintRawString read GetLineEndingString;
  382. property LineHeight: Integer read GetLineHeight;
  383. property Lines: TScintEditStrings read FLines;
  384. property LinesInWindow: Integer read GetLinesInWindow;
  385. property MainSelection: Integer read GetMainSelection write SetMainSelection;
  386. property MainSelText: String read GetMainSelText write SetMainSelText;
  387. property Modified: Boolean read GetModified;
  388. property RawCaretLineText: TScintRawString read GetRawCaretLineText;
  389. property RawMainSelText: TScintRawString read GetRawMainSelText write SetRawMainSelText;
  390. property RawSelText: TScintRawString read GetRawSelText write SetRawSelText;
  391. property RawText: TScintRawString read GetRawText write SetRawText;
  392. property RawTextLength: Integer read GetRawTextLength;
  393. property ReadOnly: Boolean read GetReadOnly write SetReadOnly;
  394. property Selection: TScintRange read GetSelection write SetSelection;
  395. property SelectionAnchorPosition[Selection: Integer]: Integer read GetSelectionAnchorPosition write SetSelectionAnchorPosition;
  396. property SelectionAnchorVirtualSpace[Selection: Integer]: Integer read GetSelectionAnchorVirtualSpace write SetSelectionAnchorVirtualSpace;
  397. property SelectionCaretPosition[Selection: Integer]: Integer read GetSelectionCaretPosition write SetSelectionCaretPosition;
  398. property SelectionCaretVirtualSpace[Selection: Integer]: Integer read GetSelectionCaretVirtualSpace write SetSelectionCaretVirtualSpace;
  399. property SelectionCount: Integer read GetSelectionCount;
  400. property SelectionEndPosition[Selection: Integer]: Integer read GetSelectionEndPosition;
  401. property SelectionMode: TScintSelectionMode read GetSelectionMode write SetSelectionMode;
  402. property SelectionStartPosition[Selection: Integer]: Integer read GetSelectionStartPosition;
  403. property SelText: String read GetSelText write SetSelText;
  404. property Styler: TScintCustomStyler read FStyler write SetStyler;
  405. property Target: TScintRange read GetTarget;
  406. property TopLine: Integer read GetTopLine write SetTopLine;
  407. property WordChars: AnsiString read FWordChars;
  408. property WordCharsAsSet: TSysCharSet read FWordCharsAsSet;
  409. published
  410. property AcceptDroppedFiles: Boolean read FAcceptDroppedFiles write SetAcceptDroppedFiles
  411. default False;
  412. property AutoCompleteFontName: String read FAutoCompleteFontName
  413. write SetAutoCompleteFontName;
  414. property AutoCompleteFontSize: Integer read FAutoCompleteFontSize
  415. write SetAutoCompleteFontSize default 0;
  416. property ChangeHistory: TScintChangeHistory read FChangeHistory write SetChangeHistory default schDisabled;
  417. property CodePage: Integer read FCodePage write SetCodePage default CP_UTF8;
  418. property Color;
  419. property FillSelectionToEdge: Boolean read FFillSelectionToEdge write SetFillSelectionToEdge
  420. default False;
  421. property Font;
  422. property IndentationGuides: TScintIndentationGuides read FIndentationGuides
  423. write SetIndentationGuides default sigNone;
  424. property LineNumbers: Boolean read FLineNumbers write SetLineNumbers default False;
  425. property ParentFont;
  426. property PopupMenu;
  427. property ReportCaretPositionToStyler: Boolean read FReportCaretPositionToStyler
  428. write FReportCaretPositionToStyler;
  429. property TabStop default True;
  430. property TabWidth: Integer read FTabWidth write SetTabWidth default 8;
  431. property UseStyleAttributes: Boolean read FUseStyleAttributes write SetUseStyleAttributes
  432. default True;
  433. property UseTabCharacter: Boolean read FUseTabCharacter write SetUseTabCharacter
  434. default True;
  435. property VirtualSpaceOptions: TScintVirtualSpaceOptions read FVirtualSpaceOptions
  436. write SetVirtualSpaceOptions default [];
  437. property WordWrap: Boolean read FWordWrap write SetWordWrap default False;
  438. property Zoom: Integer read GetZoom write SetZoom default 0;
  439. property OnAutoCompleteSelection: TScintEditAutoCompleteSelectionEvent read FOnAutoCompleteSelection write FOnAutoCompleteSelection;
  440. property OnCallTipArrowClick: TScintEditCallTipArrowClick read FOnCallTipArrowClick write FOnCallTipArrowClick;
  441. property OnChange: TScintEditChangeEvent read FOnChange write FOnChange;
  442. property OnCharAdded: TScintEditCharAddedEvent read FOnCharAdded write FOnCharAdded;
  443. property OnDropFiles: TScintEditDropFilesEvent read FOnDropFiles write FOnDropFiles;
  444. property OnHintShow: TScintEditHintShowEvent read FOnHintShow write FOnHintShow;
  445. property OnKeyDown;
  446. property OnKeyPress;
  447. property OnKeyUp;
  448. property OnMarginClick: TScintEditMarginClickEvent read FOnMarginClick write FOnMarginClick;
  449. property OnMarginRightClick: TScintEditMarginClickEvent read FOnMarginRightClick write FOnMarginRightClick;
  450. property OnModifiedChange: TNotifyEvent read FOnModifiedChange write FOnModifiedChange;
  451. property OnMouseDown;
  452. property OnMouseMove;
  453. property OnMouseUp;
  454. property OnUpdateUI: TScintEditUpdateUIEvent read FOnUpdateUI write FOnUpdateUI;
  455. property OnZoom: TNotifyEvent read FOnZoom write FOnZoom;
  456. end;
  457. TScintEditStrings = class(TStrings)
  458. private
  459. FEdit: TScintEdit;
  460. function GetLineEndingLength(const Index: Integer): Integer;
  461. function GetRawLine(Index: Integer): TScintRawString;
  462. function GetRawLineWithEnding(Index: Integer): TScintRawString;
  463. function GetRawLineLength(Index: Integer): Integer;
  464. function GetRawLineLengthWithEnding(Index: Integer): Integer;
  465. function GetState(Index: Integer): TScintLineState;
  466. procedure PutRawLine(Index: Integer; const S: TScintRawString);
  467. protected
  468. procedure CheckIndexRange(const Index: Integer);
  469. procedure CheckIndexRangePlusOne(const Index: Integer);
  470. function Get(Index: Integer): String; override;
  471. function GetCount: Integer; override;
  472. function GetTextStr: String; override;
  473. procedure Put(Index: Integer; const S: String); override;
  474. procedure SetTextStr(const Value: String); override;
  475. public
  476. procedure Clear; override;
  477. procedure Delete(Index: Integer); override;
  478. procedure Insert(Index: Integer; const S: String); override;
  479. procedure InsertRawLine(Index: Integer; const S: TScintRawString);
  480. procedure SetText(Text: PChar); override;
  481. property RawLineLengths[Index: Integer]: Integer read GetRawLineLength;
  482. property RawLineLengthsWithEnding[Index: Integer]: Integer read GetRawLineLengthWithEnding;
  483. property RawLines[Index: Integer]: TScintRawString read GetRawLine write PutRawLine;
  484. property RawLinesWithEnding[Index: Integer]: TScintRawString read GetRawLineWithEnding;
  485. property State[Index: Integer]: TScintLineState read GetState;
  486. end;
  487. TScintStyleAttributes = record
  488. FontName: String;
  489. FontSize: Integer;
  490. FontStyle: TFontStyles;
  491. FontCharset: TFontCharset;
  492. ForeColor: TColor;
  493. BackColor: TColor;
  494. end;
  495. TScintCustomStyler = class(TComponent)
  496. private
  497. FCaretIndex: Integer;
  498. FCurIndex: Integer;
  499. FLineState: TScintLineState;
  500. FStyleStartIndex: Integer;
  501. FStyleStr: AnsiString;
  502. FText: TScintRawString;
  503. FTextLen: Integer;
  504. function GetCurChar: AnsiChar;
  505. function GetEndOfLine: Boolean;
  506. protected
  507. procedure ApplyStyleByteIndicators(const Indicators: TScintStyleByteIndicatorNumbers;
  508. StartIndex, EndIndex: Integer);
  509. procedure ApplyStyle(const Style: TScintStyleNumber;
  510. StartIndex, EndIndex: Integer);
  511. procedure CommitStyle(const Style: TScintStyleNumber);
  512. function ConsumeAllRemaining: Boolean;
  513. function ConsumeChar(const C: AnsiChar): Boolean;
  514. function ConsumeCharIn(const Chars: TScintRawCharSet): Boolean;
  515. function ConsumeChars(const Chars: TScintRawCharSet): Boolean;
  516. function ConsumeCharsNot(const Chars: TScintRawCharSet): Boolean;
  517. function ConsumeString(const Chars: TScintRawCharSet): TScintRawString;
  518. function CurCharIn(const Chars: TScintRawCharSet): Boolean;
  519. function CurCharIs(const C: AnsiChar): Boolean;
  520. procedure GetFoldLevel(const LineState, PreviousLineState: TScintLineState;
  521. var Level: Integer; var Header, EnableHeaderOnPrevious: Boolean); virtual; abstract;
  522. procedure GetStyleAttributes(const Style: Integer;
  523. var Attributes: TScintStyleAttributes); virtual; abstract;
  524. function LineTextSpans(const S: TScintRawString): Boolean; virtual;
  525. function NextCharIs(const C: AnsiChar): Boolean;
  526. function PreviousCharIn(const Chars: TScintRawCharSet): Boolean;
  527. procedure ResetCurIndexTo(Index: Integer);
  528. procedure ReplaceText(StartIndex, EndIndex: Integer; const C: AnsiChar);
  529. procedure StyleNeeded; virtual; abstract;
  530. property CaretIndex: Integer read FCaretIndex;
  531. property CurChar: AnsiChar read GetCurChar;
  532. property CurIndex: Integer read FCurIndex;
  533. property EndOfLine: Boolean read GetEndOfLine;
  534. property LineState: TScintLineState read FLineState write FLineState;
  535. property StyleStartIndex: Integer read FStyleStartIndex;
  536. property Text: TScintRawString read FText;
  537. property TextLength: Integer read FTextLen;
  538. end;
  539. TScintPixmap = class
  540. private
  541. type
  542. TPixmap = array of AnsiString;
  543. class var
  544. ColorCodes: String;
  545. var
  546. FPixmap: TPixmap;
  547. class constructor Create;
  548. function GetPixmap: Pointer;
  549. public
  550. procedure InitializeFromBitmap(const ABitmap: TBitmap; const TransparentColor: TColorRef);
  551. property Pixmap: Pointer read GetPixmap;
  552. end;
  553. implementation
  554. uses
  555. ShellAPI, RTLConsts, UITypes, GraphUtil;
  556. { TScintEdit }
  557. const
  558. AUTOCSETSEPARATOR = #9;
  559. constructor TScintEdit.Create(AOwner: TComponent);
  560. begin
  561. inherited;
  562. FCodePage := CP_UTF8;
  563. FLines := TScintEditStrings.Create;
  564. FLines.FEdit := Self;
  565. FTabWidth := 8;
  566. FUseStyleAttributes := True;
  567. FUseTabCharacter := True;
  568. SetBounds(0, 0, 257, 193);
  569. ParentColor := False;
  570. TabStop := True;
  571. end;
  572. destructor TScintEdit.Destroy;
  573. begin
  574. SetStyler(nil);
  575. FLines.Free;
  576. FLines := nil;
  577. inherited;
  578. end;
  579. procedure TScintEdit.AddMarker(const Line: Integer;
  580. const Marker: TScintMarkerNumber);
  581. begin
  582. FLines.CheckIndexRange(Line);
  583. Call(SCI_MARKERADD, Line, Marker);
  584. end;
  585. procedure TScintEdit.AddSelection(const CaretPos, AnchorPos: Integer);
  586. { Adds a new selection as the main selection retaining all other selections as
  587. additional selections without scrolling the caret into view. The first
  588. selection should be added with SetSingleSelection. }
  589. begin
  590. Call(SCI_ADDSELECTION, CaretPos, AnchorPos);
  591. end;
  592. procedure TScintEdit.ApplyOptions;
  593. const
  594. IndentationGuides: array [TScintIndentationGuides] of Integer = (SC_IV_NONE, SC_IV_REAL,
  595. SC_IV_LOOKFORWARD, SC_IV_LOOKBOTH);
  596. var
  597. Flags: Integer;
  598. begin
  599. if not HandleAllocated then
  600. Exit;
  601. Call(SCI_SETSELEOLFILLED, Ord(FFillSelectionToEdge), 0);
  602. Call(SCI_SETTABWIDTH, FTabWidth, 0);
  603. Call(SCI_SETUSETABS, Ord(FUseTabCharacter), 0);
  604. Flags := 0;
  605. if svsRectangularSelection in VirtualSpaceOptions then
  606. Flags := Flags or SCVS_RECTANGULARSELECTION;
  607. if svsUserAccessible in VirtualSpaceOptions then
  608. Flags := Flags or SCVS_USERACCESSIBLE;
  609. if svsNoWrapLineStart in VirtualSpaceOptions then
  610. Flags := Flags or SCVS_NOWRAPLINESTART;
  611. Call(SCI_SETVIRTUALSPACEOPTIONS, Flags, 0);
  612. Call(SCI_SETWRAPMODE, Ord(FWordWrap), 0);
  613. Call(SCI_SETINDENTATIONGUIDES, IndentationGuides[FIndentationGuides], 0);
  614. { If FChangeHistory is not schDisabled then next call to ClearUndo will enable
  615. change history and else we should disable it now }
  616. if FChangeHistory = schDisabled then
  617. Call(SCI_SETCHANGEHISTORY, SC_CHANGE_HISTORY_DISABLED, 0);
  618. end;
  619. procedure TScintEdit.AssignCmdKey(const Key: AnsiChar; const Shift: TShiftState;
  620. const Command: TScintCommand);
  621. begin
  622. AssignCmdKey(KeyToKeyCode(Key), Shift, Command);
  623. end;
  624. procedure TScintEdit.AssignCmdKey(const KeyCode: TScintKeyCode;
  625. const Shift: TShiftState; const Command: TScintCommand);
  626. begin
  627. Call(SCI_ASSIGNCMDKEY, KeyCodeAndShiftToKeyDefinition(KeyCode, Shift), Command);
  628. end;
  629. procedure TScintEdit.BeginUndoAction;
  630. begin
  631. Call(SCI_BEGINUNDOACTION, 0, 0);
  632. end;
  633. function TScintEdit.Call(Msg: Cardinal; WParam: Longint; LParam: Longint): Longint;
  634. begin
  635. var Dummy: Integer;
  636. Result := Call(Msg, WParam, LParam, Dummy);
  637. end;
  638. function TScintEdit.Call(Msg: Cardinal; WParam: Longint; LParam: Longint;
  639. out WarnStatus: Integer): Longint;
  640. begin
  641. HandleNeeded;
  642. if FDirectPtr = nil then
  643. Error('Call: FDirectPtr is nil');
  644. if not Assigned(FDirectStatusFunction) then
  645. Error('Call: FDirectStatusFunction is nil');
  646. var ErrorStatus: Integer;
  647. Result := FDirectStatusFunction(FDirectPtr, Msg, WParam, LParam, ErrorStatus);
  648. if ErrorStatus <> 0 then begin
  649. var Dummy: Integer;
  650. FDirectStatusFunction(FDirectPtr, SCI_SETSTATUS, 0, 0, Dummy);
  651. if ErrorStatus < SC_STATUS_WARN_START then
  652. ErrorFmt('Error status %d returned after Call(%u, %d, %d) = %d',
  653. [ErrorStatus, Msg, WParam, LParam, Result]);
  654. end;
  655. WarnStatus := ErrorStatus;
  656. end;
  657. function TScintEdit.Call(Msg: Cardinal; WParam: Longint;
  658. const LParamStr: TScintRawString): Longint;
  659. begin
  660. var Dummy: Integer;
  661. Result := Call(Msg, WParam, LParamStr, Dummy);
  662. end;
  663. function TScintEdit.Call(Msg: Cardinal; WParam: Longint;
  664. const LParamStr: TScintRawString; out WarnStatus: Integer): Longint;
  665. begin
  666. Result := Call(Msg, WParam, LPARAM(PAnsiChar(LParamStr)), WarnStatus);
  667. end;
  668. procedure TScintEdit.CancelAutoComplete;
  669. begin
  670. Call(SCI_AUTOCCANCEL, 0, 0);
  671. end;
  672. procedure TScintEdit.CancelAutoCompleteAndCallTip;
  673. begin
  674. CancelAutoComplete;
  675. CancelCallTip;
  676. end;
  677. procedure TScintEdit.CancelCallTip;
  678. begin
  679. Call(SCI_CALLTIPCANCEL, 0, 0);
  680. end;
  681. function TScintEdit.CanPaste: Boolean;
  682. begin
  683. Result := Call(SCI_CANPASTE, 0, 0) <> 0;
  684. end;
  685. function TScintEdit.CanRedo: Boolean;
  686. begin
  687. Result := Call(SCI_CANREDO, 0, 0) <> 0;
  688. end;
  689. function TScintEdit.CanUndo: Boolean;
  690. begin
  691. Result := Call(SCI_CANUNDO, 0, 0) <> 0;
  692. end;
  693. procedure TScintEdit.Change(const AInserting: Boolean;
  694. const AStartPos, ALength, ALinesDelta: Integer);
  695. var
  696. Info: TScintEditChangeInfo;
  697. begin
  698. inherited Changed;
  699. if Assigned(FOnChange) then begin
  700. Info.Inserting := AInserting;
  701. Info.StartPos := AStartPos;
  702. Info.Length := ALength;
  703. Info.LinesDelta := ALinesDelta;
  704. FOnChange(Self, Info);
  705. end;
  706. end;
  707. procedure TScintEdit.CheckPosRange(const StartPos, EndPos: Integer);
  708. begin
  709. if (StartPos < 0) or (StartPos > EndPos) or (EndPos > GetRawTextLength) then
  710. ErrorFmt('CheckPosRange: Invalid range (%d, %d)', [StartPos, EndPos]);
  711. end;
  712. procedure TScintEdit.ChooseCaretX;
  713. begin
  714. Call(SCI_CHOOSECARETX, 0, 0);
  715. end;
  716. procedure TScintEdit.ClearAll;
  717. begin
  718. Call(SCI_CLEARALL, 0, 0);
  719. ChooseCaretX;
  720. end;
  721. procedure TScintEdit.ClearCmdKey(const Key: AnsiChar; const Shift: TShiftState);
  722. begin
  723. ClearCmdKey(KeyToKeyCode(Key), Shift);
  724. end;
  725. procedure TScintEdit.ClearCmdKey(const KeyCode: TScintKeyCode; const Shift: TShiftState);
  726. begin
  727. Call(SCI_CLEARCMDKEY, KeyCodeAndShiftToKeyDefinition(KeyCode, Shift), 0);
  728. end;
  729. procedure TScintEdit.ClearIndicators(
  730. const IndicatorNumber: TScintIndicatorNumber);
  731. begin
  732. Call(SCI_SETINDICATORCURRENT, IndicatorNumber, 0);
  733. Call(SCI_INDICATORCLEARRANGE, 0, RawTextLength);
  734. end;
  735. procedure TScintEdit.ClearSelection;
  736. begin
  737. Call(SCI_CLEAR, 0, 0);
  738. end;
  739. procedure TScintEdit.ClearUndo(const ClearChangeHistory: Boolean);
  740. begin
  741. { SCI_EMPTYUNDOBUFFER resets the save point but doesn't send a
  742. SCN_SAVEPOINTREACHED notification. Call SetSavePoint manually to get
  743. that. SetSavePoint additionally resets FForceModified. }
  744. SetSavePoint;
  745. Call(SCI_EMPTYUNDOBUFFER, 0, 0);
  746. if ClearChangeHistory and (FChangeHistory <> schDisabled) then begin
  747. Call(SCI_SETCHANGEHISTORY, SC_CHANGE_HISTORY_DISABLED, 0);
  748. var Flags := SC_CHANGE_HISTORY_ENABLED;
  749. if FChangeHistory = schMarkers then
  750. Flags := Flags or SC_CHANGE_HISTORY_MARKERS
  751. else
  752. Flags := Flags or SC_CHANGE_HISTORY_INDICATORS;
  753. Call(SCI_SETCHANGEHISTORY, Flags, 0);
  754. end;
  755. end;
  756. function TScintEdit.ConvertRawStringToString(const S: TScintRawString): String;
  757. var
  758. SrcLen, DestLen: Integer;
  759. DestStr: UnicodeString;
  760. begin
  761. SrcLen := Length(S);
  762. if SrcLen > 0 then begin
  763. DestLen := MultiByteToWideChar(FCodePage, 0, PAnsiChar(S), SrcLen, nil, 0);
  764. if DestLen <= 0 then
  765. Error('MultiByteToWideChar failed');
  766. SetString(DestStr, nil, DestLen);
  767. if MultiByteToWideChar(FCodePage, 0, PAnsiChar(S), SrcLen, @DestStr[1],
  768. Length(DestStr)) <> DestLen then
  769. Error('Unexpected result from MultiByteToWideChar');
  770. end;
  771. Result := DestStr;
  772. end;
  773. function TScintEdit.ConvertPCharToRawString(const Text: PChar;
  774. const TextLen: Integer): TScintRawString;
  775. var
  776. DestLen: Integer;
  777. DestStr: TScintRawString;
  778. begin
  779. if TextLen > 0 then begin
  780. DestLen := WideCharToMultiByte(FCodePage, 0, Text, TextLen, nil, 0, nil, nil);
  781. if DestLen <= 0 then
  782. Error('WideCharToMultiByte failed');
  783. InitRawString(DestStr, DestLen);
  784. if WideCharToMultiByte(FCodePage, 0, Text, TextLen, @DestStr[1], Length(DestStr),
  785. nil, nil) <> DestLen then
  786. Error('Unexpected result from WideCharToMultiByte');
  787. end;
  788. Result := DestStr;
  789. end;
  790. function TScintEdit.ConvertStringToRawString(const S: String): TScintRawString;
  791. begin
  792. Result := ConvertPCharToRawString(PChar(S), Length(S));
  793. end;
  794. procedure TScintEdit.CopyToClipboard;
  795. begin
  796. Call(SCI_COPY, 0, 0);
  797. end;
  798. procedure TScintEdit.CreateParams(var Params: TCreateParams);
  799. begin
  800. inherited;
  801. CreateSubClass(Params, 'Scintilla');
  802. //Params.ExStyle := Params.ExStyle or WS_EX_CLIENTEDGE;
  803. Params.WindowClass.style := Params.WindowClass.style and
  804. not (CS_HREDRAW or CS_VREDRAW);
  805. end;
  806. procedure TScintEdit.CreateWnd;
  807. begin
  808. if IsscintLibrary = 0 then
  809. Error('CreateWnd: IsscintLibrary is 0');
  810. inherited;
  811. FDirectPtr := Pointer(SendMessage(Handle, SCI_GETDIRECTPOINTER, 0, 0));
  812. if FDirectPtr = nil then
  813. Error('CreateWnd: FDirectPtr is nil');
  814. FDirectStatusFunction := SciFnDirectStatus(SendMessage(Handle, SCI_GETDIRECTSTATUSFUNCTION, 0, 0));
  815. if not Assigned(FDirectStatusFunction) then
  816. Error('CreateWnd: FDirectStatusFunction is nil');
  817. UpdateCodePage;
  818. Call(SCI_SETCOMMANDEVENTS, 0, 0);
  819. Call(SCI_SETMODEVENTMASK, SC_MOD_INSERTTEXT or SC_MOD_DELETETEXT, 0);
  820. Call(SCI_SETCARETPERIOD, GetCaretBlinkTime, 0);
  821. Call(SCI_SETSCROLLWIDTHTRACKING, 1, 0);
  822. { The default popup menu conflicts with the VCL's PopupMenu }
  823. Call(SCI_USEPOPUP, 0, 0);
  824. SetDefaultWordChars;
  825. ApplyOptions;
  826. UpdateStyleAttributes;
  827. if FAcceptDroppedFiles then
  828. DragAcceptFiles(Handle, True);
  829. end;
  830. procedure TScintEdit.CutToClipboard;
  831. begin
  832. Call(SCI_CUT, 0, 0);
  833. end;
  834. procedure TScintEdit.DeleteAllMarkersOnLine(const Line: Integer);
  835. begin
  836. FLines.CheckIndexRange(Line);
  837. Call(SCI_MARKERDELETE, Line, -1);
  838. end;
  839. procedure TScintEdit.DeleteMarker(const Line: Integer;
  840. const Marker: TScintMarkerNumber);
  841. begin
  842. FLines.CheckIndexRange(Line);
  843. Call(SCI_MARKERDELETE, Line, Marker);
  844. end;
  845. procedure TScintEdit.EndUndoAction;
  846. begin
  847. Call(SCI_ENDUNDOACTION, 0, 0);
  848. end;
  849. procedure TScintEdit.EnsureLineVisible(const Line: Integer);
  850. begin
  851. FLines.CheckIndexRange(Line);
  852. Call(SCI_ENSUREVISIBLE, Line, 0);
  853. end;
  854. class function TScintEdit.GetErrorException(const S: String): EScintEditError;
  855. { Can be used when just calling Error would cause a compiler warning because it doesn't realize Error always raises }
  856. begin
  857. Result := EScintEditError.Create('TScintEdit error: ' + S);
  858. end;
  859. class procedure TScintEdit.Error(const S: String);
  860. begin
  861. raise GetErrorException(S);
  862. end;
  863. class procedure TScintEdit.ErrorFmt(const S: String; const Args: array of const);
  864. begin
  865. Error(Format(S, Args));
  866. end;
  867. function TScintEdit.FindRawText(const StartPos, EndPos: Integer;
  868. const S: TScintRawString; const Options: TScintFindOptions;
  869. out MatchRange: TScintRange): Boolean;
  870. begin
  871. SetTarget(StartPos, EndPos);
  872. Call(SCI_SETSEARCHFLAGS, GetSearchFlags(Options), 0);
  873. Result := Call(SCI_SEARCHINTARGET, Length(S), S) >= 0;
  874. if Result then
  875. MatchRange := GetTarget;
  876. end;
  877. function TScintEdit.FindText(const StartPos, EndPos: Integer; const S: String;
  878. const Options: TScintFindOptions; out MatchRange: TScintRange): Boolean;
  879. begin
  880. Result := FindRawText(StartPos, EndPos, ConvertStringToRawString(S),
  881. Options, MatchRange);
  882. end;
  883. procedure TScintEdit.FoldLine(const Line: Integer; const Fold: Boolean);
  884. begin
  885. FLines.CheckIndexRange(Line);
  886. { If the line is not part of a fold the following will return False }
  887. var Folded := Call(SCI_GETFOLDEXPANDED, Line, 0) = 0;
  888. if Fold <> Folded then begin
  889. { If the line is not part of a fold the following will do nothing
  890. and else if the line is not the header Scintilla will lookup the
  891. header for us }
  892. Call(SCI_TOGGLEFOLD, Line, 0);
  893. end;
  894. end;
  895. procedure TScintEdit.ForceModifiedState;
  896. begin
  897. if not FForceModified then begin
  898. FForceModified := True;
  899. if Assigned(FOnModifiedChange) then
  900. FOnModifiedChange(Self);
  901. end;
  902. end;
  903. function TScintEdit.FormatRange(const Draw: Boolean;
  904. const RangeToFormat: PScintRangeToFormat): Integer;
  905. begin
  906. Result := Call(SCI_FORMATRANGE, Ord(Draw), LPARAM(RangeToFormat));
  907. end;
  908. procedure TScintEdit.ForwardMessage(const Message: TMessage);
  909. begin
  910. if HandleAllocated then
  911. CallWindowProc(DefWndProc, Handle, Message.Msg, Message.WParam, Message.LParam);
  912. end;
  913. function TScintEdit.GetAutoCompleteActive: Boolean;
  914. begin
  915. Result := Call(SCI_AUTOCACTIVE, 0, 0) <> 0;
  916. end;
  917. function TScintEdit.GetByteAtPosition(const Pos: Integer): AnsiChar;
  918. begin
  919. Result := AnsiChar(Call(SCI_GETCHARAT, Pos, 0));
  920. end;
  921. function TScintEdit.GetCallTipActive: Boolean;
  922. begin
  923. Result := Call(SCI_CALLTIPACTIVE, 0, 0) <> 0;
  924. end;
  925. function TScintEdit.GetCaretColumn: Integer;
  926. begin
  927. Result := GetColumnFromPosition(GetCaretPosition);
  928. end;
  929. function TScintEdit.GetCaretColumnExpandedForTabs: Integer;
  930. begin
  931. Result := Call(SCI_GETCOLUMN, GetCaretPosition, 0);
  932. Inc(Result, GetCaretVirtualSpace);
  933. end;
  934. function TScintEdit.GetCaretLine: Integer;
  935. begin
  936. Result := GetLineFromPosition(GetCaretPosition);
  937. end;
  938. function TScintEdit.GetCaretLineText: String;
  939. begin
  940. Result := ConvertRawStringToString(GetRawCaretLineText);
  941. end;
  942. function TScintEdit.GetCaretPosition: Integer;
  943. begin
  944. Result := Call(SCI_GETCURRENTPOS, 0, 0);
  945. end;
  946. function TScintEdit.GetCaretPositionInLine: Integer;
  947. begin
  948. var Caret := CaretPosition;
  949. var LineStart := GetPositionFromLine(GetLineFromPosition(Caret));
  950. Result := Caret - LineStart;
  951. end;
  952. function TScintEdit.GetCaretVirtualSpace: Integer;
  953. begin
  954. Result := GetSelectionCaretVirtualSpace(GetMainSelection);
  955. end;
  956. function TScintEdit.GetCharacterCount(const StartPos, EndPos: Integer): Integer;
  957. begin
  958. CheckPosRange(StartPos, EndPos);
  959. Result := Call(SCI_COUNTCHARACTERS, StartPos, EndPos);
  960. end;
  961. function TScintEdit.GetColumnFromPosition(const Pos: Integer): Integer;
  962. var
  963. Line: Integer;
  964. begin
  965. Line := GetLineFromPosition(Pos);
  966. Result := Pos - GetPositionFromLine(Line);
  967. end;
  968. function TScintEdit.GetDefaultWordChars: AnsiString;
  969. begin
  970. Result := 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_';
  971. end;
  972. function TScintEdit.GetDocLineFromVisibleLine(const VisibleLine: Integer): Integer;
  973. begin
  974. Result := Call(SCI_DOCLINEFROMVISIBLE, VisibleLine, 0);
  975. end;
  976. function TScintEdit.GetIndicatorAtPosition(
  977. const IndicatorNumber: TScintIndicatorNumber; const Pos: Integer): Boolean;
  978. begin
  979. Result := Call(SCI_INDICATORVALUEAT, IndicatorNumber, Pos) <> 0;
  980. end;
  981. function TScintEdit.GetInsertMode: Boolean;
  982. begin
  983. Result := Call(SCI_GETOVERTYPE, 0, 0) = 0;
  984. end;
  985. function TScintEdit.GetLineEndings: TScintLineEndings;
  986. begin
  987. case Call(SCI_GETEOLMODE, 0, 0) of
  988. SC_EOL_CR: Result := sleCR;
  989. SC_EOL_LF: Result := sleLF;
  990. SC_EOL_CRLF: Result := sleCRLF;
  991. else
  992. raise GetErrorException('Unexpected SCI_GETEOLMODE result');
  993. end;
  994. end;
  995. function TScintEdit.GetLineEndingString: TScintRawString;
  996. const
  997. EndingStrs: array[TScintLineEndings] of TScintRawString =
  998. (#13#10, #13, #10);
  999. begin
  1000. Result := EndingStrs[LineEndings];
  1001. end;
  1002. function TScintEdit.GetLineEndPosition(const Line: Integer): Integer;
  1003. { Returns the position at the end of the line, before any line end characters. }
  1004. begin
  1005. FLines.CheckIndexRange(Line);
  1006. Result := Call(SCI_GETLINEENDPOSITION, Line, 0);
  1007. end;
  1008. function TScintEdit.GetLineFromPosition(const Pos: Integer): Integer;
  1009. begin
  1010. Result := Call(SCI_LINEFROMPOSITION, Pos, 0);
  1011. end;
  1012. function TScintEdit.GetLineHeight: Integer;
  1013. begin
  1014. Result := Call(SCI_TEXTHEIGHT, 0, 0);
  1015. end;
  1016. function TScintEdit.GetLineIndentation(const Line: Integer): Integer;
  1017. begin
  1018. FLines.CheckIndexRange(Line);
  1019. Result := Call(SCI_GETLINEINDENTATION, Line, 0);
  1020. end;
  1021. function TScintEdit.GetLineIndentPosition(const Line: Integer): Integer;
  1022. begin
  1023. FLines.CheckIndexRange(Line);
  1024. Result := Call(SCI_GETLINEINDENTPOSITION, Line, 0);
  1025. end;
  1026. function TScintEdit.GetLinesInWindow: Integer;
  1027. begin
  1028. Result := Call(SCI_LINESONSCREEN, 0, 0);
  1029. end;
  1030. function TScintEdit.GetMainSelection: Integer;
  1031. begin
  1032. Result := Call(SCI_GETMAINSELECTION, 0, 0);
  1033. end;
  1034. function TScintEdit.GetMainSelText: String;
  1035. begin
  1036. Result := ConvertRawStringToString(GetRawMainSelText);
  1037. end;
  1038. function TScintEdit.GetMarkers(const Line: Integer): TScintMarkerNumbers;
  1039. begin
  1040. FLines.CheckIndexRange(Line);
  1041. Integer(Result) := Call(SCI_MARKERGET, Line, 0);
  1042. end;
  1043. function TScintEdit.GetModified: Boolean;
  1044. begin
  1045. Result := FForceModified or (Call(SCI_GETMODIFY, 0, 0) <> 0);
  1046. end;
  1047. function TScintEdit.GetPointFromPosition(const Pos: Integer): TPoint;
  1048. begin
  1049. Result.X := Call(SCI_POINTXFROMPOSITION, 0, Pos);
  1050. Result.Y := Call(SCI_POINTYFROMPOSITION, 0, Pos);
  1051. end;
  1052. function TScintEdit.GetPositionAfter(const Pos: Integer): Integer;
  1053. begin
  1054. Result := Call(SCI_POSITIONAFTER, Pos, 0);
  1055. end;
  1056. function TScintEdit.GetPositionBefore(const Pos: Integer): Integer;
  1057. begin
  1058. Result := Call(SCI_POSITIONBEFORE, Pos, 0);
  1059. end;
  1060. function TScintEdit.GetPositionFromLine(const Line: Integer): Integer;
  1061. begin
  1062. FLines.CheckIndexRangePlusOne(Line);
  1063. Result := Call(SCI_POSITIONFROMLINE, Line, 0);
  1064. end;
  1065. function TScintEdit.GetPositionFromLineColumn(const Line, Column: Integer): Integer;
  1066. var
  1067. Col, Len: Integer;
  1068. begin
  1069. Col := Column;
  1070. Result := GetPositionFromLine(Line);
  1071. Len := GetLineEndPosition(Line) - Result;
  1072. if Col > Len then
  1073. Col := Len;
  1074. if Col > 0 then
  1075. Inc(Result, Col);
  1076. end;
  1077. function TScintEdit.GetPositionFromLineExpandedColumn(const Line,
  1078. ExpandedColumn: Integer): Integer;
  1079. begin
  1080. FLines.CheckIndexRange(Line);
  1081. Result := Call(SCI_FINDCOLUMN, Line, ExpandedColumn);
  1082. end;
  1083. function TScintEdit.GetPositionFromPoint(const P: TPoint;
  1084. const CharPosition, CloseOnly: Boolean): Integer;
  1085. begin
  1086. if CharPosition then begin
  1087. if CloseOnly then
  1088. Result := Call(SCI_CHARPOSITIONFROMPOINTCLOSE, P.X, P.Y)
  1089. else
  1090. Result := Call(SCI_CHARPOSITIONFROMPOINT, P.X, P.Y);
  1091. end
  1092. else begin
  1093. if CloseOnly then
  1094. Result := Call(SCI_POSITIONFROMPOINTCLOSE, P.X, P.Y)
  1095. else
  1096. Result := Call(SCI_POSITIONFROMPOINT, P.X, P.Y);
  1097. end;
  1098. end;
  1099. function TScintEdit.GetPositionOfMatchingBrace(const Pos: Integer): Integer;
  1100. begin
  1101. Result := Call(SCI_BRACEMATCH, Pos, 0);
  1102. end;
  1103. function TScintEdit.GetPositionRelative(const Pos,
  1104. CharacterCount: Integer): Integer;
  1105. begin
  1106. Result := Call(SCI_POSITIONRELATIVE, Pos, CharacterCount);
  1107. end;
  1108. function TScintEdit.GetRawCaretLineText: TScintRawString;
  1109. begin
  1110. var Line := CaretLine;
  1111. Result := GetRawTextRange(GetPositionFromLine(Line), GetPositionFromLine(Line+1));
  1112. end;
  1113. function TScintEdit.GetRawMainSelText: TScintRawString;
  1114. begin
  1115. var MainSel := MainSelection;
  1116. var CaretPos := SelectionCaretPosition[MainSel];
  1117. var AnchorPos := SelectionAnchorPosition[MainSel];
  1118. if AnchorPos < CaretPos then
  1119. Result := GetRawTextRange(AnchorPos, CaretPos)
  1120. else
  1121. Result := GetRawTextRange(CaretPos, AnchorPos);
  1122. end;
  1123. function TScintEdit.GetRawSelText: TScintRawString;
  1124. { Gets the combined text of *all* selections }
  1125. var
  1126. Len: Integer;
  1127. S: TScintRawString;
  1128. begin
  1129. Len := Call(SCI_GETSELTEXT, 0, 0);
  1130. if Len > 0 then begin
  1131. InitRawString(S, Len);
  1132. Call(SCI_GETSELTEXT, 0, LPARAM(PAnsiChar(@S[1])));
  1133. end;
  1134. Result := S;
  1135. end;
  1136. function TScintEdit.GetRawText: TScintRawString;
  1137. begin
  1138. Result := GetRawTextRange(0, GetRawTextLength);
  1139. end;
  1140. function TScintEdit.GetRawTextLength: Integer;
  1141. begin
  1142. Result := Call(SCI_GETLENGTH, 0, 0);
  1143. end;
  1144. function TScintEdit.GetRawTextRange(const StartPos, EndPos: Integer): TScintRawString;
  1145. var
  1146. S: TScintRawString;
  1147. Range: TSci_TextRange;
  1148. begin
  1149. CheckPosRange(StartPos, EndPos);
  1150. if EndPos > StartPos then begin
  1151. InitRawString(S, EndPos - StartPos);
  1152. Range.chrg.cpMin := StartPos;
  1153. Range.chrg.cpMax := EndPos;
  1154. Range.lpstrText := @S[1];
  1155. if Call(SCI_GETTEXTRANGE, 0, LPARAM(@Range)) <> EndPos - StartPos then
  1156. Error('Unexpected result from SCI_GETTEXTRANGE');
  1157. end;
  1158. Result := S;
  1159. end;
  1160. function TScintEdit.GetReadOnly: Boolean;
  1161. begin
  1162. Result := Call(SCI_GETREADONLY, 0, 0) <> 0;
  1163. end;
  1164. class function TScintEdit.GetReplaceTargetMessage(
  1165. const ReplaceMode: TScintReplaceMode): Cardinal;
  1166. begin
  1167. case ReplaceMode of
  1168. srmNormal: Result := SCI_REPLACETARGET;
  1169. srmMinimal: Result := SCI_REPLACETARGETMINIMAL;
  1170. srmRegEx: Result := SCI_REPLACETARGETRE;
  1171. else
  1172. raise GetErrorException('Unknown ReplaceMode');
  1173. end;
  1174. end;
  1175. class function TScintEdit.GetSearchFlags(const Options: TScintFindOptions): Integer;
  1176. begin
  1177. { Note: Scintilla ignores SCFIND_WHOLEWORD when SCFIND_REGEXP is set }
  1178. Result := 0;
  1179. if sfoMatchCase in Options then
  1180. Result := Result or SCFIND_MATCHCASE;
  1181. if sfoWholeWord in Options then
  1182. Result := Result or SCFIND_WHOLEWORD;
  1183. if sfoRegEx in Options then
  1184. Result := Result or (SCFIND_REGEXP or SCFIND_CXX11REGEX);
  1185. end;
  1186. function TScintEdit.GetSelection: TScintRange;
  1187. begin
  1188. Result.StartPos := Call(SCI_GETSELECTIONSTART, 0, 0);
  1189. Result.EndPos := Call(SCI_GETSELECTIONEND, 0, 0);
  1190. end;
  1191. procedure TScintEdit.GetSelections(const RangeList: TScintRangeList);
  1192. begin
  1193. RangeList.Clear;
  1194. for var I := 0 to SelectionCount-1 do begin
  1195. var StartPos := GetSelectionStartPosition(I);
  1196. var EndPos := GetSelectionEndPosition(I);
  1197. RangeList.Add(TScintRange.Create(StartPos, EndPos));
  1198. end;
  1199. end;
  1200. procedure TScintEdit.GetSelections(const CaretAndAnchorList: TScintCaretAndAnchorList);
  1201. begin
  1202. CaretAndAnchorList.Clear;
  1203. for var I := 0 to SelectionCount-1 do begin
  1204. var CaretPos := GetSelectionCaretPosition(I);
  1205. var AnchorPos := GetSelectionAnchorPosition(I);
  1206. CaretAndAnchorList.Add(TScintCaretAndAnchor.Create(CaretPos, AnchorPos));
  1207. end;
  1208. end;
  1209. procedure TScintEdit.GetSelections(const CaretAndAnchorList, VirtualSpacesList: TScintCaretAndAnchorList);
  1210. begin
  1211. GetSelections(CaretAndAnchorList);
  1212. VirtualSpacesList.Clear;
  1213. for var I := 0 to SelectionCount-1 do begin
  1214. var CaretPos := GetSelectionCaretVirtualSpace(I);
  1215. var AnchorPos := GetSelectionAnchorVirtualSpace(I);
  1216. VirtualSpacesList.Add(TScintCaretAndAnchor.Create(CaretPos, AnchorPos));
  1217. end;
  1218. end;
  1219. function TScintEdit.GetSelectionAnchorPosition(Selection: Integer): Integer;
  1220. begin
  1221. Result := Call(SCI_GETSELECTIONNANCHOR, Selection, 0);
  1222. end;
  1223. function TScintEdit.GetSelectionAnchorVirtualSpace(Selection: Integer): Integer;
  1224. begin
  1225. Result := Call(SCI_GETSELECTIONNANCHORVIRTUALSPACE, Selection, 0);
  1226. end;
  1227. function TScintEdit.GetSelectionCaretPosition(Selection: Integer): Integer;
  1228. begin
  1229. Result := Call(SCI_GETSELECTIONNCARET, Selection, 0);
  1230. end;
  1231. function TScintEdit.GetSelectionCaretVirtualSpace(Selection: Integer): Integer;
  1232. begin
  1233. Result := Call(SCI_GETSELECTIONNCARETVIRTUALSPACE, Selection, 0);
  1234. end;
  1235. function TScintEdit.GetSelectionCount: Integer;
  1236. { Returns the number of selections currently active. Rectangular selections are
  1237. handled (and returned) as multiple selections, one for each line. }
  1238. begin
  1239. Result := Call(SCI_GETSELECTIONS, 0, 0);
  1240. end;
  1241. function TScintEdit.GetSelectionEndPosition(Selection: Integer): Integer;
  1242. begin
  1243. Result := Call(SCI_GETSELECTIONNEND, Selection, 0)
  1244. end;
  1245. function TScintEdit.GetSelectionMode: TScintSelectionMode;
  1246. begin
  1247. case Call(SCI_GETSELECTIONMODE, 0, 0) of
  1248. SC_SEL_STREAM: Result := ssmStream;
  1249. SC_SEL_RECTANGLE: Result := ssmRectangular;
  1250. SC_SEL_LINES: Result := ssmLines;
  1251. SC_SEL_THIN: Result := ssmThinRectangular;
  1252. else
  1253. raise GetErrorException('Unexpected SCI_GETSELECTIONMODE result');
  1254. end;
  1255. end;
  1256. function TScintEdit.GetSelectionStartPosition(Selection: Integer): Integer;
  1257. begin
  1258. Result := Call(SCI_GETSELECTIONNSTART, Selection, 0);
  1259. end;
  1260. function TScintEdit.GetSelText: String;
  1261. begin
  1262. Result := ConvertRawStringToString(GetRawSelText);
  1263. end;
  1264. function TScintEdit.GetStyleAtPosition(const Pos: Integer): TScintStyleNumber;
  1265. begin
  1266. Result := Call(SCI_GETSTYLEAT, Pos, 0);
  1267. end;
  1268. function TScintEdit.GetTarget: TScintRange;
  1269. begin
  1270. Result.StartPos := Call(SCI_GETTARGETSTART, 0, 0);
  1271. Result.EndPos := Call(SCI_GETTARGETEND, 0, 0);
  1272. end;
  1273. function TScintEdit.GetTextRange(const StartPos, EndPos: Integer): String;
  1274. begin
  1275. Result := ConvertRawStringToString(GetRawTextRange(StartPos, EndPos));
  1276. end;
  1277. function TScintEdit.GetTopLine: Integer;
  1278. begin
  1279. Result := Call(SCI_GETFIRSTVISIBLELINE, 0, 0);
  1280. end;
  1281. function TScintEdit.GetVisibleLineFromDocLine(const DocLine: Integer): Integer;
  1282. begin
  1283. FLines.CheckIndexRange(DocLine);
  1284. Result := Call(SCI_VISIBLEFROMDOCLINE, DocLine, 0);
  1285. end;
  1286. function TScintEdit.GetWordEndPosition(const Pos: Integer;
  1287. const OnlyWordChars: Boolean): Integer;
  1288. begin
  1289. Result := Call(SCI_WORDENDPOSITION, Pos, Ord(OnlyWordChars));
  1290. end;
  1291. function TScintEdit.GetWordStartPosition(const Pos: Integer;
  1292. const OnlyWordChars: Boolean): Integer;
  1293. begin
  1294. Result := Call(SCI_WORDSTARTPOSITION, Pos, Ord(OnlyWordChars));
  1295. end;
  1296. function TScintEdit.GetZoom: Integer;
  1297. begin
  1298. Result := Call(SCI_GETZOOM, 0, 0);
  1299. end;
  1300. procedure TScintEdit.InitRawString(var S: TScintRawString; const Len: Integer);
  1301. begin
  1302. SetString(S, nil, Len);
  1303. //experimental, dont need this ATM:
  1304. if FCodePage <> 0 then
  1305. System.SetCodePage(RawByteString(S), FCodePage, False);
  1306. end;
  1307. function TScintEdit.IsPositionInViewVertically(const Pos: Integer): Boolean;
  1308. var
  1309. P: TPoint;
  1310. begin
  1311. P := GetPointFromPosition(Pos);
  1312. Result := (P.Y >= 0) and (P.Y + GetLineHeight <= ClientHeight);
  1313. end;
  1314. class function TScintEdit.KeyCodeAndShiftToKeyDefinition(
  1315. const KeyCode: TScintKeyCode; Shift: TShiftState): TScintKeyDefinition;
  1316. begin
  1317. Result := KeyCode;
  1318. if ssShift in Shift then
  1319. Result := Result or (SCMOD_SHIFT shl 16);
  1320. if ssAlt in Shift then
  1321. Result := Result or (SCMOD_ALT shl 16);
  1322. if ssCtrl in Shift then
  1323. Result := Result or (SCMOD_CTRL shl 16);
  1324. end;
  1325. class function TScintEdit.KeyToKeyCode(const Key: AnsiChar): TScintKeyCode;
  1326. begin
  1327. Result := Ord(UpCase(Key));
  1328. end;
  1329. function TScintEdit.MainSelTextEquals(const S: String;
  1330. const Options: TScintFindOptions): Boolean;
  1331. begin
  1332. Result := RawMainSelTextEquals(ConvertStringToRawString(S), Options);
  1333. end;
  1334. procedure TScintEdit.Notification(AComponent: TComponent; Operation: TOperation);
  1335. begin
  1336. inherited;
  1337. if Operation = opRemove then
  1338. if AComponent = FStyler then
  1339. SetStyler(nil);
  1340. end;
  1341. procedure TScintEdit.Notify(const N: TSCNotification);
  1342. begin
  1343. case N.nmhdr.code of
  1344. SCN_AUTOCSELECTION:
  1345. begin
  1346. if Assigned(FOnAutoCompleteSelection) then
  1347. FOnAutoCompleteSelection(Self);
  1348. end;
  1349. SCN_CALLTIPCLICK:
  1350. begin
  1351. if (N.position in [1, 2]) and Assigned(FOnCallTipArrowClick) then
  1352. FOnCallTipArrowClick(Self, N.position = 1);
  1353. end;
  1354. SCN_CHARADDED:
  1355. begin
  1356. if Assigned(FOnCharAdded) then
  1357. FOnCharAdded(Self, AnsiChar(N.ch));
  1358. end;
  1359. SCN_MARGINCLICK:
  1360. begin
  1361. if Assigned(FOnMarginClick) then
  1362. FOnMarginClick(Self, N.margin, GetLineFromPosition(N.position));
  1363. end;
  1364. SCN_MARGINRIGHTCLICK:
  1365. begin
  1366. if Assigned(FOnMarginRightClick) then
  1367. FOnMarginRightClick(Self, N.margin, GetLineFromPosition(N.position));
  1368. end;
  1369. SCN_MODIFIED:
  1370. begin
  1371. { CreateWnd limits SCN_MODIFIED to INSERTTEXT and DELETETEXT }
  1372. if N.modificationType and SC_MOD_INSERTTEXT <> 0 then
  1373. Change(True, N.position, N.length, N.linesAdded)
  1374. else if N.modificationType and SC_MOD_DELETETEXT <> 0 then
  1375. Change(False, N.position, N.length, N.linesAdded);
  1376. if (N.linesAdded > 0) and FLineNumbers then
  1377. UpdateLineNumbersWidth;
  1378. end;
  1379. SCN_SAVEPOINTLEFT,
  1380. SCN_SAVEPOINTREACHED:
  1381. begin
  1382. if Assigned(FOnModifiedChange) then
  1383. FOnModifiedChange(Self);
  1384. end;
  1385. SCN_STYLENEEDED: StyleNeeded(N.position);
  1386. SCN_UPDATEUI:
  1387. begin
  1388. if Assigned(FOnUpdateUI) then
  1389. FOnUpdateUI(Self, TScintEditUpdates(Byte(N.updated)));
  1390. end;
  1391. SCN_ZOOM:
  1392. begin
  1393. if Assigned(FOnZoom) then
  1394. FOnZoom(Self);
  1395. if FLineNumbers then
  1396. UpdateLineNumbersWidth;
  1397. end;
  1398. end;
  1399. end;
  1400. procedure TScintEdit.PasteFromClipboard;
  1401. begin
  1402. Call(SCI_PASTE, 0, 0);
  1403. end;
  1404. function TScintEdit.RawMainSelTextEquals(const S: TScintRawString;
  1405. const Options: TScintFindOptions): Boolean;
  1406. begin
  1407. Call(SCI_TARGETFROMSELECTION, 0, 0);
  1408. Call(SCI_SETSEARCHFLAGS, GetSearchFlags(Options), 0);
  1409. Result := False;
  1410. if Call(SCI_SEARCHINTARGET, Length(S), S) >= 0 then begin
  1411. var Target := GetTarget;
  1412. var Sel := GetSelection;
  1413. if (Target.StartPos = Sel.StartPos) and (Target.EndPos = Sel.EndPos) then
  1414. Result := True;
  1415. end;
  1416. end;
  1417. class function TScintEdit.RawStringIsBlank(const S: TScintRawString): Boolean;
  1418. begin
  1419. for var I := 1 to Length(S) do
  1420. if not(S[I] in [#9, ' ']) then
  1421. Exit(False);
  1422. Result := True;
  1423. end;
  1424. procedure TScintEdit.Redo;
  1425. begin
  1426. Call(SCI_REDO, 0, 0);
  1427. end;
  1428. procedure TScintEdit.RemoveAdditionalSelections;
  1429. { Removes additional selections without scrolling the caret into view }
  1430. begin
  1431. var MainSel := MainSelection;
  1432. var CaretPos := SelectionCaretPosition[MainSel];
  1433. var AnchorPos := SelectionAnchorPosition[MainSel];
  1434. SetSingleSelection(CaretPos, AnchorPos);
  1435. end;
  1436. function TScintEdit.ReplaceMainSelText(const S: String;
  1437. const ReplaceMode: TScintReplaceMode): TScintRange;
  1438. begin
  1439. ReplaceRawMainSelText(ConvertStringToRawString(S), ReplaceMode);
  1440. end;
  1441. function TScintEdit.ReplaceRawMainSelText(const S: TScintRawString;
  1442. const ReplaceMode: TScintReplaceMode): TScintRange;
  1443. { Replaces the main selection just like SetRawSelText/SCI_REPLACESEL but
  1444. without removing additional selections }
  1445. begin
  1446. { First replace the selection }
  1447. Call(SCI_TARGETFROMSELECTION, 0, 0);
  1448. Call(GetReplaceTargetMessage(ReplaceMode), Length(S), S);
  1449. { Then make the main selection an empty selection at the end of the inserted
  1450. text, just like SCI_REPLACESEL }
  1451. var Pos := GetTarget.EndPos; { SCI_REPLACETARGET* updates the target }
  1452. var MainSel := MainSelection;
  1453. SetSelectionCaretPosition(MainSel, Pos);
  1454. SetSelectionAnchorPosition(MainSel, Pos);
  1455. { Finally call Editor::SetLastXChosen and scroll caret into view, also just
  1456. like SCI_REPLACESEL }
  1457. ChooseCaretX;
  1458. ScrollCaretIntoView;
  1459. end;
  1460. function TScintEdit.ReplaceRawTextRange(const StartPos, EndPos: Integer;
  1461. const S: TScintRawString; const ReplaceMode: TScintReplaceMode): TScintRange;
  1462. begin
  1463. CheckPosRange(StartPos, EndPos);
  1464. SetTarget(StartPos, EndPos);
  1465. Call(GetReplaceTargetMessage(ReplaceMode), Length(S), S);
  1466. Result := GetTarget;
  1467. end;
  1468. function TScintEdit.ReplaceTextRange(const StartPos, EndPos: Integer;
  1469. const S: String; const ReplaceMode: TScintReplaceMode): TScintRange;
  1470. begin
  1471. Result := ReplaceRawTextRange(StartPos, EndPos, ConvertStringToRawString(S), ReplaceMode);
  1472. end;
  1473. procedure TScintEdit.RestyleLine(const Line: Integer);
  1474. begin
  1475. var StartPos := GetPositionFromLine(Line);
  1476. var EndPos := GetPositionFromLine(Line + 1);
  1477. { Back up the 'last styled position' if necessary using SCI_STARTSTYLINE
  1478. (SCI_SETENDSTYLED would have been a clearer name because setting the
  1479. 'last styled position' is all it does) }
  1480. if StartPos < Call(SCI_GETENDSTYLED, 0, 0) then
  1481. Call(SCI_STARTSTYLING, StartPos, 0);
  1482. StyleNeeded(EndPos);
  1483. end;
  1484. procedure TScintEdit.ScrollCaretIntoView;
  1485. begin
  1486. Call(SCI_SCROLLCARET, 0, 0);
  1487. end;
  1488. procedure TScintEdit.SelectAllOccurrences(const Options: TScintFindOptions);
  1489. { At the moment this does not automatically expand folds, unlike VSCode. Also
  1490. see SelectNextOccurrence. }
  1491. begin
  1492. Call(SCI_TARGETWHOLEDOCUMENT, 0, 0);
  1493. Call(SCI_SETSEARCHFLAGS, GetSearchFlags(Options), 0);
  1494. Call(SCI_MULTIPLESELECTADDEACH, 0, 0);
  1495. end;
  1496. procedure TScintEdit.SelectAndEnsureVisible(const Range: TScintRange);
  1497. begin
  1498. CheckPosRange(Range.StartPos, Range.EndPos);
  1499. { If the range is in a contracted section, expand it }
  1500. var StartLine := GetLineFromPosition(Range.StartPos);
  1501. var EndLine := GetLineFromPosition(Range.EndPos);
  1502. for var Line := StartLine to EndLine do
  1503. EnsureLineVisible(Line);
  1504. { Select }
  1505. Selection := Range;
  1506. end;
  1507. procedure TScintEdit.SelectNextOccurrence(const Options: TScintFindOptions);
  1508. { At the moment this does not automatically expand folds, unlike VSCode. Also
  1509. see SelectAllOccurrences. }
  1510. begin
  1511. Call(SCI_TARGETWHOLEDOCUMENT, 0, 0);
  1512. Call(SCI_SETSEARCHFLAGS, GetSearchFlags(Options), 0);
  1513. Call(SCI_MULTIPLESELECTADDNEXT, 0, 0);
  1514. end;
  1515. function TScintEdit.SelEmpty: Boolean;
  1516. { Returns True if the main selection is empty even if there are additional
  1517. selections. }
  1518. begin
  1519. var Sel: TScintRange;
  1520. Result := not SelNotEmpty(Sel);
  1521. end;
  1522. function TScintEdit.SelNotEmpty(out Sel: TScintRange): Boolean;
  1523. begin
  1524. Sel := GetSelection;
  1525. Result := Sel.EndPos > Sel.StartPos;
  1526. end;
  1527. procedure TScintEdit.SelectAll;
  1528. begin
  1529. Call(SCI_SELECTALL, 0, 0);
  1530. end;
  1531. procedure TScintEdit.SetAcceptDroppedFiles(const Value: Boolean);
  1532. begin
  1533. if FAcceptDroppedFiles <> Value then begin
  1534. FAcceptDroppedFiles := Value;
  1535. if HandleAllocated then
  1536. DragAcceptFiles(Handle, Value);
  1537. end;
  1538. end;
  1539. procedure TScintEdit.SetAutoCompleteFillupChars(const FillupChars: AnsiString);
  1540. begin
  1541. Call(SCI_AUTOCSETFILLUPS, 0, FillupChars);
  1542. end;
  1543. procedure TScintEdit.SetAutoCompleteFontName(const Value: String);
  1544. begin
  1545. if FAutoCompleteFontName <> Value then begin
  1546. FAutoCompleteFontName := Value;
  1547. UpdateStyleAttributes;
  1548. end;
  1549. end;
  1550. procedure TScintEdit.SetAutoCompleteFontSize(const Value: Integer);
  1551. begin
  1552. if FAutoCompleteFontSize <> Value then begin
  1553. FAutoCompleteFontSize := Value;
  1554. UpdateStyleAttributes;
  1555. end;
  1556. end;
  1557. procedure TScintEdit.SetAutoCompleteSelectedItem(const S: TScintRawString);
  1558. begin
  1559. Call(SCI_AUTOCSELECT, 0, S);
  1560. end;
  1561. procedure TScintEdit.SetAutoCompleteSeparators(const Separator, TypeSeparator: AnsiChar);
  1562. begin
  1563. Call(SCI_AUTOCSETSEPARATOR, WParam(Separator), 0);
  1564. Call(SCI_AUTOCSETTYPESEPARATOR, WParam(TypeSeparator), 0);
  1565. end;
  1566. procedure TScintEdit.SetAutoCompleteStopChars(const StopChars: AnsiString);
  1567. begin
  1568. Call(SCI_AUTOCSTOPS, 0, StopChars);
  1569. end;
  1570. procedure TScintEdit.SetBraceBadHighlighting(const Pos: Integer);
  1571. begin
  1572. Call(SCI_BRACEBADLIGHT, Pos, 0);
  1573. end;
  1574. procedure TScintEdit.SetBraceHighlighting(const Pos1, Pos2: Integer);
  1575. begin
  1576. Call(SCI_BRACEHIGHLIGHT, Pos1, Pos2);
  1577. end;
  1578. procedure TScintEdit.SetCallTipHighlight(HighlightStart, HighlightEnd: Integer);
  1579. begin
  1580. Call(SCI_CALLTIPSETHLT, HighlightStart, HighlightEnd);
  1581. end;
  1582. procedure TScintEdit.SetCaretColumn(const Value: Integer);
  1583. begin
  1584. SetCaretPosition(GetPositionFromLineColumn(GetCaretLine, Value));
  1585. end;
  1586. procedure TScintEdit.SetCaretLine(const Value: Integer);
  1587. begin
  1588. Call(SCI_GOTOLINE, Value, 0);
  1589. ChooseCaretX;
  1590. end;
  1591. procedure TScintEdit.SetCaretPosition(const Value: Integer);
  1592. begin
  1593. Call(SCI_GOTOPOS, Value, 0);
  1594. ChooseCaretX;
  1595. end;
  1596. procedure TScintEdit.SetCaretPositionWithSelectFromAnchor(const Value: Integer);
  1597. { Sets the caret position and creates a selection between the anchor and the
  1598. caret position without scrolling the caret into view. }
  1599. begin
  1600. Call(SCI_SETCURRENTPOS, Value, 0);
  1601. end;
  1602. procedure TScintEdit.SetCaretVirtualSpace(const Value: Integer);
  1603. { Also sets the anchor's virtual space! }
  1604. var
  1605. Pos, LineEndPos, MainSel: Integer;
  1606. begin
  1607. { Weird things happen if a non-zero virtual space is set when the caret
  1608. isn't at the end of a line, so don't allow it }
  1609. Pos := GetCaretPosition;
  1610. LineEndPos := GetLineEndPosition(GetLineFromPosition(Pos));
  1611. if (Pos = LineEndPos) or (Value = 0) then begin
  1612. MainSel := GetMainSelection;
  1613. SetSelectionAnchorVirtualSpace(MainSel, Value);
  1614. SetSelectionCaretVirtualSpace(MainSel, Value);
  1615. ChooseCaretX;
  1616. end;
  1617. end;
  1618. procedure TScintEdit.SetChangeHistory(const Value: TScintChangeHistory);
  1619. begin
  1620. if FChangeHistory <> Value then begin
  1621. FChangeHistory := Value;
  1622. ApplyOptions;
  1623. end;
  1624. end;
  1625. procedure TScintEdit.SetCodePage(const Value: Integer);
  1626. begin
  1627. if FCodePage <> Value then begin
  1628. FCodePage := Value;
  1629. UpdateCodePage;
  1630. end;
  1631. end;
  1632. procedure TScintEdit.SetCursorID(const CursorID: Integer);
  1633. begin
  1634. Call(SCI_SETCURSOR, CursorID, 0);
  1635. end;
  1636. procedure TScintEdit.SetDefaultWordChars;
  1637. begin
  1638. SetWordChars(GetDefaultWordChars);
  1639. end;
  1640. procedure TScintEdit.SetEmptySelection;
  1641. { Make the main selection empty and removes additional selections without
  1642. scrolling the caret into view }
  1643. begin
  1644. Call(SCI_SETEMPTYSELECTION, GetCaretPosition, 0);
  1645. end;
  1646. procedure TScintEdit.SetEmptySelections;
  1647. { Makes all selections empty without scrolling the caret into view }
  1648. begin
  1649. for var Selection := 0 to SelectionCount-1 do begin
  1650. var Pos := SelectionCaretPosition[Selection];
  1651. SelectionAnchorPosition[Selection] := Pos;
  1652. end;
  1653. end;
  1654. procedure TScintEdit.SetFillSelectionToEdge(const Value: Boolean);
  1655. begin
  1656. if FFillSelectionToEdge <> Value then begin
  1657. FFillSelectionToEdge := Value;
  1658. ApplyOptions;
  1659. end;
  1660. end;
  1661. procedure TScintEdit.SetFoldFlags(const Value: TScintFoldFlags);
  1662. begin
  1663. var Flags := 0;
  1664. if sffLineBeforeExpanded in Value then
  1665. Flags := Flags or SC_FOLDFLAG_LINEBEFORE_EXPANDED;
  1666. if sffLineBeforeContracted in Value then
  1667. Flags := Flags or SC_FOLDFLAG_LINEBEFORE_CONTRACTED;
  1668. if sffLineAfterExpanded in Value then
  1669. Flags := Flags or SC_FOLDFLAG_LINEAFTER_EXPANDED;
  1670. if sffLineAfterContracted in Value then
  1671. Flags := Flags or SC_FOLDFLAG_LINEAFTER_CONTRACTED;
  1672. if sffLevelNumbers in Value then
  1673. Flags := Flags or SC_FOLDFLAG_LEVELNUMBERS
  1674. else if sffLineState in Value then
  1675. Flags := Flags or SC_FOLDFLAG_LINESTATE;
  1676. Call(SCI_SETFOLDFLAGS, Flags, 0);
  1677. var FoldLevelNumbersOrLineState := Value * [sffLevelNumbers, sffLineState] <> [];
  1678. if FoldLevelNumbersOrLineState <> FFoldLevelNumbersOrLineState then begin
  1679. FFoldLevelNumbersOrLineState := FoldLevelNumbersOrLineState;
  1680. UpdateLineNumbersWidth;
  1681. end;
  1682. end;
  1683. procedure TScintEdit.SetIndicators(const StartPos, EndPos: Integer;
  1684. const IndicatorNumber: TScintIndicatorNumber; const Value: Boolean);
  1685. begin
  1686. CheckPosRange(StartPos, EndPos);
  1687. Call(SCI_SETINDICATORCURRENT, IndicatorNumber, 0);
  1688. if Value then begin
  1689. Call(SCI_SETINDICATORVALUE, IndicatorNumber, 1);
  1690. Call(SCI_INDICATORFILLRANGE, StartPos, EndPos - StartPos);
  1691. end else
  1692. Call(SCI_INDICATORCLEARRANGE, StartPos, EndPos - StartPos);
  1693. end;
  1694. procedure TScintEdit.SetLineIndentation(const Line, Indentation: Integer);
  1695. begin
  1696. FLines.CheckIndexRange(Line);
  1697. Call(SCI_SETLINEINDENTATION, Line, Indentation);
  1698. end;
  1699. procedure TScintEdit.SetIndentationGuides(const Value: TScintIndentationGuides);
  1700. begin
  1701. if FIndentationGuides <> Value then begin
  1702. FIndentationGuides := Value;
  1703. ApplyOptions;
  1704. end;
  1705. end;
  1706. procedure TScintEdit.SetLineNumbers(const Value: Boolean);
  1707. begin
  1708. if FLineNumbers <> Value then begin
  1709. FLineNumbers := Value;
  1710. UpdateLineNumbersWidth;
  1711. end;
  1712. end;
  1713. procedure TScintEdit.SetMainSelection(const Value: Integer);
  1714. begin
  1715. Call(SCI_SETMAINSELECTION, Value, 0);
  1716. end;
  1717. procedure TScintEdit.SetMainSelText(const Value: String);
  1718. begin
  1719. SetRawMainSelText(ConvertStringToRawString(Value));
  1720. end;
  1721. procedure TScintEdit.SetRawMainSelText(const Value: TScintRawString);
  1722. begin
  1723. ReplaceRawMainSelText(Value, srmMinimal);
  1724. end;
  1725. procedure TScintEdit.SetRawSelText(const Value: TScintRawString);
  1726. { Replaces the main selection's text and *clears* additional selections }
  1727. begin
  1728. Call(SCI_REPLACESEL, 0, Value);
  1729. end;
  1730. procedure TScintEdit.SetRawText(const Value: TScintRawString);
  1731. begin
  1732. { Workaround: Without this call, if the caret is on line 0 and out in
  1733. virtual space, it'll remain in virtual space after the replacement }
  1734. Call(SCI_CLEARSELECTIONS, 0, 0);
  1735. { Using ReplaceRawTextRange instead of SCI_SETTEXT for embedded null support }
  1736. ReplaceRawTextRange(0, GetRawTextLength, Value);
  1737. ChooseCaretX;
  1738. end;
  1739. procedure TScintEdit.SetReadOnly(const Value: Boolean);
  1740. begin
  1741. Call(SCI_SETREADONLY, Ord(Value), 0);
  1742. end;
  1743. procedure TScintEdit.SetSavePoint;
  1744. begin
  1745. if FForceModified then begin
  1746. FForceModified := False;
  1747. if Assigned(FOnModifiedChange) then
  1748. FOnModifiedChange(Self);
  1749. end;
  1750. Call(SCI_SETSAVEPOINT, 0, 0);
  1751. end;
  1752. procedure TScintEdit.SetSelection(const Value: TScintRange);
  1753. { Sets the main selection and removes additional selections. Very similar
  1754. to SetSingleSelection, not sure why both messages exist and are slightly
  1755. different }
  1756. begin
  1757. Call(SCI_SETSEL, Value.StartPos, Value.EndPos);
  1758. end;
  1759. procedure TScintEdit.SetSelectionAnchorPosition(Selection: Integer;
  1760. const Value: Integer);
  1761. { Also sets anchors's virtual space to 0 }
  1762. begin
  1763. Call(SCI_SETSELECTIONNANCHOR, Selection, Value);
  1764. end;
  1765. procedure TScintEdit.SetSelectionAnchorVirtualSpace(Selection: Integer;
  1766. const Value: Integer);
  1767. begin
  1768. Call(SCI_SETSELECTIONNANCHORVIRTUALSPACE, Selection, Value);
  1769. end;
  1770. procedure TScintEdit.SetSelectionCaretPosition(Selection: Integer;
  1771. const Value: Integer);
  1772. { Also sets caret's virtual space to 0 }
  1773. begin
  1774. Call(SCI_SETSELECTIONNCARET, Selection, Value);
  1775. end;
  1776. procedure TScintEdit.SetSelectionCaretVirtualSpace(Selection: Integer;
  1777. const Value: Integer);
  1778. begin
  1779. Call(SCI_SETSELECTIONNCARETVIRTUALSPACE, Selection, Value);
  1780. end;
  1781. procedure TScintEdit.SetSelectionMode(const Value: TScintSelectionMode);
  1782. begin
  1783. var Mode: Integer;
  1784. if Value = ssmStream then
  1785. Mode := SC_SEL_STREAM
  1786. else if Value = ssmRectangular then
  1787. Mode := SC_SEL_RECTANGLE
  1788. else if Value = ssmLines then
  1789. Mode := SC_SEL_LINES
  1790. else
  1791. Mode := SC_SEL_THIN;
  1792. { Note this uses *CHANGE* and not *SET* }
  1793. Call(SCI_CHANGESELECTIONMODE, Mode, 0);
  1794. end;
  1795. procedure TScintEdit.SetSelText(const Value: String);
  1796. begin
  1797. SetRawSelText(ConvertStringToRawString(Value));
  1798. end;
  1799. procedure TScintEdit.SetSingleSelection(const CaretPos, AnchorPos: Integer);
  1800. { Sets the main selection and removes additional selections without scrolling
  1801. the caret into view }
  1802. begin
  1803. Call(SCI_SETSELECTION, CaretPos, AnchorPos);
  1804. end;
  1805. procedure TScintEdit.SetStyler(const Value: TScintCustomStyler);
  1806. begin
  1807. if FStyler <> Value then begin
  1808. if Assigned(Value) then
  1809. Value.FreeNotification(Self);
  1810. FStyler := Value;
  1811. if HandleAllocated then begin
  1812. Call(SCI_CLEARDOCUMENTSTYLE, 0, 0);
  1813. Call(SCI_STARTSTYLING, 0, 0);
  1814. UpdateStyleAttributes;
  1815. end;
  1816. end;
  1817. end;
  1818. procedure TScintEdit.SetTabWidth(const Value: Integer);
  1819. begin
  1820. if (FTabWidth <> Value) and (Value > 0) and (Value < 100) then begin
  1821. FTabWidth := Value;
  1822. ApplyOptions;
  1823. end;
  1824. end;
  1825. procedure TScintEdit.SetTarget(const StartPos, EndPos: Integer);
  1826. begin
  1827. Call(SCI_SETTARGETSTART, StartPos, 0);
  1828. Call(SCI_SETTARGETEND, EndPos, 0);
  1829. end;
  1830. procedure TScintEdit.SetTopLine(const Value: Integer);
  1831. begin
  1832. Call(SCI_SETFIRSTVISIBLELINE, Value, 0);
  1833. end;
  1834. procedure TScintEdit.SetUseStyleAttributes(const Value: Boolean);
  1835. begin
  1836. if FUseStyleAttributes <> Value then begin
  1837. FUseStyleAttributes := Value;
  1838. UpdateStyleAttributes;
  1839. end;
  1840. end;
  1841. procedure TScintEdit.SetUseTabCharacter(const Value: Boolean);
  1842. begin
  1843. if FUseTabCharacter <> Value then begin
  1844. FUseTabCharacter := Value;
  1845. ApplyOptions;
  1846. end;
  1847. end;
  1848. procedure TScintEdit.SetVirtualSpaceOptions(const Value: TScintVirtualSpaceOptions);
  1849. begin
  1850. if FVirtualSpaceOptions <> Value then begin
  1851. FVirtualSpaceOptions := Value;
  1852. ApplyOptions;
  1853. end;
  1854. end;
  1855. procedure TScintEdit.SetWordChars(const S: AnsiString);
  1856. begin
  1857. FWordChars := S;
  1858. FWordCharsAsSet := [];
  1859. for var C in S do
  1860. Include(FWordCharsAsSet, C);
  1861. Call(SCI_SETWORDCHARS, 0, S);
  1862. end;
  1863. procedure TScintEdit.SetWordWrap(const Value: Boolean);
  1864. begin
  1865. if FWordWrap <> Value then begin
  1866. FWordWrap := Value;
  1867. ApplyOptions;
  1868. end;
  1869. end;
  1870. procedure TScintEdit.SetZoom(const Value: Integer);
  1871. begin
  1872. Call(SCI_SETZOOM, Value, 0);
  1873. end;
  1874. procedure TScintEdit.ShowAutoComplete(const CharsEntered: Integer;
  1875. const WordList: AnsiString);
  1876. begin
  1877. Call(SCI_AUTOCSHOW, CharsEntered, WordList);
  1878. end;
  1879. procedure TScintEdit.ShowCallTip(const Pos: Integer;
  1880. const Definition: AnsiString);
  1881. begin
  1882. Call(SCI_CALLTIPSHOW, Pos, Definition);
  1883. end;
  1884. procedure TScintEdit.StyleNeeded(const EndPos: Integer);
  1885. function CalcCaretIndex(const FirstLine, LastLine: Integer): Integer;
  1886. var
  1887. CaretPos, StartPos, EndPos: Integer;
  1888. begin
  1889. Result := 0;
  1890. if FReportCaretPositionToStyler then begin
  1891. CaretPos := GetCaretPosition;
  1892. StartPos := GetPositionFromLine(FirstLine);
  1893. EndPos := GetLineEndPosition(LastLine);
  1894. if (CaretPos >= StartPos) and (CaretPos <= EndPos) then
  1895. Result := CaretPos - StartPos + 1;
  1896. end;
  1897. end;
  1898. procedure MaskDoubleByteCharacters(var S: TScintRawString);
  1899. var
  1900. Len, I: Integer;
  1901. begin
  1902. { This replaces all lead and trail bytes in S with #$80 and #$81 to
  1903. ensure that stylers do not mistake trail bytes for single-byte ASCII
  1904. characters (e.g. #131'A' is a valid combination on CP 932). }
  1905. if not FEffectiveCodePageDBCS then
  1906. Exit;
  1907. Len := Length(S);
  1908. I := 1;
  1909. while I <= Len do begin
  1910. if S[I] in FLeadBytes then begin
  1911. S[I] := #$80;
  1912. if I < Len then begin
  1913. Inc(I);
  1914. S[I] := #$81;
  1915. end;
  1916. end;
  1917. Inc(I);
  1918. end;
  1919. end;
  1920. function LineSpans(const Line: Integer): Boolean;
  1921. var
  1922. S: TScintRawString;
  1923. begin
  1924. S := FLines.RawLines[Line];
  1925. MaskDoubleByteCharacters(S);
  1926. Result := FStyler.LineTextSpans(S);
  1927. end;
  1928. function StyleLine(const FirstLine: Integer; const StartStylingPos: Integer): Integer;
  1929. begin
  1930. { Find final line in series of spanned lines }
  1931. var LastLine := FirstLine;
  1932. while (LastLine < Lines.Count - 1) and LineSpans(LastLine) do
  1933. Inc(LastLine);
  1934. { We don't pass line endings to the styler, because when the style of a
  1935. line ending changes, Scintilla assumes it must be a 'hanging' style and
  1936. immediately repaints all subsequent lines. (To see this in the IS IDE,
  1937. insert and remove a ';' character before a [Setup] directive, i.e.
  1938. toggle comment styling.) }
  1939. FStyler.FCaretIndex := CalcCaretIndex(FirstLine, LastLine);
  1940. FStyler.FCurIndex := 1;
  1941. FStyler.FStyleStartIndex := 1;
  1942. FStyler.FLineState := 0;
  1943. if FirstLine > 0 then
  1944. FStyler.FLineState := FLines.GetState(FirstLine-1);
  1945. FStyler.FText := GetRawTextRange(GetPositionFromLine(FirstLine),
  1946. GetLineEndPosition(LastLine));
  1947. MaskDoubleByteCharacters(FStyler.FText);
  1948. FStyler.FTextLen := Length(FStyler.FText);
  1949. FStyler.FStyleStr := StringOfChar(AnsiChar(0), FStyler.FTextLen +
  1950. FLines.GetLineEndingLength(LastLine));
  1951. var PreviousLineState := FStyler.LineState;
  1952. FStyler.StyleNeeded;
  1953. var N := Length(FStyler.FStyleStr);
  1954. if N > 0 then begin
  1955. var HadStyleByteIndicators := False;
  1956. { Apply style byte indicators. Add first as INDICATOR_CONTAINER and so on. }
  1957. for var Indicator := 0 to High(TScintStyleByteIndicatorNumber) do begin
  1958. var PrevI := 1;
  1959. var PrevValue := Indicator in TScintStyleByteIndicatorNumbers(Byte(Ord(FStyler.FStyleStr[1]) shr StyleNumberBits));
  1960. for var CurI := 2 to N do begin
  1961. var CurValue := Indicator in TScintStyleByteIndicatorNumbers(Byte(Ord(FStyler.FStyleStr[CurI]) shr StyleNumberBits));
  1962. if CurValue <> PrevValue then begin
  1963. SetIndicators(StartStylingPos+PrevI-1, StartStylingPos+CurI-1, Ord(Indicator)+INDICATOR_CONTAINER, PrevValue);
  1964. HadStyleByteIndicators := HadStyleByteIndicators or PrevValue;
  1965. PrevI := CurI;
  1966. PrevValue := CurValue;
  1967. end;
  1968. end;
  1969. SetIndicators(StartStylingPos+PrevI-1, StartStylingPos+N, Ord(Indicator)+INDICATOR_CONTAINER, PrevValue);
  1970. HadStyleByteIndicators := HadStyleByteIndicators or PrevValue;
  1971. end;
  1972. { Apply styles after removing any style byte indicators }
  1973. if HadStyleByteIndicators then
  1974. for var I := 1 to N do
  1975. FStyler.FStyleStr[I] := AnsiChar(Ord(FStyler.FStyleStr[I]) and StyleNumberMask);
  1976. Call(SCI_SETSTYLINGEX, Length(FStyler.FStyleStr), FStyler.FStyleStr);
  1977. FStyler.FStyleStr := '';
  1978. FStyler.FText := '';
  1979. end;
  1980. { Get fold level }
  1981. var LineState := FStyler.LineState;
  1982. var FoldLevel: Integer;
  1983. var FoldHeader, EnableFoldHeaderOnPrevious: Boolean;
  1984. FStyler.GetFoldLevel(LineState, PreviousLineState, FoldLevel, FoldHeader, EnableFoldHeaderOnPrevious);
  1985. Inc(FoldLevel, SC_FOLDLEVELBASE);
  1986. if FoldHeader then
  1987. FoldLevel := FoldLevel or SC_FOLDLEVELHEADERFLAG;
  1988. { Apply line state and fold level }
  1989. for var I := FirstLine to LastLine do begin
  1990. var OldState := FLines.GetState(I);
  1991. if FStyler.FLineState <> OldState then
  1992. Call(SCI_SETLINESTATE, I, FStyler.FLineState);
  1993. var OldLevel := Call(SCI_GETFOLDLEVEL, I, 0);
  1994. var NewLevel := FoldLevel;
  1995. { Setting SC_FOLDLEVELWHITEFLAG on empty lines causes a problem: when
  1996. Scintilla auto expands a contracted section (for example after removing ']'
  1997. from a section header) all the empty lines stay invisible, even any which
  1998. are in the middle of the section. See https://sourceforge.net/p/scintilla/bugs/2442/ }
  1999. //if FLines.GetRawLineLength(I) = 0 then
  2000. // NewLevel := NewLevel or SC_FOLDLEVELWHITEFLAG;
  2001. if NewLevel <> OldLevel then
  2002. Call(SCI_SETFOLDLEVEL, I, NewLevel);
  2003. end;
  2004. { Retroactively set header on previous line if requested to do so. Must be
  2005. *after* the loop above. Not sure why. Problem reproduction: move code above
  2006. the loop, run it, open Debug.iss, change [Setup] to [Set up] and notice
  2007. styling of the [Languages] section below it is now broken. If you turn on
  2008. sffLevelNumbers you will also see that the first entry in that section got
  2009. a header flag. }
  2010. if (FirstLine > 0) and EnableFoldHeaderOnPrevious then begin
  2011. var PreviousLine := FirstLine-1;
  2012. var OldLevel := Call(SCI_GETFOLDLEVEL, PreviousLine, 0);
  2013. var NewLevel := OldLevel or SC_FOLDLEVELHEADERFLAG;
  2014. if NewLevel <> OldLevel then
  2015. Call(SCI_SETFOLDLEVEL, PreviousLine, NewLevel);
  2016. end;
  2017. Result := LastLine;
  2018. end;
  2019. procedure DefaultStyleLine(const Line: Integer);
  2020. var
  2021. StyleStr: AnsiString;
  2022. begin
  2023. { Note: Using SCI_SETSTYLINGEX because it only redraws the part of the
  2024. range that changed, whereas SCI_SETSTYLING redraws the entire range. }
  2025. StyleStr := StringOfChar(AnsiChar(0), FLines.GetRawLineLengthWithEnding(Line));
  2026. Call(SCI_SETSTYLINGEX, Length(StyleStr), StyleStr);
  2027. end;
  2028. var
  2029. StartPos, StartLine, EndLine, Line: Integer;
  2030. begin
  2031. StartPos := Call(SCI_GETENDSTYLED, 0, 0);
  2032. StartLine := GetLineFromPosition(StartPos);
  2033. { EndPos (always?) points to the position *after* the last character of the
  2034. last line needing styling (usually an LF), so subtract 1 to avoid
  2035. restyling one extra line unnecessarily.
  2036. But don't do this if we're being asked to style all the way to the end.
  2037. When the document's last line is empty, 'EndPos - 1' will point to the
  2038. line preceding the last line, so StyleLine() will never be called on the
  2039. last line, and it will never be assigned a LINESTATE. This causes IS's
  2040. autocompletion to think the last line's section is scNone. }
  2041. if EndPos < GetRawTextLength then
  2042. EndLine := GetLineFromPosition(EndPos - 1)
  2043. else
  2044. EndLine := GetLineFromPosition(EndPos);
  2045. //outputdebugstring('-----');
  2046. //outputdebugstring(pchar(format('StyleNeeded poses: %d, %d', [StartPos, EndPos])));
  2047. //outputdebugstring(pchar(format('StyleNeeded lines: %d, %d', [StartLine, EndLine])));
  2048. { If StartLine is within a series of spanned lines, back up }
  2049. if Assigned(FStyler) then
  2050. while (StartLine > 0) and (LineSpans(StartLine - 1)) do
  2051. Dec(StartLine);
  2052. Line := StartLine;
  2053. while Line <= EndLine do begin
  2054. var StartStylingPos := GetPositionFromLine(Line);
  2055. Call(SCI_STARTSTYLING, StartStylingPos, 0);
  2056. if Assigned(FStyler) then
  2057. Line := StyleLine(Line, StartStylingPos)
  2058. else
  2059. DefaultStyleLine(Line);
  2060. Inc(Line);
  2061. end;
  2062. end;
  2063. procedure TScintEdit.SysColorChange(const Message: TMessage);
  2064. begin
  2065. ForwardMessage(Message);
  2066. end;
  2067. function TScintEdit.TestRawRegularExpression(const S: TScintRawString): Boolean;
  2068. { Example invalid regular expression: ( }
  2069. begin
  2070. Call(SCI_SETTARGETRANGE, 0, 0);
  2071. Call(SCI_SETSEARCHFLAGS, GetSearchFlags([sfoRegEx]), 0);
  2072. var WarnStatus: Integer;
  2073. var Res := Call(SCI_SEARCHINTARGET, Length(S), S, WarnStatus);
  2074. Result := not ((Res = -1) and (WarnStatus = SC_STATUS_WARN_REGEX));
  2075. end;
  2076. function TScintEdit.TestRegularExpression(const S: String): Boolean;
  2077. begin
  2078. Result := TestRawRegularExpression(ConvertStringToRawString(S));
  2079. end;
  2080. procedure TScintEdit.Undo;
  2081. begin
  2082. Call(SCI_UNDO, 0, 0);
  2083. end;
  2084. procedure TScintEdit.UpdateCodePage;
  2085. procedure InitLeadBytes;
  2086. var
  2087. Info: TCPInfo;
  2088. I: Integer;
  2089. J: Byte;
  2090. begin
  2091. FLeadBytes := [];
  2092. if FEffectiveCodePageDBCS and GetCPInfo(FEffectiveCodePage, Info) then begin
  2093. I := 0;
  2094. while (I < MAX_LEADBYTES) and ((Info.LeadByte[I] or Info.LeadByte[I+1]) <> 0) do begin
  2095. for J := Info.LeadByte[I] to Info.LeadByte[I+1] do
  2096. Include(FLeadBytes, AnsiChar(J));
  2097. Inc(I, 2);
  2098. end;
  2099. end;
  2100. end;
  2101. var
  2102. CP: Integer;
  2103. begin
  2104. if HandleAllocated then begin
  2105. { To Scintilla, code page 0 does not mean the current ANSI code page, but
  2106. an unspecified single byte code page. So that DBCS support is properly
  2107. enabled when running on a DBCS ANSI code page, replace 0 with GetACP. }
  2108. CP := FCodePage;
  2109. if CP = 0 then
  2110. CP := GetACP;
  2111. Call(SCI_SETCODEPAGE, CP, 0);
  2112. { Scintilla ignores attempts to set a code page it has no special support
  2113. for. But the editor could currently be set for UTF-8 or DBCS, so get it
  2114. out of that mode by setting the code page to 0 (a value it does
  2115. recognize). }
  2116. if Call(SCI_GETCODEPAGE, 0, 0) <> CP then
  2117. Call(SCI_SETCODEPAGE, 0, 0);
  2118. FEffectiveCodePage := Call(SCI_GETCODEPAGE, 0, 0);
  2119. FEffectiveCodePageDBCS := (FEffectiveCodePage <> 0) and
  2120. (FEffectiveCodePage <> SC_CP_UTF8);
  2121. InitLeadBytes;
  2122. end;
  2123. end;
  2124. procedure TScintEdit.UpdateLineNumbersWidth;
  2125. var
  2126. LineCount, PixelWidth: Integer;
  2127. Nines: String;
  2128. begin
  2129. if FLineNumbers or FFoldLevelNumbersOrLineState then begin
  2130. { Note: Based on SciTE's SciTEBase::SetLineNumberWidth. }
  2131. if FFoldLevelNumbersOrLineState then
  2132. Nines := StringOfChar('9', 12)
  2133. else begin
  2134. LineCount := Call(SCI_GETLINECOUNT, 0, 0);
  2135. Nines := '9';
  2136. while LineCount >= 10 do begin
  2137. LineCount := LineCount div 10;
  2138. Nines := Nines + '9';
  2139. end;
  2140. end;
  2141. PixelWidth := 4 + Call(SCI_TEXTWIDTH, STYLE_LINENUMBER, AnsiString(Nines));
  2142. end else
  2143. PixelWidth := 0;
  2144. Call(SCI_SETMARGINWIDTHN, 0, PixelWidth);
  2145. end;
  2146. procedure TScintEdit.UpdateStyleAttributes;
  2147. var
  2148. DefaultAttr: TScintStyleAttributes;
  2149. procedure SetStyleAttr(const StyleNumber: Integer;
  2150. const Attr: TScintStyleAttributes; const Force: Boolean);
  2151. begin
  2152. if Force or (Attr.FontName <> DefaultAttr.FontName) then
  2153. Call(SCI_STYLESETFONT, StyleNumber, AnsiString(Attr.FontName));
  2154. if Force or (Attr.FontSize <> DefaultAttr.FontSize) then
  2155. { Note: Scintilla doesn't support negative point sizes like the VCL }
  2156. Call(SCI_STYLESETSIZE, StyleNumber, Abs(Attr.FontSize));
  2157. if Force or (Attr.FontCharset <> DefaultAttr.FontCharset) then
  2158. Call(SCI_STYLESETCHARACTERSET, StyleNumber, Attr.FontCharset);
  2159. if Force or (Attr.FontStyle <> DefaultAttr.FontStyle) then begin
  2160. Call(SCI_STYLESETBOLD, StyleNumber, Ord(fsBold in Attr.FontStyle));
  2161. Call(SCI_STYLESETITALIC, StyleNumber, Ord(fsItalic in Attr.FontStyle));
  2162. Call(SCI_STYLESETUNDERLINE, StyleNumber, Ord(fsUnderline in Attr.FontStyle));
  2163. end;
  2164. if Force or (Attr.ForeColor <> DefaultAttr.ForeColor) then
  2165. Call(SCI_STYLESETFORE, StyleNumber, ColorToRGB(Attr.ForeColor));
  2166. if Force or (Attr.BackColor <> DefaultAttr.BackColor) then
  2167. Call(SCI_STYLESETBACK, StyleNumber, ColorToRGB(Attr.BackColor));
  2168. end;
  2169. procedure SetStyleAttrFromStyler(const StyleNumber: Integer);
  2170. var
  2171. Attr: TScintStyleAttributes;
  2172. begin
  2173. Attr := DefaultAttr;
  2174. FStyler.GetStyleAttributes(StyleNumber, Attr);
  2175. SetStyleAttr(StyleNumber, Attr, False);
  2176. end;
  2177. var
  2178. I: Integer;
  2179. begin
  2180. if not HandleAllocated then
  2181. Exit;
  2182. Call(SCI_SETCARETFORE, ColorToRGB(Font.Color), 0);
  2183. DefaultAttr.FontName := Font.Name;
  2184. DefaultAttr.FontSize := Font.Size;
  2185. DefaultAttr.FontStyle := Font.Style;
  2186. DefaultAttr.FontCharset := Font.Charset;
  2187. DefaultAttr.ForeColor := Font.Color;
  2188. DefaultAttr.BackColor := Color;
  2189. Call(SCI_STYLERESETDEFAULT, 0, 0);
  2190. SetStyleAttr(STYLE_DEFAULT, DefaultAttr, True);
  2191. Call(SCI_STYLECLEARALL, 0, 0);
  2192. if Assigned(FStyler) then begin
  2193. if FUseStyleAttributes then begin
  2194. for I := 0 to StyleNumbers-1 do
  2195. SetStyleAttrFromStyler(I);
  2196. SetStyleAttrFromStyler(STYLE_BRACEBAD);
  2197. SetStyleAttrFromStyler(STYLE_BRACELIGHT);
  2198. SetStyleAttrFromStyler(STYLE_INDENTGUIDE);
  2199. end;
  2200. SetStyleAttrFromStyler(STYLE_LINENUMBER);
  2201. end;
  2202. if (AutoCompleteFontName <> '') or (AutoCompleteFontSize > 0) then begin
  2203. if AutoCompleteFontName <> '' then
  2204. DefaultAttr.FontName := AutoCompleteFontName;
  2205. if AutoCompleteFontSize > 0 then
  2206. DefaultAttr.FontSize := AutoCompleteFontSize;
  2207. DefaultAttr.FontStyle := [];
  2208. { Note: Scintilla doesn't actually use the colors set here }
  2209. DefaultAttr.ForeColor := clWindowText;
  2210. DefaultAttr.BackColor := clWindow;
  2211. if FAutoCompleteStyle = 0 then
  2212. FAutoCompleteStyle := Call(SCI_ALLOCATEEXTENDEDSTYLES, 1, 0);
  2213. SetStyleAttr(FAutoCompleteStyle, DefaultAttr, True);
  2214. Call(SCI_AUTOCSETSTYLE, FAutoCompleteStyle, 0);
  2215. end else
  2216. Call(SCI_AUTOCSETSTYLE, 0, 0);
  2217. end;
  2218. function TScintEdit.WordAtCaret: String;
  2219. begin
  2220. var Range := WordAtCaretRange;
  2221. Result := GetTextRange(Range.StartPos, Range.EndPos);
  2222. end;
  2223. function TScintEdit.WordAtCaretRange: TScintRange;
  2224. begin
  2225. var Pos := GetCaretPosition;
  2226. Result.StartPos := GetWordStartPosition(Pos, True);
  2227. Result.EndPos := GetWordEndPosition(Pos, True);
  2228. end;
  2229. procedure TScintEdit.ZoomIn;
  2230. begin
  2231. Call(SCI_ZOOMIN, 0, 0);
  2232. end;
  2233. procedure TScintEdit.ZoomOut;
  2234. begin
  2235. Call(SCI_ZOOMOUT, 0, 0);
  2236. end;
  2237. procedure TScintEdit.CMColorChanged(var Message: TMessage);
  2238. begin
  2239. inherited;
  2240. UpdateStyleAttributes;
  2241. end;
  2242. procedure TScintEdit.CMFontChanged(var Message: TMessage);
  2243. begin
  2244. inherited;
  2245. UpdateStyleAttributes;
  2246. end;
  2247. procedure TScintEdit.CMHintShow(var Message: TCMHintShow);
  2248. begin
  2249. inherited;
  2250. if Assigned(FOnHintShow) then
  2251. FOnHintShow(Self, Message.HintInfo^);
  2252. end;
  2253. procedure TScintEdit.CMSysColorChange(var Message: TMessage);
  2254. begin
  2255. inherited;
  2256. UpdateStyleAttributes;
  2257. end;
  2258. procedure TScintEdit.CNNotify(var Message: TWMNotify);
  2259. begin
  2260. Notify(PSCNotification(Message.NMHdr)^);
  2261. end;
  2262. procedure TScintEdit.WMDestroy(var Message: TWMDestroy);
  2263. begin
  2264. FDirectPtr := nil;
  2265. FDirectStatusFunction := nil;
  2266. inherited;
  2267. end;
  2268. procedure TScintEdit.DpiChanged(const Message: TMessage);
  2269. begin
  2270. ForwardMessage(Message);
  2271. end;
  2272. procedure TScintEdit.WMDropFiles(var Message: TWMDropFiles);
  2273. var
  2274. FileList: TStringList;
  2275. NumFiles, I: Integer;
  2276. Filename: array[0..MAX_PATH-1] of Char;
  2277. P: TPoint;
  2278. begin
  2279. FileList := nil;
  2280. try
  2281. if FAcceptDroppedFiles and Assigned(FOnDropFiles) then begin
  2282. FileList := TStringList.Create;
  2283. NumFiles := DragQueryFile(Message.Drop, UINT(-1), nil, 0);
  2284. for I := 0 to NumFiles-1 do
  2285. if DragQueryFile(Message.Drop, I, Filename,
  2286. SizeOf(Filename) div SizeOf(Filename[0])) <> 0 then
  2287. FileList.Add(Filename);
  2288. if FileList.Count > 0 then begin
  2289. if not DragQueryPoint(Message.Drop, P) then begin
  2290. P.X := -1;
  2291. P.Y := -1;
  2292. end;
  2293. FOnDropFiles(Self, P.X, P.Y, FileList);
  2294. end;
  2295. end;
  2296. finally
  2297. FileList.Free;
  2298. DragFinish(Message.Drop);
  2299. Message.Drop := 0;
  2300. end;
  2301. end;
  2302. procedure TScintEdit.WMEraseBkgnd(var Message: TMessage);
  2303. begin
  2304. { Bypass the VCL's WM_ERASEBKGND handler; it causes flicker when selecting +
  2305. scrolling downward using the mouse }
  2306. Message.Result := CallWindowProc(DefWndProc, Handle, Message.Msg,
  2307. Message.WParam, Message.LParam);
  2308. end;
  2309. procedure TScintEdit.WMGetDlgCode(var Message: TWMGetDlgCode);
  2310. begin
  2311. inherited;
  2312. Message.Result := Message.Result or (DLGC_WANTARROWS or DLGC_WANTTAB);
  2313. end;
  2314. procedure TScintEdit.WMMouseWheel(var Message: TMessage);
  2315. begin
  2316. { Bypass TControl's broken WM_MOUSEWHEEL handler: it translates WParamLo
  2317. from a combination of MK_* values to a TShiftState -- which is only
  2318. meaningful to the VCL -- but it doesn't restore the original value before
  2319. passing an unhandled WM_MOUSEWHEEL message up to DefWndProc. This causes
  2320. Scintilla to see Ctrl+wheel as Shift+wheel, breaking zoom. (Observed on
  2321. Delphi 2009 and still needed in Delphi 11.3.) }
  2322. Message.Result := CallWindowProc(DefWndProc, Handle, Message.Msg,
  2323. Message.WParam, Message.LParam);
  2324. end;
  2325. procedure TScintEdit.SettingChange(const Message: TMessage);
  2326. begin
  2327. ForwardMessage(Message);
  2328. end;
  2329. { TScintEditStrings }
  2330. procedure TScintEditStrings.CheckIndexRange(const Index: Integer);
  2331. begin
  2332. if (Index < 0) or (Index >= GetCount) then
  2333. Error(@SListIndexError, Index);
  2334. end;
  2335. procedure TScintEditStrings.CheckIndexRangePlusOne(const Index: Integer);
  2336. begin
  2337. if (Index < 0) or (Index > GetCount) then
  2338. Error(@SListIndexError, Index);
  2339. end;
  2340. procedure TScintEditStrings.Clear;
  2341. begin
  2342. FEdit.SetRawText('');
  2343. end;
  2344. procedure TScintEditStrings.Delete(Index: Integer);
  2345. var
  2346. StartPos, EndPos: Integer;
  2347. begin
  2348. CheckIndexRange(Index);
  2349. StartPos := FEdit.GetPositionFromLine(Index);
  2350. EndPos := FEdit.GetPositionFromLine(Index + 1);
  2351. FEdit.ReplaceRawTextRange(StartPos, EndPos, '');
  2352. end;
  2353. function TScintEditStrings.Get(Index: Integer): String;
  2354. begin
  2355. Result := FEdit.ConvertRawStringToString(GetRawLine(Index));
  2356. end;
  2357. function TScintEditStrings.GetCount: Integer;
  2358. begin
  2359. Result := FEdit.Call(SCI_GETLINECOUNT, 0, 0);
  2360. end;
  2361. function TScintEditStrings.GetLineEndingLength(const Index: Integer): Integer;
  2362. var
  2363. StartPos, EndPos: Integer;
  2364. begin
  2365. CheckIndexRange(Index);
  2366. StartPos := FEdit.GetLineEndPosition(Index);
  2367. EndPos := FEdit.GetPositionFromLine(Index + 1);
  2368. Result := EndPos - StartPos;
  2369. end;
  2370. function TScintEditStrings.GetRawLine(Index: Integer): TScintRawString;
  2371. var
  2372. StartPos, EndPos: Integer;
  2373. begin
  2374. CheckIndexRange(Index);
  2375. StartPos := FEdit.GetPositionFromLine(Index);
  2376. EndPos := FEdit.GetLineEndPosition(Index);
  2377. Result := FEdit.GetRawTextRange(StartPos, EndPos);
  2378. end;
  2379. function TScintEditStrings.GetRawLineLength(Index: Integer): Integer;
  2380. var
  2381. StartPos, EndPos: Integer;
  2382. begin
  2383. CheckIndexRange(Index);
  2384. StartPos := FEdit.GetPositionFromLine(Index);
  2385. EndPos := FEdit.GetLineEndPosition(Index);
  2386. Result := EndPos - StartPos;
  2387. end;
  2388. function TScintEditStrings.GetRawLineLengthWithEnding(Index: Integer): Integer;
  2389. var
  2390. StartPos, EndPos: Integer;
  2391. begin
  2392. CheckIndexRange(Index);
  2393. StartPos := FEdit.GetPositionFromLine(Index);
  2394. EndPos := FEdit.GetPositionFromLine(Index + 1);
  2395. Result := EndPos - StartPos;
  2396. end;
  2397. function TScintEditStrings.GetRawLineWithEnding(Index: Integer): TScintRawString;
  2398. var
  2399. StartPos, EndPos: Integer;
  2400. begin
  2401. CheckIndexRange(Index);
  2402. StartPos := FEdit.GetPositionFromLine(Index);
  2403. EndPos := FEdit.GetPositionFromLine(Index + 1);
  2404. Result := FEdit.GetRawTextRange(StartPos, EndPos);
  2405. end;
  2406. function TScintEditStrings.GetState(Index: Integer): TScintLineState;
  2407. begin
  2408. CheckIndexRange(Index);
  2409. Result := FEdit.Call(SCI_GETLINESTATE, Index, 0);
  2410. end;
  2411. function TScintEditStrings.GetTextStr: String;
  2412. begin
  2413. Result := FEdit.ConvertRawStringToString(FEdit.GetRawText);
  2414. end;
  2415. procedure TScintEditStrings.Insert(Index: Integer; const S: String);
  2416. begin
  2417. InsertRawLine(Index, FEdit.ConvertStringToRawString(S));
  2418. end;
  2419. procedure TScintEditStrings.InsertRawLine(Index: Integer; const S: TScintRawString);
  2420. var
  2421. Pos: Integer;
  2422. EndingStr, InsertStr: TScintRawString;
  2423. begin
  2424. CheckIndexRangePlusOne(Index);
  2425. EndingStr := FEdit.GetLineEndingString;
  2426. Pos := FEdit.GetPositionFromLine(Index);
  2427. if (Index = GetCount) and (Pos <> FEdit.GetPositionFromLine(Index - 1)) then
  2428. InsertStr := EndingStr + S + EndingStr
  2429. else
  2430. InsertStr := S + EndingStr;
  2431. { Using ReplaceRawTextRange instead of SCI_INSERTTEXT for embedded null support }
  2432. FEdit.ReplaceRawTextRange(Pos, Pos, InsertStr);
  2433. end;
  2434. procedure TScintEditStrings.Put(Index: Integer; const S: String);
  2435. begin
  2436. PutRawLine(Index, FEdit.ConvertStringToRawString(S));
  2437. end;
  2438. procedure TScintEditStrings.PutRawLine(Index: Integer; const S: TScintRawString);
  2439. var
  2440. StartPos, EndPos: Integer;
  2441. begin
  2442. CheckIndexRange(Index);
  2443. StartPos := FEdit.GetPositionFromLine(Index);
  2444. EndPos := FEdit.GetLineEndPosition(Index);
  2445. FEdit.ReplaceRawTextRange(StartPos, EndPos, S, srmMinimal);
  2446. end;
  2447. procedure TScintEditStrings.SetText(Text: PChar);
  2448. begin
  2449. FEdit.SetRawText(FEdit.ConvertPCharToRawString(Text, StrLen(Text)));
  2450. end;
  2451. procedure TScintEditStrings.SetTextStr(const Value: String);
  2452. begin
  2453. FEdit.SetRawText(FEdit.ConvertStringToRawString(Value));
  2454. end;
  2455. { TScintCustomStyler }
  2456. procedure TScintCustomStyler.ApplyStyleByteIndicators(const Indicators: TScintStyleByteIndicatorNumbers;
  2457. StartIndex, EndIndex: Integer);
  2458. begin
  2459. var IndByte := Byte(Indicators) shl StyleNumberBits;
  2460. if IndByte <> 0 then begin
  2461. if StartIndex < 1 then
  2462. StartIndex := 1;
  2463. if EndIndex > FTextLen then
  2464. EndIndex := FTextLen;
  2465. for var I := StartIndex to EndIndex do
  2466. FStyleStr[I] := AnsiChar(Ord(FStyleStr[I]) or IndByte);
  2467. end;
  2468. end;
  2469. procedure TScintCustomStyler.ApplyStyle(const Style: TScintStyleNumber;
  2470. StartIndex, EndIndex: Integer);
  2471. begin
  2472. if StartIndex < 1 then
  2473. StartIndex := 1;
  2474. if EndIndex > FTextLen then
  2475. EndIndex := FTextLen;
  2476. for var I := StartIndex to EndIndex do
  2477. if Ord(FStyleStr[I]) and StyleNumberMask = 0 then
  2478. FStyleStr[I] := AnsiChar(Style or (Ord(FStyleStr[I]) and not StyleNumberMask));
  2479. end;
  2480. procedure TScintCustomStyler.CommitStyle(const Style: TScintStyleNumber);
  2481. begin
  2482. ApplyStyle(Style, FStyleStartIndex, FCurIndex - 1);
  2483. FStyleStartIndex := FCurIndex;
  2484. end;
  2485. function TScintCustomStyler.ConsumeAllRemaining: Boolean;
  2486. begin
  2487. Result := FCurIndex <= FTextLen;
  2488. if Result then
  2489. FCurIndex := FTextLen + 1;
  2490. end;
  2491. function TScintCustomStyler.ConsumeChar(const C: AnsiChar): Boolean;
  2492. begin
  2493. Result := (FCurIndex <= FTextLen) and (FText[FCurIndex] = C);
  2494. if Result then
  2495. Inc(FCurIndex);
  2496. end;
  2497. function TScintCustomStyler.ConsumeCharIn(const Chars: TScintRawCharSet): Boolean;
  2498. begin
  2499. Result := (FCurIndex <= FTextLen) and (FText[FCurIndex] in Chars);
  2500. if Result then
  2501. Inc(FCurIndex);
  2502. end;
  2503. function TScintCustomStyler.ConsumeChars(const Chars: TScintRawCharSet): Boolean;
  2504. begin
  2505. Result := False;
  2506. while FCurIndex <= FTextLen do begin
  2507. if not(FText[FCurIndex] in Chars) then
  2508. Break;
  2509. Result := True;
  2510. Inc(FCurIndex);
  2511. end;
  2512. end;
  2513. function TScintCustomStyler.ConsumeCharsNot(const Chars: TScintRawCharSet): Boolean;
  2514. begin
  2515. Result := False;
  2516. while FCurIndex <= FTextLen do begin
  2517. if FText[FCurIndex] in Chars then
  2518. Break;
  2519. Result := True;
  2520. Inc(FCurIndex);
  2521. end;
  2522. end;
  2523. function TScintCustomStyler.ConsumeString(const Chars: TScintRawCharSet): TScintRawString;
  2524. var
  2525. StartIndex: Integer;
  2526. begin
  2527. StartIndex := FCurIndex;
  2528. ConsumeChars(Chars);
  2529. Result := Copy(FText, StartIndex, FCurIndex - StartIndex);
  2530. end;
  2531. function TScintCustomStyler.CurCharIn(const Chars: TScintRawCharSet): Boolean;
  2532. begin
  2533. Result := (FCurIndex <= FTextLen) and (FText[FCurIndex] in Chars);
  2534. end;
  2535. function TScintCustomStyler.CurCharIs(const C: AnsiChar): Boolean;
  2536. begin
  2537. Result := (FCurIndex <= FTextLen) and (FText[FCurIndex] = C);
  2538. end;
  2539. function TScintCustomStyler.GetCurChar: AnsiChar;
  2540. begin
  2541. Result := #0;
  2542. if FCurIndex <= FTextLen then
  2543. Result := FText[FCurIndex];
  2544. end;
  2545. function TScintCustomStyler.GetEndOfLine: Boolean;
  2546. begin
  2547. Result := FCurIndex > FTextLen;
  2548. end;
  2549. function TScintCustomStyler.LineTextSpans(const S: TScintRawString): Boolean;
  2550. begin
  2551. Result := False;
  2552. end;
  2553. function TScintCustomStyler.NextCharIs(const C: AnsiChar): Boolean;
  2554. begin
  2555. Result := (FCurIndex < FTextLen) and (FText[FCurIndex+1] = C);
  2556. end;
  2557. function TScintCustomStyler.PreviousCharIn(const Chars: TScintRawCharSet): Boolean;
  2558. begin
  2559. Result := (FCurIndex > 1) and (FCurIndex-1 <= FTextLen) and
  2560. (FText[FCurIndex-1] in Chars);
  2561. end;
  2562. procedure TScintCustomStyler.ReplaceText(StartIndex, EndIndex: Integer;
  2563. const C: AnsiChar);
  2564. var
  2565. P: PAnsiChar;
  2566. I: Integer;
  2567. begin
  2568. if StartIndex < 1 then
  2569. StartIndex := 1;
  2570. if EndIndex > FTextLen then
  2571. EndIndex := FTextLen;
  2572. P := @FText[1];
  2573. for I := StartIndex to EndIndex do
  2574. P[I-1] := C;
  2575. end;
  2576. procedure TScintCustomStyler.ResetCurIndexTo(Index: Integer);
  2577. begin
  2578. FCurIndex := Index;
  2579. FStyleStartIndex := Index;
  2580. end;
  2581. { TScintPixmap }
  2582. const
  2583. XPMTransparentChar = ' ';
  2584. XPMTerminatorChar = '"';
  2585. class constructor TScintPixmap.Create;
  2586. begin
  2587. { Chars 128-255 are supported below but don't work in Scintilla }
  2588. for var C := #1 to #127 do
  2589. if (C <> XPMTransparentChar) and (C <> XPMTerminatorChar) then
  2590. ColorCodes := ColorCodes + C;
  2591. end;
  2592. function TScintPixmap.GetPixmap: Pointer;
  2593. begin
  2594. Result := FPixmap;
  2595. end;
  2596. type
  2597. TRGBTripleArray = array[0..MaxInt div SizeOf(TRGBTriple) - 1] of TRGBTriple;
  2598. PRGBTripleArray = ^TRGBTripleArray;
  2599. procedure TScintPixmap.InitializeFromBitmap(const ABitmap: TBitmap;
  2600. const TransparentColor: TColorRef);
  2601. procedure SetNextPixmapLine(const Pixmap: TPixmap; var Index: Integer; const Line: String);
  2602. begin
  2603. if Index > High(Pixmap) then
  2604. TScintEdit.Error('SetNextPixmapLine: Index out of range');
  2605. { Convert Line to an AnsiString, but copy the exact ordinal values;
  2606. i.e. don't do any translation of 128-255 }
  2607. var AnsiLine: AnsiString;
  2608. SetLength(AnsiLine, Length(Line));
  2609. for var I := 1 to Length(AnsiLine) do
  2610. AnsiLine[I] := AnsiChar(Ord(Line[I]));
  2611. Pixmap[Index] := AnsiLine;
  2612. Inc(Index);
  2613. end;
  2614. begin
  2615. if ABitmap.PixelFormat <> pf24bit then
  2616. TScintEdit.Error('Invalid PixelFormat');
  2617. var Colors := TDictionary<Integer, TPair<Char, String>>.Create; { RGB -> Code & WebColor }
  2618. try
  2619. { Build colors list }
  2620. for var Y := 0 to ABitmap.Height-1 do begin
  2621. var Pixels: PRGBTripleArray := ABitmap.ScanLine[Y];
  2622. for var X := 0 to ABitmap.Width-1 do begin
  2623. var Color := RGB(Pixels[X].rgbtRed, Pixels[X].rgbtGreen, Pixels[X].rgbtBlue);
  2624. if (Color <> TransparentColor) and not Colors.ContainsKey(Color) then begin
  2625. var ColorCodeIndex := Colors.Count+1;
  2626. if ColorCodeIndex > Length(ColorCodes) then
  2627. TScintEdit.Error('Too many colors');
  2628. Colors.Add(Color, TPair<Char, String>.Create(ColorCodes[ColorCodeIndex], RGBToWebColorStr(Color)))
  2629. end;
  2630. end;
  2631. end;
  2632. { Build pixmap }
  2633. var Line: String;
  2634. SetLength(FPixmap, 0); { Not really needed but makes things clearer while debugging }
  2635. SetLength(FPixmap, 1 + Colors.Count + ABitmap.Height + 1);
  2636. Line := Format('%d %d %d 1', [ABitmap.Width, ABitmap.Height, Colors.Count]);
  2637. var Index := 0;
  2638. SetNextPixmapLine(FPixmap, Index, Line);
  2639. for var Color in Colors do begin
  2640. Line := Format('%s c %s', [Color.Value.Key, Color.Value.Value]);
  2641. SetNextPixmapLine(FPixmap, Index, Line);
  2642. end;
  2643. for var Y := 0 to ABitmap.Height-1 do begin
  2644. Line := '';
  2645. var Pixels: PRGBTripleArray := ABitmap.ScanLine[Y];
  2646. for var X := 0 to ABitmap.Width-1 do begin
  2647. var Color := RGB(Pixels[X].rgbtRed, Pixels[X].rgbtGreen, Pixels[X].rgbtBlue);
  2648. if Color = TransparentColor then
  2649. Line := Line + XPMTransparentChar
  2650. else
  2651. Line := Line + Colors[Color].Key;
  2652. end;
  2653. SetNextPixmapLine(FPixmap, Index, Line);
  2654. end;
  2655. { Add terminating nil pointer - Scintilla doesnt really need it but setting it anyway }
  2656. SetNextPixmapLine(FPixmap, Index, '');
  2657. finally
  2658. Colors.Free;
  2659. end;
  2660. end;
  2661. { TScintRange }
  2662. constructor TScintRange.Create(const AStartPos, AEndPos: Integer);
  2663. begin
  2664. StartPos := AStartPos;
  2665. EndPos := AEndPos;
  2666. end;
  2667. function TScintRange.Overlaps(const ARange: TScintRange): Boolean;
  2668. begin
  2669. Result := not ARange.Empty and (StartPos <= ARange.EndPos) and (EndPos >= ARange.StartPos);
  2670. end;
  2671. function TScintRange.Empty: Boolean;
  2672. begin
  2673. Result := StartPos = EndPos;
  2674. end;
  2675. function TScintRange.Within(const ARange: TScintRange): Boolean;
  2676. begin
  2677. Result := (StartPos >= ARange.StartPos) and (EndPos <= ARange.EndPos);
  2678. end;
  2679. { TScintRangeList }
  2680. function TScintRangeList.Overlaps(const ARange: TScintRange;
  2681. var AOverlappingRange: TScintRange): Boolean;
  2682. begin
  2683. for var Item in Self do begin
  2684. if Item.Overlaps(ARange) then begin
  2685. AOverlappingRange := Item;
  2686. Exit(True);
  2687. end;
  2688. end;
  2689. Result := False;
  2690. end;
  2691. { TScintCaretAndAnchor }
  2692. constructor TScintCaretAndAnchor.Create(const ACaretPos, AAnchorPos: Integer);
  2693. begin
  2694. CaretPos := ACaretPos;
  2695. AnchorPos := AAnchorPos;
  2696. end;
  2697. function TScintCaretAndAnchor.Range: TScintRange;
  2698. begin
  2699. if CaretPos <= AnchorPos then begin
  2700. Result.StartPos := CaretPos;
  2701. Result.EndPos := AnchorPos;
  2702. end else begin
  2703. Result.StartPos := AnchorPos;
  2704. Result.EndPos := CaretPos;
  2705. end;
  2706. end;
  2707. end.