ScintEdit.pas 107 KB

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