IDE.ScintStylerInnoSetup.pas 78 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013
  1. unit IDE.ScintStylerInnoSetup;
  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. TInnoSetupStyler: styler for Inno Setup scripts
  8. }
  9. interface
  10. uses
  11. SysUtils, Classes, Graphics, Generics.Collections, TypInfo,
  12. ScintEdit, ModernColors, Shared.ScriptFunc, Shared.SetupSectionDirectives;
  13. const
  14. InnoSetupStylerWordListSeparator = #9;
  15. InnoSetupStylerWordListTypeSeparator = '!'; { Must sort before numbers - so the default '?' is not ok }
  16. { AutoComplete word types }
  17. awtSection = 0;
  18. awtParameter = 1;
  19. awtDirective = 2;
  20. awtFlagOrSetupDirectiveValue = 3;
  21. awtPreprocessorDirective = 4;
  22. awtConstant = 5;
  23. awtScriptFunction = 10;
  24. awtScriptType = 11;
  25. awtScriptVariable = 12;
  26. awtScriptConstant = 13;
  27. awtScriptInterface = 14;
  28. awtScriptProperty = 15;
  29. awtScriptEvent = 16;
  30. awtScriptKeyword = 17;
  31. awtScriptEnumValue = 18;
  32. type
  33. TInnoSetupStylerSection = (
  34. scNone, { Not inside a section (start of file, or previous section was closed )
  35. Section tags themselves are not associated with any section! }
  36. scUnknown, { Inside an unrecognized section }
  37. scThirdParty, { Inside a '_' section (reserved for third-party tools) }
  38. scCode,
  39. scCodeBlock, { Block headers themselves are still associated with scCode }
  40. scComponents,
  41. scCustomMessages,
  42. scDirs,
  43. scISSigKeys,
  44. scFiles,
  45. scIcons,
  46. scINI,
  47. scInstallDelete,
  48. scLangOptions,
  49. scLanguages,
  50. scMessages,
  51. scRegistry,
  52. scRun,
  53. scSetup,
  54. scTasks,
  55. scTypes,
  56. scUninstallDelete,
  57. scUninstallRun);
  58. { Internally-used types }
  59. TInnoSetupStylerSpanState = (spNone, spBraceComment, spStarComment);
  60. { Starts at 1 instead of 0 to make sure ApplyStyle doesn't overwrite already applied stDefault
  61. styles which is needed for PreStyleInlineISPPDirectives to work properly when the inline
  62. directive is inside a comment or string. This is done by added a dummy 'st0' style. If done by
  63. using 'stDefault = 1' then this enum looses its TypeInfo. }
  64. TInnoSetupStylerStyle = (st0, stDefault, stCompilerDirective,
  65. stComment, stSection, stSymbol, stKeyword, stParameterValue,
  66. stEventFunction, stConstant, stMessageArg,
  67. stPascalReservedWord, stPascalString, stPascalNumber,
  68. stISPPReservedWord, stISPPString, stISPPNumber);
  69. TWordsBySection = TObjectDictionary<TInnoSetupStylerSection, TStringList>;
  70. TFunctionDefinition = record
  71. ScriptFuncWithoutHeader: AnsiString;
  72. HeaderKind: TScriptFuncHeaderKind;
  73. HasParams: Boolean;
  74. constructor Create(const ScriptFunc: AnsiString);
  75. end;
  76. TFunctionDefinitions = array of TFunctionDefinition;
  77. TFunctionDefinitionsByName = TDictionary<String, TFunctionDefinitions>;
  78. TInnoSetupStyler = class(TScintCustomStyler)
  79. private
  80. FEventFunctionsWordList: array[Boolean] of AnsiString;
  81. FKeywordsWordList, FFlagsWordList: array[TInnoSetupStylerSection] of AnsiString;
  82. FNoHighlightAtCursorWords: TWordsBySection;
  83. FFlagsWords: TWordsBySection;
  84. FISPPDirectivesWordList, FConstantsWordList: AnsiString;
  85. FScriptFunctionsByName: array[Boolean] of TFunctionDefinitionsByName; { Only has functions with at least 1 parameter }
  86. FScriptWordList: array[Boolean] of AnsiString;
  87. FSectionsWordList: AnsiString;
  88. FSetupSectionDirectiveValueAutoYesNoWordList: AnsiString;
  89. FSetupSectionDirectiveValueYesNoWordList: AnsiString;
  90. FSetupSectionDirectiveValueWordList: array[TSetupSectionDirective] of AnsiString;
  91. FISPPInstalled: Boolean;
  92. FTheme: TTheme;
  93. procedure AddWordToList(const SL: TStringList; const Word: AnsiString;
  94. const Typ: Integer);
  95. procedure ApplyPendingSquigglyFromToIndex(const StartIndex, EndIndex: Integer);
  96. procedure ApplyPendingSquigglyFromIndex(const StartIndex: Integer);
  97. procedure ApplySquigglyFromIndex(const StartIndex: Integer);
  98. procedure BuildConstantsWordList;
  99. procedure BuildEventFunctionsWordList;
  100. procedure BuildFlagsWordList(const Section: TInnoSetupStylerSection;
  101. const Flags: array of TScintRawString);
  102. procedure BuildISPPDirectivesWordList;
  103. procedure BuildKeywordsWordList(const Section: TInnoSetupStylerSection;
  104. const Parameters: array of TScintRawString);
  105. procedure BuildKeywordsWordListFromTypeInfo(const Section: TInnoSetupStylerSection;
  106. const EnumTypeInfo: Pointer; const PrefixLength: Integer);
  107. procedure BuildScriptFunctionsLists(const ScriptFuncTable: TScriptTable;
  108. const ClassMembers: Boolean; const SL: TStringList);
  109. procedure BuildSectionsWordList;
  110. function BuildWordList(const Values: array of TScintRawString): AnsiString; overload;
  111. function BuildWordList(const WordStringList: TStringList): AnsiString; overload;
  112. procedure CommitStyleSq(const Style: TInnoSetupStylerStyle;
  113. const Squigglify: Boolean);
  114. procedure CommitStyleSqPending(const Style: TInnoSetupStylerStyle);
  115. function GetEventFunctionsWordList(Procedures: Boolean): AnsiString;
  116. function GetFlagsWordList(Section: TInnoSetupStylerSection): AnsiString;
  117. function GetKeywordsWordList(Section: TInnoSetupStylerSection): AnsiString;
  118. procedure HandleCodeSection(var SpanState: TInnoSetupStylerSpanState; var CodeBlockHeader: Boolean);
  119. procedure HandleKeyValueSection(const Section: TInnoSetupStylerSection);
  120. procedure HandleParameterSection(const ValidParameters: array of TScintRawString);
  121. procedure HandleCompilerDirective(const InlineDirective: Boolean;
  122. const InlineDirectiveEndIndex: Integer; var OpenCount: ShortInt);
  123. procedure PreStyleInlineISPPDirectives;
  124. procedure SkipWhitespace;
  125. procedure SquigglifyUntilChars(const Chars: TScintRawCharSet;
  126. const Style: TInnoSetupStylerStyle);
  127. procedure StyleConstsUntilChars(const Chars: TScintRawCharSet;
  128. const NonConstStyle: TInnoSetupStylerStyle; var BraceLevel: Integer);
  129. procedure SetISPPInstalled(const Value: Boolean);
  130. function GetScriptWordList(ClassOrRecordMembers: Boolean): AnsiString;
  131. function GetSetupSectionDirectiveValueIsMultiValue(SetupSectionDirective: TSetupSectionDirective): Boolean;
  132. function GetSetupSectionDirectiveValueWordList(SetupSectionDirective: TSetupSectionDirective): AnsiString;
  133. protected
  134. procedure CommitStyle(const Style: TInnoSetupStylerStyle);
  135. procedure GetFoldLevel(const LineState, PreviousLineState: TScintLineState;
  136. var Level: Integer; var Header, EnableHeaderOnPrevious: Boolean); override;
  137. procedure GetStyleAttributes(const Style: Integer;
  138. var Attributes: TScintStyleAttributes); override;
  139. function LineTextSpans(const S: TScintRawString): Boolean; override;
  140. procedure StyleNeeded; override;
  141. public
  142. constructor Create(AOwner: TComponent); override;
  143. destructor Destroy; override;
  144. class function GetSectionFromLineState(const LineState: TScintLineState; const ReturnCodeBlockAsCode: Boolean = True): TInnoSetupStylerSection;
  145. class function IsCommentOrKeywordStyle(const Style: TScintStyleNumber): Boolean;
  146. class function IsCommentOrPascalStringStyle(const Style: TScintStyleNumber): Boolean;
  147. class function IsParamSection(const Section: TInnoSetupStylerSection): Boolean;
  148. class function IsSymbolStyle(const Style: TScintStyleNumber): Boolean;
  149. function GetScriptFunctionDefinition(const ClassMember: Boolean;
  150. const Name: String; const Index: Integer; out Count: Integer): TFunctionDefinition; overload;
  151. function GetScriptFunctionDefinition(const ClassMember: Boolean;
  152. const Name: String; const Index: Integer): TFunctionDefinition; overload;
  153. function SectionHasFlag(const Section: TInnoSetupStylerSection; const Flag: String): Boolean;
  154. function HighlightAtCursorAllowed(const Section: TInnoSetupStylerSection; const Word: String): Boolean;
  155. property ConstantsWordList: AnsiString read FConstantsWordList;
  156. property EventFunctionsWordList[Procedures: Boolean]: AnsiString read GetEventFunctionsWordList;
  157. property FlagsWordList[Section: TInnoSetupStylerSection]: AnsiString read GetFlagsWordList;
  158. property ISPPDirectivesWordList: AnsiString read FISPPDirectivesWordList;
  159. property ISPPInstalled: Boolean read FISPPInstalled write SetISPPInstalled;
  160. property KeywordsWordList[Section: TInnoSetupStylerSection]: AnsiString read GetKeywordsWordList;
  161. property ScriptWordList[ClassOrRecordMembers: Boolean]: AnsiString read GetScriptWordList;
  162. property SectionsWordList: AnsiString read FSectionsWordList;
  163. property SetupSectionDirectiveValueIsMultiValue[SetupSectionDirective: TSetupSectionDirective]: Boolean read GetSetupSectionDirectiveValueIsMultiValue;
  164. property SetupSectionDirectiveValueWordList[SetupSectionDirective: TSetupSectionDirective]: AnsiString read GetSetupSectionDirectiveValueWordList;
  165. property Theme: TTheme read FTheme write FTheme;
  166. end;
  167. implementation
  168. uses
  169. Generics.Defaults,
  170. Shared.SetupMessageIDs, ScintInt, Shared.LangOptionsSectionDirectives,
  171. Shared.CommonFunc.Vcl, Shared.SetupSteps, Shared.Struct, Shared.DotNetVersion, isxclasses_wordlists_generated;
  172. type
  173. { Size must be <= SizeOf(TScintLineState) }
  174. TInnoSetupStylerLineState = record
  175. Section, NextLineSection: TInnoSetupStylerSection;
  176. SpanState: TInnoSetupStylerSpanState;
  177. OpenCompilerDirectivesCount: ShortInt;
  178. end;
  179. type
  180. TSectionMapItem = record
  181. Name: TScintRawString;
  182. Section: TInnoSetupStylerSection;
  183. end;
  184. var
  185. SectionMap: array of TSectionMapItem; { Initialized below }
  186. const
  187. ComponentsSectionParameters: array of TScintRawString = [
  188. 'Check', 'Description', 'ExtraDiskSpaceRequired', 'Flags', 'Languages',
  189. 'MinVersion', 'Name', 'OnlyBelowVersion', 'Types'
  190. ];
  191. ComponentsSectionFlags: array of TScintRawString = [
  192. 'checkablealone', 'disablenouninstallwarning', 'dontinheritcheck', 'exclusive',
  193. 'fixed', 'restart'
  194. ];
  195. DeleteSectionParameters: array of TScintRawString = [
  196. 'AfterInstall', 'BeforeInstall', 'Check', 'Components', 'Languages',
  197. 'MinVersion', 'Name', 'OnlyBelowVersion', 'Tasks', 'Type'
  198. ];
  199. DeleteSectionTypes: array of TScintRawString = [
  200. 'files', 'filesandordirs', 'dirifempty'
  201. ];
  202. DirsSectionParameters: array of TScintRawString = [
  203. 'AfterInstall', 'Attribs', 'BeforeInstall', 'Check', 'Components', 'Flags',
  204. 'Languages', 'MinVersion', 'Name', 'OnlyBelowVersion', 'Permissions', 'Tasks'
  205. ];
  206. DirsSectionFlags: array of TScintRawString = [
  207. 'deleteafterinstall', 'setntfscompression', 'uninsalwaysuninstall',
  208. 'uninsneveruninstall', 'unsetntfscompression'
  209. ];
  210. ISSigKeysSectionParameters: array of TScintRawString = [
  211. 'Name', 'Group', 'KeyFile', 'KeyID', 'PublicX', 'PublicY', 'RuntimeID'
  212. ];
  213. FilesSectionParameters: array of TScintRawString = [
  214. 'AfterInstall', 'Attribs', 'BeforeInstall', 'Check', 'Components', 'CopyMode',
  215. 'DestDir', 'DestName', 'DownloadISSigSource', 'DownloadPassword',
  216. 'DownloadUserName', 'Excludes', 'ExternalSize', 'ExtractArchivePassword',
  217. 'Flags', 'FontInstall', 'Hash', 'ISSigAllowedKeys', 'Languages', 'MinVersion',
  218. 'OnlyBelowVersion', 'Permissions', 'Source', 'StrongAssemblyName', 'Tasks'
  219. ];
  220. FilesSectionFlags: array of TScintRawString = [
  221. '32bit', '64bit', 'allowunsafefiles', 'comparetimestamp', 'confirmoverwrite',
  222. 'createallsubdirs', 'deleteafterinstall', 'dontcopy', 'dontverifychecksum', 'download',
  223. 'external', 'extractarchive', 'fontisnttruetype', 'gacinstall', 'ignoreversion',
  224. 'isreadme', 'issigverify', 'nocompression', 'noencryption', 'notimestamp', 'noregerror',
  225. 'onlyifdestfileexists', 'onlyifdoesntexist', 'overwritereadonly', 'promptifolder',
  226. 'recursesubdirs', 'regserver', 'regtypelib', 'replacesameversion', 'restartreplace',
  227. 'setntfscompression', 'sharedfile', 'sign', 'signcheck', 'signonce',
  228. 'skipifsourcedoesntexist', 'solidbreak', 'sortfilesbyextension',
  229. 'sortfilesbyname', 'touch', 'uninsnosharedfileprompt', 'uninsremovereadonly',
  230. 'uninsrestartdelete', 'uninsneveruninstall', 'unsetntfscompression'
  231. ];
  232. IconsSectionParameters: array of TScintRawString = [
  233. 'AfterInstall', 'AppUserModelID', 'AppUserModelToastActivatorCLSID',
  234. 'BeforeInstall', 'Check', 'Comment', 'Components', 'Filename', 'Flags',
  235. 'HotKey', 'IconFilename', 'IconIndex', 'Languages', 'MinVersion', 'Name',
  236. 'OnlyBelowVersion', 'Parameters', 'Tasks', 'WorkingDir'
  237. ];
  238. IconsSectionFlags: array of TScintRawString = [
  239. 'closeonexit', 'createonlyiffileexists', 'dontcloseonexit',
  240. 'excludefromshowinnewinstall', 'preventpinning', 'runmaximized',
  241. 'runminimized', 'uninsneveruninstall', 'useapppaths'
  242. ];
  243. INISectionParameters: array of TScintRawString = [
  244. 'AfterInstall', 'BeforeInstall', 'Check', 'Components', 'Filename',
  245. 'Flags', 'Key', 'Languages', 'MinVersion', 'OnlyBelowVersion', 'Section',
  246. 'String', 'Tasks'
  247. ];
  248. INISectionFlags: array of TScintRawString = [
  249. 'createkeyifdoesntexist', 'uninsdeleteentry', 'uninsdeletesection',
  250. 'uninsdeletesectionifempty'
  251. ];
  252. LanguagesSectionParameters: array of TScintRawString = [
  253. 'InfoAfterFile', 'InfoBeforeFile', 'LicenseFile', 'MessagesFile', 'Name'
  254. ];
  255. RegistrySectionParameters: array of TScintRawString = [
  256. 'AfterInstall', 'BeforeInstall', 'Check', 'Components', 'Flags', 'Languages',
  257. 'MinVersion', 'OnlyBelowVersion', 'Permissions', 'Root', 'Subkey', 'Tasks',
  258. 'ValueData', 'ValueName', 'ValueType'
  259. ];
  260. RegistrySectionFlags: array of TScintRawString = [
  261. 'createvalueifdoesntexist', 'deletekey', 'deletevalue', 'dontcreatekey',
  262. 'noerror', 'preservestringtype', 'uninsclearvalue', 'uninsdeletekey',
  263. 'uninsdeletekeyifempty', 'uninsdeletevalue'
  264. ];
  265. RunSectionParameters: array of TScintRawString = [
  266. 'AfterInstall', 'BeforeInstall', 'Check', 'Components', 'Description',
  267. 'Filename', 'Flags', 'Languages', 'MinVersion', 'OnlyBelowVersion',
  268. 'Parameters', 'StatusMsg', 'Tasks', 'Verb', 'WorkingDir'
  269. ];
  270. RunSectionFlags: array of TScintRawString = [
  271. '32bit', '64bit', 'dontlogparameters', 'hidewizard', 'logoutput', 'nowait',
  272. 'postinstall', 'runascurrentuser', 'runasoriginaluser', 'runhidden',
  273. 'runmaximized', 'runminimized', 'shellexec', 'skipifdoesntexist', 'skipifnotsilent',
  274. 'skipifsilent', 'unchecked', 'waituntilidle', 'waituntilterminated'
  275. ];
  276. UninstallRunSectionParameters: array of TScintRawString = [
  277. 'AfterInstall', 'BeforeInstall', 'Check', 'Components', 'Filename', 'Flags',
  278. 'Languages', 'MinVersion', 'OnlyBelowVersion', 'Parameters', 'RunOnceId',
  279. 'Tasks', 'Verb', 'WorkingDir'
  280. ];
  281. UninstallRunSectionFlags: array of TScintRawString = [
  282. '32bit', '64bit', 'dontlogparameters', 'hidewizard', 'logoutput', 'nowait',
  283. 'runascurrentuser', 'runhidden', 'runmaximized', 'runminimized', 'shellexec',
  284. 'skipifdoesntexist', 'waituntilidle', 'waituntilterminated'
  285. ];
  286. TasksSectionParameters: array of TScintRawString = [
  287. 'Check', 'Components', 'Description', 'Flags', 'GroupDescription', 'Languages',
  288. 'MinVersion', 'Name', 'OnlyBelowVersion'
  289. ];
  290. TasksSectionFlags: array of TScintRawString = [
  291. 'checkablealone', 'checkedonce', 'dontinheritcheck', 'exclusive', 'restart',
  292. 'unchecked'
  293. ];
  294. TypesSectionParameters: array of TScintRawString = [
  295. 'Check', 'Description', 'Flags', 'Languages', 'MinVersion', 'Name',
  296. 'OnlyBelowVersion'
  297. ];
  298. TypesSectionFlags: array of TScintRawString = [
  299. 'iscustom'
  300. ];
  301. type
  302. TISPPDirective = record
  303. Name: TScintRawString;
  304. RequiresParameter: Boolean;
  305. OpenCountChange: ShortInt;
  306. end;
  307. var
  308. ISPPDirectives: array of TISPPDirective; { Initialized below }
  309. const
  310. { The following and some others below are not used by StyleNeeded and therefore
  311. simply of type AnsiString instead of TScintRawString }
  312. ConstantsWithParam: array of AnsiString = [
  313. 'cm', 'code', 'drive', 'ini', 'param', 'reg'
  314. ];
  315. Constants: array of AnsiString = [
  316. { Doesnt include constants with non words chars }
  317. '{', 'app', 'win', 'sys', 'sysnative', 'syswow64', 'src', 'sd', 'commonpf',
  318. 'commoncf', 'tmp', 'commonfonts', 'dao', 'dotnet11', 'dotnet20', 'dotnet40',
  319. 'group', 'localappdata', 'userappdata', 'commonappdata', 'usercf',
  320. 'userdesktop', 'commondesktop', 'userdocs', 'commondocs', 'userfavorites',
  321. 'userfonts', 'userpf', 'userprograms', 'commonprograms', 'usersavedgames',
  322. 'userstartmenu', 'commonstartmenu', 'userstartup', 'commonstartup',
  323. 'usertemplates', 'commontemplates', 'autoappdata', 'autocf', 'autodesktop',
  324. 'autodocs', 'autofonts', 'autopf', 'autoprograms', 'autostartmenu', 'cmd',
  325. 'computername', 'groupname', 'hwnd', 'wizardhwnd', 'language', 'srcexe',
  326. 'uninstallexe', 'sysuserinfoname', 'sysuserinfoorg', 'userinfoname',
  327. 'userinfoorg', 'userinfoserial', 'username', 'log'
  328. ];
  329. ISPPPredefinedVariables: array of AnsiString = [
  330. { #emit and #file handled separately by BuildConstantsWordList.
  331. Only includes predefined variables that are useful on their own. }
  332. 'CompilerPath', 'SourcePath'
  333. ];
  334. PascalConstants: array of AnsiString = [
  335. { ROPS }
  336. 'varEmpty', 'varNull', 'varSmallInt', 'varInteger', 'varSingle', 'varDouble',
  337. 'varCurrency', 'varDate', 'varOleStr', 'varDispatch', 'varError', 'varBoolean',
  338. 'varVariant', 'varUnknown', 'varShortInt', 'varByte', 'varWord', 'varLongWord',
  339. 'varInt64', 'varStrArg', 'varAny', 'varString', 'varTypeMask', 'varArray',
  340. 'varByRef', 'varUString', 'False', 'True',
  341. { ScriptFunc }
  342. 'MaxInt', 'wpWelcome', 'wpLicense', 'wpPassword', 'wpInfoBefore',
  343. 'wpUserInfo', 'wpSelectDir', 'wpSelectComponents', 'wpSelectProgramGroup',
  344. 'wpSelectTasks', 'wpReady', 'wpPreparing', 'wpInstalling', 'wpInfoAfter',
  345. 'wpFinished', 'MB_OK', 'MB_OKCANCEL', 'MB_ABORTRETRYIGNORE', 'MB_YESNOCANCEL',
  346. 'MB_YESNO', 'MB_RETRYCANCEL', 'MB_DEFBUTTON1', 'MB_DEFBUTTON2', 'MB_DEFBUTTON3',
  347. 'MB_SETFOREGROUND', 'IDOK', 'IDCANCEL', 'IDABORT', 'IDRETRY', 'IDIGNORE',
  348. 'IDYES', 'IDNO', 'HWND_BROADCAST', 'HKEY_AUTO', 'HKEY_AUTO_32', 'HKEY_AUTO_64',
  349. 'HKEY_CLASSES_ROOT', 'HKEY_CLASSES_ROOT_32', 'HKEY_CLASSES_ROOT_64',
  350. 'HKEY_CURRENT_USER', 'HKEY_CURRENT_USER_32', 'HKEY_CURRENT_USER_64',
  351. 'HKEY_LOCAL_MACHINE', 'HKEY_LOCAL_MACHINE_32', 'HKEY_LOCAL_MACHINE_64',
  352. 'HKEY_USERS', 'HKEY_USERS_32', 'HKEY_USERS_64', 'HKEY_PERFORMANCE_DATA',
  353. 'HKEY_CURRENT_CONFIG', 'HKEY_CURRENT_CONFIG_32', 'HKEY_CURRENT_CONFIG_64',
  354. 'HKEY_DYN_DATA', 'HKA', 'HKA32', 'HKA64', 'HKCR', 'HKCR32', 'HKCR64', 'HKCU',
  355. 'HKCU32', 'HKCU64', 'HKLM', 'HKLM32', 'HKLM64', 'HKU', 'HKU32', 'HKU64',
  356. 'HKCC', 'HKCC32', 'HKCC64', 'SW_HIDE', 'SW_SHOWNORMAL', 'SW_SHOWMINIMIZED',
  357. 'SW_SHOWMAXIMIZED', 'SW_SHOWMINNOACTIVE', 'SW_SHOW', 'FILE_ATTRIBUTE_READONLY',
  358. 'FILE_ATTRIBUTE_HIDDEN', 'FILE_ATTRIBUTE_SYSTEM', 'FILE_ATTRIBUTE_DIRECTORY',
  359. 'FILE_ATTRIBUTE_ARCHIVE', 'FILE_ATTRIBUTE_DEVICE', 'FILE_ATTRIBUTE_NORMAL',
  360. 'FILE_ATTRIBUTE_TEMPORARY', 'FILE_ATTRIBUTE_SPARSE_FILE','FILE_ATTRIBUTE_REPARSE_POINT',
  361. 'FILE_ATTRIBUTE_COMPRESSED', 'FILE_ATTRIBUTE_OFFLINE', 'FILE_ATTRIBUTE_NOT_CONTENT_INDEXED',
  362. 'FILE_ATTRIBUTE_ENCRYPTED', 'VER_NT_WORKSTATION', 'VER_NT_DOMAIN_CONTROLLER',
  363. 'VER_NT_SERVER', 'VER_SUITE_SMALLBUSINESS', 'VER_SUITE_ENTERPRISE', 'VER_SUITE_BACKOFFICE',
  364. 'VER_SUITE_COMMUNICATIONS', 'VER_SUITE_TERMINAL', 'VER_SUITE_SMALLBUSINESS_RESTRICTED',
  365. 'VER_SUITE_EMBEDDEDNT', 'VER_SUITE_DATACENTER', 'VER_SUITE_SINGLEUSERTS',
  366. 'VER_SUITE_PERSONAL', 'VER_SUITE_BLADE', 'VER_SUITE_EMBEDDED_RESTRICTED',
  367. 'VER_SUITE_SECURITY_APPLIANCE',
  368. 'SIID_DOCNOASSOC', 'SIID_DOCASSOC', 'SIID_APPLICATION', 'SIID_FOLDER', 'SIID_FOLDEROPEN',
  369. 'SIID_DRIVE525', 'SIID_DRIVE35', 'SIID_DRIVEREMOVE', 'SIID_DRIVEFIXED', 'SIID_DRIVENET',
  370. 'SIID_DRIVENETDISABLED', 'SIID_DRIVECD', 'SIID_DRIVERAM', 'SIID_WORLD', 'SIID_SERVER',
  371. 'SIID_PRINTER', 'SIID_MYNETWORK', 'SIID_FIND', 'SIID_HELP', 'SIID_SHARE', 'SIID_LINK',
  372. 'SIID_SLOWFILE', 'SIID_RECYCLER', 'SIID_RECYCLERFULL', 'SIID_MEDIACDAUDIO', 'SIID_LOCK',
  373. 'SIID_AUTOLIST', 'SIID_PRINTERNET', 'SIID_SERVERSHARE', 'SIID_PRINTERFAX',
  374. 'SIID_PRINTERFAXNET', 'SIID_PRINTERFILE', 'SIID_STACK', 'SIID_MEDIASVCD',
  375. 'SIID_STUFFEDFOLDER', 'SIID_DRIVEUNKNOWN', 'SIID_DRIVEDVD', 'SIID_MEDIADVD',
  376. 'SIID_MEDIADVDRAM', 'SIID_MEDIADVDRW', 'SIID_MEDIADVDR', 'SIID_MEDIADVDROM',
  377. 'SIID_MEDIACDAUDIOPLUS', 'SIID_MEDIACDRW', 'SIID_MEDIACDR', 'SIID_MEDIACDBURN',
  378. 'SIID_MEDIABLANKCD', 'SIID_MEDIACDROM', 'SIID_AUDIOFILES', 'SIID_IMAGEFILES',
  379. 'SIID_VIDEOFILES', 'SIID_MIXEDFILES', 'SIID_FOLDERBACK', 'SIID_FOLDERFRONT', 'SIID_SHIELD',
  380. 'SIID_WARNING', 'SIID_INFO', 'SIID_ERROR', 'SIID_KEY', 'SIID_SOFTWARE', 'SIID_RENAME',
  381. 'SIID_DELETE', 'SIID_MEDIAAUDIODVD', 'SIID_MEDIAMOVIEDVD', 'SIID_MEDIAENHANCEDCD',
  382. 'SIID_MEDIAENHANCEDDVD', 'SIID_MEDIAHDDVD', 'SIID_MEDIABLURAY', 'SIID_MEDIAVCD',
  383. 'SIID_MEDIADVDPLUSR', 'SIID_MEDIADVDPLUSRW', 'SIID_DESKTOPPC', 'SIID_MOBILEPC',
  384. 'SIID_USERS', 'SIID_MEDIASMARTMEDIA', 'SIID_MEDIACOMPACTFLASH', 'SIID_DEVICECELLPHONE',
  385. 'SIID_DEVICECAMERA', 'SIID_DEVICEVIDEOCAMERA', 'SIID_DEVICEAUDIOPLAYER',
  386. 'SIID_NETWORKCONNECT', 'SIID_INTERNET', 'SIID_ZIPFILE', 'SIID_SETTINGS', 'SIID_DRIVEHDDVD',
  387. 'SIID_DRIVEBD', 'SIID_MEDIAHDDVDROM', 'SIID_MEDIAHDDVDR', 'SIID_MEDIAHDDVDRAM',
  388. 'SIID_MEDIABDROM', 'SIID_MEDIABDR', 'SIID_MEDIABDRE', 'SIID_CLUSTEREDDRIVE'
  389. //undocumented: irInstall
  390. { ScriptClasses: see PascalConstants_Isxclasses in isxclasses_wordlists_generated }
  391. ];
  392. PascalInterfaces: array of AnsiString = [
  393. { ROPS }
  394. 'IUnknown', 'IInterface', 'IDispatch'
  395. ];
  396. PascalReservedWords: array of TScintRawString = [
  397. 'and', 'array', 'as', 'begin', 'case', 'const', 'div', 'do', 'downto',
  398. 'else', 'end', 'except', 'external', 'finally', 'for', 'forward', 'function',
  399. 'goto', 'if', 'in', 'is', 'label', 'mod', 'nil', 'not', 'of', 'or', 'out',
  400. 'procedure', 'program', 'record', 'repeat', 'set', 'shl', 'shr', 'then',
  401. 'to', 'try', 'type', 'until', 'var', 'while', 'with', 'xor', 'delayload',
  402. 'loadwithalteredsearchpath', 'stdcall', 'cdecl', 'register', 'pascal',
  403. 'setuponly', 'uninstallonly', 'event'
  404. ];
  405. PascalTypes: array of AnsiString = [
  406. { ROPS }
  407. 'Byte', 'Boolean', 'LongBool', 'WordBool', 'ByteBool', 'AnsiChar', 'Char',
  408. 'WideChar', 'WideString', 'UnicodeString', 'AnsiString', 'String', 'ShortInt',
  409. 'Word', 'SmallInt', 'LongInt', 'LongWord', 'Integer', 'Cardinal', 'Int64',
  410. 'Single', 'Double', 'Extended', 'Currency', 'PAnsiChar', 'Variant',
  411. 'TVariantArray',
  412. //undocumented: NativeString, AnyString, AnyMethod, ___Pointer, tbtString, NativeString, !NotificationVariant
  413. 'TVarType',
  414. //undocumented: TIFException
  415. { ScriptFunc's real enums, values done via PascalRealEnumValues instead of PascalEnumValues}
  416. 'TMsgBoxType', 'TSetupMessageID', 'TSetupStep', 'TUninstallStep',
  417. 'TSetupProcessorArchitecture', 'TDotNetVersion',
  418. { ScriptFunc's non real enums and other types - also see PascalEnumValues below }
  419. 'TArrayOfString', 'TArrayOfChar', 'TArrayOfBoolean', 'TArrayOfInteger', 'TArrayOfGraphic',
  420. 'DWORD', 'UINT', 'BOOL', 'DWORD_PTR', 'UINT_PTR', 'INT_PTR', 'TFileTime',
  421. 'TSplitType', 'TExecWait', 'TExecOutput', 'TFindRec', 'TWindowsVersion',
  422. 'TOnDownloadProgress', 'TOnExtractionProgress', 'TOnLog'
  423. { ScriptClasses: see PascalTypes_Isxclasses in isxclasses_wordlists_generated }
  424. ];
  425. PascalEnumValues: array of AnsiString = [
  426. { ScriptFunc's values of non real enums - also see PascalTypes above }
  427. 'stAll', 'stExcludeEmpty', 'stExcludeLastEmpty',
  428. 'ewNoWait', 'ewWaitUntilTerminated', 'ewWaitUntilIdle'
  429. { ScriptClasses: see PascalEnumValues_Isxclasses in isxclasses_wordlists_generated }
  430. ];
  431. var
  432. PascalRealEnumValues: array of PTypeInfo; { Initialized below }
  433. const
  434. PascalVariables: array of AnsiString = [
  435. { ROPS }
  436. 'Result',
  437. { ScriptClasses }
  438. 'WizardForm', 'MainForm', 'UninstallProgressForm'
  439. ];
  440. BasicEventFunctions: array of TScintRawString = [
  441. 'InitializeSetup', 'InitializeWizard', 'DeinitializeSetup', 'CurStepChanged',
  442. 'CurInstallProgressChanged', 'NextButtonClick', 'BackButtonClick',
  443. 'CancelButtonClick', 'ShouldSkipPage', 'CurPageChanged', 'CheckPassword',
  444. 'NeedRestart', 'UpdateReadyMemo', 'RegisterPreviousData', 'CheckSerial',
  445. 'GetCustomSetupExitCode', 'PrepareToInstall',
  446. 'RegisterExtraCloseApplicationsResources', 'InitializeUninstall',
  447. 'InitializeUninstallProgressForm', 'DeinitializeUninstall',
  448. 'CurUninstallStepChanged', 'UninstallNeedRestart'
  449. ];
  450. FullEventFunctions: array of AnsiString = [
  451. 'function InitializeSetup: Boolean;',
  452. 'procedure InitializeWizard;',
  453. 'procedure DeinitializeSetup;',
  454. 'procedure CurStepChanged(CurStep: TSetupStep);',
  455. 'procedure CurInstallProgressChanged(CurProgress, MaxProgress: Integer);',
  456. 'function NextButtonClick(CurPageID: Integer): Boolean;',
  457. 'function BackButtonClick(CurPageID: Integer): Boolean;',
  458. 'procedure CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean);',
  459. 'function ShouldSkipPage(PageID: Integer): Boolean;',
  460. 'procedure CurPageChanged(CurPageID: Integer);',
  461. 'function CheckPassword(Password: String): Boolean;',
  462. 'function NeedRestart: Boolean;',
  463. 'function UpdateReadyMemo(Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo, MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo: String): String;',
  464. 'procedure RegisterPreviousData(PreviousDataKey: Integer);',
  465. 'function CheckSerial(Serial: String): Boolean;',
  466. 'function GetCustomSetupExitCode: Integer;',
  467. 'function PrepareToInstall(var NeedsRestart: Boolean): String;',
  468. 'procedure RegisterExtraCloseApplicationsResources;',
  469. 'function InitializeUninstall: Boolean;',
  470. 'procedure InitializeUninstallProgressForm;',
  471. 'procedure DeinitializeUninstall;',
  472. 'procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);',
  473. 'function UninstallNeedRestart: Boolean;'
  474. ];
  475. EventFunctionsParameters: array of AnsiString = [
  476. 'CurStep', 'CurProgress', 'MaxProgress', 'CurPageID', 'Cancel', 'Confirm',
  477. 'PageID', 'Password', 'Space', 'NewLine', 'MemoUserInfoInfo',
  478. 'MemoDirInfo', 'MemoTypeInfo', 'MemoComponentsInfo', 'MemoGroupInfo',
  479. 'MemoTasksInfo', 'PreviousDataKey', 'Serial', 'NeedsRestart',
  480. 'CurUninstallStep'
  481. ];
  482. SetupSectionDirectivesYesNo = [
  483. ssAllowCancelDuringInstall, ssAllowNetworkDrive, ssAllowNoIcons, ssAllowRootDirectory,
  484. ssAllowUNCPath, ssAlwaysRestart, ssAlwaysShowComponentsList, ssAlwaysShowDirOnReadyPage,
  485. ssAlwaysShowGroupOnReadyPage, ssAlwaysUsePersonalGroup, ssAppendDefaultDirName,
  486. ssAppendDefaultGroupName, ssASLRCompatible, ssCreateAppDir, ssDEPCompatible,
  487. ssDisableFinishedPage, ssDisableReadyMemo, ssDisableReadyPage, ssDisableStartupPrompt,
  488. ssDisableWelcomePage, ssDiskSpanning, ssDontMergeDuplicateFiles, ssEnableDirDoesntExistWarning,
  489. ssFlatComponentsList, ssMergeDuplicateFiles, ssMissingMessagesWarning,
  490. ssMissingRunOnceIdsWarning, ssNotRecognizedMessagesWarning, ssOutput, ssRedirectionGuard,
  491. ssRestartApplications, ssRestartIfNeededByRun, ssSetupLogging, ssShowComponentSizes,
  492. ssShowTasksTreeLines, ssSignedUninstaller, ssSignToolRunMinimized, ssSolidCompression,
  493. ssTerminalServicesAware, ssTimeStampsInUTC, ssUpdateUninstallLogAppName, ssUninstallLogging,
  494. ssUninstallRestartComputer, ssUsedUserAreasWarning, ssUsePreviousLanguage, ssUsePreviousPrivileges,
  495. ssUserInfoPage, ssWizardImageStretch, ssWizardKeepAspectRatio];
  496. SetupSectionDirectivesYesNoOrScripted = [ssChangesAssociations, ssChangesEnvironment,
  497. ssCreateUninstallRegKey, ssUninstallable, ssUsePreviousAppDir, ssUsePreviousGroup,
  498. ssUsePreviousSetupType, ssUsePreviousTasks, ssUsePreviousUserInfo];
  499. SetupSectionDirectivesAutoYesNo = [
  500. ssDirExistsWarning, ssDisableDirPage, ssDisableProgramGroupPage, ssShowLanguageDialog];
  501. SYes = 'yes';
  502. SNo = 'no';
  503. SAuto = 'auto';
  504. type
  505. TSetupSectionDirectiveValue = record
  506. Directive: TSetupSectionDirective;
  507. Values: TArray<TScintRawString>;
  508. end;
  509. var
  510. SetupSectionDirectivesValues: array of TSetupSectionDirectiveValue; { Initialized below }
  511. const
  512. inSquiggly = 0;
  513. inPendingSquiggly = 1;
  514. AllChars = [#0..#255];
  515. WhitespaceChars = [#0..' '];
  516. AlphaChars = ['A'..'Z', 'a'..'z'];
  517. DigitChars = ['0'..'9'];
  518. HexDigitChars = DigitChars + ['A'..'F', 'a'..'f'];
  519. AlphaUnderscoreChars = AlphaChars + ['_'];
  520. AlphaDigitChars = AlphaChars + DigitChars;
  521. AlphaDigitUnderscoreChars = AlphaChars + DigitChars + ['_'];
  522. PascalIdentFirstChars = AlphaUnderscoreChars;
  523. PascalIdentChars = AlphaDigitUnderscoreChars;
  524. ISPPIdentFirstChars = AlphaUnderscoreChars;
  525. ISPPIdentChars = AlphaDigitUnderscoreChars;
  526. function SameRawText(const S1, S2: TScintRawString): Boolean;
  527. var
  528. Len, I: Integer;
  529. C1, C2: AnsiChar;
  530. begin
  531. Len := Length(S1);
  532. if Length(S2) <> Len then begin
  533. Result := False;
  534. Exit;
  535. end;
  536. for I := 1 to Len do begin
  537. C1 := S1[I];
  538. C2 := S2[I];
  539. if C1 in ['A'..'Z'] then
  540. Inc(C1, 32);
  541. if C2 in ['A'..'Z'] then
  542. Inc(C2, 32);
  543. if C1 <> C2 then begin
  544. Result := False;
  545. Exit;
  546. end;
  547. end;
  548. Result := True;
  549. end;
  550. { TFunctionDefinition }
  551. constructor TFunctionDefinition.Create(const ScriptFunc: AnsiString);
  552. begin
  553. ScriptFuncWithoutHeader := RemoveScriptFuncHeader(ScriptFunc, HeaderKind);
  554. HasParams := ScriptFuncHasParameters(ScriptFunc);
  555. end;
  556. { TInnoSetupStyler }
  557. constructor TInnoSetupStyler.Create(AOwner: TComponent);
  558. procedure BuildFlagsWordLists;
  559. begin
  560. { Builds FFlagsWordList (for autocomplete) and FFlagsWords }
  561. BuildFlagsWordList(scFiles, FilesSectionFlags);
  562. BuildFlagsWordList(scComponents, ComponentsSectionFlags);
  563. BuildFlagsWordList(scDirs, DirsSectionFlags);
  564. BuildFlagsWordList(scIcons, IconsSectionFlags);
  565. BuildFlagsWordList(scINI, INISectionFlags);
  566. BuildFlagsWordList(scRegistry, RegistrySectionFlags);
  567. BuildFlagsWordList(scRun, RunSectionFlags);
  568. BuildFlagsWordList(scTasks, TasksSectionFlags);
  569. BuildFlagsWordList(scTypes, TypesSectionFlags);
  570. BuildFlagsWordList(scUninstallRun, UninstallRunSectionFlags);
  571. { Bit of a trick }
  572. BuildFlagsWordList(scInstallDelete, DeleteSectionTypes);
  573. BuildFlagsWordList(scUninstallDelete, DeleteSectionTypes);
  574. end;
  575. procedure BuildKeywordsWordLists;
  576. begin
  577. { Builds FKeywordsWordList (for autocomplete) and FNoHighlightAtCursorWords }
  578. BuildKeywordsWordList(scISSigKeys, ISSigKeysSectionParameters);
  579. BuildKeywordsWordList(scFiles, FilesSectionParameters);
  580. BuildKeywordsWordList(scComponents, ComponentsSectionParameters);
  581. BuildKeywordsWordList(scDirs, DirsSectionParameters);
  582. BuildKeywordsWordList(scIcons, IconsSectionParameters);
  583. BuildKeywordsWordList(scINI, INISectionParameters);
  584. BuildKeywordsWordList(scInstallDelete, DeleteSectionParameters);
  585. BuildKeywordsWordListFromTypeInfo(scLangOptions, TypeInfo(TLangOptionsSectionDirective), LangOptionsSectionDirectivePrefixLength);
  586. BuildKeywordsWordList(scLanguages, LanguagesSectionParameters);
  587. BuildKeywordsWordList(scRegistry, RegistrySectionParameters);
  588. BuildKeywordsWordList(scRun, RunSectionParameters);
  589. BuildKeywordsWordListFromTypeInfo(scSetup, TypeInfo(TSetupSectionDirective), Length(SetupSectionDirectivePrefix));
  590. BuildKeywordsWordList(scTasks, TasksSectionParameters);
  591. BuildKeywordsWordList(scTypes, TypesSectionParameters);
  592. BuildKeywordsWordList(scUninstallDelete, DeleteSectionParameters);
  593. BuildKeywordsWordList(scUninstallRun, UninstallRunSectionParameters);
  594. BuildKeywordsWordListFromTypeInfo(scMessages, TypeInfo(TSetupMessageID), SetupMessageIDPrefixLength);
  595. end;
  596. procedure BuildScriptLists;
  597. begin
  598. { Builds FScriptFunctionsByName (for calltips) and FScriptWordList (for autocomplete)
  599. and FNoHighlightAtCursorWords }
  600. const SL1 = FNoHighlightAtCursorWords[scCode];
  601. const SL2 = TStringList.Create;
  602. try
  603. { Add stuff from ScriptFunc }
  604. var ClassMembers := False;
  605. for var ScriptFuncTable in ScriptFuncTables do
  606. BuildScriptFunctionsLists(ScriptFuncTable, ClassMembers, SL2);
  607. BuildScriptFunctionsLists(DelphiScriptFuncTable, ClassMembers, SL2);
  608. BuildScriptFunctionsLists(ROPSScriptFuncTable, ClassMembers, SL2);
  609. { Add stuff from this unit }
  610. for var S in PascalConstants do
  611. AddWordToList(SL2, S, awtScriptConstant);
  612. for var S in PascalConstants_Isxclasses do
  613. AddWordToList(SL2, S, awtScriptConstant);
  614. for var S in PascalInterfaces do
  615. AddWordToList(SL2, S, awtScriptInterface);
  616. for var S in PascalReservedWords do begin
  617. SL1.Add(String(S));
  618. AddWordToList(SL2, S, awtScriptKeyword);
  619. end;
  620. for var S in PascalTypes do
  621. AddWordToList(SL2, S, awtScriptType);
  622. for var S in PascalTypes_Isxclasses do
  623. AddWordToList(SL2, S, awtScriptType);
  624. for var S in PascalEnumValues do
  625. AddWordToList(SL2, S, awtScriptEnumValue);
  626. for var S in PascalEnumValues_Isxclasses do
  627. AddWordToList(SL2, S, awtScriptEnumValue);
  628. for var TypeInfo in PascalRealEnumValues do begin
  629. var TypeData := GetTypeData(TypeInfo);
  630. for var I := TypeData.MinValue to TypeData.MaxValue do
  631. AddWordToList(SL2, AnsiString(GetEnumName(TypeInfo, I)), awtScriptEnumValue);
  632. end;
  633. for var S in PascalVariables do
  634. AddWordToList(SL2, S, awtScriptVariable);
  635. for var S in EventFunctionsParameters do
  636. AddWordToList(SL2, S, awtScriptVariable);
  637. FScriptWordList[False] := BuildWordList(SL2);
  638. { Add stuff from Isxclasses }
  639. SL2.Clear;
  640. ClassMembers := True;
  641. BuildScriptFunctionsLists(PascalMembers_Isxclasses, ClassMembers, SL2);
  642. for var S in PascalProperties_Isxclasses do
  643. AddWordToList(SL2, S, awtScriptProperty);
  644. FScriptWordList[True] := BuildWordList(SL2);
  645. finally
  646. SL2.Free;
  647. end;
  648. end;
  649. procedure BuildSetupDirectiveValueWordLists;
  650. begin
  651. { Yes/no directives: we don't list true/false/1/0 }
  652. FSetupSectionDirectiveValueYesNoWordList := BuildWordList([SYes, SNo]);
  653. FSetupSectionDirectiveValueAutoYesNoWordList := BuildWordList([SAuto, SYes, SNo]);
  654. for var Item in SetupSectionDirectivesValues do
  655. FSetupSectionDirectiveValueWordList[Item.Directive] := BuildWordList(Item.Values);
  656. end;
  657. function CreateWordsBySectionList: TStringList;
  658. begin
  659. Result := TStringList.Create;
  660. Result.CaseSensitive := False;
  661. Result.Sorted := True;
  662. end;
  663. begin
  664. inherited;
  665. FNoHighlightAtCursorWords := TWordsBySection.Create([doOwnsValues]);
  666. FFlagsWords := TWordsBySection.Create([doOwnsValues]);
  667. for var Section := Low(TInnoSetupStylerSection) to High(TInnoSetupStylerSection) do begin
  668. FNoHighlightAtCursorWords.Add(Section, CreateWordsBySectionList);
  669. FFlagsWords.Add(Section, CreateWordsBySectionList);
  670. end;
  671. BuildConstantsWordList;
  672. BuildEventFunctionsWordList;
  673. BuildFlagsWordLists;
  674. BuildISPPDirectivesWordList;
  675. BuildKeywordsWordLists;
  676. BuildSectionsWordList;
  677. BuildSetupDirectiveValueWordLists;
  678. FScriptFunctionsByName[False] := TFunctionDefinitionsByName.Create(TIStringComparer.Ordinal);
  679. FScriptFunctionsByName[True] := TFunctionDefinitionsByName.Create(TIStringComparer.Ordinal);
  680. BuildScriptLists;
  681. end;
  682. destructor TInnoSetupStyler.Destroy;
  683. begin
  684. FScriptFunctionsByName[False].Free;
  685. FScriptFunctionsByName[True].Free;
  686. FFlagsWords.Free;
  687. FNoHighlightAtCursorWords.Free;
  688. inherited;
  689. end;
  690. procedure TInnoSetupStyler.AddWordToList(const SL: TStringList;
  691. const Word: AnsiString; const Typ: Integer);
  692. begin
  693. if Typ >= 0 then
  694. SL.Add(Format('%s%s%d', [Word, InnoSetupStylerWordListTypeSeparator, Typ]))
  695. else
  696. SL.Add(String(Word));
  697. end;
  698. procedure TInnoSetupStyler.ApplyPendingSquigglyFromToIndex(const StartIndex, EndIndex: Integer);
  699. begin
  700. if (CaretIndex >= StartIndex) and (CaretIndex <= EndIndex + 1) then
  701. ApplyStyleByteIndicators([inPendingSquiggly], StartIndex, EndIndex)
  702. else
  703. ApplyStyleByteIndicators([inSquiggly], StartIndex, EndIndex);
  704. end;
  705. procedure TInnoSetupStyler.ApplyPendingSquigglyFromIndex(const StartIndex: Integer);
  706. begin
  707. ApplyPendingSquigglyFromToIndex(StartIndex, CurIndex - 1);
  708. end;
  709. procedure TInnoSetupStyler.ApplySquigglyFromIndex(const StartIndex: Integer);
  710. begin
  711. ApplyStyleByteIndicators([inSquiggly], StartIndex, CurIndex - 1);
  712. end;
  713. function TInnoSetupStyler.BuildWordList(const Values: array of TScintRawString): AnsiString;
  714. begin
  715. const SL = TStringList.Create;
  716. try
  717. for var Value in Values do
  718. AddWordToList(SL, Value, awtFlagOrSetupDirectiveValue);
  719. Result := BuildWordList(SL);
  720. finally
  721. SL.Free;
  722. end;
  723. end;
  724. function TInnoSetupStyler.BuildWordList(const WordStringList: TStringList): AnsiString;
  725. begin
  726. { Scintilla uses an ASCII binary search so the list must be in ASCII sort
  727. order (case-insensitive). }
  728. WordStringList.CaseSensitive := False;
  729. WordStringList.UseLocale := False; { Make sure it uses CompareText and not AnsiCompareText }
  730. WordStringList.Sort;
  731. Result := '';
  732. for var S in WordStringList do begin
  733. var A := AnsiString(S);
  734. if Result = '' then
  735. Result := A
  736. else
  737. Result := Result + InnoSetupStylerWordListSeparator + A;
  738. end;
  739. end;
  740. procedure TInnoSetupStyler.BuildSectionsWordList;
  741. begin
  742. var SL := TStringList.Create;
  743. try
  744. for var Section in SectionMap do
  745. AddWordToList(SL, '[' + Section.Name + ']', awtSection);
  746. FSectionsWordList := BuildWordList(SL);
  747. finally
  748. SL.Free;
  749. end;
  750. end;
  751. procedure TInnoSetupStyler.BuildKeywordsWordList(
  752. const Section: TInnoSetupStylerSection;
  753. const Parameters: array of TScintRawString);
  754. begin
  755. const SL1 = FNoHighlightAtCursorWords[Section];
  756. const SL2 = TStringList.Create;
  757. try
  758. for var Parameter in Parameters do begin
  759. SL1.Add(String(Parameter));
  760. AddWordToList(SL2, Parameter, awtParameter);
  761. end;
  762. FKeywordsWordList[Section] := BuildWordList(SL2);
  763. finally
  764. SL2.Free;
  765. end;
  766. end;
  767. procedure TInnoSetupStyler.BuildKeywordsWordListFromTypeInfo(
  768. const Section: TInnoSetupStylerSection; const EnumTypeInfo: Pointer;
  769. const PrefixLength: Integer);
  770. begin
  771. const SL1 = FNoHighlightAtCursorWords[Section];
  772. const SL2 = TStringList.Create;
  773. try
  774. for var I := 0 to GetTypeData(EnumTypeInfo).MaxValue do begin
  775. const Parameter = Copy(GetEnumName(EnumTypeInfo, I), PrefixLength+1, MaxInt);
  776. SL1.Add(Parameter);
  777. AddWordToList(SL2, AnsiString(Parameter), awtDirective);
  778. end;
  779. FKeywordsWordList[Section] := BuildWordList(SL2);
  780. finally
  781. SL2.Free;
  782. end;
  783. end;
  784. procedure TInnoSetupStyler.BuildFlagsWordList(const Section: TInnoSetupStylerSection;
  785. const Flags: array of TScintRawString);
  786. begin
  787. const SL1 = FFlagsWords[Section];
  788. const SL2 = TStringList.Create;
  789. try
  790. for var Flag in Flags do begin
  791. SL1.Add(String(Flag));
  792. AddWordToList(SL2, Flag, awtFlagOrSetupDirectiveValue);
  793. end;
  794. FFlagsWordList[Section] := BuildWordList(SL2);
  795. finally
  796. SL2.Free;
  797. end;
  798. end;
  799. procedure TInnoSetupStyler.BuildScriptFunctionsLists(
  800. const ScriptFuncTable: TScriptTable; const ClassMembers: Boolean;
  801. const SL: TStringList);
  802. begin
  803. for var ScriptFunc in ScriptFuncTable do begin
  804. var FunctionDefinition := TFunctionDefinition.Create(ScriptFunc);
  805. var ScriptFuncName := ExtractScriptFuncWithoutHeaderName(FunctionDefinition.ScriptFuncWithoutHeader);
  806. var DoAddWordToList := True;
  807. var Key := String(ScriptFuncName);
  808. if not FScriptFunctionsByName[ClassMembers].TryAdd(Key, [FunctionDefinition]) then begin
  809. { Function has multiple prototypes }
  810. var ScriptFunctions := FScriptFunctionsByName[ClassMembers][Key];
  811. var N := Length(ScriptFunctions);
  812. SetLength(ScriptFunctions, N+1);
  813. ScriptFunctions[N] := FunctionDefinition;
  814. FScriptFunctionsByName[ClassMembers][Key] := ScriptFunctions;
  815. DoAddWordToList := False; { Already added it when the first prototype was found }
  816. end;
  817. if DoAddWordToList then
  818. AddWordToList(SL, ScriptFuncName, awtScriptFunction);
  819. end;
  820. end;
  821. procedure TInnoSetupStyler.BuildISPPDirectivesWordList;
  822. begin
  823. var SL := TStringList.Create;
  824. try
  825. for var ISPPDirective in ISPPDirectives do
  826. AddWordToList(SL, '#' + ISPPDirective.Name, awtPreprocessorDirective);
  827. FISPPDirectivesWordList := BuildWordList(SL);
  828. finally
  829. SL.Free;
  830. end;
  831. end;
  832. procedure TInnoSetupStyler.BuildConstantsWordList;
  833. begin
  834. var SL := TStringList.Create;
  835. try
  836. for var Constant in Constants do
  837. AddWordToList(SL, '{' + Constant + '}', awtConstant);
  838. if ISPPInstalled then begin
  839. AddWordToList(SL, '{#', awtConstant);
  840. AddWordToList(SL, '{#file ', awtConstant);
  841. for var ISPPPredefinedVariable in ISPPPredefinedVariables do
  842. AddWordToList(SL, '{#' + ISPPPredefinedVariable + '}', awtConstant);
  843. end;
  844. for var ConstantWithParam in ConstantsWithParam do
  845. AddWordToList(SL, '{' + ConstantWithParam, awtConstant);
  846. FConstantsWordList := BuildWordList(SL);
  847. finally
  848. SL.Free;
  849. end;
  850. end;
  851. procedure TInnoSetupStyler.BuildEventFunctionsWordList;
  852. begin
  853. var SLFunctions: TStringList := nil;
  854. var SLProcedures: TStringList := nil;
  855. try
  856. SLFunctions := TStringList.Create;
  857. SLProcedures := TStringList.Create;
  858. for var FullEventFunction in FullEventFunctions do begin
  859. var HeaderKind: TScriptFuncHeaderKind;
  860. var S := RemoveScriptFuncHeader(FullEventFunction, HeaderKind);
  861. if HeaderKind = hkFunction then
  862. AddWordToList(SLFunctions, S, awtScriptEvent)
  863. else if HeaderKind = hkProcedure then
  864. AddWordToList(SLProcedures, S, awtScriptEvent)
  865. else
  866. raise Exception.Create('Got invalid HeaderKind for event function');
  867. end;
  868. FEventFunctionsWordList[False] := BuildWordList(SLFunctions);
  869. FEventFunctionsWordList[True] := BuildWordList(SLProcedures);
  870. finally
  871. SLProcedures.Free;
  872. SLFunctions.Free;
  873. end;
  874. end;
  875. procedure TInnoSetupStyler.CommitStyle(const Style: TInnoSetupStylerStyle);
  876. begin
  877. inherited CommitStyle(Ord(Style));
  878. end;
  879. procedure TInnoSetupStyler.CommitStyleSq(const Style: TInnoSetupStylerStyle;
  880. const Squigglify: Boolean);
  881. begin
  882. if Squigglify then
  883. ApplySquigglyFromIndex(StyleStartIndex);
  884. CommitStyle(Style);
  885. end;
  886. procedure TInnoSetupStyler.CommitStyleSqPending(const Style: TInnoSetupStylerStyle);
  887. begin
  888. ApplyPendingSquigglyFromIndex(StyleStartIndex);
  889. CommitStyle(Style);
  890. end;
  891. function TInnoSetupStyler.GetEventFunctionsWordList(Procedures: Boolean): AnsiString;
  892. begin
  893. Result := FEventFunctionsWordList[Procedures];
  894. end;
  895. function TInnoSetupStyler.GetFlagsWordList(Section: TInnoSetupStylerSection): AnsiString;
  896. begin
  897. Result := FFlagsWordList[Section];
  898. end;
  899. procedure TInnoSetupStyler.GetFoldLevel(const LineState, PreviousLineState: TScintLineState;
  900. var Level: Integer; var Header, EnableHeaderOnPrevious: Boolean);
  901. begin
  902. { Set folding per section. Lines outside of a section (=lines at the start of
  903. the document and section tags and section end tags and lines after section
  904. end tags) get level 0 with header flags for section tags. Other lines
  905. (=lines inside a section) get level 1. }
  906. var Section := TInnoSetupStyler.GetSectionFromLineState(LineState, False);
  907. if Section = scNone then begin
  908. Level := 0;
  909. Header := False; { Might be set to True via EnableHeaderOnPrevious below when we know about next line }
  910. EnableHeaderOnPrevious := False;
  911. end else begin
  912. Level := 1;
  913. Header := False;
  914. var PreviousSection := TInnoSetupStyler.GetSectionFromLineState(PreviousLineState, False);
  915. if Section = scCodeBlock then begin
  916. Inc(Level);
  917. EnableHeaderOnPrevious := PreviousSection = scCode;
  918. end else
  919. EnableHeaderOnPrevious := PreviousSection = scNone;
  920. end;
  921. end;
  922. function TInnoSetupStyler.GetKeywordsWordList(Section: TInnoSetupStylerSection): AnsiString;
  923. begin
  924. Result := FKeywordsWordList[Section];
  925. end;
  926. function TInnoSetupStyler.GetScriptFunctionDefinition(const ClassMember: Boolean;
  927. const Name: String; const Index: Integer; out Count: Integer): TFunctionDefinition;
  928. begin
  929. var ScriptFunctions: TFunctionDefinitions;
  930. if FScriptFunctionsByName[ClassMember].TryGetValue(Name, ScriptFunctions) then begin
  931. Count := Length(ScriptFunctions);
  932. var ResultIndex := Index;
  933. if ResultIndex >= Count then
  934. ResultIndex := Count-1;
  935. Result := ScriptFunctions[ResultIndex]
  936. end else
  937. Count := 0;
  938. end;
  939. function TInnoSetupStyler.GetScriptFunctionDefinition(
  940. const ClassMember: Boolean; const Name: String;
  941. const Index: Integer): TFunctionDefinition;
  942. begin
  943. var Count: Integer;
  944. Result := GetScriptFunctionDefinition(ClassMember, Name, Index, Count);
  945. end;
  946. function TInnoSetupStyler.GetScriptWordList(
  947. ClassOrRecordMembers: Boolean): AnsiString;
  948. begin
  949. Result := FScriptWordList[ClassOrRecordMembers];
  950. end;
  951. class function TInnoSetupStyler.GetSectionFromLineState(
  952. const LineState: TScintLineState; const ReturnCodeBlockAsCode: Boolean = True): TInnoSetupStylerSection;
  953. begin
  954. Result := TInnoSetupStylerLineState(LineState).Section;
  955. if ReturnCodeBlockAsCode and (Result = scCodeBlock) then
  956. Result := scCode;
  957. end;
  958. function TInnoSetupStyler.GetSetupSectionDirectiveValueIsMultiValue(
  959. SetupSectionDirective: TSetupSectionDirective): Boolean;
  960. { "MultiValue" means a directive like WizardStyle which accepts a space separated list of values }
  961. begin
  962. Result := SetupSectionDirective in [ssArchitecturesAllowed,
  963. ssArchitecturesInstallIn64BitMode, ssDisablePrecompiledFileVerifications,
  964. ssPrivilegesRequiredOverridesAllowed, ssWizardStyle];
  965. end;
  966. function TInnoSetupStyler.GetSetupSectionDirectiveValueWordList(
  967. SetupSectionDirective: TSetupSectionDirective): AnsiString;
  968. begin
  969. if SetupSectionDirective in SetupSectionDirectivesAutoYesNo then
  970. Result := FSetupSectionDirectiveValueAutoYesNoWordList
  971. else if (SetupSectionDirective in SetupSectionDirectivesYesNo) or
  972. (SetupSectionDirective in SetupSectionDirectivesYesNoOrScripted) then
  973. Result := FSetupSectionDirectiveValueYesNoWordList
  974. else
  975. Result := FSetupSectionDirectiveValueWordList[SetupSectionDirective];
  976. end;
  977. procedure TInnoSetupStyler.GetStyleAttributes(const Style: Integer;
  978. var Attributes: TScintStyleAttributes);
  979. begin
  980. if FTheme <> nil then begin
  981. if (Style >= 0) and (Style <= Ord(High(TInnoSetupStylerStyle))) then begin
  982. if not FTheme.Modern then begin
  983. { Check for some exceptions }
  984. case TInnoSetupStylerStyle(Style) of
  985. stCompilerDirective, stISPPReservedWord: begin Attributes.ForeColor := $4040C0; Exit; end;
  986. stMessageArg: begin Attributes.ForeColor := $FF8000; Exit; end;
  987. stPascalString, stPascalNumber, stISPPString, stISPPNumber: begin Attributes.ForeColor := clMaroon; Exit; end;
  988. end;
  989. end;
  990. case TInnoSetupStylerStyle(Style) of
  991. stCompilerDirective, stISPPReservedWord: Attributes.ForeColor := FTheme.Colors[tcRed];
  992. stComment: Attributes.ForeColor := FTheme.Colors[tcGreen];
  993. stSection: Attributes.FontStyle := [fsBold];
  994. stSymbol: Attributes.ForeColor := FTheme.Colors[tcGray];
  995. stKeyword, stPascalReservedWord: Attributes.ForeColor := FTheme.Colors[tcBlue];
  996. //stParameterValue: Attributes.ForeColor := FTheme.Colors[tcTeal];
  997. stEventFunction: Attributes.FontStyle := [fsBold];
  998. stConstant: Attributes.ForeColor := FTheme.Colors[tcPurple];
  999. stMessageArg: Attributes.ForeColor := FTheme.Colors[tcRed];
  1000. stPascalString, stPascalNumber, stISPPString, stISPPNumber: Attributes.ForeColor := FTheme.Colors[tcOrange];
  1001. end;
  1002. end else begin
  1003. case Style of
  1004. STYLE_LINENUMBER: { Also sets the background colour for the margin with the markers like mmIconBreakpoint }
  1005. begin
  1006. Attributes.ForeColor := FTheme.Colors[tcMarginFore];
  1007. Attributes.BackColor := FTheme.Colors[tcMarginBack];
  1008. end;
  1009. STYLE_BRACEBAD: Attributes.ForeColor := FTheme.Colors[tcRed];
  1010. STYLE_BRACELIGHT: Attributes.BackColor := FTheme.Colors[tcBraceBack];
  1011. STYLE_INDENTGUIDE: Attributes.ForeColor := FTheme.Colors[tcIndentGuideFore];
  1012. end;
  1013. end;
  1014. end;
  1015. end;
  1016. procedure TInnoSetupStyler.HandleCodeSection(var SpanState: TInnoSetupStylerSpanState; var CodeBlockHeader: Boolean);
  1017. function FinishConsumingBraceComment: Boolean;
  1018. begin
  1019. ConsumeCharsNot(['}']);
  1020. Result := ConsumeChar('}');
  1021. CommitStyle(stComment);
  1022. end;
  1023. function FinishConsumingStarComment: Boolean;
  1024. begin
  1025. Result := False;
  1026. while True do begin
  1027. ConsumeCharsNot(['*']);
  1028. if not ConsumeChar('*') then
  1029. Break;
  1030. if ConsumeChar(')') then begin
  1031. Result := True;
  1032. Break;
  1033. end;
  1034. end;
  1035. CommitStyle(stComment);
  1036. end;
  1037. begin
  1038. case SpanState of
  1039. spBraceComment:
  1040. if not FinishConsumingBraceComment then
  1041. Exit;
  1042. spStarComment:
  1043. if not FinishConsumingStarComment then
  1044. Exit;
  1045. end;
  1046. SpanState := spNone;
  1047. SkipWhitespace;
  1048. while not EndOfLine do begin
  1049. if CurChar in PascalIdentFirstChars then begin
  1050. var S := ConsumeString(PascalIdentChars);
  1051. for var Word in PascalReservedWords do
  1052. if SameRawText(S, Word) then begin
  1053. if SameRawText(S, 'function') or SameRawText(S, 'procedure') or SameRawText(S, 'type') then
  1054. CodeBlockHeader := True; { Global 'var' and 'const' blocks are currently not detected }
  1055. CommitStyle(stPascalReservedWord);
  1056. Break;
  1057. end;
  1058. for var EventFunction in BasicEventFunctions do
  1059. if SameRawText(S, EventFunction) then begin
  1060. CommitStyle(stEventFunction);
  1061. Break;
  1062. end;
  1063. CommitStyle(stDefault);
  1064. end else if ConsumeChars(DigitChars) then begin
  1065. if not CurCharIs('.') or not NextCharIs('.') then begin
  1066. if ConsumeChar('.') then
  1067. ConsumeChars(DigitChars);
  1068. var C := CurChar;
  1069. if C in ['E', 'e'] then begin
  1070. ConsumeChar(C);
  1071. if not ConsumeChar('-') then
  1072. ConsumeChar('+');
  1073. if not ConsumeChars(DigitChars) then
  1074. CommitStyleSqPending(stPascalNumber);
  1075. end;
  1076. end;
  1077. CommitStyle(stPascalNumber);
  1078. end else begin
  1079. var C := CurChar;
  1080. ConsumeChar(C);
  1081. case C of
  1082. ';', ':', '=', '+', '-', '*', '/', '<', '>', ',', '(', ')',
  1083. '.', '[', ']', '@', '^':
  1084. begin
  1085. if (C = '/') and ConsumeChar('/') then begin
  1086. ConsumeAllRemaining;
  1087. CommitStyle(stComment);
  1088. end else if (C = '(') and ConsumeChar('*') then begin
  1089. if not FinishConsumingStarComment then begin
  1090. SpanState := spStarComment;
  1091. Exit;
  1092. end;
  1093. end else
  1094. CommitStyle(stSymbol);
  1095. end;
  1096. '''':
  1097. begin
  1098. while True do begin
  1099. ConsumeCharsNot([C]);
  1100. if not ConsumeChar(C) then begin
  1101. CommitStyleSqPending(stPascalString);
  1102. Break;
  1103. end;
  1104. if not ConsumeChar(C) then begin
  1105. CommitStyle(stPascalString);
  1106. Break;
  1107. end;
  1108. end;
  1109. end;
  1110. '{':
  1111. begin
  1112. if not FinishConsumingBraceComment then begin
  1113. SpanState := spBraceComment;
  1114. Exit;
  1115. end;
  1116. end;
  1117. '$':
  1118. begin
  1119. if not ConsumeChars(HexDigitChars) then
  1120. CommitStyleSqPending(stPascalNumber);
  1121. CommitStyle(stPascalNumber);
  1122. end;
  1123. '#':
  1124. begin
  1125. if ConsumeChar('$') then begin
  1126. if not ConsumeChars(HexDigitChars) then
  1127. CommitStyleSqPending(stPascalString);
  1128. end else if not ConsumeChars(DigitChars) then
  1129. CommitStyleSqPending(stPascalString);
  1130. CommitStyle(stPascalString);
  1131. end;
  1132. else
  1133. { Illegal character }
  1134. CommitStyleSq(stSymbol, True);
  1135. end;
  1136. end;
  1137. SkipWhitespace;
  1138. end;
  1139. end;
  1140. procedure TInnoSetupStyler.HandleCompilerDirective(const InlineDirective: Boolean; const InlineDirectiveEndIndex: Integer; var OpenCount: ShortInt);
  1141. function EndOfDirective: Boolean;
  1142. begin
  1143. Result := EndOfLine or (InlineDirective and (CurIndex > InlineDirectiveEndIndex));
  1144. end;
  1145. procedure FinishDirectiveNameOrShorthand(const RequiresParameter: Boolean);
  1146. begin
  1147. if RequiresParameter then begin
  1148. ConsumeChars(WhitespaceChars); { This will give the whitespace the stCompilerDirective style instead of stDefault but that's ok }
  1149. if EndOfDirective then
  1150. CommitStyleSqPending(stCompilerDirective)
  1151. else
  1152. CommitStyle(stCompilerDirective);
  1153. end else
  1154. CommitStyle(stCompilerDirective);
  1155. end;
  1156. function FinishConsumingStarComment: Boolean;
  1157. begin
  1158. Result := False;
  1159. while True do begin
  1160. ConsumeCharsNot(['*']);
  1161. if not ConsumeChar('*') then
  1162. Break;
  1163. if ConsumeChar('/') then begin
  1164. Result := True;
  1165. Break;
  1166. end;
  1167. end;
  1168. if Result then
  1169. CommitStyle(stComment)
  1170. else
  1171. CommitStyleSqPending(stComment);
  1172. end;
  1173. procedure ConsumeISPPString(const Terminator: AnsiChar; const AllowEscapedTerminator: Boolean);
  1174. begin
  1175. while True do begin
  1176. ConsumeCharsNot([Terminator]);
  1177. if not ConsumeChar(Terminator) then begin
  1178. { Non terminated string found }
  1179. CommitStyleSqPending(stISPPString);
  1180. Break;
  1181. end;
  1182. { Terminated string found and consumed. Now check if the terminator is actually escaped by doubling, if allowed }
  1183. if not AllowEscapedTerminator or not ConsumeChar(Terminator) then begin
  1184. { Doubling not allowed or no double terminator found, so we're done }
  1185. CommitStyle(stISPPString);
  1186. Break;
  1187. end;
  1188. { The terminator was doubled so we should continue to find the real terminator }
  1189. end;
  1190. end;
  1191. const
  1192. ISPPReservedWords: array[0..16] of TScintRawString = (
  1193. 'private', 'protected', 'public', 'any', 'int',
  1194. 'str', 'func', 'option', 'parseroption', 'inlinestart',
  1195. 'inlineend', 'message', 'warning', 'error',
  1196. 'verboselevel', 'include', 'spansymbol');
  1197. ISPPDirectiveShorthands: TScintRawCharSet =
  1198. [':' {define},
  1199. 'x' {undef},
  1200. '+' {include},
  1201. '=' {emit},
  1202. '!' {expr}];
  1203. begin
  1204. var StartIndex := CurIndex;
  1205. var NeedIspp: Boolean;
  1206. if InlineDirective then begin
  1207. ConsumeChar('{');
  1208. NeedIspp := True;
  1209. end else
  1210. NeedIspp := False; { Might be updated later to True later }
  1211. var ForDirectiveExpressionsNext := False;
  1212. var DoIncludeFileNotationCheck := False;
  1213. var ErrorDirective := False;
  1214. ConsumeChar('#');
  1215. CommitStyle(stCompilerDirective);
  1216. { Directive name or shorthand }
  1217. SkipWhiteSpace;
  1218. var C := CurChar;
  1219. if ConsumeCharIn(ISPPDirectiveShorthands) then begin
  1220. DoIncludeFileNotationCheck := C = '+'; { We need to check the include file notation }
  1221. NeedIspp := True;
  1222. FinishDirectiveNameOrShorthand(True); { All shorthands require a parameter }
  1223. end else begin
  1224. var S := ConsumeString(ISPPIdentChars);
  1225. for var ISPPDirective in ISPPDirectives do
  1226. if SameRawText(S, ISPPDirective.Name) then begin
  1227. if SameRawText(S, 'error') then
  1228. ErrorDirective := True
  1229. else if SameRawText(S, 'include') then
  1230. DoIncludeFileNotationCheck := True { See above }
  1231. else
  1232. NeedIspp := True; { Built-in preprocessor only supports '#include' }
  1233. ForDirectiveExpressionsNext := SameRawText(S, 'for'); { #for uses ';' as an expressions list separator so we need to remember that ';' doesn't start a comment until the list is done }
  1234. Inc(OpenCount, ISPPDirective.OpenCountChange);
  1235. if OpenCount < 0 then begin
  1236. CommitStyleSq(stCompilerDirective, True);
  1237. OpenCount := 0; { Reset so that next doesn't automatically gets error as well }
  1238. end;
  1239. FinishDirectiveNameOrShorthand(ISPPDirective.RequiresParameter);
  1240. Break;
  1241. end;
  1242. if InlineDirective then
  1243. CommitStyle(stDefault) { #emit shorthand was used (='#' directly followed by an expression): not an error }
  1244. else
  1245. CommitStyleSqPending(stCompilerDirective);
  1246. end;
  1247. { Rest of the directive }
  1248. if ErrorDirective then begin
  1249. SkipWhitespace;
  1250. while not EndOfDirective do begin
  1251. C := CurChar;
  1252. ConsumeChar(C);
  1253. if InlineDirective and (C = '}') then
  1254. CommitStyle(stCompilerDirective)
  1255. else
  1256. CommitStyle(stISPPString);
  1257. end;
  1258. end else begin
  1259. SkipWhitespace;
  1260. while not EndOfDirective do begin
  1261. if DoIncludeFileNotationCheck then begin
  1262. if CurChar <> '"' then begin
  1263. NeedIspp := True; { Built-in preprocessor requires a '"' quoted string after the '#include' and doesn't support anything else }
  1264. if CurChar = '<' then { Check for ISPP's special bracket notation for include files }
  1265. ConsumeISPPString('>', False); { Consume now instead of using regular consumption }
  1266. end;
  1267. DoIncludeFileNotationCheck := False;
  1268. end;
  1269. if CurChar in ISPPIdentFirstChars then begin
  1270. var S := ConsumeString(ISPPIdentChars);
  1271. for var ISPPReservedWord in ISPPReservedWords do
  1272. if SameRawText(S, ISPPReservedWord) then begin
  1273. CommitStyle(stISPPReservedWord);
  1274. Break;
  1275. end;
  1276. CommitStyle(stDefault)
  1277. end else if ConsumeChars(DigitChars) then begin
  1278. if not CurCharIs('.') or not NextCharIs('.') then begin
  1279. if ConsumeChar('.') then
  1280. ConsumeChars(DigitChars);
  1281. C := CurChar;
  1282. if C in ['X', 'x'] then begin
  1283. ConsumeChar(C);
  1284. if not ConsumeChars(HexDigitChars) then
  1285. CommitStyleSqPending(stISPPNumber);
  1286. end;
  1287. ConsumeChars(['L', 'U', 'l', 'u']);
  1288. end;
  1289. CommitStyle(stISPPNumber);
  1290. end else begin
  1291. C := CurChar;
  1292. ConsumeChar(C);
  1293. case C of
  1294. '!', '&', '=', '|', '^', '>', '<', '+', '-', '/', '%', '*',
  1295. '?', ':', ',', '.', '~', '(', '[', '{', ')', ']', '}', '@',
  1296. '#':
  1297. begin
  1298. if (C = '}') and ForDirectiveExpressionsNext then
  1299. ForDirectiveExpressionsNext := False;
  1300. if (C = '/') and ConsumeChar('*') then
  1301. FinishConsumingStarComment
  1302. else if InlineDirective and (C = '}') then
  1303. CommitStyle(stCompilerDirective) (* Closing '}' of the ISPP inline directive *)
  1304. else
  1305. CommitStyle(stSymbol);
  1306. end;
  1307. ';':
  1308. begin
  1309. if ForDirectiveExpressionsNext then
  1310. CommitStyle(stSymbol)
  1311. else begin
  1312. if not InlineDirective then
  1313. ConsumeAllRemaining
  1314. else
  1315. ConsumeCharsNot(['}']);
  1316. CommitStyle(stComment);
  1317. end;
  1318. end;
  1319. '''', '"':
  1320. ConsumeISPPString(C, True);
  1321. else
  1322. { Illegal character }
  1323. CommitStyleSq(stSymbol, True);
  1324. end;
  1325. end;
  1326. SkipWhitespace;
  1327. end;
  1328. end;
  1329. if NeedIspp and not ISPPInstalled then begin
  1330. if InlineDirective then
  1331. ApplyPendingSquigglyFromToIndex(StartIndex + 1, InlineDirectiveEndIndex - 1)
  1332. else
  1333. ApplyPendingSquigglyFromIndex(StartIndex + 1);
  1334. end;
  1335. end;
  1336. procedure TInnoSetupStyler.HandleParameterSection(
  1337. const ValidParameters: array of TScintRawString);
  1338. var
  1339. ParamsSpecified: set of 0..31;
  1340. S: TScintRawString;
  1341. I, ParamValueIndex, BraceLevel: Integer;
  1342. NamePresent, ValidName, DuplicateName, ColonPresent: Boolean;
  1343. begin
  1344. ParamsSpecified := [];
  1345. while not EndOfLine do begin
  1346. { Squigglify any bogus characters before the parameter name }
  1347. SquigglifyUntilChars(AlphaChars + [':'], stDefault);
  1348. { Parameter name }
  1349. S := ConsumeString(AlphaDigitChars);
  1350. NamePresent := (S <> '');
  1351. ValidName := False;
  1352. DuplicateName := False;
  1353. for I := Low(ValidParameters) to High(ValidParameters) do
  1354. if SameRawText(S, ValidParameters[I]) then begin
  1355. ValidName := True;
  1356. DuplicateName := (I in ParamsSpecified);
  1357. Include(ParamsSpecified, I);
  1358. Break;
  1359. end;
  1360. if DuplicateName then
  1361. CommitStyleSqPending(stKeyword)
  1362. else if ValidName then
  1363. CommitStyle(stKeyword)
  1364. else
  1365. CommitStyleSqPending(stDefault);
  1366. SkipWhitespace;
  1367. { If there's a semicolon with no colon, squigglify the semicolon }
  1368. if ConsumeChar(';') then begin
  1369. CommitStyleSq(stSymbol, True);
  1370. SkipWhitespace;
  1371. Continue;
  1372. end;
  1373. { Colon }
  1374. ColonPresent := ConsumeChar(':');
  1375. CommitStyleSq(stSymbol, not NamePresent);
  1376. SkipWhitespace;
  1377. { Parameter value. This consumes until a ';' is found or EOL is reached. }
  1378. ParamValueIndex := CurIndex;
  1379. BraceLevel := 0;
  1380. if ConsumeChar('"') then begin
  1381. while True do begin
  1382. StyleConstsUntilChars(['"'], stParameterValue, BraceLevel);
  1383. { If no closing quote exists, squigglify the whole value and break }
  1384. if not ConsumeChar('"') then begin
  1385. ApplyPendingSquigglyFromIndex(ParamValueIndex);
  1386. Break;
  1387. end;
  1388. { Quote found, now break, unless there are two quotes in a row }
  1389. if not ConsumeChar('"') then
  1390. Break;
  1391. end;
  1392. end else begin
  1393. while True do begin
  1394. StyleConstsUntilChars([';', '"'], stParameterValue, BraceLevel);
  1395. { Squigglify any quote characters inside an unquoted string }
  1396. if ConsumeChar('"') then
  1397. ApplySquigglyFromIndex(CurIndex - 1)
  1398. else
  1399. Break;
  1400. end;
  1401. end;
  1402. CommitStyle(stParameterValue);
  1403. if not ColonPresent then
  1404. ApplySquigglyFromIndex(ParamValueIndex);
  1405. { Squigglify any characters between a quoted string and the next ';' }
  1406. SquigglifyUntilChars([';'], stDefault);
  1407. { Semicolon }
  1408. ConsumeChar(';');
  1409. CommitStyle(stSymbol);
  1410. SkipWhitespace;
  1411. end;
  1412. end;
  1413. procedure TInnoSetupStyler.HandleKeyValueSection(const Section: TInnoSetupStylerSection);
  1414. procedure StyleMessageArgs;
  1415. begin
  1416. while True do begin
  1417. ConsumeCharsNot(['%']);
  1418. CommitStyle(stDefault);
  1419. if not ConsumeChar('%') then
  1420. Break;
  1421. if CurCharIn(['1'..'9', '%', 'n']) then begin
  1422. ConsumeChar(CurChar);
  1423. CommitStyle(stMessageArg);
  1424. end;
  1425. end;
  1426. end;
  1427. var
  1428. S: String;
  1429. I, BraceLevel: Integer;
  1430. begin
  1431. { Squigglify any bogus characters at the start of the line }
  1432. SquigglifyUntilChars(AlphaUnderscoreChars, stDefault);
  1433. if EndOfLine then
  1434. Exit;
  1435. S := String(ConsumeString(AlphaDigitUnderscoreChars));
  1436. { Was that a language name? }
  1437. if (Section in [scCustomMessages, scLangOptions, scMessages]) and
  1438. CurCharIs('.') then begin
  1439. CommitStyle(stDefault);
  1440. ConsumeChar('.');
  1441. CommitStyle(stSymbol);
  1442. { Squigglify any spaces or bogus characters between the '.' and key name }
  1443. if ConsumeCharsNot(AlphaUnderscoreChars) then
  1444. CommitStyleSq(stDefault, True);
  1445. S := String(ConsumeString(AlphaDigitUnderscoreChars));
  1446. end;
  1447. case Section of
  1448. scCustomMessages:
  1449. I := 0;
  1450. scLangOptions:
  1451. I := GetEnumValue(TypeInfo(TLangOptionsSectionDirective), 'ls' + S);
  1452. scMessages:
  1453. I := GetEnumValue(TypeInfo(TSetupMessageID), 'msg' + S);
  1454. scSetup:
  1455. I := GetEnumValue(TypeInfo(TSetupSectionDirective), 'ss' + S);
  1456. else
  1457. I := -1;
  1458. end;
  1459. if I <> -1 then
  1460. CommitStyle(stKeyword)
  1461. else begin
  1462. if Section in [scLangOptions, scMessages, scSetup] then
  1463. CommitStyleSqPending(stDefault)
  1464. else
  1465. CommitStyle(stDefault);
  1466. end;
  1467. SquigglifyUntilChars(['='], stDefault);
  1468. ConsumeChar('=');
  1469. CommitStyle(stSymbol);
  1470. SkipWhitespace;
  1471. if Section in [scCustomMessages, scMessages] then
  1472. StyleMessageArgs
  1473. else begin
  1474. BraceLevel := 0;
  1475. StyleConstsUntilChars([], stDefault, BraceLevel);
  1476. CommitStyle(stDefault);
  1477. end;
  1478. end;
  1479. class function TInnoSetupStyler.IsCommentOrKeywordStyle(const Style: TScintStyleNumber): Boolean;
  1480. begin
  1481. Result := Style in [Ord(stComment), Ord(stKeyword)];
  1482. end;
  1483. class function TInnoSetupStyler.IsCommentOrPascalStringStyle(const Style: TScintStyleNumber): Boolean;
  1484. begin
  1485. Result := Style in [Ord(stComment), Ord(stPascalString)];
  1486. end;
  1487. class function TInnoSetupStyler.IsParamSection(
  1488. const Section: TInnoSetupStylerSection): Boolean;
  1489. begin
  1490. Result := not (Section in [scCustomMessages, scLangOptions, scMessages, scSetup, scCode, scCodeBlock]);
  1491. end;
  1492. class function TInnoSetupStyler.IsSymbolStyle(const Style: TScintStyleNumber): Boolean;
  1493. begin
  1494. Result := Style = Ord(stSymbol);
  1495. end;
  1496. function TInnoSetupStyler.LineTextSpans(const S: TScintRawString): Boolean;
  1497. var
  1498. I: Integer;
  1499. begin
  1500. { Note: To match ISPP behavior, require length of at least 3 }
  1501. I := Length(S);
  1502. Result := (I > 2) and (S[I] = '\') and (S[I-1] in WhitespaceChars);
  1503. end;
  1504. procedure TInnoSetupStyler.PreStyleInlineISPPDirectives;
  1505. function IsLineCommented: Boolean;
  1506. var
  1507. I: Integer;
  1508. begin
  1509. Result := False;
  1510. for I := 1 to TextLength do begin
  1511. { In ISPP, only ';' and '//' inhibit processing of inline directives }
  1512. if (Text[I] = ';') or
  1513. ((I < TextLength) and (Text[I] = '/') and (Text[I+1] = '/')) then begin
  1514. Result := True;
  1515. Break;
  1516. end;
  1517. if not(Text[I] in WhitespaceChars) then
  1518. Break;
  1519. end;
  1520. end;
  1521. const
  1522. LineEndChars = [#10, #13];
  1523. var
  1524. I, StartIndex: Integer;
  1525. Valid: Boolean;
  1526. Dummy: ShortInt;
  1527. begin
  1528. { Style span symbols, then replace them with spaces to prevent any further
  1529. processing }
  1530. for I := 3 to TextLength do begin
  1531. if ((I = TextLength) or (Text[I+1] in LineEndChars)) and
  1532. (Text[I] = '\') and (Text[I-1] in WhitespaceChars) and
  1533. not(Text[I-2] in LineEndChars) then begin
  1534. ReplaceText(I, I, ' ');
  1535. ApplyStyle(Ord(stSymbol), I, I);
  1536. if not ISPPInstalled then
  1537. ApplyStyleByteIndicators([inSquiggly], I, I);
  1538. end;
  1539. end;
  1540. { Style all '{#' ISPP inline directives before anything else }
  1541. if not IsLineCommented then begin
  1542. I := 1;
  1543. while I < TextLength do begin
  1544. if (Text[I] = '{') and (Text[I+1] = '#') then begin
  1545. StartIndex := I;
  1546. Valid := False;
  1547. while I <= TextLength do begin
  1548. Inc(I);
  1549. if Text[I-1] = '}' then begin
  1550. Valid := True;
  1551. Break;
  1552. end;
  1553. end;
  1554. ResetCurIndexTo(StartIndex);
  1555. try
  1556. HandleCompilerDirective(True, I - 1, Dummy);
  1557. finally
  1558. ResetCurIndexTo(0);
  1559. end;
  1560. if not Valid then
  1561. ApplyPendingSquigglyFromToIndex(StartIndex, I - 1);
  1562. { Replace the directive with spaces to prevent any further processing }
  1563. ReplaceText(StartIndex, I - 1, ' ');
  1564. end else
  1565. Inc(I);
  1566. end;
  1567. end;
  1568. end;
  1569. function TInnoSetupStyler.SectionHasFlag(const Section: TInnoSetupStylerSection;
  1570. const Flag: String): Boolean;
  1571. begin
  1572. Result := FFlagsWords[Section].IndexOf(Flag) <> -1;
  1573. end;
  1574. function TInnoSetupStyler.HighlightAtCursorAllowed(const Section: TInnoSetupStylerSection;
  1575. const Word: string): Boolean;
  1576. begin
  1577. Result := FNoHighlightAtCursorWords[Section].IndexOf(Word) = -1;
  1578. end;
  1579. procedure TInnoSetupStyler.SetISPPInstalled(const Value: Boolean);
  1580. begin
  1581. if Value <> FISPPInstalled then begin
  1582. FISPPInstalled := Value;
  1583. BuildConstantsWordList;
  1584. end;
  1585. end;
  1586. procedure TInnoSetupStyler.SkipWhitespace;
  1587. begin
  1588. ConsumeChars(WhitespaceChars);
  1589. CommitStyle(stDefault);
  1590. end;
  1591. procedure TInnoSetupStyler.SquigglifyUntilChars(const Chars: TScintRawCharSet;
  1592. const Style: TInnoSetupStylerStyle);
  1593. var
  1594. IsWhitespace: Boolean;
  1595. begin
  1596. { Consume and squigglify all non-whitespace characters until one of Chars
  1597. is encountered }
  1598. while not EndOfLine and not CurCharIn(Chars) do begin
  1599. IsWhitespace := CurCharIn(WhitespaceChars);
  1600. ConsumeChar(CurChar);
  1601. if IsWhitespace then
  1602. CommitStyle(stDefault)
  1603. else
  1604. CommitStyleSq(Style, True);
  1605. end;
  1606. CommitStyle(stDefault);
  1607. end;
  1608. procedure TInnoSetupStyler.StyleConstsUntilChars(const Chars: TScintRawCharSet;
  1609. const NonConstStyle: TInnoSetupStylerStyle; var BraceLevel: Integer);
  1610. var
  1611. C: AnsiChar;
  1612. begin
  1613. while not EndOfLine and not CurCharIn(Chars) do begin
  1614. if BraceLevel = 0 then
  1615. CommitStyle(NonConstStyle);
  1616. C := CurChar;
  1617. ConsumeChar(C);
  1618. if C = '{' then begin
  1619. if not ConsumeChar('{') then
  1620. Inc(BraceLevel);
  1621. end;
  1622. if (C = '}') and (BraceLevel > 0) then begin
  1623. Dec(BraceLevel);
  1624. if BraceLevel = 0 then
  1625. CommitStyle(stConstant);
  1626. end;
  1627. end;
  1628. end;
  1629. procedure TInnoSetupStyler.StyleNeeded;
  1630. function MapSectionNameString(const S: TScintRawString): TInnoSetupStylerSection;
  1631. begin
  1632. if (S <> '') and (S[1] = '_') then
  1633. Result := scThirdParty
  1634. else begin
  1635. Result := scUnknown;
  1636. for var Section in SectionMap do
  1637. if SameRawText(S, Section.Name) then begin
  1638. Result := Section.Section;
  1639. Break;
  1640. end;
  1641. end;
  1642. end;
  1643. function CheckSectionEnd(const NewSection, Section: TInnoSetupStylerSection): Boolean;
  1644. begin
  1645. Result := (NewSection = Section) or ((NewSection = scCode) and (Section = scCodeBlock));
  1646. end;
  1647. begin
  1648. var NewLineState := TInnoSetupStylerLineState(LineState);
  1649. if NewLineState.NextLineSection <> scNone then begin
  1650. { Previous line started a section }
  1651. NewLineState.Section := NewLineState.NextLineSection;
  1652. NewLineState.NextLineSection := scNone;
  1653. end;
  1654. var Section := NewLineState.Section;
  1655. PreStyleInlineISPPDirectives;
  1656. const IsCodeSection = Section in [scCode, scCodeBlock];
  1657. SkipWhitespace;
  1658. if not IsCodeSection and ConsumeChar(';') then begin
  1659. ConsumeAllRemaining;
  1660. CommitStyle(stComment);
  1661. end else if CurCharIs('/') and NextCharIs('/') then begin
  1662. ConsumeAllRemaining;
  1663. CommitStyleSq(stComment, not ISPPInstalled and not IsCodeSection)
  1664. end else if ConsumeChar('[') then begin
  1665. const SectionEnd = ConsumeChar('/');
  1666. const S = ConsumeString(AlphaUnderscoreChars);
  1667. if ConsumeChar(']') then begin
  1668. const NewSection = MapSectionNameString(S);
  1669. { Unknown section names and erroneously-placed end tags get squigglified }
  1670. CommitStyleSq(stSection, (NewSection = scUnknown) or
  1671. (SectionEnd and not CheckSectionEnd(NewSection, Section)));
  1672. if not SectionEnd then
  1673. NewLineState.NextLineSection := NewSection;
  1674. end else
  1675. CommitStyleSqPending(stDefault);
  1676. { Section tags themselves are not associated with any section }
  1677. Section := scNone;
  1678. SquigglifyUntilChars([], stDefault);
  1679. end else if CurCharIs('#') then
  1680. HandleCompilerDirective(False, -1, NewLineState.OpenCompilerDirectivesCount)
  1681. else if IsCodeSection then begin
  1682. var CodeBlockHeader := False;
  1683. HandleCodeSection(NewLineState.SpanState, CodeBlockHeader);
  1684. if CodeBlockHeader then begin
  1685. Section := scCode;
  1686. NewLineState.NextLineSection := scCodeBlock;
  1687. end;
  1688. end else begin
  1689. case Section of
  1690. scUnknown: ;
  1691. scThirdParty: ;
  1692. scComponents: HandleParameterSection(ComponentsSectionParameters);
  1693. scCustomMessages: HandleKeyValueSection(Section);
  1694. scDirs: HandleParameterSection(DirsSectionParameters);
  1695. scISSigKeys: HandleParameterSection(ISSigKeysSectionParameters);
  1696. scFiles: HandleParameterSection(FilesSectionParameters);
  1697. scIcons: HandleParameterSection(IconsSectionParameters);
  1698. scINI: HandleParameterSection(INISectionParameters);
  1699. scInstallDelete: HandleParameterSection(DeleteSectionParameters);
  1700. scLangOptions: HandleKeyValueSection(Section);
  1701. scLanguages: HandleParameterSection(LanguagesSectionParameters);
  1702. scMessages: HandleKeyValueSection(Section);
  1703. scRegistry: HandleParameterSection(RegistrySectionParameters);
  1704. scRun: HandleParameterSection(RunSectionParameters);
  1705. scSetup: HandleKeyValueSection(Section);
  1706. scTasks: HandleParameterSection(TasksSectionParameters);
  1707. scTypes: HandleParameterSection(TypesSectionParameters);
  1708. scUninstallDelete: HandleParameterSection(DeleteSectionParameters);
  1709. scUninstallRun: HandleParameterSection(UninstallRunSectionParameters);
  1710. end;
  1711. end;
  1712. NewLineState.Section := Section;
  1713. LineState := TScintLineState(NewLineState);
  1714. end;
  1715. function SMI(const Name: TScintRawString; const Section: TInnoSetupStylerSection): TSectionMapItem;
  1716. begin
  1717. Result.Name := Name;
  1718. Result.Section := Section;
  1719. end;
  1720. function ISPPD(const Name: TScintRawString; const RequiresParameter: Boolean; const OpenCountChange: ShortInt): TISPPDirective;
  1721. begin
  1722. Result.Name := Name;
  1723. Result.RequiresParameter := RequiresParameter;
  1724. Result.OpenCountChange := OpenCountChange;
  1725. end;
  1726. function SSDV(const Directive: TSetupSectionDirective; const Values: TArray<TScintRawString>): TSetupSectionDirectiveValue;
  1727. begin
  1728. Result.Directive := Directive;
  1729. Result.Values := Values;
  1730. end;
  1731. type
  1732. TZipLevel = 1..9;
  1733. const
  1734. LZMALevels: TArray<TScintRawString> = ['fast', 'normal', 'max', 'ultra', 'ultra64'];
  1735. function GetCompressionValues: TArray<TScintRawString>;
  1736. procedure SetResult(var I: Integer; const S: TScintRawString);
  1737. begin
  1738. Result[I] := S;
  1739. Inc(I);
  1740. end;
  1741. const
  1742. ZipAlgos: TArray<TScintRawString> = ['zip', 'bzip'];
  1743. LZMAAlgos: TArray<TScintRawString> = ['lzma', 'lzma2'];
  1744. type
  1745. TZipLevels = 1..9;
  1746. begin
  1747. SetLength(Result, 1 +
  1748. Length(ZipAlgos) + Length(ZipAlgos) * (High(TZipLevel) - Low(TZipLevel) + 1) +
  1749. Length(LZMAAlgos) + Length(LZMAAlgos) * Length(LZMALevels));
  1750. var I := 0;
  1751. SetResult(I, 'none');
  1752. for var Algo in ZipAlgos do begin
  1753. SetResult(I, Algo);
  1754. for var Level := Low(TZipLevel) to High(TZipLevel) do
  1755. SetResult(I, TScintRawString(String(Algo) + '/' + Level.ToString));
  1756. end;
  1757. for var Algo in LZMAAlgos do begin
  1758. SetResult(I, Algo);
  1759. for var Level in LZMALevels do
  1760. SetResult(I, TScintRawString(Algo + '/' + Level));
  1761. end;
  1762. end;
  1763. initialization
  1764. SectionMap := [
  1765. SMI('Code', scCode),
  1766. SMI('Components', scComponents),
  1767. SMI('CustomMessages', scCustomMessages),
  1768. SMI('Dirs', scDirs),
  1769. SMI('ISSigKeys', scISSigKeys),
  1770. SMI('Files', scFiles),
  1771. SMI('Icons', scIcons),
  1772. SMI('INI', scINI),
  1773. SMI('InstallDelete', scInstallDelete),
  1774. SMI('LangOptions', scLangOptions),
  1775. SMI('Languages', scLanguages),
  1776. SMI('Messages', scMessages),
  1777. SMI('Registry', scRegistry),
  1778. SMI('Run', scRun),
  1779. SMI('Setup', scSetup),
  1780. SMI('Tasks', scTasks),
  1781. SMI('Types', scTypes),
  1782. SMI('UninstallDelete', scUninstallDelete),
  1783. SMI('UninstallRun', scUninstallRun)];
  1784. ISPPDirectives := [
  1785. ISPPD('preproc', True, 0),
  1786. ISPPD('define', True, 0),
  1787. ISPPD('dim', True, 0),
  1788. ISPPD('redim', True, 0),
  1789. ISPPD('undef', True, 0),
  1790. ISPPD('include', True, 0),
  1791. ISPPD('file', True, 0),
  1792. ISPPD('emit', True, 0),
  1793. ISPPD('expr', True, 0),
  1794. ISPPD('insert', True, 0),
  1795. ISPPD('append', False, 0),
  1796. ISPPD('if', True, 1),
  1797. ISPPD('elif', False { bug in ISPP? }, 0),
  1798. ISPPD('else', False, 0),
  1799. ISPPD('endif', False, -1),
  1800. ISPPD('ifdef', True, 1),
  1801. ISPPD('ifndef', True, 1),
  1802. ISPPD('ifexist', True, 1),
  1803. ISPPD('ifnexist', True, 1),
  1804. ISPPD('for', True, 0),
  1805. ISPPD('sub', True, 1),
  1806. ISPPD('endsub', False, -1),
  1807. ISPPD('pragma', False, 0),
  1808. ISPPD('error', False, 0)];
  1809. SetLength(PascalRealEnumValues, 6);
  1810. PascalRealEnumValues[0] := TypeInfo(TMsgBoxType);
  1811. PascalRealEnumValues[1] := TypeInfo(TSetupMessageID);
  1812. PascalRealEnumValues[2] := TypeInfo(TSetupStep);
  1813. PascalRealEnumValues[3] := TypeInfo(TUninstallStep);
  1814. PascalRealEnumValues[4] := TypeInfo(TSetupProcessorArchitecture);
  1815. PascalRealEnumValues[5] := TypeInfo(TDotNetVersion);
  1816. const ArchitecturesExpressionValues: TArray<TScintRawString> = [
  1817. 'not', 'and', 'or',
  1818. 'arm32compatible', 'arm64', 'win64',
  1819. 'x64', 'x64os', 'x64compatible',
  1820. 'x86', 'x86os', 'x86compatible'];
  1821. SetupSectionDirectivesValues := [
  1822. SSDV(ssArchitecturesAllowed, ArchitecturesExpressionValues),
  1823. SSDV(ssArchitecturesInstallIn64BitMode, ArchitecturesExpressionValues),
  1824. SSDV(ssArchiveExtraction, ['enhanced/nopassword', 'enhanced', 'full', 'basic']),
  1825. SSDV(ssCloseApplications, ['force', SYes, SNo]),
  1826. SSDV(ssCompression, GetCompressionValues),
  1827. SSDV(ssDisablePrecompiledFileVerifications, ['setup', 'setupcustomstyle', 'setupldr', 'is7z', 'isbunzip', 'isunzlib', 'islzma']),
  1828. SSDV(ssEncryption, ['full', SYes, SNo]),
  1829. SSDV(ssInternalCompressLevel, ['none'] + LZMALevels), { We don't list 0 }
  1830. SSDV(ssLanguageDetectionMethod, ['uilanguage', 'locale', 'none']),
  1831. SSDV(ssLZMAAlgorithm, ['0', '1']),
  1832. SSDV(ssLZMAMatchFinder, ['BT', 'HC']),
  1833. SSDV(ssLZMAUseSeparateProcess, ['x86', SYes, SNo]),
  1834. SSDV(ssPrivilegesRequired, ['admin', 'lowest']), { We don't list none/poweruser }
  1835. SSDV(ssPrivilegesRequiredOverridesAllowed, ['commandline', 'dialog']),
  1836. SSDV(ssUninstallLogMode, ['append', 'new', 'override']),
  1837. SSDV(ssUseSetupLdr, ['x86', 'x64', SYes, SNo]),
  1838. SSDV(ssWizardImageAlphaFormat, ['none', 'defined', 'premultiplied']),
  1839. SSDV(ssWizardStyle, ['classic', 'modern', 'light', 'dark', 'dynamic', 'excludelightbuttons', 'excludelightcontrols', 'includetitlebar', 'hidebevels', 'polar', 'slate', 'windows11', 'zircon'])];
  1840. end.