IDE.ScintStylerInnoSetup.pas 78 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016
  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; static;
  145. class function IsCommentOrKeywordStyle(const Style: TScintStyleNumber): Boolean; static;
  146. class function IsCommentOrPascalStringStyle(const Style: TScintStyleNumber): Boolean; static;
  147. class function IsParamSection(const Section: TInnoSetupStylerSection): Boolean; static;
  148. class function IsSymbolStyle(const Style: TScintStyleNumber): Boolean; static;
  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 - should not include ScriptClasses constants, see below }
  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', 'safecall',
  403. 'setuponly', 'uninstallonly', 'event'
  404. ];
  405. PascalTypes: array of AnsiString = [
  406. { ROPS - should not include ScriptClasses types, see below }
  407. 'Byte', 'Boolean', 'LongBool', 'WordBool', 'ByteBool', 'AnsiChar', 'Char',
  408. 'WideChar', 'WideString', 'UnicodeString', 'AnsiString', 'String', 'ShortInt',
  409. 'Word', 'SmallInt', 'LongInt', 'LongWord', 'Integer', 'Cardinal', 'Int64', 'UInt64',
  410. 'Single', 'Double', 'Extended', 'Currency', 'PAnsiChar', 'Variant',
  411. 'TVariantArray', 'NativeInt', 'NativeUInt',
  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', 'INT_PTR', 'DWORD_PTR', 'UINT_PTR', 'LRESULT', 'HMODULE', 'WPARAM', 'LPARAM',
  421. 'TFileTime', 'TSplitType', 'TExecWait', 'TExecOutput', 'TFindRec', 'TWindowsVersion',
  422. 'TOnDownloadProgress', 'TOnExtractionProgress', 'TOnLog',
  423. { ScriptClasses: see PascalTypes_Isxclasses in isxclasses_wordlists_generated +
  424. also the following from USPC_comobj.pas }
  425. 'HResult', 'TGUID', 'TCLSID', 'TIID'
  426. ];
  427. PascalEnumValues: array of AnsiString = [
  428. { ScriptFunc's values of non real enums - also see PascalTypes above }
  429. 'stAll', 'stExcludeEmpty', 'stExcludeLastEmpty',
  430. 'ewNoWait', 'ewWaitUntilTerminated', 'ewWaitUntilIdle'
  431. { ScriptClasses: see PascalEnumValues_Isxclasses in isxclasses_wordlists_generated }
  432. ];
  433. var
  434. PascalRealEnumValues: array of PTypeInfo; { Initialized below }
  435. const
  436. PascalVariables: array of AnsiString = [
  437. { ROPS }
  438. 'Result',
  439. { ScriptClasses }
  440. 'WizardForm', 'MainForm', 'UninstallProgressForm'
  441. ];
  442. BasicEventFunctions: array of TScintRawString = [
  443. 'InitializeSetup', 'InitializeWizard', 'DeinitializeSetup', 'CurStepChanged',
  444. 'CurInstallProgressChanged', 'NextButtonClick', 'BackButtonClick',
  445. 'CancelButtonClick', 'ShouldSkipPage', 'CurPageChanged', 'CheckPassword',
  446. 'NeedRestart', 'UpdateReadyMemo', 'RegisterPreviousData', 'CheckSerial',
  447. 'GetCustomSetupExitCode', 'PrepareToInstall',
  448. 'RegisterExtraCloseApplicationsResources', 'InitializeUninstall',
  449. 'InitializeUninstallProgressForm', 'DeinitializeUninstall',
  450. 'CurUninstallStepChanged', 'UninstallNeedRestart'
  451. ];
  452. FullEventFunctions: array of AnsiString = [
  453. 'function InitializeSetup: Boolean;',
  454. 'procedure InitializeWizard;',
  455. 'procedure DeinitializeSetup;',
  456. 'procedure CurStepChanged(CurStep: TSetupStep);',
  457. 'procedure CurInstallProgressChanged(CurProgress, MaxProgress: Integer);',
  458. 'function NextButtonClick(CurPageID: Integer): Boolean;',
  459. 'function BackButtonClick(CurPageID: Integer): Boolean;',
  460. 'procedure CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean);',
  461. 'function ShouldSkipPage(PageID: Integer): Boolean;',
  462. 'procedure CurPageChanged(CurPageID: Integer);',
  463. 'function CheckPassword(Password: String): Boolean;',
  464. 'function NeedRestart: Boolean;',
  465. 'function UpdateReadyMemo(Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo, MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo: String): String;',
  466. 'procedure RegisterPreviousData(PreviousDataKey: Integer);',
  467. 'function CheckSerial(Serial: String): Boolean;',
  468. 'function GetCustomSetupExitCode: Integer;',
  469. 'function PrepareToInstall(var NeedsRestart: Boolean): String;',
  470. 'procedure RegisterExtraCloseApplicationsResources;',
  471. 'function InitializeUninstall: Boolean;',
  472. 'procedure InitializeUninstallProgressForm;',
  473. 'procedure DeinitializeUninstall;',
  474. 'procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);',
  475. 'function UninstallNeedRestart: Boolean;'
  476. ];
  477. EventFunctionsParameters: array of AnsiString = [
  478. 'CurStep', 'CurProgress', 'MaxProgress', 'CurPageID', 'Cancel', 'Confirm',
  479. 'PageID', 'Password', 'Space', 'NewLine', 'MemoUserInfoInfo',
  480. 'MemoDirInfo', 'MemoTypeInfo', 'MemoComponentsInfo', 'MemoGroupInfo',
  481. 'MemoTasksInfo', 'PreviousDataKey', 'Serial', 'NeedsRestart',
  482. 'CurUninstallStep'
  483. ];
  484. SetupSectionDirectivesYesNo = [
  485. ssAllowCancelDuringInstall, ssAllowNetworkDrive, ssAllowNoIcons, ssAllowRootDirectory,
  486. ssAllowUNCPath, ssAlwaysRestart, ssAlwaysShowComponentsList, ssAlwaysShowDirOnReadyPage,
  487. ssAlwaysShowGroupOnReadyPage, ssAlwaysUsePersonalGroup, ssAppendDefaultDirName,
  488. ssAppendDefaultGroupName, ssASLRCompatible, ssCreateAppDir, ssDEPCompatible,
  489. ssDisableFinishedPage, ssDisableReadyMemo, ssDisableReadyPage, ssDisableStartupPrompt,
  490. ssDisableWelcomePage, ssDiskSpanning, ssDontMergeDuplicateFiles, ssEnableDirDoesntExistWarning,
  491. ssFlatComponentsList, ssMergeDuplicateFiles, ssMissingMessagesWarning,
  492. ssMissingRunOnceIdsWarning, ssNotRecognizedMessagesWarning, ssOutput, ssRedirectionGuard,
  493. ssRestartApplications, ssRestartIfNeededByRun, ssSetupLogging, ssShowComponentSizes,
  494. ssShowTasksTreeLines, ssSignedUninstaller, ssSignToolRunMinimized, ssSolidCompression,
  495. ssTerminalServicesAware, ssTimeStampsInUTC, ssUpdateUninstallLogAppName, ssUninstallLogging,
  496. ssUninstallRestartComputer, ssUsedUserAreasWarning, ssUsePreviousLanguage, ssUsePreviousPrivileges,
  497. ssUserInfoPage, ssWizardImageStretch, ssWizardKeepAspectRatio];
  498. SetupSectionDirectivesYesNoOrScripted = [ssChangesAssociations, ssChangesEnvironment,
  499. ssCreateUninstallRegKey, ssUninstallable, ssUsePreviousAppDir, ssUsePreviousGroup,
  500. ssUsePreviousSetupType, ssUsePreviousTasks, ssUsePreviousUserInfo];
  501. SetupSectionDirectivesAutoYesNo = [
  502. ssDirExistsWarning, ssDisableDirPage, ssDisableProgramGroupPage, ssShowLanguageDialog];
  503. SYes = 'yes';
  504. SNo = 'no';
  505. SAuto = 'auto';
  506. type
  507. TSetupSectionDirectiveValue = record
  508. Directive: TSetupSectionDirective;
  509. Values: TArray<TScintRawString>;
  510. end;
  511. var
  512. SetupSectionDirectivesValues: array of TSetupSectionDirectiveValue; { Initialized below }
  513. const
  514. inSquiggly = 0;
  515. inPendingSquiggly = 1;
  516. AllChars = [#0..#255];
  517. WhitespaceChars = [#0..' '];
  518. AlphaChars = ['A'..'Z', 'a'..'z'];
  519. DigitChars = ['0'..'9'];
  520. HexDigitChars = DigitChars + ['A'..'F', 'a'..'f'];
  521. AlphaUnderscoreChars = AlphaChars + ['_'];
  522. AlphaDigitChars = AlphaChars + DigitChars;
  523. AlphaDigitUnderscoreChars = AlphaChars + DigitChars + ['_'];
  524. PascalIdentFirstChars = AlphaUnderscoreChars;
  525. PascalIdentChars = AlphaDigitUnderscoreChars;
  526. ISPPIdentFirstChars = AlphaUnderscoreChars;
  527. ISPPIdentChars = AlphaDigitUnderscoreChars;
  528. function SameRawText(const S1, S2: TScintRawString): Boolean;
  529. var
  530. Len, I: Integer;
  531. C1, C2: AnsiChar;
  532. begin
  533. Len := Length(S1);
  534. if Length(S2) <> Len then begin
  535. Result := False;
  536. Exit;
  537. end;
  538. for I := 1 to Len do begin
  539. C1 := S1[I];
  540. C2 := S2[I];
  541. if C1 in ['A'..'Z'] then
  542. Inc(C1, 32);
  543. if C2 in ['A'..'Z'] then
  544. Inc(C2, 32);
  545. if C1 <> C2 then begin
  546. Result := False;
  547. Exit;
  548. end;
  549. end;
  550. Result := True;
  551. end;
  552. { TFunctionDefinition }
  553. constructor TFunctionDefinition.Create(const ScriptFunc: AnsiString);
  554. begin
  555. ScriptFuncWithoutHeader := RemoveScriptFuncHeader(ScriptFunc, HeaderKind);
  556. HasParams := ScriptFuncHasParameters(ScriptFunc);
  557. end;
  558. { TInnoSetupStyler }
  559. constructor TInnoSetupStyler.Create(AOwner: TComponent);
  560. procedure BuildFlagsWordLists;
  561. begin
  562. { Builds FFlagsWordList (for autocomplete) and FFlagsWords }
  563. BuildFlagsWordList(scFiles, FilesSectionFlags);
  564. BuildFlagsWordList(scComponents, ComponentsSectionFlags);
  565. BuildFlagsWordList(scDirs, DirsSectionFlags);
  566. BuildFlagsWordList(scIcons, IconsSectionFlags);
  567. BuildFlagsWordList(scINI, INISectionFlags);
  568. BuildFlagsWordList(scRegistry, RegistrySectionFlags);
  569. BuildFlagsWordList(scRun, RunSectionFlags);
  570. BuildFlagsWordList(scTasks, TasksSectionFlags);
  571. BuildFlagsWordList(scTypes, TypesSectionFlags);
  572. BuildFlagsWordList(scUninstallRun, UninstallRunSectionFlags);
  573. { Bit of a trick }
  574. BuildFlagsWordList(scInstallDelete, DeleteSectionTypes);
  575. BuildFlagsWordList(scUninstallDelete, DeleteSectionTypes);
  576. end;
  577. procedure BuildKeywordsWordLists;
  578. begin
  579. { Builds FKeywordsWordList (for autocomplete) and FNoHighlightAtCursorWords }
  580. BuildKeywordsWordList(scISSigKeys, ISSigKeysSectionParameters);
  581. BuildKeywordsWordList(scFiles, FilesSectionParameters);
  582. BuildKeywordsWordList(scComponents, ComponentsSectionParameters);
  583. BuildKeywordsWordList(scDirs, DirsSectionParameters);
  584. BuildKeywordsWordList(scIcons, IconsSectionParameters);
  585. BuildKeywordsWordList(scINI, INISectionParameters);
  586. BuildKeywordsWordList(scInstallDelete, DeleteSectionParameters);
  587. BuildKeywordsWordListFromTypeInfo(scLangOptions, TypeInfo(TLangOptionsSectionDirective), LangOptionsSectionDirectivePrefixLength);
  588. BuildKeywordsWordList(scLanguages, LanguagesSectionParameters);
  589. BuildKeywordsWordList(scRegistry, RegistrySectionParameters);
  590. BuildKeywordsWordList(scRun, RunSectionParameters);
  591. BuildKeywordsWordListFromTypeInfo(scSetup, TypeInfo(TSetupSectionDirective), Length(SetupSectionDirectivePrefix));
  592. BuildKeywordsWordList(scTasks, TasksSectionParameters);
  593. BuildKeywordsWordList(scTypes, TypesSectionParameters);
  594. BuildKeywordsWordList(scUninstallDelete, DeleteSectionParameters);
  595. BuildKeywordsWordList(scUninstallRun, UninstallRunSectionParameters);
  596. BuildKeywordsWordListFromTypeInfo(scMessages, TypeInfo(TSetupMessageID), SetupMessageIDPrefixLength);
  597. end;
  598. procedure BuildScriptLists;
  599. begin
  600. { Builds FScriptFunctionsByName (for calltips) and FScriptWordList (for autocomplete)
  601. and FNoHighlightAtCursorWords }
  602. const SL1 = FNoHighlightAtCursorWords[scCode];
  603. const SL2 = TStringList.Create;
  604. try
  605. { Add stuff from ScriptFunc }
  606. var ClassMembers := False;
  607. for var ScriptFuncTable in ScriptFuncTables do
  608. BuildScriptFunctionsLists(ScriptFuncTable, ClassMembers, SL2);
  609. BuildScriptFunctionsLists(DelphiScriptFuncTable, ClassMembers, SL2);
  610. BuildScriptFunctionsLists(ROPSScriptFuncTable, ClassMembers, SL2);
  611. { Add stuff from this unit }
  612. for var S in PascalConstants do
  613. AddWordToList(SL2, S, awtScriptConstant);
  614. for var S in PascalConstants_Isxclasses do
  615. AddWordToList(SL2, S, awtScriptConstant);
  616. for var S in PascalInterfaces do
  617. AddWordToList(SL2, S, awtScriptInterface);
  618. for var S in PascalReservedWords do begin
  619. SL1.Add(String(S));
  620. AddWordToList(SL2, S, awtScriptKeyword);
  621. end;
  622. for var S in PascalTypes do
  623. AddWordToList(SL2, S, awtScriptType);
  624. for var S in PascalTypes_Isxclasses do
  625. AddWordToList(SL2, S, awtScriptType);
  626. for var S in PascalEnumValues do
  627. AddWordToList(SL2, S, awtScriptEnumValue);
  628. for var S in PascalEnumValues_Isxclasses do
  629. AddWordToList(SL2, S, awtScriptEnumValue);
  630. for var TypeInfo in PascalRealEnumValues do begin
  631. var TypeData := GetTypeData(TypeInfo);
  632. for var I := TypeData.MinValue to TypeData.MaxValue do
  633. AddWordToList(SL2, AnsiString(GetEnumName(TypeInfo, I)), awtScriptEnumValue);
  634. end;
  635. for var S in PascalVariables do
  636. AddWordToList(SL2, S, awtScriptVariable);
  637. for var S in EventFunctionsParameters do
  638. AddWordToList(SL2, S, awtScriptVariable);
  639. FScriptWordList[False] := BuildWordList(SL2);
  640. { Add stuff from Isxclasses }
  641. SL2.Clear;
  642. ClassMembers := True;
  643. BuildScriptFunctionsLists(PascalMembers_Isxclasses, ClassMembers, SL2);
  644. for var S in PascalProperties_Isxclasses do
  645. AddWordToList(SL2, S, awtScriptProperty);
  646. FScriptWordList[True] := BuildWordList(SL2);
  647. finally
  648. SL2.Free;
  649. end;
  650. end;
  651. procedure BuildSetupDirectiveValueWordLists;
  652. begin
  653. { Yes/no directives: we don't list true/false/1/0 }
  654. FSetupSectionDirectiveValueYesNoWordList := BuildWordList([SYes, SNo]);
  655. FSetupSectionDirectiveValueAutoYesNoWordList := BuildWordList([SAuto, SYes, SNo]);
  656. for var Item in SetupSectionDirectivesValues do
  657. FSetupSectionDirectiveValueWordList[Item.Directive] := BuildWordList(Item.Values);
  658. end;
  659. function CreateWordsBySectionList: TStringList;
  660. begin
  661. Result := TStringList.Create;
  662. Result.CaseSensitive := False;
  663. Result.Sorted := True;
  664. end;
  665. begin
  666. inherited;
  667. FNoHighlightAtCursorWords := TWordsBySection.Create([doOwnsValues]);
  668. FFlagsWords := TWordsBySection.Create([doOwnsValues]);
  669. for var Section := Low(TInnoSetupStylerSection) to High(TInnoSetupStylerSection) do begin
  670. FNoHighlightAtCursorWords.Add(Section, CreateWordsBySectionList);
  671. FFlagsWords.Add(Section, CreateWordsBySectionList);
  672. end;
  673. BuildConstantsWordList;
  674. BuildEventFunctionsWordList;
  675. BuildFlagsWordLists;
  676. BuildISPPDirectivesWordList;
  677. BuildKeywordsWordLists;
  678. BuildSectionsWordList;
  679. BuildSetupDirectiveValueWordLists;
  680. FScriptFunctionsByName[False] := TFunctionDefinitionsByName.Create(TIStringComparer.Ordinal);
  681. FScriptFunctionsByName[True] := TFunctionDefinitionsByName.Create(TIStringComparer.Ordinal);
  682. BuildScriptLists;
  683. end;
  684. destructor TInnoSetupStyler.Destroy;
  685. begin
  686. FScriptFunctionsByName[False].Free;
  687. FScriptFunctionsByName[True].Free;
  688. FFlagsWords.Free;
  689. FNoHighlightAtCursorWords.Free;
  690. inherited;
  691. end;
  692. procedure TInnoSetupStyler.AddWordToList(const SL: TStringList;
  693. const Word: AnsiString; const Typ: Integer);
  694. begin
  695. if Typ >= 0 then
  696. SL.Add(Format('%s%s%d', [Word, InnoSetupStylerWordListTypeSeparator, Typ]))
  697. else
  698. SL.Add(String(Word));
  699. end;
  700. procedure TInnoSetupStyler.ApplyPendingSquigglyFromToIndex(const StartIndex, EndIndex: Integer);
  701. begin
  702. if (CaretIndex >= StartIndex) and (CaretIndex <= EndIndex + 1) then
  703. ApplyStyleByteIndicators([inPendingSquiggly], StartIndex, EndIndex)
  704. else
  705. ApplyStyleByteIndicators([inSquiggly], StartIndex, EndIndex);
  706. end;
  707. procedure TInnoSetupStyler.ApplyPendingSquigglyFromIndex(const StartIndex: Integer);
  708. begin
  709. ApplyPendingSquigglyFromToIndex(StartIndex, CurIndex - 1);
  710. end;
  711. procedure TInnoSetupStyler.ApplySquigglyFromIndex(const StartIndex: Integer);
  712. begin
  713. ApplyStyleByteIndicators([inSquiggly], StartIndex, CurIndex - 1);
  714. end;
  715. function TInnoSetupStyler.BuildWordList(const Values: array of TScintRawString): AnsiString;
  716. begin
  717. const SL = TStringList.Create;
  718. try
  719. for var Value in Values do
  720. AddWordToList(SL, Value, awtFlagOrSetupDirectiveValue);
  721. Result := BuildWordList(SL);
  722. finally
  723. SL.Free;
  724. end;
  725. end;
  726. function TInnoSetupStyler.BuildWordList(const WordStringList: TStringList): AnsiString;
  727. begin
  728. { Scintilla uses an ASCII binary search so the list must be in ASCII sort
  729. order (case-insensitive). }
  730. WordStringList.CaseSensitive := False;
  731. WordStringList.UseLocale := False; { Make sure it uses CompareText and not AnsiCompareText }
  732. WordStringList.Sort;
  733. Result := '';
  734. for var S in WordStringList do begin
  735. var A := AnsiString(S);
  736. if Result = '' then
  737. Result := A
  738. else
  739. Result := Result + InnoSetupStylerWordListSeparator + A;
  740. end;
  741. end;
  742. procedure TInnoSetupStyler.BuildSectionsWordList;
  743. begin
  744. var SL := TStringList.Create;
  745. try
  746. for var Section in SectionMap do
  747. AddWordToList(SL, '[' + Section.Name + ']', awtSection);
  748. FSectionsWordList := BuildWordList(SL);
  749. finally
  750. SL.Free;
  751. end;
  752. end;
  753. procedure TInnoSetupStyler.BuildKeywordsWordList(
  754. const Section: TInnoSetupStylerSection;
  755. const Parameters: array of TScintRawString);
  756. begin
  757. const SL1 = FNoHighlightAtCursorWords[Section];
  758. const SL2 = TStringList.Create;
  759. try
  760. for var Parameter in Parameters do begin
  761. SL1.Add(String(Parameter));
  762. AddWordToList(SL2, Parameter, awtParameter);
  763. end;
  764. FKeywordsWordList[Section] := BuildWordList(SL2);
  765. finally
  766. SL2.Free;
  767. end;
  768. end;
  769. procedure TInnoSetupStyler.BuildKeywordsWordListFromTypeInfo(
  770. const Section: TInnoSetupStylerSection; const EnumTypeInfo: Pointer;
  771. const PrefixLength: Integer);
  772. begin
  773. const SL1 = FNoHighlightAtCursorWords[Section];
  774. const SL2 = TStringList.Create;
  775. try
  776. for var I := 0 to GetTypeData(EnumTypeInfo).MaxValue do begin
  777. const Parameter = Copy(GetEnumName(EnumTypeInfo, I), PrefixLength+1, MaxInt);
  778. SL1.Add(Parameter);
  779. AddWordToList(SL2, AnsiString(Parameter), awtDirective);
  780. end;
  781. FKeywordsWordList[Section] := BuildWordList(SL2);
  782. finally
  783. SL2.Free;
  784. end;
  785. end;
  786. procedure TInnoSetupStyler.BuildFlagsWordList(const Section: TInnoSetupStylerSection;
  787. const Flags: array of TScintRawString);
  788. begin
  789. const SL1 = FFlagsWords[Section];
  790. const SL2 = TStringList.Create;
  791. try
  792. for var Flag in Flags do begin
  793. SL1.Add(String(Flag));
  794. AddWordToList(SL2, Flag, awtFlagOrSetupDirectiveValue);
  795. end;
  796. FFlagsWordList[Section] := BuildWordList(SL2);
  797. finally
  798. SL2.Free;
  799. end;
  800. end;
  801. procedure TInnoSetupStyler.BuildScriptFunctionsLists(
  802. const ScriptFuncTable: TScriptTable; const ClassMembers: Boolean;
  803. const SL: TStringList);
  804. begin
  805. for var ScriptFunc in ScriptFuncTable do begin
  806. var FunctionDefinition := TFunctionDefinition.Create(ScriptFunc);
  807. var ScriptFuncName := ExtractScriptFuncWithoutHeaderName(FunctionDefinition.ScriptFuncWithoutHeader);
  808. var DoAddWordToList := True;
  809. var Key := String(ScriptFuncName);
  810. if not FScriptFunctionsByName[ClassMembers].TryAdd(Key, [FunctionDefinition]) then begin
  811. { Function has multiple prototypes }
  812. var ScriptFunctions := FScriptFunctionsByName[ClassMembers][Key];
  813. var N := Length(ScriptFunctions);
  814. SetLength(ScriptFunctions, N+1);
  815. ScriptFunctions[N] := FunctionDefinition;
  816. FScriptFunctionsByName[ClassMembers][Key] := ScriptFunctions;
  817. DoAddWordToList := False; { Already added it when the first prototype was found }
  818. end;
  819. if DoAddWordToList then
  820. AddWordToList(SL, ScriptFuncName, awtScriptFunction);
  821. end;
  822. end;
  823. procedure TInnoSetupStyler.BuildISPPDirectivesWordList;
  824. begin
  825. var SL := TStringList.Create;
  826. try
  827. for var ISPPDirective in ISPPDirectives do
  828. AddWordToList(SL, '#' + ISPPDirective.Name, awtPreprocessorDirective);
  829. FISPPDirectivesWordList := BuildWordList(SL);
  830. finally
  831. SL.Free;
  832. end;
  833. end;
  834. procedure TInnoSetupStyler.BuildConstantsWordList;
  835. begin
  836. var SL := TStringList.Create;
  837. try
  838. for var Constant in Constants do
  839. AddWordToList(SL, '{' + Constant + '}', awtConstant);
  840. if ISPPInstalled then begin
  841. AddWordToList(SL, '{#', awtConstant);
  842. AddWordToList(SL, '{#file ', awtConstant);
  843. for var ISPPPredefinedVariable in ISPPPredefinedVariables do
  844. AddWordToList(SL, '{#' + ISPPPredefinedVariable + '}', awtConstant);
  845. end;
  846. for var ConstantWithParam in ConstantsWithParam do
  847. AddWordToList(SL, '{' + ConstantWithParam, awtConstant);
  848. FConstantsWordList := BuildWordList(SL);
  849. finally
  850. SL.Free;
  851. end;
  852. end;
  853. procedure TInnoSetupStyler.BuildEventFunctionsWordList;
  854. begin
  855. var SLFunctions: TStringList := nil;
  856. var SLProcedures: TStringList := nil;
  857. try
  858. SLFunctions := TStringList.Create;
  859. SLProcedures := TStringList.Create;
  860. for var FullEventFunction in FullEventFunctions do begin
  861. var HeaderKind: TScriptFuncHeaderKind;
  862. var S := RemoveScriptFuncHeader(FullEventFunction, HeaderKind);
  863. if HeaderKind = hkFunction then
  864. AddWordToList(SLFunctions, S, awtScriptEvent)
  865. else if HeaderKind = hkProcedure then
  866. AddWordToList(SLProcedures, S, awtScriptEvent)
  867. else
  868. raise Exception.Create('Got invalid HeaderKind for event function');
  869. end;
  870. FEventFunctionsWordList[False] := BuildWordList(SLFunctions);
  871. FEventFunctionsWordList[True] := BuildWordList(SLProcedures);
  872. finally
  873. SLProcedures.Free;
  874. SLFunctions.Free;
  875. end;
  876. end;
  877. procedure TInnoSetupStyler.CommitStyle(const Style: TInnoSetupStylerStyle);
  878. begin
  879. inherited CommitStyle(TScintStyleNumber(Ord(Style)));
  880. end;
  881. procedure TInnoSetupStyler.CommitStyleSq(const Style: TInnoSetupStylerStyle;
  882. const Squigglify: Boolean);
  883. begin
  884. if Squigglify then
  885. ApplySquigglyFromIndex(StyleStartIndex);
  886. CommitStyle(Style);
  887. end;
  888. procedure TInnoSetupStyler.CommitStyleSqPending(const Style: TInnoSetupStylerStyle);
  889. begin
  890. ApplyPendingSquigglyFromIndex(StyleStartIndex);
  891. CommitStyle(Style);
  892. end;
  893. function TInnoSetupStyler.GetEventFunctionsWordList(Procedures: Boolean): AnsiString;
  894. begin
  895. Result := FEventFunctionsWordList[Procedures];
  896. end;
  897. function TInnoSetupStyler.GetFlagsWordList(Section: TInnoSetupStylerSection): AnsiString;
  898. begin
  899. Result := FFlagsWordList[Section];
  900. end;
  901. procedure TInnoSetupStyler.GetFoldLevel(const LineState, PreviousLineState: TScintLineState;
  902. var Level: Integer; var Header, EnableHeaderOnPrevious: Boolean);
  903. begin
  904. { Set folding per section. Lines outside of a section (=lines at the start of
  905. the document and section tags and section end tags and lines after section
  906. end tags) get level 0 with header flags for section tags. Other lines
  907. (=lines inside a section) get level 1. }
  908. var Section := TInnoSetupStyler.GetSectionFromLineState(LineState, False);
  909. if Section = scNone then begin
  910. Level := 0;
  911. Header := False; { Might be set to True via EnableHeaderOnPrevious below when we know about next line }
  912. EnableHeaderOnPrevious := False;
  913. end else begin
  914. Level := 1;
  915. Header := False;
  916. var PreviousSection := TInnoSetupStyler.GetSectionFromLineState(PreviousLineState, False);
  917. if Section = scCodeBlock then begin
  918. Inc(Level);
  919. EnableHeaderOnPrevious := PreviousSection = scCode;
  920. end else
  921. EnableHeaderOnPrevious := PreviousSection = scNone;
  922. end;
  923. end;
  924. function TInnoSetupStyler.GetKeywordsWordList(Section: TInnoSetupStylerSection): AnsiString;
  925. begin
  926. Result := FKeywordsWordList[Section];
  927. end;
  928. function TInnoSetupStyler.GetScriptFunctionDefinition(const ClassMember: Boolean;
  929. const Name: String; const Index: Integer; out Count: Integer): TFunctionDefinition;
  930. begin
  931. var ScriptFunctions: TFunctionDefinitions;
  932. if FScriptFunctionsByName[ClassMember].TryGetValue(Name, ScriptFunctions) then begin
  933. Count := Integer(Length(ScriptFunctions));
  934. var ResultIndex := Index;
  935. if ResultIndex >= Count then
  936. ResultIndex := Count-1;
  937. Result := ScriptFunctions[ResultIndex]
  938. end else
  939. Count := 0;
  940. end;
  941. function TInnoSetupStyler.GetScriptFunctionDefinition(
  942. const ClassMember: Boolean; const Name: String;
  943. const Index: Integer): TFunctionDefinition;
  944. begin
  945. var Count: Integer;
  946. Result := GetScriptFunctionDefinition(ClassMember, Name, Index, Count);
  947. end;
  948. function TInnoSetupStyler.GetScriptWordList(
  949. ClassOrRecordMembers: Boolean): AnsiString;
  950. begin
  951. Result := FScriptWordList[ClassOrRecordMembers];
  952. end;
  953. class function TInnoSetupStyler.GetSectionFromLineState(
  954. const LineState: TScintLineState; const ReturnCodeBlockAsCode: Boolean = True): TInnoSetupStylerSection;
  955. begin
  956. Result := TInnoSetupStylerLineState(LineState).Section;
  957. if ReturnCodeBlockAsCode and (Result = scCodeBlock) then
  958. Result := scCode;
  959. end;
  960. function TInnoSetupStyler.GetSetupSectionDirectiveValueIsMultiValue(
  961. SetupSectionDirective: TSetupSectionDirective): Boolean;
  962. { "MultiValue" means a directive like WizardStyle which accepts a space separated list of values }
  963. begin
  964. Result := SetupSectionDirective in [ssArchitecturesAllowed,
  965. ssArchitecturesInstallIn64BitMode, ssDisablePrecompiledFileVerifications,
  966. ssPrivilegesRequiredOverridesAllowed, ssWizardStyle];
  967. end;
  968. function TInnoSetupStyler.GetSetupSectionDirectiveValueWordList(
  969. SetupSectionDirective: TSetupSectionDirective): AnsiString;
  970. begin
  971. if SetupSectionDirective in SetupSectionDirectivesAutoYesNo then
  972. Result := FSetupSectionDirectiveValueAutoYesNoWordList
  973. else if (SetupSectionDirective in SetupSectionDirectivesYesNo) or
  974. (SetupSectionDirective in SetupSectionDirectivesYesNoOrScripted) then
  975. Result := FSetupSectionDirectiveValueYesNoWordList
  976. else
  977. Result := FSetupSectionDirectiveValueWordList[SetupSectionDirective];
  978. end;
  979. procedure TInnoSetupStyler.GetStyleAttributes(const Style: Integer;
  980. var Attributes: TScintStyleAttributes);
  981. begin
  982. if FTheme <> nil then begin
  983. if (Style >= 0) and (Style <= Ord(High(TInnoSetupStylerStyle))) then begin
  984. if not FTheme.Modern then begin
  985. { Check for some exceptions }
  986. case TInnoSetupStylerStyle(Style) of
  987. stCompilerDirective, stISPPReservedWord: begin Attributes.ForeColor := $4040C0; Exit; end;
  988. stMessageArg: begin Attributes.ForeColor := $FF8000; Exit; end;
  989. stPascalString, stPascalNumber, stISPPString, stISPPNumber: begin Attributes.ForeColor := clMaroon; Exit; end;
  990. end;
  991. end;
  992. case TInnoSetupStylerStyle(Style) of
  993. stCompilerDirective, stISPPReservedWord: Attributes.ForeColor := FTheme.Colors[tcRed];
  994. stComment: Attributes.ForeColor := FTheme.Colors[tcGreen];
  995. stSection: Attributes.FontStyle := [fsBold];
  996. stSymbol: Attributes.ForeColor := FTheme.Colors[tcGray];
  997. stKeyword, stPascalReservedWord: Attributes.ForeColor := FTheme.Colors[tcBlue];
  998. //stParameterValue: Attributes.ForeColor := FTheme.Colors[tcTeal];
  999. stEventFunction: Attributes.FontStyle := [fsBold];
  1000. stConstant: Attributes.ForeColor := FTheme.Colors[tcPurple];
  1001. stMessageArg: Attributes.ForeColor := FTheme.Colors[tcRed];
  1002. stPascalString, stPascalNumber, stISPPString, stISPPNumber: Attributes.ForeColor := FTheme.Colors[tcOrange];
  1003. end;
  1004. end else begin
  1005. case Style of
  1006. STYLE_LINENUMBER: { Also sets the background colour for the margin with the markers like mmIconBreakpoint }
  1007. begin
  1008. Attributes.ForeColor := FTheme.Colors[tcMarginFore];
  1009. Attributes.BackColor := FTheme.Colors[tcMarginBack];
  1010. end;
  1011. STYLE_BRACEBAD: Attributes.ForeColor := FTheme.Colors[tcRed];
  1012. STYLE_BRACELIGHT: Attributes.BackColor := FTheme.Colors[tcBraceBack];
  1013. STYLE_INDENTGUIDE: Attributes.ForeColor := FTheme.Colors[tcIndentGuideFore];
  1014. end;
  1015. end;
  1016. end;
  1017. end;
  1018. procedure TInnoSetupStyler.HandleCodeSection(var SpanState: TInnoSetupStylerSpanState; var CodeBlockHeader: Boolean);
  1019. function FinishConsumingBraceComment: Boolean;
  1020. begin
  1021. ConsumeCharsNot(['}']);
  1022. Result := ConsumeChar('}');
  1023. CommitStyle(stComment);
  1024. end;
  1025. function FinishConsumingStarComment: Boolean;
  1026. begin
  1027. Result := False;
  1028. while True do begin
  1029. ConsumeCharsNot(['*']);
  1030. if not ConsumeChar('*') then
  1031. Break;
  1032. if ConsumeChar(')') then begin
  1033. Result := True;
  1034. Break;
  1035. end;
  1036. end;
  1037. CommitStyle(stComment);
  1038. end;
  1039. begin
  1040. case SpanState of
  1041. spBraceComment:
  1042. if not FinishConsumingBraceComment then
  1043. Exit;
  1044. spStarComment:
  1045. if not FinishConsumingStarComment then
  1046. Exit;
  1047. end;
  1048. SpanState := spNone;
  1049. SkipWhitespace;
  1050. while not EndOfLine do begin
  1051. if CurChar in PascalIdentFirstChars then begin
  1052. var S := ConsumeString(PascalIdentChars);
  1053. for var Word in PascalReservedWords do
  1054. if SameRawText(S, Word) then begin
  1055. if SameRawText(S, 'function') or SameRawText(S, 'procedure') or SameRawText(S, 'type') then
  1056. CodeBlockHeader := True; { Global 'var' and 'const' blocks are currently not detected }
  1057. CommitStyle(stPascalReservedWord);
  1058. Break;
  1059. end;
  1060. for var EventFunction in BasicEventFunctions do
  1061. if SameRawText(S, EventFunction) then begin
  1062. CommitStyle(stEventFunction);
  1063. Break;
  1064. end;
  1065. CommitStyle(stDefault);
  1066. end else if ConsumeChars(DigitChars) then begin
  1067. if not CurCharIs('.') or not NextCharIs('.') then begin
  1068. if ConsumeChar('.') then
  1069. ConsumeChars(DigitChars);
  1070. var C := CurChar;
  1071. if C in ['E', 'e'] then begin
  1072. ConsumeChar(C);
  1073. if not ConsumeChar('-') then
  1074. ConsumeChar('+');
  1075. if not ConsumeChars(DigitChars) then
  1076. CommitStyleSqPending(stPascalNumber);
  1077. end;
  1078. end;
  1079. CommitStyle(stPascalNumber);
  1080. end else begin
  1081. var C := CurChar;
  1082. ConsumeChar(C);
  1083. case C of
  1084. ';', ':', '=', '+', '-', '*', '/', '<', '>', ',', '(', ')',
  1085. '.', '[', ']', '@', '^':
  1086. begin
  1087. if (C = '/') and ConsumeChar('/') then begin
  1088. ConsumeAllRemaining;
  1089. CommitStyle(stComment);
  1090. end else if (C = '(') and ConsumeChar('*') then begin
  1091. if not FinishConsumingStarComment then begin
  1092. SpanState := spStarComment;
  1093. Exit;
  1094. end;
  1095. end else
  1096. CommitStyle(stSymbol);
  1097. end;
  1098. '''':
  1099. begin
  1100. while True do begin
  1101. ConsumeCharsNot([C]);
  1102. if not ConsumeChar(C) then begin
  1103. CommitStyleSqPending(stPascalString);
  1104. Break;
  1105. end;
  1106. if not ConsumeChar(C) then begin
  1107. CommitStyle(stPascalString);
  1108. Break;
  1109. end;
  1110. end;
  1111. end;
  1112. '{':
  1113. begin
  1114. if not FinishConsumingBraceComment then begin
  1115. SpanState := spBraceComment;
  1116. Exit;
  1117. end;
  1118. end;
  1119. '$':
  1120. begin
  1121. if not ConsumeChars(HexDigitChars) then
  1122. CommitStyleSqPending(stPascalNumber);
  1123. CommitStyle(stPascalNumber);
  1124. end;
  1125. '#':
  1126. begin
  1127. if ConsumeChar('$') then begin
  1128. if not ConsumeChars(HexDigitChars) then
  1129. CommitStyleSqPending(stPascalString);
  1130. end else if not ConsumeChars(DigitChars) then
  1131. CommitStyleSqPending(stPascalString);
  1132. CommitStyle(stPascalString);
  1133. end;
  1134. else
  1135. { Illegal character }
  1136. CommitStyleSq(stSymbol, True);
  1137. end;
  1138. end;
  1139. SkipWhitespace;
  1140. end;
  1141. end;
  1142. procedure TInnoSetupStyler.HandleCompilerDirective(const InlineDirective: Boolean; const InlineDirectiveEndIndex: Integer; var OpenCount: ShortInt);
  1143. function EndOfDirective: Boolean;
  1144. begin
  1145. Result := EndOfLine or (InlineDirective and (CurIndex > InlineDirectiveEndIndex));
  1146. end;
  1147. procedure FinishDirectiveNameOrShorthand(const RequiresParameter: Boolean);
  1148. begin
  1149. if RequiresParameter then begin
  1150. ConsumeChars(WhitespaceChars); { This will give the whitespace the stCompilerDirective style instead of stDefault but that's ok }
  1151. if EndOfDirective then
  1152. CommitStyleSqPending(stCompilerDirective)
  1153. else
  1154. CommitStyle(stCompilerDirective);
  1155. end else
  1156. CommitStyle(stCompilerDirective);
  1157. end;
  1158. function FinishConsumingStarComment: Boolean;
  1159. begin
  1160. Result := False;
  1161. while True do begin
  1162. ConsumeCharsNot(['*']);
  1163. if not ConsumeChar('*') then
  1164. Break;
  1165. if ConsumeChar('/') then begin
  1166. Result := True;
  1167. Break;
  1168. end;
  1169. end;
  1170. if Result then
  1171. CommitStyle(stComment)
  1172. else
  1173. CommitStyleSqPending(stComment);
  1174. end;
  1175. procedure ConsumeISPPString(const Terminator: AnsiChar; const AllowEscapedTerminator: Boolean);
  1176. begin
  1177. while True do begin
  1178. ConsumeCharsNot([Terminator]);
  1179. if not ConsumeChar(Terminator) then begin
  1180. { Non terminated string found }
  1181. CommitStyleSqPending(stISPPString);
  1182. Break;
  1183. end;
  1184. { Terminated string found and consumed. Now check if the terminator is actually escaped by doubling, if allowed }
  1185. if not AllowEscapedTerminator or not ConsumeChar(Terminator) then begin
  1186. { Doubling not allowed or no double terminator found, so we're done }
  1187. CommitStyle(stISPPString);
  1188. Break;
  1189. end;
  1190. { The terminator was doubled so we should continue to find the real terminator }
  1191. end;
  1192. end;
  1193. const
  1194. ISPPReservedWords: array[0..16] of TScintRawString = (
  1195. 'private', 'protected', 'public', 'any', 'int',
  1196. 'str', 'func', 'option', 'parseroption', 'inlinestart',
  1197. 'inlineend', 'message', 'warning', 'error',
  1198. 'verboselevel', 'include', 'spansymbol');
  1199. ISPPDirectiveShorthands: TScintRawCharSet =
  1200. [':' {define},
  1201. 'x' {undef},
  1202. '+' {include},
  1203. '=' {emit},
  1204. '!' {expr}];
  1205. begin
  1206. var StartIndex := CurIndex;
  1207. var NeedIspp: Boolean;
  1208. if InlineDirective then begin
  1209. ConsumeChar('{');
  1210. NeedIspp := True;
  1211. end else
  1212. NeedIspp := False; { Might be updated later to True later }
  1213. var ForDirectiveExpressionsNext := False;
  1214. var DoIncludeFileNotationCheck := False;
  1215. var ErrorDirective := False;
  1216. ConsumeChar('#');
  1217. CommitStyle(stCompilerDirective);
  1218. { Directive name or shorthand }
  1219. SkipWhiteSpace;
  1220. var C := CurChar;
  1221. if ConsumeCharIn(ISPPDirectiveShorthands) then begin
  1222. DoIncludeFileNotationCheck := C = '+'; { We need to check the include file notation }
  1223. NeedIspp := True;
  1224. FinishDirectiveNameOrShorthand(True); { All shorthands require a parameter }
  1225. end else begin
  1226. var S := ConsumeString(ISPPIdentChars);
  1227. for var ISPPDirective in ISPPDirectives do
  1228. if SameRawText(S, ISPPDirective.Name) then begin
  1229. if SameRawText(S, 'error') then
  1230. ErrorDirective := True
  1231. else if SameRawText(S, 'include') then
  1232. DoIncludeFileNotationCheck := True { See above }
  1233. else
  1234. NeedIspp := True; { Built-in preprocessor only supports '#include' }
  1235. 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 }
  1236. Inc(OpenCount, ISPPDirective.OpenCountChange);
  1237. if OpenCount < 0 then begin
  1238. CommitStyleSq(stCompilerDirective, True);
  1239. OpenCount := 0; { Reset so that next doesn't automatically gets error as well }
  1240. end;
  1241. FinishDirectiveNameOrShorthand(ISPPDirective.RequiresParameter);
  1242. Break;
  1243. end;
  1244. if InlineDirective then
  1245. CommitStyle(stDefault) { #emit shorthand was used (='#' directly followed by an expression): not an error }
  1246. else
  1247. CommitStyleSqPending(stCompilerDirective);
  1248. end;
  1249. { Rest of the directive }
  1250. if ErrorDirective then begin
  1251. SkipWhitespace;
  1252. while not EndOfDirective do begin
  1253. C := CurChar;
  1254. ConsumeChar(C);
  1255. if InlineDirective and (C = '}') then
  1256. CommitStyle(stCompilerDirective)
  1257. else
  1258. CommitStyle(stISPPString);
  1259. end;
  1260. end else begin
  1261. SkipWhitespace;
  1262. while not EndOfDirective do begin
  1263. if DoIncludeFileNotationCheck then begin
  1264. if CurChar <> '"' then begin
  1265. NeedIspp := True; { Built-in preprocessor requires a '"' quoted string after the '#include' and doesn't support anything else }
  1266. if CurChar = '<' then { Check for ISPP's special bracket notation for include files }
  1267. ConsumeISPPString('>', False); { Consume now instead of using regular consumption }
  1268. end;
  1269. DoIncludeFileNotationCheck := False;
  1270. end;
  1271. if CurChar in ISPPIdentFirstChars then begin
  1272. var S := ConsumeString(ISPPIdentChars);
  1273. for var ISPPReservedWord in ISPPReservedWords do
  1274. if SameRawText(S, ISPPReservedWord) then begin
  1275. CommitStyle(stISPPReservedWord);
  1276. Break;
  1277. end;
  1278. CommitStyle(stDefault)
  1279. end else if ConsumeChars(DigitChars) then begin
  1280. if not CurCharIs('.') or not NextCharIs('.') then begin
  1281. if ConsumeChar('.') then
  1282. ConsumeChars(DigitChars);
  1283. C := CurChar;
  1284. if C in ['X', 'x'] then begin
  1285. ConsumeChar(C);
  1286. if not ConsumeChars(HexDigitChars) then
  1287. CommitStyleSqPending(stISPPNumber);
  1288. end;
  1289. ConsumeChars(['L', 'U', 'l', 'u']);
  1290. end;
  1291. CommitStyle(stISPPNumber);
  1292. end else begin
  1293. C := CurChar;
  1294. ConsumeChar(C);
  1295. case C of
  1296. '!', '&', '=', '|', '^', '>', '<', '+', '-', '/', '%', '*',
  1297. '?', ':', ',', '.', '~', '(', '[', '{', ')', ']', '}', '@',
  1298. '#':
  1299. begin
  1300. if (C = '}') and ForDirectiveExpressionsNext then
  1301. ForDirectiveExpressionsNext := False;
  1302. if (C = '/') and ConsumeChar('*') then
  1303. FinishConsumingStarComment
  1304. else if InlineDirective and (C = '}') then
  1305. CommitStyle(stCompilerDirective) (* Closing '}' of the ISPP inline directive *)
  1306. else
  1307. CommitStyle(stSymbol);
  1308. end;
  1309. ';':
  1310. begin
  1311. if ForDirectiveExpressionsNext then
  1312. CommitStyle(stSymbol)
  1313. else begin
  1314. if not InlineDirective then
  1315. ConsumeAllRemaining
  1316. else
  1317. ConsumeCharsNot(['}']);
  1318. CommitStyle(stComment);
  1319. end;
  1320. end;
  1321. '''', '"':
  1322. ConsumeISPPString(C, True);
  1323. else
  1324. { Illegal character }
  1325. CommitStyleSq(stSymbol, True);
  1326. end;
  1327. end;
  1328. SkipWhitespace;
  1329. end;
  1330. end;
  1331. if NeedIspp and not ISPPInstalled then begin
  1332. if InlineDirective then
  1333. ApplyPendingSquigglyFromToIndex(StartIndex + 1, InlineDirectiveEndIndex - 1)
  1334. else
  1335. ApplyPendingSquigglyFromIndex(StartIndex + 1);
  1336. end;
  1337. end;
  1338. procedure TInnoSetupStyler.HandleParameterSection(
  1339. const ValidParameters: array of TScintRawString);
  1340. var
  1341. ParamsSpecified: set of 0..31;
  1342. S: TScintRawString;
  1343. ParamValueIndex, BraceLevel: Integer;
  1344. NamePresent, ValidName, DuplicateName, ColonPresent: Boolean;
  1345. begin
  1346. ParamsSpecified := [];
  1347. while not EndOfLine do begin
  1348. { Squigglify any bogus characters before the parameter name }
  1349. SquigglifyUntilChars(AlphaChars + [':'], stDefault);
  1350. { Parameter name }
  1351. S := ConsumeString(AlphaDigitChars);
  1352. NamePresent := (S <> '');
  1353. ValidName := False;
  1354. DuplicateName := False;
  1355. for var I := Low(ValidParameters) to High(ValidParameters) do
  1356. if SameRawText(S, ValidParameters[I]) then begin
  1357. ValidName := True;
  1358. DuplicateName := (I in ParamsSpecified);
  1359. Include(ParamsSpecified, I);
  1360. Break;
  1361. end;
  1362. if DuplicateName then
  1363. CommitStyleSqPending(stKeyword)
  1364. else if ValidName then
  1365. CommitStyle(stKeyword)
  1366. else
  1367. CommitStyleSqPending(stDefault);
  1368. SkipWhitespace;
  1369. { If there's a semicolon with no colon, squigglify the semicolon }
  1370. if ConsumeChar(';') then begin
  1371. CommitStyleSq(stSymbol, True);
  1372. SkipWhitespace;
  1373. Continue;
  1374. end;
  1375. { Colon }
  1376. ColonPresent := ConsumeChar(':');
  1377. CommitStyleSq(stSymbol, not NamePresent);
  1378. SkipWhitespace;
  1379. { Parameter value. This consumes until a ';' is found or EOL is reached. }
  1380. ParamValueIndex := CurIndex;
  1381. BraceLevel := 0;
  1382. if ConsumeChar('"') then begin
  1383. while True do begin
  1384. StyleConstsUntilChars(['"'], stParameterValue, BraceLevel);
  1385. { If no closing quote exists, squigglify the whole value and break }
  1386. if not ConsumeChar('"') then begin
  1387. ApplyPendingSquigglyFromIndex(ParamValueIndex);
  1388. Break;
  1389. end;
  1390. { Quote found, now break, unless there are two quotes in a row }
  1391. if not ConsumeChar('"') then
  1392. Break;
  1393. end;
  1394. end else begin
  1395. while True do begin
  1396. StyleConstsUntilChars([';', '"'], stParameterValue, BraceLevel);
  1397. { Squigglify any quote characters inside an unquoted string }
  1398. if ConsumeChar('"') then
  1399. ApplySquigglyFromIndex(CurIndex - 1)
  1400. else
  1401. Break;
  1402. end;
  1403. end;
  1404. CommitStyle(stParameterValue);
  1405. if not ColonPresent then
  1406. ApplySquigglyFromIndex(ParamValueIndex);
  1407. { Squigglify any characters between a quoted string and the next ';' }
  1408. SquigglifyUntilChars([';'], stDefault);
  1409. { Semicolon }
  1410. ConsumeChar(';');
  1411. CommitStyle(stSymbol);
  1412. SkipWhitespace;
  1413. end;
  1414. end;
  1415. procedure TInnoSetupStyler.HandleKeyValueSection(const Section: TInnoSetupStylerSection);
  1416. procedure StyleMessageArgs;
  1417. begin
  1418. while True do begin
  1419. ConsumeCharsNot(['%']);
  1420. CommitStyle(stDefault);
  1421. if not ConsumeChar('%') then
  1422. Break;
  1423. if CurCharIn(['1'..'9', '%', 'n']) then begin
  1424. ConsumeChar(CurChar);
  1425. CommitStyle(stMessageArg);
  1426. end;
  1427. end;
  1428. end;
  1429. var
  1430. S: String;
  1431. I, BraceLevel: Integer;
  1432. begin
  1433. { Squigglify any bogus characters at the start of the line }
  1434. SquigglifyUntilChars(AlphaUnderscoreChars, stDefault);
  1435. if EndOfLine then
  1436. Exit;
  1437. S := String(ConsumeString(AlphaDigitUnderscoreChars));
  1438. { Was that a language name? }
  1439. if (Section in [scCustomMessages, scLangOptions, scMessages]) and
  1440. CurCharIs('.') then begin
  1441. CommitStyle(stDefault);
  1442. ConsumeChar('.');
  1443. CommitStyle(stSymbol);
  1444. { Squigglify any spaces or bogus characters between the '.' and key name }
  1445. if ConsumeCharsNot(AlphaUnderscoreChars) then
  1446. CommitStyleSq(stDefault, True);
  1447. S := String(ConsumeString(AlphaDigitUnderscoreChars));
  1448. end;
  1449. case Section of
  1450. scCustomMessages:
  1451. I := 0;
  1452. scLangOptions:
  1453. I := GetEnumValue(TypeInfo(TLangOptionsSectionDirective), 'ls' + S);
  1454. scMessages:
  1455. I := GetEnumValue(TypeInfo(TSetupMessageID), 'msg' + S);
  1456. scSetup:
  1457. I := GetEnumValue(TypeInfo(TSetupSectionDirective), 'ss' + S);
  1458. else
  1459. I := -1;
  1460. end;
  1461. if I <> -1 then
  1462. CommitStyle(stKeyword)
  1463. else begin
  1464. if Section in [scLangOptions, scMessages, scSetup] then
  1465. CommitStyleSqPending(stDefault)
  1466. else
  1467. CommitStyle(stDefault);
  1468. end;
  1469. SquigglifyUntilChars(['='], stDefault);
  1470. ConsumeChar('=');
  1471. CommitStyle(stSymbol);
  1472. SkipWhitespace;
  1473. if Section in [scCustomMessages, scMessages] then
  1474. StyleMessageArgs
  1475. else begin
  1476. BraceLevel := 0;
  1477. StyleConstsUntilChars([], stDefault, BraceLevel);
  1478. CommitStyle(stDefault);
  1479. end;
  1480. end;
  1481. class function TInnoSetupStyler.IsCommentOrKeywordStyle(const Style: TScintStyleNumber): Boolean;
  1482. begin
  1483. Result := Style in [Ord(stComment), Ord(stKeyword)];
  1484. end;
  1485. class function TInnoSetupStyler.IsCommentOrPascalStringStyle(const Style: TScintStyleNumber): Boolean;
  1486. begin
  1487. Result := Style in [Ord(stComment), Ord(stPascalString)];
  1488. end;
  1489. class function TInnoSetupStyler.IsParamSection(
  1490. const Section: TInnoSetupStylerSection): Boolean;
  1491. begin
  1492. Result := not (Section in [scCustomMessages, scLangOptions, scMessages, scSetup, scCode, scCodeBlock]);
  1493. end;
  1494. class function TInnoSetupStyler.IsSymbolStyle(const Style: TScintStyleNumber): Boolean;
  1495. begin
  1496. Result := Style = Ord(stSymbol);
  1497. end;
  1498. function TInnoSetupStyler.LineTextSpans(const S: TScintRawString): Boolean;
  1499. var
  1500. I: Integer;
  1501. begin
  1502. { Note: To match ISPP behavior, require length of at least 3 }
  1503. I := Length(S);
  1504. Result := (I > 2) and (S[I] = '\') and (S[I-1] in WhitespaceChars);
  1505. end;
  1506. procedure TInnoSetupStyler.PreStyleInlineISPPDirectives;
  1507. function IsLineCommented: Boolean;
  1508. var
  1509. I: Integer;
  1510. begin
  1511. Result := False;
  1512. for I := 1 to TextLength do begin
  1513. { In ISPP, only ';' and '//' inhibit processing of inline directives }
  1514. if (Text[I] = ';') or
  1515. ((I < TextLength) and (Text[I] = '/') and (Text[I+1] = '/')) then begin
  1516. Result := True;
  1517. Break;
  1518. end;
  1519. if not(Text[I] in WhitespaceChars) then
  1520. Break;
  1521. end;
  1522. end;
  1523. const
  1524. LineEndChars = [#10, #13];
  1525. var
  1526. I, StartIndex: Integer;
  1527. Valid: Boolean;
  1528. Dummy: ShortInt;
  1529. begin
  1530. { Style span symbols, then replace them with spaces to prevent any further
  1531. processing }
  1532. for I := 3 to TextLength do begin
  1533. if ((I = TextLength) or (Text[I+1] in LineEndChars)) and
  1534. (Text[I] = '\') and (Text[I-1] in WhitespaceChars) and
  1535. not(Text[I-2] in LineEndChars) then begin
  1536. ReplaceText(I, I, ' ');
  1537. ApplyStyle(Ord(stSymbol), I, I);
  1538. if not ISPPInstalled then
  1539. ApplyStyleByteIndicators([inSquiggly], I, I);
  1540. end;
  1541. end;
  1542. { Style all '{#' ISPP inline directives before anything else }
  1543. if not IsLineCommented then begin
  1544. I := 1;
  1545. while I < TextLength do begin
  1546. if (Text[I] = '{') and (Text[I+1] = '#') then begin
  1547. StartIndex := I;
  1548. Valid := False;
  1549. while I <= TextLength do begin
  1550. Inc(I);
  1551. if Text[I-1] = '}' then begin
  1552. Valid := True;
  1553. Break;
  1554. end;
  1555. end;
  1556. ResetCurIndexTo(StartIndex);
  1557. try
  1558. HandleCompilerDirective(True, I - 1, Dummy);
  1559. finally
  1560. ResetCurIndexTo(0);
  1561. end;
  1562. if not Valid then
  1563. ApplyPendingSquigglyFromToIndex(StartIndex, I - 1);
  1564. { Replace the directive with spaces to prevent any further processing }
  1565. ReplaceText(StartIndex, I - 1, ' ');
  1566. end else
  1567. Inc(I);
  1568. end;
  1569. end;
  1570. end;
  1571. function TInnoSetupStyler.SectionHasFlag(const Section: TInnoSetupStylerSection;
  1572. const Flag: String): Boolean;
  1573. begin
  1574. Result := FFlagsWords[Section].IndexOf(Flag) <> -1;
  1575. end;
  1576. function TInnoSetupStyler.HighlightAtCursorAllowed(const Section: TInnoSetupStylerSection;
  1577. const Word: string): Boolean;
  1578. begin
  1579. Result := FNoHighlightAtCursorWords[Section].IndexOf(Word) = -1;
  1580. end;
  1581. procedure TInnoSetupStyler.SetISPPInstalled(const Value: Boolean);
  1582. begin
  1583. if Value <> FISPPInstalled then begin
  1584. FISPPInstalled := Value;
  1585. BuildConstantsWordList;
  1586. end;
  1587. end;
  1588. procedure TInnoSetupStyler.SkipWhitespace;
  1589. begin
  1590. ConsumeChars(WhitespaceChars);
  1591. CommitStyle(stDefault);
  1592. end;
  1593. procedure TInnoSetupStyler.SquigglifyUntilChars(const Chars: TScintRawCharSet;
  1594. const Style: TInnoSetupStylerStyle);
  1595. var
  1596. IsWhitespace: Boolean;
  1597. begin
  1598. { Consume and squigglify all non-whitespace characters until one of Chars
  1599. is encountered }
  1600. while not EndOfLine and not CurCharIn(Chars) do begin
  1601. IsWhitespace := CurCharIn(WhitespaceChars);
  1602. ConsumeChar(CurChar);
  1603. if IsWhitespace then
  1604. CommitStyle(stDefault)
  1605. else
  1606. CommitStyleSq(Style, True);
  1607. end;
  1608. CommitStyle(stDefault);
  1609. end;
  1610. procedure TInnoSetupStyler.StyleConstsUntilChars(const Chars: TScintRawCharSet;
  1611. const NonConstStyle: TInnoSetupStylerStyle; var BraceLevel: Integer);
  1612. var
  1613. C: AnsiChar;
  1614. begin
  1615. while not EndOfLine and not CurCharIn(Chars) do begin
  1616. if BraceLevel = 0 then
  1617. CommitStyle(NonConstStyle);
  1618. C := CurChar;
  1619. ConsumeChar(C);
  1620. if C = '{' then begin
  1621. if not ConsumeChar('{') then
  1622. Inc(BraceLevel);
  1623. end;
  1624. if (C = '}') and (BraceLevel > 0) then begin
  1625. Dec(BraceLevel);
  1626. if BraceLevel = 0 then
  1627. CommitStyle(stConstant);
  1628. end;
  1629. end;
  1630. end;
  1631. procedure TInnoSetupStyler.StyleNeeded;
  1632. function MapSectionNameString(const S: TScintRawString): TInnoSetupStylerSection;
  1633. begin
  1634. if (S <> '') and (S[1] = '_') then
  1635. Result := scThirdParty
  1636. else begin
  1637. Result := scUnknown;
  1638. for var Section in SectionMap do
  1639. if SameRawText(S, Section.Name) then begin
  1640. Result := Section.Section;
  1641. Break;
  1642. end;
  1643. end;
  1644. end;
  1645. function CheckSectionEnd(const NewSection, Section: TInnoSetupStylerSection): Boolean;
  1646. begin
  1647. Result := (NewSection = Section) or ((NewSection = scCode) and (Section = scCodeBlock));
  1648. end;
  1649. begin
  1650. var NewLineState := TInnoSetupStylerLineState(LineState);
  1651. if NewLineState.NextLineSection <> scNone then begin
  1652. { Previous line started a section }
  1653. NewLineState.Section := NewLineState.NextLineSection;
  1654. NewLineState.NextLineSection := scNone;
  1655. end;
  1656. var Section := NewLineState.Section;
  1657. PreStyleInlineISPPDirectives;
  1658. const IsCodeSection = Section in [scCode, scCodeBlock];
  1659. SkipWhitespace;
  1660. if not IsCodeSection and ConsumeChar(';') then begin
  1661. ConsumeAllRemaining;
  1662. CommitStyle(stComment);
  1663. end else if CurCharIs('/') and NextCharIs('/') then begin
  1664. ConsumeAllRemaining;
  1665. CommitStyleSq(stComment, not ISPPInstalled and not IsCodeSection)
  1666. end else if ConsumeChar('[') then begin
  1667. const SectionEnd = ConsumeChar('/');
  1668. const S = ConsumeString(AlphaUnderscoreChars);
  1669. if ConsumeChar(']') then begin
  1670. const NewSection = MapSectionNameString(S);
  1671. { Unknown section names and erroneously-placed end tags get squigglified }
  1672. CommitStyleSq(stSection, (NewSection = scUnknown) or
  1673. (SectionEnd and not CheckSectionEnd(NewSection, Section)));
  1674. if not SectionEnd then
  1675. NewLineState.NextLineSection := NewSection;
  1676. end else
  1677. CommitStyleSqPending(stDefault);
  1678. { Section tags themselves are not associated with any section }
  1679. Section := scNone;
  1680. SquigglifyUntilChars([], stDefault);
  1681. end else if CurCharIs('#') then
  1682. HandleCompilerDirective(False, -1, NewLineState.OpenCompilerDirectivesCount)
  1683. else if IsCodeSection then begin
  1684. var CodeBlockHeader := False;
  1685. HandleCodeSection(NewLineState.SpanState, CodeBlockHeader);
  1686. if CodeBlockHeader then begin
  1687. Section := scCode;
  1688. NewLineState.NextLineSection := scCodeBlock;
  1689. end;
  1690. end else begin
  1691. case Section of
  1692. scUnknown: ;
  1693. scThirdParty: ;
  1694. scComponents: HandleParameterSection(ComponentsSectionParameters);
  1695. scCustomMessages: HandleKeyValueSection(Section);
  1696. scDirs: HandleParameterSection(DirsSectionParameters);
  1697. scISSigKeys: HandleParameterSection(ISSigKeysSectionParameters);
  1698. scFiles: HandleParameterSection(FilesSectionParameters);
  1699. scIcons: HandleParameterSection(IconsSectionParameters);
  1700. scINI: HandleParameterSection(INISectionParameters);
  1701. scInstallDelete: HandleParameterSection(DeleteSectionParameters);
  1702. scLangOptions: HandleKeyValueSection(Section);
  1703. scLanguages: HandleParameterSection(LanguagesSectionParameters);
  1704. scMessages: HandleKeyValueSection(Section);
  1705. scRegistry: HandleParameterSection(RegistrySectionParameters);
  1706. scRun: HandleParameterSection(RunSectionParameters);
  1707. scSetup: HandleKeyValueSection(Section);
  1708. scTasks: HandleParameterSection(TasksSectionParameters);
  1709. scTypes: HandleParameterSection(TypesSectionParameters);
  1710. scUninstallDelete: HandleParameterSection(DeleteSectionParameters);
  1711. scUninstallRun: HandleParameterSection(UninstallRunSectionParameters);
  1712. end;
  1713. end;
  1714. NewLineState.Section := Section;
  1715. LineState := TScintLineState(NewLineState);
  1716. end;
  1717. function SMI(const Name: TScintRawString; const Section: TInnoSetupStylerSection): TSectionMapItem;
  1718. begin
  1719. Result.Name := Name;
  1720. Result.Section := Section;
  1721. end;
  1722. function ISPPD(const Name: TScintRawString; const RequiresParameter: Boolean; const OpenCountChange: ShortInt): TISPPDirective;
  1723. begin
  1724. Result.Name := Name;
  1725. Result.RequiresParameter := RequiresParameter;
  1726. Result.OpenCountChange := OpenCountChange;
  1727. end;
  1728. function SSDV(const Directive: TSetupSectionDirective; const Values: TArray<TScintRawString>): TSetupSectionDirectiveValue;
  1729. begin
  1730. Result.Directive := Directive;
  1731. Result.Values := Values;
  1732. end;
  1733. type
  1734. TZipLevel = 1..9;
  1735. const
  1736. LZMALevels: TArray<TScintRawString> = ['fast', 'normal', 'max', 'ultra', 'ultra64'];
  1737. function GetCompressionValues: TArray<TScintRawString>;
  1738. procedure SetResult(var I: Integer; const S: TScintRawString);
  1739. begin
  1740. Result[I] := S;
  1741. Inc(I);
  1742. end;
  1743. const
  1744. ZipAlgos: TArray<TScintRawString> = ['zip', 'bzip'];
  1745. LZMAAlgos: TArray<TScintRawString> = ['lzma', 'lzma2'];
  1746. type
  1747. TZipLevels = 1..9;
  1748. begin
  1749. SetLength(Result, 1 +
  1750. Length(ZipAlgos) + Length(ZipAlgos) * (High(TZipLevel) - Low(TZipLevel) + 1) +
  1751. Length(LZMAAlgos) + Length(LZMAAlgos) * Length(LZMALevels));
  1752. var I := 0;
  1753. SetResult(I, 'none');
  1754. for var Algo in ZipAlgos do begin
  1755. SetResult(I, Algo);
  1756. for var Level := Low(TZipLevel) to High(TZipLevel) do
  1757. SetResult(I, TScintRawString(String(Algo) + '/' + Level.ToString));
  1758. end;
  1759. for var Algo in LZMAAlgos do begin
  1760. SetResult(I, Algo);
  1761. for var Level in LZMALevels do
  1762. SetResult(I, TScintRawString(Algo + '/' + Level));
  1763. end;
  1764. end;
  1765. initialization
  1766. SectionMap := [
  1767. SMI('Code', scCode),
  1768. SMI('Components', scComponents),
  1769. SMI('CustomMessages', scCustomMessages),
  1770. SMI('Dirs', scDirs),
  1771. SMI('ISSigKeys', scISSigKeys),
  1772. SMI('Files', scFiles),
  1773. SMI('Icons', scIcons),
  1774. SMI('INI', scINI),
  1775. SMI('InstallDelete', scInstallDelete),
  1776. SMI('LangOptions', scLangOptions),
  1777. SMI('Languages', scLanguages),
  1778. SMI('Messages', scMessages),
  1779. SMI('Registry', scRegistry),
  1780. SMI('Run', scRun),
  1781. SMI('Setup', scSetup),
  1782. SMI('Tasks', scTasks),
  1783. SMI('Types', scTypes),
  1784. SMI('UninstallDelete', scUninstallDelete),
  1785. SMI('UninstallRun', scUninstallRun)];
  1786. ISPPDirectives := [
  1787. ISPPD('preproc', True, 0),
  1788. ISPPD('define', True, 0),
  1789. ISPPD('dim', True, 0),
  1790. ISPPD('redim', True, 0),
  1791. ISPPD('undef', True, 0),
  1792. ISPPD('include', True, 0),
  1793. ISPPD('file', True, 0),
  1794. ISPPD('emit', True, 0),
  1795. ISPPD('expr', True, 0),
  1796. ISPPD('insert', True, 0),
  1797. ISPPD('append', False, 0),
  1798. ISPPD('if', True, 1),
  1799. ISPPD('elif', False { bug in ISPP? }, 0),
  1800. ISPPD('else', False, 0),
  1801. ISPPD('endif', False, -1),
  1802. ISPPD('ifdef', True, 1),
  1803. ISPPD('ifndef', True, 1),
  1804. ISPPD('ifexist', True, 1),
  1805. ISPPD('ifnexist', True, 1),
  1806. ISPPD('for', True, 0),
  1807. ISPPD('sub', True, 1),
  1808. ISPPD('endsub', False, -1),
  1809. ISPPD('pragma', False, 0),
  1810. ISPPD('error', False, 0)];
  1811. SetLength(PascalRealEnumValues, 6);
  1812. PascalRealEnumValues[0] := TypeInfo(TMsgBoxType);
  1813. PascalRealEnumValues[1] := TypeInfo(TSetupMessageID);
  1814. PascalRealEnumValues[2] := TypeInfo(TSetupStep);
  1815. PascalRealEnumValues[3] := TypeInfo(TUninstallStep);
  1816. PascalRealEnumValues[4] := TypeInfo(TSetupProcessorArchitecture);
  1817. PascalRealEnumValues[5] := TypeInfo(TDotNetVersion);
  1818. const ArchitecturesExpressionValues: TArray<TScintRawString> = [
  1819. 'not', 'and', 'or',
  1820. 'arm32compatible', 'arm64', 'win64',
  1821. 'x64', 'x64os', 'x64compatible',
  1822. 'x86', 'x86os', 'x86compatible'];
  1823. SetupSectionDirectivesValues := [
  1824. SSDV(ssArchitecturesAllowed, ArchitecturesExpressionValues),
  1825. SSDV(ssArchitecturesInstallIn64BitMode, ArchitecturesExpressionValues),
  1826. SSDV(ssArchiveExtraction, ['enhanced/nopassword', 'enhanced', 'full', 'basic']),
  1827. SSDV(ssCloseApplications, ['force', SYes, SNo]),
  1828. SSDV(ssCompression, GetCompressionValues),
  1829. SSDV(ssDisablePrecompiledFileVerifications, ['setup', 'setupcustomstyle', 'setupldr', 'is7z', 'isbunzip', 'isunzlib', 'islzma']),
  1830. SSDV(ssEncryption, ['full', SYes, SNo]),
  1831. SSDV(ssInternalCompressLevel, ['none'] + LZMALevels), { We don't list 0 }
  1832. SSDV(ssLanguageDetectionMethod, ['uilanguage', 'locale', 'none']),
  1833. SSDV(ssLZMAAlgorithm, ['0', '1']),
  1834. SSDV(ssLZMAMatchFinder, ['BT', 'HC']),
  1835. SSDV(ssLZMAUseSeparateProcess, ['x86', SYes, SNo]),
  1836. SSDV(ssPrivilegesRequired, ['admin', 'lowest']), { We don't list none/poweruser }
  1837. SSDV(ssPrivilegesRequiredOverridesAllowed, ['commandline', 'dialog']),
  1838. SSDV(ssSetupArchitecture, ['x86', 'x64']),
  1839. SSDV(ssUninstallLogMode, ['append', 'new', 'override']),
  1840. SSDV(ssUseSetupLdr, ['x86', 'x64', SYes, SNo]),
  1841. SSDV(ssWizardImageAlphaFormat, ['none', 'defined', 'premultiplied']),
  1842. SSDV(ssWizardStyle, ['classic', 'modern', 'light', 'dark', 'dynamic', 'excludelightbuttons', 'excludelightcontrols', 'includetitlebar', 'hidebevels', 'polar', 'slate', 'windows11', 'zircon'])];
  1843. end.