ScintEdit.pas 104 KB

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