TFPET.Mod 93 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910
  1. MODULE TFPET; (** AUTHOR "TF, PL"; PURPOSE "Programmer's Editing Tool"; *)
  2. (**
  3. * Shortcuts:
  4. *
  5. * CTRL-F: Show search panel of current page, set focus to its editor and clear the content of the editor
  6. * CTRL-N: If search panel is visible: Find next occurence downwards
  7. * elsif error grid is visible: Jump to next error position
  8. * CTRL-P: If search panel is visible: Find next occurence upwards
  9. * elsif error grid is visible: Jump to previous error position
  10. *
  11. * CTRL-0: Set cursor to position zero
  12. * CTRL-9: Move cursor to end of text
  13. *
  14. * CTRL-O: Set focus to filename editor and clear its content
  15. * CTRL-S: Store current page
  16. *
  17. * CTRL-M: Toggle visibility of sidepanel
  18. *
  19. * CTRL-H: Compile file opened in current page
  20. * CTRL-U: Unload module opened in current page
  21. * CTRL-D: Diff current tab to file
  22. *
  23. * CTRL-DEL Delete end-of-line whitespace in current page
  24. *
  25. * ALT-INS Uncomment selected code of commented
  26. * ALT-DEL Comment selected code
  27. *
  28. * CTRL-PgUp Load PET state from file
  29. * CTRL-PgDn Save PET state to file
  30. *
  31. * CTRL-SHIFT-Tab Select previous tab
  32. * CTRL-Tab Select next tab
  33. *
  34. * SHIFT-F1..F12 Store current cursor position
  35. * CTRL-F1..F12 Recall cursor position
  36. *
  37. * When the filename editor has the keyboard focus:
  38. *
  39. * ESC Reset filename to filename of currently opened tab
  40. * ENTER Open file
  41. * SHIFT_ENTER Open file in new PET window instance
  42. *)
  43. IMPORT
  44. KernelLog, Modules, Commands, Options, Streams, Inputs, Files, WMRestorable, XML, XMLScanner, XMLParser, XMLObjects,
  45. WMStandardComponents, WMGraphics, CompilerInterface,
  46. WMComponents, WMRectangles, WMMessages, WMDialogs,
  47. WMTextView, WMEditors, Strings, TextUtilities, Texts,
  48. WMWindowManager, WMGrids, WMMacros, WMPopups, WMDropTarget, WMDiagnostics,
  49. PETTrees, Configuration, Codecs, WMTabComponents, UndoManager, WMSearchComponents, WhitespaceRemover,
  50. TFModuleTrees;
  51. CONST
  52. WindowWidth = 800; WindowHeight = 600;
  53. (* Default Settings for all PET instances *)
  54. (* backup levels when storing a file *)
  55. No = 0; (* don't create backup file *)
  56. Yes = 1; (* create backup file *)
  57. Paranoid = 2; (* create backup file for each store *)
  58. (* General *)
  59. DefaultBackupOnStore = No;
  60. DefaultBackupOnCompile = FALSE;
  61. DefaultShowPathInTabs = FALSE;
  62. DefaultScratchPanelHeight = 250;
  63. DefaultEnableWhitespaceWarnings = FALSE;
  64. DefaultShowLineNumbers = FALSE;
  65. DefaultIndicateTabs = FALSE;
  66. DefaultCurrentLineColor = 0;
  67. (* Compiler *)
  68. DefaultCompilerName = "Fox";
  69. DefaultCompilerCaption = "Compile";
  70. DefaultCompilerOptions = "-b=AMD --warnings";
  71. DefaultCompilerLoadModule = "Compiler";
  72. DefaultCompilerFileExtension = "MOD";
  73. DefaultCompilerFindPC = TRUE;
  74. (* Diff *)
  75. (* The Diff shortcurt will use the DiffCommand to compare the file currently opened in PET to a file specified by the user... *)
  76. DefaultDiffCommand = "WMDiff.Open";
  77. (* PET will suggest a filename based on the following constants: *)
  78. DefaultDiffPrefix = ""; (* Add this string as prefix to the current filename (e.g. path) *)
  79. DefaultDiffSuffix = ".Bak"; (* Add this string as suffix to the current filename (e.g. ".Bak") *)
  80. (* Search *)
  81. DefaultSearchWrap = FALSE;
  82. DefaultSearchCaseSensitive = TRUE;
  83. DefaultSearchHighlightAll = FALSE;
  84. (* If you really don't like any shortcuts, disable them! *)
  85. DisableShortcuts = FALSE;
  86. BackupOnCompileFilename = "PETBackup.Mod.Bak";
  87. ScratchTextFilename = "PETScratch.Text";
  88. StateFileExtension = ".pet";
  89. SearchStringMaxLen = 128;
  90. MaxNbrOfTabs = 100;
  91. MaxNbrOfCompilers = 8;
  92. WindowTitle = "TF Programmer's Editing Tool v2.1";
  93. DefaultTextFormat = "UTF-8";
  94. EditorFocus = 1;
  95. SplitEditorFocus = 2;
  96. TYPE
  97. CompilerOptions = ARRAY 256 OF CHAR;
  98. Filename = ARRAY 256 OF CHAR;
  99. String = ARRAY 128 OF CHAR;
  100. SearchString = ARRAY SearchStringMaxLen OF CHAR;
  101. TYPE
  102. CompilerSettings = RECORD
  103. name : ARRAY 32 OF CHAR; (* name of compiler (same as in CompilerInterface) *)
  104. caption : ARRAY 16 OF CHAR; (* Caption of "compile" button *)
  105. options : CompilerOptions; (* default compiler options *)
  106. fileExtension : ARRAY 16 OF CHAR; (* file extension *)
  107. loadmodule : Filename; (* module to be loaded to register compiler at CompilerInterface *)
  108. genTree : ARRAY 128 OF CHAR; (* Factory procedure to generate a sidepanel tree *)
  109. findPC : BOOLEAN; (* Use Find PC button? *)
  110. END;
  111. (* Global PET settings for all window instances *)
  112. Settings = OBJECT
  113. VAR
  114. (* General *)
  115. backupOnStore : LONGINT; (* No | Yes | Always *)
  116. backupOnCompile : BOOLEAN;
  117. showPathInTabs : BOOLEAN;
  118. scratchPanelHeight : LONGINT;
  119. enableWhitespaceWarnings : BOOLEAN;
  120. showLineNumbers : BOOLEAN;
  121. indicateTabs : BOOLEAN;
  122. currentLineColor : LONGINT;
  123. (* Compiler *)
  124. defaultCompilerOptions : CompilerOptions;
  125. defaultCompilerSettings : CompilerSettings;
  126. compilers : ARRAY MaxNbrOfCompilers OF CompilerSettings;
  127. nofCompilers : LONGINT;
  128. (* Diff *)
  129. diffCommand, diffPrefix, diffSuffix : String;
  130. (* Search *)
  131. searchWrap, searchHighlightAll, searchCaseSensitive : BOOLEAN;
  132. (* Initialize settings to default values *)
  133. PROCEDURE &Init*;
  134. BEGIN
  135. (* General *)
  136. backupOnStore := DefaultBackupOnStore;
  137. backupOnCompile := DefaultBackupOnCompile;
  138. showPathInTabs := DefaultShowPathInTabs;
  139. scratchPanelHeight := DefaultScratchPanelHeight;
  140. enableWhitespaceWarnings := DefaultEnableWhitespaceWarnings;
  141. showLineNumbers := DefaultShowLineNumbers;
  142. indicateTabs := DefaultIndicateTabs;
  143. currentLineColor := DefaultCurrentLineColor;
  144. (* Compiler *)
  145. COPY(DefaultCompilerOptions, defaultCompilerOptions);
  146. nofCompilers := 0;
  147. defaultCompilerSettings.name := DefaultCompilerName;
  148. defaultCompilerSettings.caption := DefaultCompilerCaption;
  149. defaultCompilerSettings.options := DefaultCompilerOptions;
  150. defaultCompilerSettings.fileExtension := DefaultCompilerFileExtension;
  151. defaultCompilerSettings.loadmodule := DefaultCompilerLoadModule;
  152. defaultCompilerSettings.genTree := "";
  153. defaultCompilerSettings.findPC := DefaultCompilerFindPC;
  154. (* Diff *)
  155. diffCommand := DefaultDiffCommand; diffPrefix := DefaultDiffPrefix; diffSuffix := DefaultDiffSuffix;
  156. (* Search *)
  157. searchWrap := DefaultSearchWrap; searchCaseSensitive := DefaultSearchCaseSensitive; searchHighlightAll := DefaultSearchHighlightAll;
  158. END Init;
  159. PROCEDURE GetCompilerSettings(CONST filename : ARRAY OF CHAR) : CompilerSettings;
  160. VAR settings : CompilerSettings; i : LONGINT; extension : ARRAY 16 OF CHAR;
  161. BEGIN
  162. settings := defaultCompilerSettings;
  163. i := 0;
  164. LOOP
  165. IF (i >= nofCompilers) THEN (* no compiler found *) EXIT; END;
  166. extension := ".";
  167. Strings.Append(extension, compilers[i].fileExtension);
  168. IF ContainsFileExtension(filename, extension) THEN (* found *) EXIT; END;
  169. INC(i);
  170. END;
  171. IF (i < nofCompilers) THEN (* found *)
  172. settings := compilers[i];
  173. END;
  174. RETURN settings;
  175. END GetCompilerSettings;
  176. PROCEDURE LoadCompilerSettings;
  177. VAR
  178. element, e : XML.Element;
  179. sectionEnumerator : XMLObjects.Enumerator;
  180. p : ANY; string : XML.String;
  181. PROCEDURE GetAttributeValue(element : XML.Element; CONST attributeName : ARRAY OF CHAR; VAR value : ARRAY OF CHAR);
  182. VAR attribute : XML.Attribute;
  183. BEGIN
  184. ASSERT(element # NIL);
  185. COPY("", value);
  186. attribute := element.GetAttribute(attributeName);
  187. IF (attribute # NIL) THEN
  188. string := attribute.GetValue();
  189. IF (string # NIL) THEN
  190. COPY(string^, value);
  191. END;
  192. END;
  193. END GetAttributeValue;
  194. PROCEDURE ParseCompilerSettings(element : XML.Element; VAR settings : CompilerSettings);
  195. VAR enumerator : XMLObjects.Enumerator; e : XML.Element; p : ANY; string : XML.String; value : ARRAY 64OF CHAR;
  196. BEGIN
  197. ASSERT(element # NIL);
  198. GetAttributeValue(element, "name", value);
  199. IF (value # "") THEN
  200. COPY(value, settings.name);
  201. enumerator := element.GetContents();
  202. WHILE enumerator.HasMoreElements() DO
  203. p := enumerator.GetNext();
  204. IF (p IS XML.Element) THEN
  205. e := p (XML.Element);
  206. string := e.GetName();
  207. IF (string # NIL) & (string^ = "Setting") THEN
  208. GetAttributeValue(e, "name", value);
  209. IF (value = "caption") THEN
  210. GetAttributeValue(e, "value", settings.caption);
  211. IF (settings.caption = "") THEN settings.caption := "Action"; END;
  212. ELSIF (value = "options") THEN
  213. GetAttributeValue(e, "value", settings.options);
  214. ELSIF (value = "fileExtension") THEN
  215. GetAttributeValue(e, "value", settings.fileExtension);
  216. ELSIF (value = "loadmodule") THEN
  217. GetAttributeValue(e, "value", settings.loadmodule);
  218. ELSIF (value = "genTree") THEN
  219. GetAttributeValue(e, "value", value);
  220. Strings.TrimWS(value);
  221. COPY(value, settings.genTree);
  222. ELSIF (value = "findPC") THEN
  223. GetAttributeValue(e, "value", value);
  224. Strings.UpperCase(value); Strings.TrimWS(value);
  225. settings.findPC := (value = "TRUE");
  226. ELSE
  227. KernelLog.String("PET: Warning: Unknown compiler setting '");
  228. KernelLog.String(value); KernelLog.String("'"); KernelLog.Ln;
  229. END;
  230. ELSE
  231. KernelLog.String("PET: Warning: Expected 'Setting' element."); KernelLog.Ln;
  232. END;
  233. END;
  234. END;
  235. END;
  236. END ParseCompilerSettings;
  237. BEGIN
  238. element := Configuration.GetSection("Applications.PET.Compilers");
  239. IF (element # NIL) THEN
  240. sectionEnumerator := element.GetContents();
  241. WHILE sectionEnumerator.HasMoreElements() DO
  242. p := sectionEnumerator.GetNext();
  243. IF (p IS XML.Element) THEN
  244. e := p (XML.Element);
  245. string := e.GetName();
  246. IF (string # NIL) & (string^ = "Section") THEN (* sanity check *)
  247. IF (nofCompilers < LEN(compilers)) THEN
  248. ParseCompilerSettings(e, compilers[nofCompilers]);
  249. INC(nofCompilers);
  250. ELSE
  251. KernelLog.String("PET: Warning: Maximum number of compiler settings exceeded."); KernelLog.Ln;
  252. END;
  253. ELSE
  254. KernelLog.String("PET: Warning: Expected 'Section' element."); KernelLog.Ln;
  255. END;
  256. END;
  257. END;
  258. END;
  259. END LoadCompilerSettings;
  260. (* Load settings from system configuration database *)
  261. PROCEDURE Load;
  262. VAR string : String; temp: LONGINT; res: WORD;
  263. BEGIN
  264. (* General *)
  265. Configuration.Get("Applications.PET.General.BackupOnStore", string, res);
  266. Strings.TrimWS(string);
  267. Strings.LowerCase(string);
  268. IF (string = "yes") THEN backupOnStore := Yes;
  269. ELSIF (string = "no") THEN backupOnStore := No;
  270. ELSIF (string = "paranoid") THEN backupOnStore := Paranoid;
  271. ELSE
  272. KernelLog.String("Warning: PET.Settings.Load: BackupOnStore # Yes | No | Paranoid, using default."); KernelLog.Ln;
  273. backupOnStore := DefaultBackupOnStore;
  274. END;
  275. IF (backupOnStore < No) OR (Paranoid < backupOnStore) THEN backupOnStore := DefaultBackupOnStore; END;
  276. Configuration.GetBoolean("Applications.PET.General.BackupOnCompile", backupOnCompile, res);
  277. Configuration.GetBoolean("Applications.PET.General.ShowPathInTabs", showPathInTabs, res);
  278. Configuration.GetInteger("Applications.PET.General.ScratchPanelHeight", scratchPanelHeight, res);
  279. Configuration.GetBoolean("Applications.PET.General.EnableWhitespaceWarnings", enableWhitespaceWarnings, res);
  280. Configuration.GetBoolean("Applications.PET.General.ShowLineNumbers", showLineNumbers, res);
  281. Configuration.GetBoolean("Applications.PET.General.IndicateTabs", indicateTabs, res);
  282. Configuration.Get("Applications.PET.General.CurrentLineColor", string, res);
  283. IF (res = Configuration.Ok) THEN
  284. Strings.TrimWS(string);
  285. Strings.HexStrToInt(string, temp, res);
  286. IF (res = Strings.Ok) THEN currentLineColor := temp; END;
  287. END;
  288. (* Compiler *)
  289. Configuration.Get("Applications.PET.Compilers.DefaultOptions", defaultCompilerOptions, res);
  290. LoadCompilerSettings;
  291. (* Diff *)
  292. Configuration.Get("Applications.PET.Diff.Command", diffCommand, res);
  293. Configuration.Get("Applications.PET.Diff.Prefix", diffPrefix, res);
  294. Configuration.Get("Applications.PET.Diff.Suffix", diffSuffix, res);
  295. (* Search *)
  296. Configuration.GetBoolean("Applications.PET.Search.Wrap", searchWrap, res);
  297. Configuration.GetBoolean("Applications.PET.Search.CaseSensitive", searchCaseSensitive, res);
  298. Configuration.GetBoolean("Applications.PET.Search.HighlightAll", searchHighlightAll, res);
  299. END Load;
  300. END Settings;
  301. TYPE
  302. CaptionObject = OBJECT
  303. VAR caption : ARRAY 128 OF CHAR;
  304. PROCEDURE &New*(CONST caption: ARRAY OF CHAR);
  305. BEGIN
  306. COPY(caption, SELF.caption);
  307. END New;
  308. END CaptionObject;
  309. TYPE
  310. (* Association between a text position and a key combination *)
  311. Position = OBJECT
  312. VAR
  313. marker : WMTextView.PositionMarker;
  314. ucs, keysym : LONGINT; flags : SET;
  315. next : Position;
  316. PROCEDURE &Init*(ucs, keysym : LONGINT; flags : SET);
  317. BEGIN
  318. SELF.ucs := ucs; SELF.keysym := keysym; SELF.flags := flags;
  319. marker := NIL; next := NIL;
  320. END Init;
  321. END Position;
  322. (* Store and Recall cursor positions in the main editor. Flags are ignored for now *)
  323. Positions = OBJECT
  324. VAR
  325. textView : WMTextView.TextView;
  326. positions : Position;
  327. PROCEDURE &Init*(textView : WMTextView.TextView);
  328. BEGIN
  329. ASSERT(textView # NIL);
  330. SELF.textView := textView;
  331. END Init;
  332. PROCEDURE FindPosition(ucs, keysym : LONGINT; flags : SET) : Position;
  333. VAR p : Position;
  334. BEGIN
  335. p := positions;
  336. WHILE (p # NIL) & ~((p.ucs = ucs) & (p.keysym = keysym) & (p.flags = flags)) DO
  337. p := p.next;
  338. END;
  339. RETURN p;
  340. END FindPosition;
  341. (* Associate current cursor position with the spec ified key combination. *)
  342. PROCEDURE StoreCurrentPosition(ucs, keysym : LONGINT; flags : SET);
  343. VAR newPosition : Position; intPos : LONGINT;
  344. BEGIN
  345. ASSERT(flags * { Inputs.Release} = {});
  346. newPosition := FindPosition(ucs, keysym, flags);
  347. IF (newPosition = NIL) THEN
  348. NEW(newPosition, ucs, keysym, flags);
  349. newPosition.marker := textView.CreatePositionMarker();
  350. newPosition.marker.SetVisible(FALSE);
  351. newPosition.next := positions;
  352. positions := newPosition;
  353. END;
  354. intPos := textView.GetInternalPos(textView.cursor.GetPosition());
  355. newPosition.marker.SetPosition(intPos);
  356. END StoreCurrentPosition;
  357. PROCEDURE RecallPosition(ucs, keysym : LONGINT; flags : SET);
  358. VAR position : Position;
  359. BEGIN
  360. position := FindPosition(ucs, keysym, flags);
  361. IF (position # NIL) THEN
  362. textView.cursor.SetPosition(position.marker.GetPosition());
  363. END;
  364. END RecallPosition;
  365. END Positions;
  366. TYPE
  367. ScratchPanel = OBJECT(WMComponents.VisualComponent)
  368. VAR
  369. editor : WMEditors.Editor;
  370. label : WMStandardComponents.Label;
  371. PROCEDURE &Init*;
  372. BEGIN
  373. Init^;
  374. SetNameAsString(StrScratchPanel);
  375. NEW(label); label.alignment.Set(WMComponents.AlignTop); label.bounds.SetHeight(20);
  376. label.fillColor.Set(0CCCCCCFFH); label.caption.SetAOC(" Scratch Text");
  377. AddContent(label);
  378. NEW(editor); editor.alignment.Set(WMComponents.AlignClient);
  379. editor.tv.showBorder.Set(TRUE);
  380. AddContent(editor);
  381. editor.SetText(scratchText)
  382. END Init;
  383. PROCEDURE SetText(text : Texts.Text);
  384. BEGIN
  385. ASSERT(text # NIL);
  386. editor.SetText(text);
  387. label.caption.SetAOC(" Project Text");
  388. END SetText;
  389. PROCEDURE Finalize*;
  390. BEGIN
  391. Finalize^;
  392. StoreScratchText;
  393. END Finalize;
  394. END ScratchPanel;
  395. URLDropTarget = OBJECT(WMDropTarget.DropTarget);
  396. VAR win : Window;
  397. PROCEDURE &New*(win : Window);
  398. BEGIN
  399. SELF.win := win
  400. END New;
  401. PROCEDURE GetInterface*(type : LONGINT) : WMDropTarget.DropInterface;
  402. VAR di : DropURL;
  403. BEGIN
  404. IF type = WMDropTarget.TypeURL THEN
  405. NEW(di, SELF.win);
  406. RETURN di
  407. ELSE RETURN NIL
  408. END
  409. END GetInterface;
  410. END URLDropTarget;
  411. DropURL = OBJECT(WMDropTarget.DropURLs)
  412. VAR win : Window;
  413. PROCEDURE &New*(win: Window);
  414. BEGIN
  415. SELF.win := win;
  416. END New;
  417. PROCEDURE URL*(CONST url : ARRAY OF CHAR; VAR res : WORD);
  418. BEGIN
  419. win.Load(url, "AUTO");
  420. res := 0
  421. END URL;
  422. END DropURL;
  423. TYPE
  424. PETPanel = OBJECT(WMComponents.VisualComponent)
  425. VAR
  426. editor, splitEditor : WMEditors.Editor;
  427. logEdit : WMEditors.Editor;
  428. scratchPanel, splitPanel : WMStandardComponents.Panel;
  429. scratch : ScratchPanel;
  430. sidePanel : WMStandardComponents.Panel;
  431. logPanel, editPanel: WMStandardComponents.Panel;
  432. searchPanel: WMSearchComponents.SearchPanel;
  433. errorGrid : WMDiagnostics.DiagnosticsView;
  434. diagnostics : WMDiagnostics.Model;
  435. tree : PETTrees.Tree;
  436. modified, splitted, wrap: BOOLEAN;
  437. focus : LONGINT;
  438. codecFormat: ARRAY 128 OF CHAR;
  439. autoCodecFormat: ARRAY 128 OF CHAR;
  440. name : Filename; (* name of tab (filename without path *)
  441. filename : Filename; (* Filename including path *)
  442. options : CompilerOptions;
  443. compilerSettings : CompilerSettings;
  444. showErrorMarkers : BOOLEAN;
  445. positions : Positions;
  446. owner : Window;
  447. PROCEDURE &InitPanel *(window: Window);
  448. VAR
  449. resizerH, resizerV: WMStandardComponents.Resizer;
  450. um: UndoManager.UndoManager;
  451. colWidths : WMGrids.Spacings;
  452. textViews : ARRAY 2 OF WMTextView.TextView;
  453. BEGIN
  454. Init;
  455. owner := window;
  456. tree := NIL;
  457. SetNameAsString(StrPETPanel);
  458. showErrorMarkers := TRUE;
  459. COPY("Untitled.Mod", filename);
  460. COPY("Untitled.Mod", name);
  461. (* -- left tool area *)
  462. NEW(sidePanel);
  463. sidePanel.bounds.SetWidth(250); sidePanel.alignment.Set(WMComponents.AlignLeft);
  464. AddContent(sidePanel);
  465. NEW(resizerH); resizerH.alignment.Set(WMComponents.AlignRight);
  466. resizerH.bounds.SetWidth(4);
  467. sidePanel.AddContent(resizerH);
  468. (* scratch panel *)
  469. NEW(scratchPanel);
  470. scratchPanel.bounds.SetHeight(250); scratchPanel.alignment.Set(WMComponents.AlignBottom);
  471. NEW(resizerV); resizerV.alignment.Set(WMComponents.AlignTop);
  472. resizerV.bounds.SetHeight(4);
  473. scratchPanel.AddContent(resizerV);
  474. NEW(scratch); scratch.alignment.Set(WMComponents.AlignClient);
  475. scratch.editor.tv.commandCaller := window;
  476. scratchPanel.AddContent(scratch);
  477. sidePanel.AddContent(scratchPanel);
  478. (* -- Editor Area *)
  479. NEW(editPanel); editPanel.alignment.Set(WMComponents.AlignClient);
  480. AddContent(editPanel);
  481. NEW(logPanel);
  482. logPanel.alignment.Set(WMComponents.AlignBottom);
  483. logPanel.bounds.SetHeight(130);
  484. NEW(resizerH); resizerH.alignment.Set(WMComponents.AlignTop);
  485. resizerH.bounds.SetHeight(4);
  486. logPanel.AddContent(resizerH);
  487. NEW(logEdit); logEdit.bounds.SetHeight(30); logEdit.alignment.Set(WMComponents.AlignBottom);
  488. logEdit.allowScrollbars.Set(FALSE);
  489. logEdit.tv.showBorder.Set(TRUE); logEdit.visible.Set(FALSE);
  490. NEW(resizerV); resizerV.alignment.Set(WMComponents.AlignTop);
  491. resizerV.bounds.SetHeight(4);
  492. logEdit.AddContent(resizerV);
  493. editPanel.AddContent(logEdit);
  494. editPanel.AddContent(logPanel);
  495. NEW(diagnostics);
  496. NEW(errorGrid);
  497. errorGrid.SetModel(diagnostics);
  498. errorGrid.alignment.Set(WMComponents.AlignClient);
  499. errorGrid.nofCols.Set(3);
  500. errorGrid.fixedRows.Set(1);
  501. errorGrid.adjustFocusPosition.Set(FALSE);
  502. NEW(colWidths, 3);
  503. colWidths[0] := 60;
  504. colWidths[1] := 40;
  505. colWidths[2] := 2048;
  506. errorGrid.SetColSpacings(colWidths);
  507. errorGrid.onClick.Add(ErrorClick);
  508. errorGrid.SetSelectionMode(WMGrids.GridSelectSingleRow);
  509. errorGrid.visible.Set(FALSE);
  510. logPanel.AddContent(errorGrid);
  511. NEW(searchPanel);
  512. searchPanel.alignment.Set(WMComponents.AlignBottom);
  513. searchPanel.bounds.SetHeight(40); searchPanel.visible.Set(FALSE);
  514. editPanel.AddContent(searchPanel);
  515. NEW(splitPanel);
  516. splitPanel.alignment.Set(WMComponents.AlignBottom);
  517. splitPanel.bounds.SetHeight(400);
  518. editPanel.AddContent(splitPanel);
  519. NEW(editor); editor.alignment.Set(WMComponents.AlignClient); editor.tv.showBorder.Set(TRUE);
  520. editor.tv.SetExtFocusHandler(EditorFocusHandler);
  521. editPanel.AddContent(editor);
  522. editor.macros.Add(WMMacros.Handle);
  523. editor.multiLine.Set(TRUE);
  524. editor.tv.wrapMode.Set(WMTextView.NoWrap);
  525. editor.tv.onCursorChanged := CursorChanged;
  526. editor.tv.commandCaller := window;
  527. editor.text.onTextChanged.Add(TextChanged);
  528. editor.tv.showLineNumbers.Set(settings.showLineNumbers);
  529. editor.tv.indicateTabs.Set(settings.indicateTabs);
  530. editor.tv.clBgCurrentLine.Set(settings.currentLineColor);
  531. NEW(positions, editor.tv);
  532. searchPanel.SetText(editor.text);
  533. NEW(resizerV);
  534. resizerV.bounds.SetHeight(5); resizerV.alignment.Set(WMComponents.AlignTop);
  535. resizerV.fillColor.Set(0808080FFH);
  536. splitPanel.AddContent(resizerV);
  537. NEW(splitEditor); splitEditor.alignment.Set(WMComponents.AlignClient); splitEditor.tv.showBorder.Set(TRUE);
  538. splitEditor.tv.SetExtFocusHandler(SplitEditorFocusHandler);
  539. splitPanel.AddContent(splitEditor);
  540. splitEditor.macros.Add(WMMacros.Handle);
  541. splitEditor.multiLine.Set(TRUE);
  542. splitEditor.tv.wrapMode.Set(WMTextView.NoWrap);
  543. splitEditor.tv.commandCaller := window;
  544. splitEditor.SetText(editor.text);
  545. splitEditor.tv.showLineNumbers.Set(settings.showLineNumbers);
  546. splitEditor.tv.indicateTabs.Set(settings.indicateTabs);
  547. splitEditor.tv.clBgCurrentLine.Set(settings.currentLineColor);
  548. textViews[0] := editor.tv;
  549. textViews[1] := splitEditor.tv;
  550. errorGrid.SetTextViews(textViews);
  551. logPanel.visible.Set(FALSE);
  552. splitPanel.visible.Set(FALSE);
  553. modified := FALSE;
  554. splitted := FALSE;
  555. wrap := FALSE;
  556. codecFormat := "AUTO";
  557. autoCodecFormat := DefaultTextFormat;
  558. options := settings.defaultCompilerOptions;
  559. NEW(um, 1001, TRUE);
  560. editor.text.SetUndoManager(um);
  561. editor.SetUndoManager(um);
  562. END InitPanel;
  563. PROCEDURE CreateSidePanel(settings : CompilerSettings);
  564. VAR factory : PETTrees.Factory; strings : Strings.StringArray;
  565. BEGIN
  566. IF (tree # NIL) THEN sidePanel.RemoveContent(tree); tree := NIL END;
  567. IF settings.fileExtension = "MOD" THEN
  568. GETPROCEDURE("TFModuleTrees", "GenModuleTree", factory);
  569. IF (factory # NIL) THEN
  570. tree := factory();
  571. END
  572. ELSE
  573. IF (settings.genTree # "") THEN
  574. strings := Strings.Split(settings.genTree, ".");
  575. IF (LEN(strings) = 2) THEN
  576. GETPROCEDURE(strings[0]^, strings[1]^, factory);
  577. IF (factory # NIL) THEN
  578. tree := factory();
  579. END;
  580. END
  581. END
  582. END;
  583. IF (tree # NIL) THEN
  584. tree.alignment.Set(WMComponents.AlignClient);
  585. tree.SetEditor(editor);
  586. tree.onExpandNode.Add(OnNodeExpand);
  587. tree.onGoToFile.Add(OnGoToFile);
  588. tree.onGoToDefinition.Add(OnGoToDefinition);
  589. tree.onRefresh.Add(HandleTreeRefresh);
  590. sidePanel.AddContent(tree);
  591. tree.RefreshHandler(NIL, NIL);
  592. sidePanel.visible.Set(TRUE);
  593. ELSE
  594. sidePanel.visible.Set(FALSE);
  595. scratchPanel.alignment.Set(WMComponents.AlignClient);
  596. scratchPanel.bounds.Set(sidePanel.bounds.Get());
  597. END;
  598. END CreateSidePanel;
  599. PROCEDURE OnGoToFile(sender, data : ANY);
  600. VAR info : PETTrees.ExternalInfo; file : Files.File; filename : Files.FileName;
  601. BEGIN
  602. IF (data # NIL) & (data IS PETTrees.ExternalInfo) THEN
  603. info := data (PETTrees.ExternalInfo);
  604. COPY(info.filename, filename); Strings.Append(filename, ".Mod");
  605. file := Files.Old(filename);
  606. IF (file # NIL) THEN
  607. owner.GotoFile(filename, info.position);
  608. END;
  609. END;
  610. END OnGoToFile;
  611. PROCEDURE OnGoToDefinition(sender, data : ANY);
  612. VAR info : PETTrees.ExternalDefinitionInfo;
  613. BEGIN
  614. IF (data # NIL) & (data IS PETTrees.ExternalDefinitionInfo) THEN
  615. info := data (PETTrees.ExternalDefinitionInfo);
  616. owner.GotoDefinition(info);
  617. END;
  618. END OnGoToDefinition;
  619. PROCEDURE OnNodeExpand (sender, data: ANY);
  620. BEGIN
  621. IF (tree # NIL) THEN tree.SelectNodeByPos (editor.tv.cursor.GetPosition()) END
  622. END OnNodeExpand;
  623. PROCEDURE HandleTreeRefresh(sender, data : ANY);
  624. BEGIN
  625. END HandleTreeRefresh;
  626. PROCEDURE ClearLog;
  627. BEGIN
  628. logEdit.text.AcquireWrite;
  629. logEdit.text.Delete(0, logEdit.text.GetLength());
  630. logEdit.tv.firstLine.Set(0); logEdit.tv.cursor.SetPosition(0);
  631. logEdit.text.ReleaseWrite;
  632. END ClearLog;
  633. PROCEDURE DoCompile(findPC : BOOLEAN; CONST pc :ARRAY OF CHAR; options : CompilerOptions);
  634. VAR
  635. compiler : CompilerInterface.Compiler; tw : TextUtilities.TextWriter; errors : BOOLEAN;
  636. positions : ARRAY 2 OF LONGINT;
  637. type : LONGINT;
  638. BEGIN
  639. ClearLog;
  640. IF findPC THEN Strings.Append(options, " /f") END;
  641. NEW(tw, logEdit.text);
  642. diagnostics.DisableNotification;
  643. diagnostics.Clear;
  644. compiler := CompilerInterface.GetCompilerByName(compilerSettings.name);
  645. IF (compiler = NIL) & (compilerSettings.loadmodule # "") THEN
  646. LoadModule(compilerSettings.loadmodule); (* compiler shall register itself at the CompilerInterface *)
  647. compiler := CompilerInterface.GetCompilerByName(compilerSettings.name);
  648. END;
  649. IF (compiler # NIL) THEN
  650. compiler.CompileText(editor.text, "", 0, pc, options, tw, diagnostics, errors);
  651. IF ~errors THEN
  652. IF tree IS TFModuleTrees.ModuleTree THEN
  653. (* tree(TFModuleTrees.ModuleTree).StoreSymbols(NIL, NIL);*)
  654. END
  655. END;
  656. ELSE
  657. tw.String("No compiler available for file '"); tw.String(filename); tw.String("'");
  658. logPanel.visible.Set(TRUE);
  659. END;
  660. tw.Update;
  661. IF settings.enableWhitespaceWarnings THEN
  662. WhitespaceRemover.CheckWhitespace(editor.text, diagnostics);
  663. END;
  664. diagnostics.EnableNotification;
  665. IF (diagnostics.nofEntries > 0) THEN
  666. errorGrid.GetFirstPosition(positions, type);
  667. IF (focus = EditorFocus) & (positions[0] # Streams.Invalid) THEN
  668. editor.tv.cursor.SetPosition(positions[0]);
  669. editor.SetFocus;
  670. ELSIF (focus = SplitEditorFocus) THEN
  671. splitEditor.tv.cursor.SetPosition(positions[0]);
  672. splitEditor.SetFocus;
  673. END;
  674. CursorChanged;
  675. errorGrid.visible.Set(TRUE);
  676. logPanel.visible.Set(TRUE); logEdit.visible.Set(TRUE);
  677. ELSE
  678. logPanel.visible.Set(FALSE); logEdit.visible.Set(TRUE);
  679. errorGrid.visible.Set(FALSE);
  680. END;
  681. END DoCompile;
  682. PROCEDURE ErrorClick(sender, data : ANY);
  683. VAR
  684. focusEditor: WMEditors.Editor;
  685. entry : WMDiagnostics.ViewEntry;
  686. index: LONGINT;
  687. BEGIN
  688. IF (data # NIL) & (data IS WMDiagnostics.CellInfo) & (data(WMDiagnostics.CellInfo).entryValid) THEN
  689. IF (focus = EditorFocus) THEN focusEditor := editor; index := 0;
  690. ELSIF (focus = SplitEditorFocus) THEN focusEditor := splitEditor; index := 1;
  691. ELSE
  692. HALT(99);
  693. END;
  694. entry := data(WMDiagnostics.CellInfo).entry;
  695. IF (entry.pos # NIL) & (LEN(entry.pos) = 2) & (entry.pos[index] # NIL) THEN
  696. focusEditor.tv.selection.SetFromTo(0, 0);
  697. focusEditor.tv.cursor.SetPosition(entry.pos[index].GetPosition());
  698. focusEditor.SetFocus;
  699. END;
  700. END;
  701. END ErrorClick;
  702. PROCEDURE GoToNextError(forward : BOOLEAN);
  703. VAR nearestPosition, row, index : LONGINT; focusEditor: WMEditors.Editor;
  704. BEGIN
  705. IF focus = EditorFocus THEN focusEditor := editor; index := 0;
  706. ELSIF focus = SplitEditorFocus THEN focusEditor := splitEditor; index := 1;
  707. ELSE RETURN;
  708. END;
  709. focusEditor.tv.selection.SetFromTo(0, 0);
  710. errorGrid.GetNearestPosition(editor.tv.cursor.GetPosition(), index, forward, nearestPosition, row);
  711. editor.tv.cursor.SetPosition(nearestPosition);
  712. errorGrid.SelectEntry(row, TRUE);
  713. END GoToNextError;
  714. PROCEDURE EditorFocusHandler(hasFocus: BOOLEAN);
  715. BEGIN
  716. IF hasFocus THEN
  717. focus := EditorFocus;
  718. searchPanel.SetTextView(editor.tv);
  719. IF (tree # NIL) THEN tree.SetEditor(editor) END;
  720. END;
  721. END EditorFocusHandler;
  722. PROCEDURE SplitEditorFocusHandler(hasFocus: BOOLEAN);
  723. BEGIN
  724. IF hasFocus THEN
  725. focus := SplitEditorFocus;
  726. searchPanel.SetTextView(splitEditor.tv);
  727. IF (tree # NIL) THEN tree.SetEditor(splitEditor) END;
  728. END
  729. END SplitEditorFocusHandler;
  730. PROCEDURE ToggleLabels;
  731. BEGIN
  732. IF editor.tv.showLabels.Get() THEN
  733. editor.tv.showLabels.Set(FALSE);
  734. splitEditor.tv.showLabels.Set(FALSE);
  735. ELSE
  736. editor.tv.showLabels.Set(TRUE);
  737. splitEditor.tv.showLabels.Set(TRUE);
  738. END;
  739. Invalidate;
  740. END ToggleLabels;
  741. PROCEDURE ToggleWrap;
  742. BEGIN
  743. IF (editor.tv.wrapMode.Get() = WMTextView.WrapWord) THEN
  744. editor.tv.wrapMode.Set(WMTextView.NoWrap);
  745. splitEditor.tv.wrapMode.Set(WMTextView.NoWrap);
  746. ELSE
  747. editor.tv.wrapMode.Set(WMTextView.WrapWord);
  748. splitEditor.tv.wrapMode.Set(WMTextView.WrapWord);
  749. END;
  750. wrap := ~wrap;
  751. END ToggleWrap;
  752. PROCEDURE TextChanged(sender, data : ANY);
  753. BEGIN
  754. IF logPanel.visible.Get() THEN
  755. logPanel.Invalidate
  756. END;
  757. IF ~modified THEN
  758. IF (owner # NIL) THEN owner.SetModified(TRUE) END;
  759. modified := TRUE
  760. END;
  761. CursorChanged
  762. END TextChanged;
  763. PROCEDURE CursorChanged;
  764. VAR position : LONGINT; pos : ARRAY 16 OF CHAR;
  765. BEGIN
  766. position := editor.tv.cursor.GetPosition();
  767. Strings.IntToStr(position, pos);
  768. owner.positionEdit.SetAsString(pos);
  769. IF (tree # NIL) THEN tree.SelectNodeByPos (position) END
  770. END CursorChanged;
  771. PROCEDURE HandleShortcut(ucs : LONGINT; flags : SET; keysym : LONGINT) : BOOLEAN;
  772. VAR pos : LONGINT;
  773. PROCEDURE HandlePreviousNext(forward : BOOLEAN);
  774. BEGIN
  775. IF (focus = EditorFocus) THEN
  776. editor.SetFocus;
  777. ELSE
  778. splitEditor.SetFocus;
  779. END;
  780. IF searchPanel.visible.Get() THEN
  781. searchPanel.HandlePreviousNext(forward);
  782. ELSIF errorGrid.visible.Get() THEN
  783. GoToNextError(forward);
  784. END;
  785. CursorChanged;
  786. END HandlePreviousNext;
  787. PROCEDURE HandleDiff;
  788. VAR
  789. filename, string : Filename; context : Commands.Context; res : WORD;
  790. arg : Streams.StringReader;
  791. BEGIN
  792. IF (settings.diffCommand = "") THEN
  793. WMDialogs.Error(WindowTitle, "No diff command specified");
  794. RETURN;
  795. END;
  796. COPY(settings.diffPrefix, filename);
  797. Strings.Append(filename, SELF.filename);
  798. Strings.Append(filename, settings.diffSuffix);
  799. IF (WMDialogs.QueryString("Diff to file...", filename) = WMDialogs.ResOk) THEN
  800. string := ""; Strings.Append(string, filename); Strings.Append(string, " "); Strings.Append(string, SELF.filename);
  801. NEW(arg, LEN(string)); arg.SetRaw(string, 0, LEN(string));
  802. NEW(context, NIL, arg, NIL, NIL, owner);
  803. Commands.Activate(settings.diffCommand, context, {}, res, string);
  804. IF (res # Commands.Ok) THEN
  805. WMDialogs.Error(WindowTitle, string);
  806. END;
  807. END;
  808. END HandleDiff;
  809. PROCEDURE HandlePositions;
  810. BEGIN
  811. IF (flags * Inputs.Ctrl # {}) THEN
  812. positions.RecallPosition(ucs, keysym, flags - Inputs.Ctrl);
  813. ELSE (* ShiftKeyDown(flags) *)
  814. positions.StoreCurrentPosition(ucs, keysym, flags - Inputs.Shift);
  815. END;
  816. END HandlePositions;
  817. PROCEDURE RemoveWhitespace;
  818. VAR tw : TextUtilities.TextWriter; nofRemoved : LONGINT;
  819. BEGIN
  820. ClearLog;
  821. NEW(tw, logEdit.text);
  822. WhitespaceRemover.RemoveFromText(editor.text, nofRemoved);
  823. tw.String("Removed "); tw.Int(nofRemoved, 0); tw.String(" end-of-line whitespace"); tw.Update;
  824. logEdit.visible.Set(TRUE);
  825. END RemoveWhitespace;
  826. PROCEDURE HandleComments(remove : BOOLEAN);
  827. VAR editor : WMEditors.Editor;
  828. BEGIN
  829. IF (focus = EditorFocus) THEN editor := SELF.editor; ELSE editor := splitEditor; END;
  830. editor.text.AcquireWrite;
  831. editor.tv.selection.Sort;
  832. IF (editor.tv.selection.a # editor.tv.selection.b) THEN
  833. IF remove THEN
  834. UncommentSelection(editor.text, editor.tv.selection.from, editor.tv.selection.to);
  835. ELSE
  836. CommentSelection(editor.text, editor.tv.selection.from, editor.tv.selection.to);
  837. END;
  838. END;
  839. editor.text.ReleaseWrite;
  840. END HandleComments;
  841. BEGIN
  842. IF (keysym = 06H) & ControlKeyDown(flags)THEN (* CTRL-F *)
  843. searchPanel.ToggleVisibility;
  844. ELSIF (keysym= 0EH) & ControlKeyDown(flags) THEN (* CTRL-N *)
  845. HandlePreviousNext(TRUE);
  846. ELSIF (keysym = 10H) & ControlKeyDown(flags) THEN (* CTRL-P *)
  847. HandlePreviousNext(FALSE);
  848. ELSIF (keysym = 0DH) & ControlKeyDown(flags) THEN (* CTRL-M *)
  849. IF sidePanel.visible.Get() THEN sidePanel.visible.Set(FALSE);
  850. ELSE sidePanel.visible.Set(TRUE);
  851. END;
  852. ELSIF (keysym = 04H) & ControlKeyDown(flags) THEN (* CTRL-D *)
  853. HandleDiff;
  854. ELSIF (keysym = 30H) & ControlKeyDown(flags) THEN (* CTRL- 0 *)
  855. IF (focus = EditorFocus) THEN
  856. editor.tv.cursor.SetPosition(0);
  857. ELSE
  858. splitEditor.tv.cursor.SetPosition(0);
  859. END;
  860. ELSIF (keysym = 39H) & ControlKeyDown(flags) THEN (* CTRL - 0 *)
  861. IF (focus = EditorFocus) THEN
  862. editor.text.AcquireRead; pos := editor.text.GetLength()-1; editor.text.ReleaseRead;
  863. editor.tv.cursor.SetPosition(pos);
  864. ELSE
  865. splitEditor.text.AcquireRead; pos := splitEditor.text.GetLength()-1; splitEditor.text.ReleaseRead;
  866. splitEditor.tv.cursor.SetPosition(pos);
  867. END;
  868. ELSIF (0FFBEH <= keysym) & (keysym <= 0FFC9H) & EitherShiftOrControlDown(flags) THEN
  869. HandlePositions;
  870. ELSIF (keysym = Inputs.KsTab) & (flags = {}) THEN (* TAB *)
  871. RETURN searchPanel.HandleTab();
  872. ELSIF (keysym = Inputs.KsDelete) & ControlKeyDown(flags) THEN (* CTRL-DELETE *)
  873. RemoveWhitespace;
  874. ELSIF (keysym = Inputs.KsInsert) & (flags * Inputs.Alt # {}) THEN
  875. HandleComments(FALSE);
  876. ELSIF (keysym = Inputs.KsDelete) & (flags * Inputs.Alt # {}) THEN
  877. HandleComments(TRUE);
  878. ELSE
  879. RETURN FALSE; (* Key not handled *)
  880. END;
  881. RETURN TRUE;
  882. END HandleShortcut;
  883. PROCEDURE Finalize*;
  884. BEGIN
  885. Finalize^;
  886. IF (editor # NIL) & (editor.text # NIL) THEN
  887. editor.text.onTextChanged.Remove(TextChanged);
  888. editor.tv.onCursorChanged := NIL;
  889. IF editor.undoMgr # NIL THEN
  890. editor.undoMgr.nrUpdatesListener := NIL;
  891. END;
  892. END;
  893. END Finalize;
  894. END PETPanel;
  895. TYPE
  896. KillerMsg = OBJECT
  897. END KillerMsg;
  898. BrowseEntry = POINTER TO RECORD
  899. prev, next : BrowseEntry;
  900. filename : Filename;
  901. pos : LONGINT;
  902. END;
  903. Window = OBJECT (WMComponents.FormWindow)
  904. VAR
  905. filenameEdit, optionsEdit, positionEdit: WMEditors.Editor;
  906. loadBtn, storeBtn, closeBtn, compileBtn, findPCBtn, undoBtn, redoBtn: WMStandardComponents.Button;
  907. splitBtn, formatBtn, searchBtn, labelsBtn, wrapBtn, forwardBtn, backBtn : WMStandardComponents.Button;
  908. popup: WMPopups.Popup;
  909. tabs : WMTabComponents.Tabs;
  910. pages : ARRAY MaxNbrOfTabs OF PETPanel;
  911. tabList : ARRAY MaxNbrOfTabs OF WMTabComponents.Tab;
  912. currentPage : PETPanel;
  913. currentPageNr : LONGINT;
  914. page : WMStandardComponents.Panel;
  915. xmlHasErrors : BOOLEAN;
  916. codecFormat: ARRAY 128 OF CHAR;
  917. autoCodecFormat: ARRAY 128 OF CHAR;
  918. projectText : Texts.Text;
  919. projectTextFilename : Filename;
  920. projectTextModified : BOOLEAN;
  921. showTypeHierarchy, showImportedModules : BOOLEAN;
  922. windowInfo : WMWindowManager.WindowInfo;
  923. (* window icons handling *)
  924. currentIcon : WMGraphics.Image;
  925. iconIdle, iconWorking : WMGraphics.Image;
  926. modifierFlags : SET;
  927. browseBase, browseTOS : BrowseEntry;
  928. PROCEDURE &New*(c : WMRestorable.Context);
  929. VAR vc : WMComponents.VisualComponent;
  930. BEGIN
  931. IncCount;
  932. InitCodecs;
  933. vc := CreateForm();
  934. currentPageNr := -1;
  935. projectTextFilename := "";
  936. projectText := NIL;
  937. projectTextModified := FALSE;
  938. tabs.onSelectTab.Add(TabSelected);
  939. showTypeHierarchy := FALSE;
  940. showImportedModules := FALSE;
  941. modifierFlags := {};
  942. IF (c # NIL) THEN
  943. Init(c.r - c.l, c.b - c.t, FALSE);
  944. ELSE
  945. Init(WindowWidth, WindowHeight, FALSE);
  946. END;
  947. SetContent(vc);
  948. SetTitle(Strings.NewString(WindowTitle));
  949. currentIcon := NIL;
  950. iconIdle := WMGraphics.LoadImage("WMIcons.tar://PETIdle.png", TRUE);
  951. iconWorking := WMGraphics.LoadImage("WMIcons.tar://PET.png", TRUE);
  952. IF (iconIdle = NIL) THEN
  953. iconIdle := iconWorking;
  954. ELSIF (iconWorking = NIL) THEN
  955. iconWorking := iconIdle;
  956. END;
  957. SetIcon(iconIdle);
  958. IF c # NIL THEN (* restore the desktop *)
  959. WMRestorable.AddByContext(SELF, c);
  960. IF c.appData # NIL THEN
  961. DisableUpdate;
  962. LoadPages(c.appData(XML.Element));
  963. EnableUpdate;
  964. END;
  965. vc.Invalidate;
  966. ELSE WMWindowManager.DefaultAddWindow(SELF);
  967. (* NewTab; *)
  968. codecFormat := "AUTO";
  969. autoCodecFormat := DefaultTextFormat;
  970. SetFormatCaption("AUTO");
  971. END;
  972. NEW(browseBase); (* sentinel *)
  973. browseBase.prev := browseBase;
  974. browseTOS := browseBase
  975. END New;
  976. PROCEDURE CreateForm():WMComponents.VisualComponent;
  977. VAR
  978. panel, resizerPanel : WMStandardComponents.Panel;
  979. resizer : WMStandardComponents.Resizer;
  980. posLabel : WMStandardComponents.Label;
  981. font: WMGraphics.Font;
  982. dx, dy: LONGINT;
  983. PROCEDURE CreateToolbar() : WMComponents.VisualComponent;
  984. VAR toolbar : WMStandardComponents.Panel;
  985. BEGIN
  986. (* -- top toolbar *)
  987. NEW(toolbar); toolbar.bounds.SetHeight(20); toolbar.alignment.Set(WMComponents.AlignTop);
  988. NEW(resizerPanel);
  989. resizerPanel.alignment.Set(WMComponents.AlignLeft);
  990. resizerPanel.bounds.SetWidth(200);
  991. toolbar.AddContent(resizerPanel);
  992. NEW(resizer);
  993. resizer.alignment.Set(WMComponents.AlignRight);
  994. resizer.bounds.SetWidth(4);
  995. resizerPanel.AddContent(resizer);
  996. NEW(filenameEdit); filenameEdit.alignment.Set(WMComponents.AlignClient);
  997. filenameEdit.multiLine.Set(FALSE); filenameEdit.bounds.SetWidth(200);
  998. filenameEdit.fillColor.Set(0FFFFFFFFH);
  999. filenameEdit.tv.textAlignV.Set(WMGraphics.AlignCenter);
  1000. filenameEdit.tv.showBorder.Set(TRUE);
  1001. filenameEdit.tv.borders.Set(WMRectangles.MakeRect(3,3,1,1));
  1002. filenameEdit.tv.commandCaller := SELF;
  1003. filenameEdit.onEnter.Add(LoadHandler);
  1004. filenameEdit.onEscape.Add(FilenameEditEscapeHandler);
  1005. resizerPanel.AddContent(filenameEdit);
  1006. NEW(loadBtn); loadBtn.caption.SetAOC("Load"); loadBtn.alignment.Set(WMComponents.AlignLeft);
  1007. loadBtn.onClick.Add(LoadHandler);
  1008. toolbar.AddContent(loadBtn);
  1009. NEW(storeBtn); storeBtn.caption.SetAOC("Store"); storeBtn.alignment.Set(WMComponents.AlignLeft);
  1010. storeBtn.onClick.Add(StoreHandler);
  1011. toolbar.AddContent(storeBtn);
  1012. NEW(closeBtn); closeBtn.caption.SetAOC("Close"); closeBtn.alignment.Set(WMComponents.AlignLeft);
  1013. closeBtn.onClick.Add(CloseHandler);
  1014. toolbar.AddContent(closeBtn);
  1015. NEW(formatBtn); formatBtn.caption.SetAOC("Format : ---"); formatBtn.alignment.Set(WMComponents.AlignLeft);
  1016. formatBtn.SetExtPointerDownHandler(FormatHandler);
  1017. formatBtn.bounds.SetWidth(3 * formatBtn.bounds.GetWidth());
  1018. toolbar.AddContent(formatBtn);
  1019. NEW(searchBtn); searchBtn.caption.SetAOC("Search"); searchBtn.alignment.Set(WMComponents.AlignLeft);
  1020. searchBtn.onClick.Add(ButtonHandler);
  1021. toolbar.AddContent(searchBtn);
  1022. NEW(compileBtn); compileBtn.caption.SetAOC("Compile"); compileBtn.alignment.Set(WMComponents.AlignLeft);
  1023. compileBtn.onClick.Add(ButtonHandler);
  1024. toolbar.AddContent(compileBtn);
  1025. NEW(findPCBtn); findPCBtn.caption.SetAOC("Find PC"); findPCBtn.alignment.Set(WMComponents.AlignLeft);
  1026. findPCBtn.onClick.Add(FindPC);
  1027. toolbar.AddContent(findPCBtn);
  1028. NEW(undoBtn);
  1029. font := undoBtn.GetFont();
  1030. font.GetStringSize(" Undo (000) ", dx, dy);
  1031. undoBtn.bounds.SetWidth(dx);
  1032. undoBtn.caption.SetAOC("Undo"); undoBtn.alignment.Set(WMComponents.AlignLeft);
  1033. undoBtn.onClick.Add(ButtonHandler);
  1034. toolbar.AddContent(undoBtn);
  1035. NEW(redoBtn);
  1036. font := redoBtn.GetFont();
  1037. font.GetStringSize(" Redo (000) ", dx, dy);
  1038. redoBtn.bounds.SetWidth(dx);
  1039. redoBtn.caption.SetAOC("Redo"); redoBtn.alignment.Set(WMComponents.AlignLeft);
  1040. redoBtn.onClick.Add(ButtonHandler);
  1041. toolbar.AddContent(redoBtn);
  1042. NEW(optionsEdit); optionsEdit.tv.showBorder.Set(TRUE); optionsEdit.tv.borders.Set(WMRectangles.MakeRect(3,3,1,1));
  1043. optionsEdit.alignment.Set(WMComponents.AlignClient); optionsEdit.multiLine.Set(FALSE);
  1044. optionsEdit.tv.textAlignV.Set(WMGraphics.AlignCenter);
  1045. optionsEdit.bounds.SetWidth(80); optionsEdit.fillColor.Set(0FFFFFFFFH);
  1046. optionsEdit.SetAsString(settings.defaultCompilerOptions);
  1047. toolbar.AddContent(optionsEdit);
  1048. RETURN toolbar;
  1049. END CreateToolbar;
  1050. PROCEDURE CreateStatusbar() : WMComponents.VisualComponent;
  1051. VAR statusbar : WMStandardComponents.Panel;
  1052. BEGIN
  1053. NEW(statusbar); statusbar.bounds.SetHeight(20); statusbar.alignment.Set(WMComponents.AlignBottom); statusbar.fillColor.Set(0CCCCCCFFH);
  1054. NEW(posLabel); posLabel.caption.SetAOC(" Position: "); posLabel.bounds.SetWidth(60); posLabel.alignment.Set(WMComponents.AlignLeft);
  1055. statusbar.AddContent(posLabel); posLabel.textColor.Set(0000000FFH);
  1056. NEW(positionEdit); positionEdit.tv.showBorder.Set(TRUE); positionEdit.tv.borders.Set(WMRectangles.MakeRect(3,3,1,1));
  1057. positionEdit.alignment.Set(WMComponents.AlignLeft); positionEdit.multiLine.Set(FALSE);
  1058. positionEdit.tv.textAlignV.Set(WMGraphics.AlignCenter);
  1059. positionEdit.bounds.SetWidth(80); positionEdit.fillColor.Set(0FFFFFFFFH); positionEdit.onEnter.Add(PositionHandler);
  1060. statusbar.AddContent(positionEdit);
  1061. NEW(splitBtn); splitBtn.caption.SetAOC("Split"); splitBtn.alignment.Set(WMComponents.AlignRight);
  1062. splitBtn.onClick.Add(SplitHandler);
  1063. splitBtn.isToggle.Set(TRUE); splitBtn.SetPressed(FALSE);
  1064. statusbar.AddContent(splitBtn);
  1065. NEW(labelsBtn); labelsBtn.caption.SetAOC("Labels"); labelsBtn.alignment.Set(WMComponents.AlignRight);
  1066. labelsBtn.isToggle.Set(TRUE); labelsBtn.SetPressed(FALSE);
  1067. labelsBtn.onClick.Add(ButtonHandler);
  1068. statusbar.AddContent(labelsBtn);
  1069. NEW(wrapBtn); wrapBtn.caption.SetAOC("Wrap"); wrapBtn.alignment.Set(WMComponents.AlignRight);
  1070. wrapBtn.isToggle.Set(TRUE); wrapBtn.SetPressed(FALSE);
  1071. wrapBtn.onClick.Add(ButtonHandler);
  1072. statusbar.AddContent(wrapBtn);
  1073. NEW(forwardBtn); forwardBtn.caption.SetAOC("-->"); forwardBtn.alignment.Set(WMComponents.AlignRight);
  1074. forwardBtn.onClick.Add(ButtonHandler);
  1075. statusbar.AddContent(forwardBtn);
  1076. NEW(backBtn); backBtn.caption.SetAOC("<--"); backBtn.alignment.Set(WMComponents.AlignRight);
  1077. backBtn.onClick.Add(ButtonHandler);
  1078. statusbar.AddContent(backBtn);
  1079. RETURN statusbar;
  1080. END CreateStatusbar;
  1081. BEGIN
  1082. (* -- Main Panel holding the tabs, toolbar and tabcontents (instance of PETPanel) *)
  1083. NEW(panel); panel.alignment.Set(WMComponents.AlignClient); panel.fillColor.Set(0FFFFFFFFH); panel.takesFocus.Set(TRUE);
  1084. (* -- Tabs for the PETPanels *)
  1085. NEW(tabs); tabs.fillColor.Set(00000CCCCH); tabs.bounds.SetHeight(20); tabs.alignment.Set(WMComponents.AlignTop);
  1086. panel.AddContent(tabs); tabs.SetExtDragDroppedHandler(DragDroppedHandler);
  1087. panel.AddContent(CreateToolbar());
  1088. panel.AddContent(CreateStatusbar());
  1089. (* -- Page holding the PETPanel *)
  1090. NEW(page); page.fillColor.Set(0CCCCCCFFH); page.alignment.Set(WMComponents.AlignClient);
  1091. panel.AddContent(page);
  1092. RETURN panel;
  1093. END CreateForm;
  1094. PROCEDURE ButtonHandler(sender, data : ANY);
  1095. VAR options : CompilerOptions; searchString : SearchString; res : WORD;
  1096. BEGIN
  1097. IF sender = undoBtn THEN
  1098. currentPage.editor.Undo;
  1099. ELSIF sender = redoBtn THEN
  1100. currentPage.editor.Redo;
  1101. ELSIF sender = searchBtn THEN
  1102. IF (currentPage # NIL) THEN
  1103. currentPage.searchPanel.visible.Set(TRUE);
  1104. currentPage.searchPanel.SetToLastSelection;
  1105. currentPage.searchPanel.searchEdit.GetAsString(searchString);
  1106. IF (searchString # "") THEN
  1107. currentPage.searchPanel.SearchHandler(NIL, NIL);
  1108. ELSE
  1109. currentPage.searchPanel.searchEdit.SetFocus;
  1110. END;
  1111. END;
  1112. ELSIF sender = labelsBtn THEN
  1113. IF (currentPage # NIL) THEN currentPage.ToggleLabels; END;
  1114. ELSIF sender = compileBtn THEN
  1115. IF currentPage # NIL THEN
  1116. IF (settings.backupOnCompile) THEN
  1117. TextUtilities.StoreOberonText(currentPage.editor.text, BackupOnCompileFilename, res);
  1118. IF (res = 0) THEN
  1119. KernelLog.String("PET: Backup stored in "); KernelLog.String(BackupOnCompileFilename); KernelLog.Ln;
  1120. ELSE
  1121. KernelLog.String("PET: Warning: Backup-on-compile file creating failed."); KernelLog.Ln;
  1122. END;
  1123. END;
  1124. optionsEdit.GetAsString(options);
  1125. currentPage.DoCompile(FALSE, "", options);
  1126. END;
  1127. ELSIF sender = wrapBtn THEN
  1128. IF (currentPage # NIL) THEN
  1129. currentPage.ToggleWrap;
  1130. END;
  1131. ELSIF sender = backBtn THEN
  1132. BrowseBack
  1133. ELSIF sender = forwardBtn THEN
  1134. BrowseForward
  1135. END;
  1136. END ButtonHandler;
  1137. PROCEDURE NrUpdatesChanged(nrUndos, nrRedos: LONGINT);
  1138. VAR lbl, str: ARRAY 32 OF CHAR;
  1139. BEGIN
  1140. IF nrUndos = 0 THEN
  1141. undoBtn.enabled.Set(FALSE);
  1142. undoBtn.clDefault.Set(999999FFH);
  1143. ELSE
  1144. undoBtn.enabled.Set(TRUE);
  1145. undoBtn.clDefault.Reset;
  1146. END;
  1147. lbl := "Undo (";
  1148. Strings.IntToStr(nrUndos, str);
  1149. Strings.Append(lbl, str);
  1150. Strings.Append(lbl, ")");
  1151. undoBtn.caption.SetAOC(lbl);
  1152. IF nrRedos = 0 THEN
  1153. redoBtn.enabled.Set(FALSE);
  1154. redoBtn.clDefault.Set(999999FFH);
  1155. ELSE
  1156. redoBtn.enabled.Set(TRUE);
  1157. redoBtn.clDefault.Reset;
  1158. END;
  1159. lbl := "Redo (";
  1160. Strings.IntToStr(nrRedos, str);
  1161. Strings.Append(lbl, str);
  1162. Strings.Append(lbl, ")");
  1163. redoBtn.caption.SetAOC(lbl);
  1164. END NrUpdatesChanged;
  1165. PROCEDURE ProjectTextModified(sender, data : ANY);
  1166. BEGIN
  1167. projectTextModified :=TRUE;
  1168. END ProjectTextModified;
  1169. PROCEDURE InitCodecs;
  1170. VAR caption: CaptionObject;
  1171. elem: XML.Element; enum: XMLObjects.Enumerator; ptr: ANY; str : Strings.String;
  1172. BEGIN
  1173. NEW(popup);
  1174. (* retrieve available Text-Codecs *)
  1175. elem := Configuration.config.GetRoot();
  1176. IF elem # NIL THEN
  1177. enum := elem.GetContents(); enum.Reset;
  1178. WHILE enum.HasMoreElements() DO
  1179. ptr := enum.GetNext();
  1180. IF ptr IS XML.Element THEN
  1181. str := ptr(XML.Element).GetAttributeValue("name");
  1182. IF (str # NIL) & (str^ = "Codecs") THEN
  1183. enum := ptr(XML.Element).GetContents(); enum.Reset;
  1184. WHILE enum.HasMoreElements() DO
  1185. ptr := enum.GetNext();
  1186. IF ptr IS XML.Element THEN
  1187. str := ptr(XML.Element).GetAttributeValue("name");
  1188. IF (str # NIL) & (str^ = "Decoder") THEN
  1189. enum := ptr(XML.Element).GetContents(); enum.Reset;
  1190. WHILE enum.HasMoreElements() DO
  1191. ptr := enum.GetNext();
  1192. IF ptr IS XML.Element THEN
  1193. str := ptr(XML.Element).GetAttributeValue("name");
  1194. IF (str # NIL) & (str^ = "Text") THEN
  1195. enum := ptr(XML.Element).GetContents(); enum.Reset;
  1196. WHILE enum.HasMoreElements() DO
  1197. ptr := enum.GetNext();
  1198. IF ptr IS XML.Element THEN
  1199. str := ptr(XML.Element).GetAttributeValue("name");
  1200. NEW(caption, str^);
  1201. popup.AddParButton(str^, FormatPopupHandler, caption);
  1202. END;
  1203. END;
  1204. END;
  1205. END;
  1206. END;
  1207. END;
  1208. END;
  1209. END;
  1210. END;
  1211. END;
  1212. END;
  1213. END;
  1214. NEW(caption, "AUTO");
  1215. popup.AddParButton("AUTO", FormatPopupHandler, caption);
  1216. END InitCodecs;
  1217. PROCEDURE SelectNextTab;
  1218. VAR i : LONGINT;
  1219. BEGIN
  1220. IF currentPageNr < 0 THEN RETURN; END;
  1221. i := currentPageNr + 1;
  1222. LOOP
  1223. IF (i >= MaxNbrOfTabs) OR (pages[i] # NIL) THEN EXIT; END;
  1224. INC(i);
  1225. END;
  1226. IF (i < MaxNbrOfTabs) THEN
  1227. SelectTab(i);
  1228. END;
  1229. END SelectNextTab;
  1230. PROCEDURE SelectPreviousTab;
  1231. VAR i : LONGINT;
  1232. BEGIN
  1233. IF currentPageNr < 0 THEN RETURN; END;
  1234. i := currentPageNr - 1;
  1235. LOOP
  1236. IF (i < 0) OR (pages[i] # NIL) THEN EXIT; END;
  1237. DEC(i);
  1238. END;
  1239. IF (i >= 0) THEN
  1240. SelectTab(i);
  1241. END;
  1242. END SelectPreviousTab;
  1243. PROCEDURE SelectTab(tabNr : LONGINT);
  1244. BEGIN
  1245. IF (tabNr >= 0) & (tabNr < LEN(SELF.pages)) & (SELF.pages[tabNr] # NIL) THEN
  1246. TabSelected(NIL, tabList[tabNr]);
  1247. tabs.Select(tabList[tabNr]);
  1248. END;
  1249. END SelectTab;
  1250. PROCEDURE RecordCurrentPos;
  1251. VAR be : BrowseEntry;
  1252. BEGIN
  1253. IF (currentPage # NIL) THEN
  1254. NEW(be);
  1255. COPY(currentPage.filename, be.filename);
  1256. be.pos := currentPage.editor.tv.cursor.GetPosition();
  1257. be.next := NIL;
  1258. be.prev := browseTOS;
  1259. browseTOS.next := be;
  1260. browseTOS := be;
  1261. END;
  1262. END RecordCurrentPos;
  1263. PROCEDURE GotoFileInternal(CONST filename : ARRAY OF CHAR; pos : LONGINT);
  1264. VAR page : PETPanel; i : LONGINT;
  1265. BEGIN
  1266. KernelLog.String("filename= "); KernelLog.String(filename); KernelLog.Ln;
  1267. KernelLog.String("pos= "); KernelLog.Int(pos, 0); KernelLog.Ln;
  1268. i := 0;
  1269. page := NIL;
  1270. WHILE (i < LEN(pages)-1) & (page = NIL) DO
  1271. IF (pages[i] # NIL) & (pages[i].filename = filename) THEN
  1272. page := pages[i];
  1273. ELSE
  1274. INC(i);
  1275. END;
  1276. END;
  1277. IF (page = NIL) THEN
  1278. Load(filename, "AUTO");
  1279. page := currentPage;
  1280. ELSE
  1281. SelectTab(i);
  1282. END;
  1283. IF (page # NIL) THEN
  1284. currentPage.editor.tv.cursor.SetPosition(pos);
  1285. IF (currentPage.tree # NIL) THEN
  1286. currentPage.tree.SelectNodeByPos(pos);
  1287. END;
  1288. END;
  1289. END GotoFileInternal;
  1290. PROCEDURE BrowseBack;
  1291. BEGIN
  1292. IF browseTOS.prev # browseBase THEN
  1293. browseTOS := browseTOS.prev;
  1294. (* browseBase.prev = browseBase *)
  1295. GotoFileInternal(browseTOS.filename, browseTOS.pos);
  1296. END
  1297. END BrowseBack;
  1298. PROCEDURE BrowseForward;
  1299. BEGIN
  1300. IF browseTOS.next # NIL THEN
  1301. browseTOS := browseTOS.next;
  1302. GotoFileInternal(browseTOS.filename, browseTOS.pos)
  1303. END
  1304. END BrowseForward;
  1305. PROCEDURE GotoFile(CONST filename : ARRAY OF CHAR; pos : LONGINT);
  1306. VAR page : PETPanel; i : LONGINT;
  1307. BEGIN
  1308. IF browseTOS = browseBase THEN RecordCurrentPos END;
  1309. i := 0;
  1310. page := NIL;
  1311. WHILE (i < LEN(pages)-1) & (page = NIL) DO
  1312. IF (pages[i] # NIL) & (pages[i].name = filename) THEN
  1313. page := pages[i];
  1314. ELSE
  1315. INC(i);
  1316. END;
  1317. END;
  1318. IF (page = NIL) THEN
  1319. Load(filename, "AUTO");
  1320. page := currentPage;
  1321. ELSE
  1322. SelectTab(i);
  1323. END;
  1324. IF (page # NIL) THEN
  1325. currentPage.editor.tv.cursor.SetPosition(pos);
  1326. IF (currentPage.tree # NIL) THEN
  1327. currentPage.tree.SelectNodeByPos(pos);
  1328. END;
  1329. RecordCurrentPos
  1330. END
  1331. END GotoFile;
  1332. PROCEDURE GotoDefinition(info : PETTrees.ExternalDefinitionInfo);
  1333. VAR page : PETPanel; i : LONGINT;
  1334. BEGIN
  1335. IF info.filename = "" THEN RETURN END;
  1336. IF browseTOS = browseBase THEN RecordCurrentPos END;
  1337. i := 0;
  1338. page := NIL;
  1339. WHILE (i < LEN(pages)-1) & (page = NIL) DO
  1340. IF (pages[i] # NIL) & (pages[i].filename = info.filename) THEN
  1341. page := pages[i];
  1342. ELSE
  1343. INC(i);
  1344. END;
  1345. END;
  1346. IF (page = NIL) THEN
  1347. Load(info.filename, "AUTO");
  1348. page := currentPage;
  1349. ELSE
  1350. SelectTab(i);
  1351. END;
  1352. IF (page # NIL) THEN
  1353. IF (currentPage.tree # NIL) THEN
  1354. currentPage.tree.BrowseToDefinition(SELF, info);
  1355. END;
  1356. RecordCurrentPos
  1357. END;
  1358. END GotoDefinition;
  1359. PROCEDURE GetNrFromPage(page : PETPanel): LONGINT;
  1360. VAR i : LONGINT; found : BOOLEAN;
  1361. BEGIN
  1362. i := 0; found := FALSE;
  1363. WHILE (~found & (i < MaxNbrOfTabs)) DO
  1364. IF (page = pages[i]) THEN RETURN i END;
  1365. INC(i)
  1366. END;
  1367. RETURN -1
  1368. END GetNrFromPage;
  1369. PROCEDURE TabSelected(sender, data : ANY);
  1370. VAR tab : WMTabComponents.Tab;
  1371. BEGIN
  1372. IF (data # NIL) & (data IS WMTabComponents.Tab) THEN
  1373. DisableUpdate;
  1374. optionsEdit.GetAsString(currentPage.options);
  1375. compileBtn.caption.SetAOC(currentPage.compilerSettings.caption);
  1376. findPCBtn.visible.Set(currentPage.compilerSettings.findPC);
  1377. page.RemoveContent(currentPage);
  1378. tab := data(WMTabComponents.Tab);
  1379. IF (tab.data # NIL) & (tab.data IS WMComponents.VisualComponent) THEN
  1380. currentPage := tab.data(PETPanel);
  1381. currentPageNr := GetNrFromPage(currentPage);
  1382. page.AddContent(currentPage);
  1383. IF ~currentPage.initialized THEN currentPage.Initialize END;
  1384. currentPage.Reset(SELF, NIL);
  1385. page.AlignSubComponents;
  1386. END;
  1387. EnableUpdate;
  1388. UpdateState;
  1389. page.Invalidate
  1390. END
  1391. END TabSelected;
  1392. PROCEDURE UpdatePages;
  1393. VAR i : LONGINT;
  1394. tab : WMTabComponents.Tab;
  1395. s : Strings.String;
  1396. foundModifiedPage : BOOLEAN;
  1397. BEGIN
  1398. DisableUpdate;
  1399. tabs.RemoveAllTabs;
  1400. IF currentPage # NIL THEN page.RemoveContent(currentPage);
  1401. currentPage := NIL
  1402. END;
  1403. IF currentPageNr >= 0 THEN currentPage := pages[currentPageNr] END;
  1404. foundModifiedPage := FALSE;
  1405. FOR i := 0 TO 99 DO
  1406. tabList[i] := NIL;
  1407. IF pages[i] # NIL THEN
  1408. pages[i].alignment.Set(WMComponents.AlignClient);
  1409. tab := tabs.NewTab();
  1410. tab.attention := pages[i].modified;
  1411. foundModifiedPage := foundModifiedPage OR pages[i].modified;
  1412. tabs.AddTab(tab);
  1413. tabList[i] := tab;
  1414. s := Strings.NewString(pages[i].name);
  1415. tabs.SetTabCaption(tab, s);
  1416. tabs.SetTabData(tab, pages[i]);
  1417. END
  1418. END;
  1419. IF currentPage = NIL THEN
  1420. i := 0;
  1421. WHILE (i < MaxNbrOfTabs) & (currentPage = NIL) DO
  1422. IF pages[i] # NIL THEN currentPage := pages[i]; currentPageNr := i END;
  1423. INC(i);
  1424. END;
  1425. IF currentPage = NIL THEN SetModified(FALSE) END;
  1426. END;
  1427. IF currentPage # NIL THEN
  1428. IF ~currentPage.initialized THEN currentPage.Initialize END;
  1429. page.AddContent(currentPage);
  1430. currentPage.Reset(SELF, NIL);
  1431. page.AlignSubComponents;
  1432. page.Invalidate;
  1433. IF tabList[currentPageNr] # NIL THEN tabs.Select(tabList[currentPageNr]) END
  1434. END;
  1435. UpdateState;
  1436. EnableUpdate;
  1437. UpdateInfo;
  1438. IF foundModifiedPage THEN
  1439. SetIcon(iconWorking);
  1440. ELSE
  1441. SetIcon(iconIdle);
  1442. END;
  1443. END UpdatePages;
  1444. PROCEDURE UpdateInfo;
  1445. VAR i, j : LONGINT;
  1446. BEGIN
  1447. FOR i := 0 TO LEN(windowInfo.openDocuments)-1 DO windowInfo.openDocuments[i].name := ""; END;
  1448. windowInfo.handleDocumentInfo := HandleDocumentInfo;
  1449. windowInfo.vc.generator := NIL;
  1450. j := 0;
  1451. FOR i := 0 TO LEN(pages)-1 DO
  1452. IF (pages[i] # NIL) & (j < LEN(windowInfo.openDocuments)) THEN
  1453. windowInfo.openDocuments[j].id := i;
  1454. COPY(pages[i].name, windowInfo.openDocuments[j].name);
  1455. COPY(pages[i].filename, windowInfo.openDocuments[j].fullname);
  1456. windowInfo.openDocuments[j].modified := pages[i].modified;
  1457. windowInfo.openDocuments[j].hasFocus := pages[i] = currentPage;
  1458. INC(j);
  1459. END;
  1460. END;
  1461. SetInfo(windowInfo);
  1462. END UpdateInfo;
  1463. PROCEDURE HandleDocumentInfo(CONST info : WMWindowManager.DocumentInfo; new : BOOLEAN; VAR res : WORD);
  1464. BEGIN
  1465. IF (pages[info.id] # NIL) THEN SelectTab(info.id); END;
  1466. END HandleDocumentInfo;
  1467. PROCEDURE UpdateState;
  1468. VAR tInt : LONGINT; tStr : ARRAY 16 OF CHAR;
  1469. PROCEDURE SetSplitted(splitted : BOOLEAN);
  1470. BEGIN
  1471. IF splitted THEN splitBtn.SetPressed(TRUE); ELSE splitBtn.SetPressed(FALSE); END;
  1472. END SetSplitted;
  1473. PROCEDURE SetLabels(show : BOOLEAN);
  1474. BEGIN
  1475. IF show THEN labelsBtn.SetPressed(TRUE); ELSE labelsBtn.SetPressed(FALSE); END;
  1476. END SetLabels;
  1477. PROCEDURE SetWrap(wrap : BOOLEAN);
  1478. BEGIN
  1479. IF wrap THEN wrapBtn.SetPressed(TRUE); ELSE wrapBtn.SetPressed(FALSE); END;
  1480. END SetWrap;
  1481. PROCEDURE ResetUndo;
  1482. BEGIN
  1483. undoBtn.caption.Reset;
  1484. redoBtn.caption.Reset;
  1485. undoBtn.clDefault.Reset;
  1486. redoBtn.clDefault.Reset;
  1487. END ResetUndo;
  1488. BEGIN
  1489. (* set state of current page *)
  1490. IF (currentPage # NIL) THEN
  1491. SetModified(currentPage.modified);
  1492. SetSplitted(currentPage.splitted);
  1493. SetWrap(currentPage.wrap);
  1494. SetLabels(currentPage.editor.tv.showLabels.Get());
  1495. SetFormatCaption(currentPage.codecFormat);
  1496. filenameEdit.SetAsString(currentPage.filename);
  1497. optionsEdit.SetAsString(currentPage.options);
  1498. compileBtn.caption.SetAOC(currentPage.compilerSettings.caption);
  1499. findPCBtn.visible.Set(currentPage.compilerSettings.findPC);
  1500. currentPage.editor.tv.cursor.SetVisible(TRUE);
  1501. currentPage.editor.SetFocus;
  1502. tInt := currentPage.editor.tv.cursor.GetPosition(); Strings.IntToStr(tInt, tStr);
  1503. positionEdit.SetAsString(tStr);
  1504. IF currentPage.editor.undoMgr # NIL THEN
  1505. NrUpdatesChanged(currentPage.editor.undoMgr.nrUndoUpdates, currentPage.editor.undoMgr.nrRedoUpdates);
  1506. END;
  1507. ELSE
  1508. SetModified(FALSE);
  1509. SetSplitted(FALSE);
  1510. SetWrap(FALSE);
  1511. codecFormat := "AUTO";
  1512. autoCodecFormat := DefaultTextFormat;
  1513. SetFormatCaption("AUTO");
  1514. storeBtn.caption.SetAOC("Store");
  1515. filenameEdit.SetAsString("");
  1516. optionsEdit.SetAsString("");
  1517. compileBtn.caption.Reset;
  1518. findPCBtn.visible.Set(FALSE);
  1519. positionEdit.SetAsString("-");
  1520. ResetUndo;
  1521. END;
  1522. END UpdateState;
  1523. PROCEDURE DragDroppedHandler(x, y : LONGINT; dragInfo : WMWindowManager.DragInfo; VAR handled : BOOLEAN);
  1524. VAR dropTarget : URLDropTarget;
  1525. BEGIN
  1526. NEW(dropTarget, SELF);
  1527. dragInfo.data := dropTarget;
  1528. ConfirmDrag(TRUE, dragInfo)
  1529. END DragDroppedHandler;
  1530. PROCEDURE PositionHandler(sender, data : ANY);
  1531. VAR tempString : ARRAY 16 OF CHAR;
  1532. tempInt : LONGINT;
  1533. BEGIN
  1534. IF (currentPage # NIL) THEN
  1535. positionEdit.GetAsString(tempString);
  1536. Strings.StrToInt(tempString, tempInt);
  1537. currentPage.editor.tv.cursor.SetPosition(tempInt);
  1538. currentPage.editor.tv.cursor.SetVisible(TRUE);
  1539. currentPage.editor.SetFocus;
  1540. END
  1541. END PositionHandler;
  1542. PROCEDURE FormatHandler(x, y: LONGINT; keys: SET; VAR handled: BOOLEAN);
  1543. VAR rectangle: WMRectangles.Rectangle;
  1544. BEGIN
  1545. handled := TRUE;
  1546. rectangle := formatBtn.bounds.Get();
  1547. popup.Popup(bounds.l + rectangle.l, bounds.t + rectangle.b+ 20);
  1548. END FormatHandler;
  1549. PROCEDURE SetFormatCaption(CONST format: ARRAY OF CHAR);
  1550. VAR caption : ARRAY 100 OF CHAR;
  1551. BEGIN
  1552. caption := "Format : ";
  1553. Strings.Append(caption, format);
  1554. IF (format = "AUTO") THEN
  1555. IF (currentPage # NIL) THEN Strings.Append(caption, " "); Strings.Append(caption, currentPage.autoCodecFormat);
  1556. ELSE Strings.Append(caption, " "); Strings.Append(caption, autoCodecFormat);
  1557. END;
  1558. END;
  1559. formatBtn.caption.SetAOC(caption);
  1560. END SetFormatCaption;
  1561. PROCEDURE SetCursorPosition (position: LONGINT);
  1562. VAR string : ARRAY 16 OF CHAR;
  1563. BEGIN
  1564. IF (currentPage # NIL) THEN
  1565. Strings.IntToStr(position, string);
  1566. positionEdit.SetAsString(string);
  1567. currentPage.editor.tv.cursor.SetPosition(position);
  1568. END;
  1569. END SetCursorPosition;
  1570. PROCEDURE SetModified(modified : BOOLEAN);
  1571. BEGIN
  1572. IF currentPage # NIL THEN
  1573. tabList[currentPageNr].attention := modified;
  1574. tabs.Invalidate;
  1575. IF modified THEN
  1576. SetIcon(iconWorking);
  1577. storeBtn.caption.SetAOC("Store !")
  1578. ELSE
  1579. storeBtn.caption.SetAOC("Store");
  1580. END;
  1581. END
  1582. END SetModified;
  1583. PROCEDURE SetIcon*(icon : WMGraphics.Image);
  1584. BEGIN
  1585. IF (icon # NIL) & (icon # currentIcon) THEN
  1586. currentIcon := icon;
  1587. SetIcon^(icon);
  1588. END;
  1589. END SetIcon;
  1590. PROCEDURE FormatPopupHandler(sender, data: ANY);
  1591. BEGIN
  1592. IF (data # NIL) & (data IS CaptionObject) THEN
  1593. popup.Close;
  1594. IF (currentPage # NIL) THEN
  1595. COPY(data(CaptionObject).caption, currentPage.codecFormat);
  1596. COPY(currentPage.codecFormat, codecFormat);
  1597. COPY(currentPage.autoCodecFormat, autoCodecFormat);
  1598. ELSE
  1599. COPY(data(CaptionObject).caption, codecFormat);
  1600. COPY(DefaultTextFormat, autoCodecFormat);
  1601. END;
  1602. SetFormatCaption(codecFormat);
  1603. END
  1604. END FormatPopupHandler;
  1605. (* Called when pressing the Escape key while the filename editor has the keyboard focus. *)
  1606. PROCEDURE FilenameEditEscapeHandler(sernder, data : ANY);
  1607. BEGIN
  1608. IF (currentPage # NIL) THEN
  1609. filenameEdit.SetAsString(currentPage.filename);
  1610. END;
  1611. END FilenameEditEscapeHandler;
  1612. PROCEDURE LoadHandler(sender, data : ANY);
  1613. VAR filename : Filename; command : ARRAY 1024 OF CHAR; msg : ARRAY 64 OF CHAR; ignoreRes : WORD;
  1614. BEGIN
  1615. filenameEdit.GetAsString(filename);
  1616. Strings.TrimWS(filename);
  1617. IF (filename # "") THEN
  1618. IF (Inputs.LeftShift IN modifierFlags) THEN
  1619. command := "PET.Open "; Strings.AppendX(command, filename);
  1620. Commands.Call(command, {}, ignoreRes, msg);
  1621. IF (currentPage # NIL) THEN
  1622. filenameEdit.SetAsString(currentPage.filename);
  1623. ELSE
  1624. filenameEdit.SetAsString("");
  1625. END;
  1626. ELSE
  1627. Load(filename, codecFormat);
  1628. IF (currentPage # NIL) THEN
  1629. optionsEdit.GetAsString(currentPage.options);
  1630. END;
  1631. END;
  1632. END;
  1633. END LoadHandler;
  1634. PROCEDURE Load(CONST filename, format : ARRAY OF CHAR);
  1635. VAR
  1636. text : Texts.Text; res : WORD;
  1637. decoder : Codecs.TextDecoder;
  1638. msg : ARRAY 512 OF CHAR;
  1639. readonly : BOOLEAN;
  1640. name, fullname, archiveName, entryName, path : Filename;
  1641. syntaxHighlighterName : ARRAY 32 OF CHAR;
  1642. file : Files.File;
  1643. in: Streams.Reader;
  1644. BEGIN
  1645. DisableUpdate;
  1646. res := -1;
  1647. NewTab; (* create a new Tab with an empty PETPanel to Load into *)
  1648. Codecs.SplitName(filename, archiveName, entryName);
  1649. IF (archiveName # "") THEN
  1650. COPY(archiveName, name);
  1651. ELSE
  1652. COPY(filename, name);
  1653. END;
  1654. COPY(name, fullname);
  1655. readonly := FALSE;
  1656. (* Check whether file/archive exists and get its canonical name *)
  1657. file := Files.Old(name);
  1658. IF (file # NIL) THEN
  1659. file.GetName(fullname);
  1660. readonly := Files.ReadOnly IN file.flags;
  1661. ELSE
  1662. file := Files.New(name); (* to get path *)
  1663. IF (file # NIL) THEN
  1664. file.GetName(fullname);
  1665. file := NIL;
  1666. END;
  1667. END;
  1668. IF (archiveName # "") THEN
  1669. Codecs.JoinName(fullname, entryName, currentPage.filename);
  1670. ELSE
  1671. COPY(fullname, currentPage.filename);
  1672. END;
  1673. IF (settings.showPathInTabs) THEN
  1674. COPY(fullname, currentPage.name);
  1675. IF (archiveName # "") THEN Codecs.JoinName(currentPage.name, entryName, currentPage.name); END;
  1676. ELSE
  1677. Files.SplitPath(fullname, path, currentPage.name);
  1678. IF (archiveName # "") THEN Codecs.JoinName(currentPage.name, entryName, currentPage.name); END;
  1679. END;
  1680. IF readonly THEN Strings.Append(currentPage.name, " (R)"); END;
  1681. IF (archiveName # "") THEN Codecs.JoinName(fullname, entryName, fullname); END;
  1682. filenameEdit.SetAsString(fullname);
  1683. IF projectText # NIL THEN
  1684. currentPage.scratch.SetText(projectText);
  1685. END;
  1686. text := currentPage.editor.text;
  1687. text.AcquireWrite;
  1688. currentPage.modified := TRUE; (* avoid the ! on the store button while loading *)
  1689. text.Delete(0, text.GetLength());
  1690. currentPage.editor.tv.firstLine.Set(0);
  1691. currentPage.editor.tv.onLinkClicked.Add(LinkClickedHandler);
  1692. text.ReleaseWrite;
  1693. IF (file # NIL) THEN
  1694. IF (format = "AUTO") THEN
  1695. decoder := TextUtilities.DecodeAuto(fullname, autoCodecFormat);
  1696. COPY(autoCodecFormat, currentPage.autoCodecFormat);
  1697. ELSE
  1698. decoder := Codecs.GetTextDecoder(format);
  1699. END;
  1700. IF (decoder # NIL) THEN
  1701. COPY(format, currentPage.codecFormat);
  1702. in := Codecs.OpenInputStream(fullname);
  1703. IF in # NIL THEN
  1704. decoder.Open(in, res);
  1705. IF res = 0 THEN
  1706. currentPage.editor.text.onTextChanged.Remove(currentPage.TextChanged);
  1707. currentPage.editor.SetText(decoder.GetText());
  1708. currentPage.searchPanel.SetText(decoder.GetText());
  1709. currentPage.splitEditor.SetText(currentPage.editor.text);
  1710. currentPage.editor.text.onTextChanged.Add(currentPage.TextChanged);
  1711. currentPage.editor.text.SetUndoManager(currentPage.editor.undoMgr)
  1712. END;
  1713. ELSE
  1714. msg := "Can't open input stream on file "; Strings.Append(msg, fullname);
  1715. WMDialogs.Error(WindowTitle, msg);
  1716. END;
  1717. ELSE
  1718. msg := "No decoder for file "; Strings.Append(msg, fullname);
  1719. Strings.Append(msg, " (Format: "); Strings.Append(msg, format); Strings.Append(msg, ")");
  1720. WMDialogs.Error(WindowTitle, msg);
  1721. END;
  1722. END;
  1723. SetFormatCaption(format);
  1724. currentPage.editor.tv.firstLine.Set(0);
  1725. currentPage.editor.tv.cursor.SetPosition(0);
  1726. currentPage.editor.tv.SetFocus;
  1727. currentPage.searchPanel.SetSettings(settings.searchWrap, settings.searchCaseSensitive, FALSE, settings.searchHighlightAll);
  1728. currentPage.compilerSettings := settings.GetCompilerSettings(filename);
  1729. currentPage.options := currentPage.compilerSettings.options;
  1730. GetSyntaxHighlighterName(filename, syntaxHighlighterName);
  1731. IF (syntaxHighlighterName # "") THEN
  1732. currentPage.editor.highlighting.SetAOC(syntaxHighlighterName);
  1733. currentPage.splitEditor.highlighting.SetAOC(syntaxHighlighterName);
  1734. END;
  1735. currentPage.CreateSidePanel(currentPage.compilerSettings);
  1736. COPY(currentPage.name, tabList[currentPageNr].caption^); tabs.Invalidate;
  1737. currentPage.modified := FALSE;
  1738. SetModified(FALSE);
  1739. UpdatePages;
  1740. EnableUpdate;
  1741. form.Invalidate;
  1742. END Load;
  1743. PROCEDURE StoreHandler(sender, data : ANY);
  1744. VAR filename : Filename;
  1745. BEGIN
  1746. IF (currentPage # NIL) THEN
  1747. filenameEdit.GetAsString(filename);
  1748. Strings.TrimWS(filename);
  1749. IF filename # "" THEN
  1750. Store(filename, currentPage.codecFormat);
  1751. ELSE
  1752. WMDialogs.Error(WindowTitle, "Filename invalid");
  1753. filenameEdit.SetAsString(currentPage.filename);
  1754. END;
  1755. END
  1756. END StoreHandler;
  1757. PROCEDURE CompleteHandler(sender, data : ANY);
  1758. BEGIN
  1759. IF currentPage.tree IS TFModuleTrees.ModuleTree THEN
  1760. currentPage.tree(TFModuleTrees.ModuleTree).Complete(NIL, NIL);
  1761. END
  1762. END CompleteHandler;
  1763. PROCEDURE Store(CONST filename, format : ARRAY OF CHAR);
  1764. VAR
  1765. res : WORD;
  1766. msg : ARRAY 512 OF CHAR;
  1767. name, backName, fullname, archiveName, entryName, path: Filename;
  1768. syntaxHighlighterName : ARRAY 32 OF CHAR;
  1769. backExt, t, ext: ARRAY 12 OF CHAR;
  1770. options : CompilerOptions;
  1771. encoder : Codecs.TextEncoder;
  1772. w : Streams.Writer; i : LONGINT;
  1773. file, oldFile : Files.File;
  1774. PROCEDURE FileExists(CONST filename : ARRAY OF CHAR) : BOOLEAN;
  1775. BEGIN
  1776. RETURN Files.Old(filename) # NIL
  1777. END FileExists;
  1778. PROCEDURE CreateBackupFile;
  1779. BEGIN
  1780. IF settings.backupOnStore = Paranoid THEN
  1781. Strings.Concat(filename, ".Bak", backName);
  1782. IF FileExists(backName) THEN
  1783. i := 0;
  1784. REPEAT
  1785. backExt := "."; Strings.IntToStr(i, t);
  1786. Strings.Append(backExt, t); Strings.Append(backExt, ".Bak");
  1787. Strings.Concat(filename, backExt, backName);
  1788. INC(i);
  1789. UNTIL ~FileExists(backName);
  1790. END;
  1791. ELSE
  1792. ASSERT(settings.backupOnStore = Yes);
  1793. Strings.Concat(filename, ".Bak", backName);
  1794. END;
  1795. Files.Rename(filename, backName, res);
  1796. IF res = Files.Ok THEN KernelLog.String("Backup created in "); KernelLog.String(backName); KernelLog.Ln END;
  1797. END CreateBackupFile;
  1798. BEGIN
  1799. IF currentPage # NIL THEN
  1800. filenameEdit.SetAsString(filename);
  1801. Codecs.SplitName(filename, archiveName, entryName);
  1802. IF (archiveName # "") THEN
  1803. COPY(archiveName, name);
  1804. ELSE
  1805. COPY(filename, name);
  1806. END;
  1807. COPY(name, fullname);
  1808. oldFile := Files.Old(name);
  1809. IF (oldFile # NIL) THEN
  1810. IF (Files.ReadOnly IN oldFile.flags) THEN
  1811. msg := "File is read-only: "; Strings.Append(msg, name);
  1812. WMDialogs.Error("Error", msg);
  1813. RETURN;
  1814. END;
  1815. END;
  1816. IF (archiveName = "") & (settings.backupOnStore # No) THEN CreateBackupFile; END;
  1817. IF (format = "AUTO") THEN
  1818. IF (currentPage.autoCodecFormat = "") THEN
  1819. encoder := Codecs.GetTextEncoder(DefaultTextFormat);
  1820. ELSE
  1821. encoder := Codecs.GetTextEncoder(currentPage.autoCodecFormat);
  1822. IF encoder = NIL THEN
  1823. encoder := Codecs.GetTextEncoder(DefaultTextFormat);
  1824. END;
  1825. END;
  1826. ELSE
  1827. encoder := Codecs.GetTextEncoder(format);
  1828. END;
  1829. IF (encoder # NIL) THEN
  1830. IF (archiveName # "") & (oldFile # NIL) THEN
  1831. file := oldFile;
  1832. ELSE
  1833. oldFile := NIL;
  1834. file := Files.New(name);
  1835. IF (file = NIL) THEN
  1836. msg := "Could not create file "; Strings.Append(msg, name);
  1837. WMDialogs.Error(WindowTitle, msg);
  1838. RETURN;
  1839. END;
  1840. END;
  1841. file.GetName(fullname);
  1842. IF (archiveName # "") THEN Codecs.JoinName(fullname, entryName, fullname); END;
  1843. filenameEdit.SetAsString(fullname);
  1844. w := Codecs.OpenOutputStream(fullname);
  1845. IF (w # NIL) THEN
  1846. encoder.Open(w);
  1847. currentPage.editor.text.AcquireWrite;
  1848. encoder.WriteText(currentPage.editor.text, res);
  1849. currentPage.editor.text.ReleaseWrite;
  1850.  w.Update;
  1851.  IF res # 0 THEN
  1852.  msg := "Could not encode file "; Strings.Append(msg, fullname);
  1853. WMDialogs.Error(WindowTitle, msg);
  1854.  END;
  1855. ELSE
  1856.  msg := "Could not store to file "; Strings.Append(msg, fullname); Strings.Append(msg, " (Could not open output stream)");
  1857.  WMDialogs.Error(WindowTitle, msg);
  1858. END;
  1859. ELSE
  1860. msg := "Could not store file "; Strings.Append(msg, fullname); Strings.Append(msg, " (No encoder found)");
  1861. WMDialogs.Error(WindowTitle, msg);
  1862. END;
  1863. IF (settings.showPathInTabs) THEN
  1864. COPY(fullname, pages[currentPageNr].name);
  1865. ELSE
  1866. IF (archiveName # "") THEN
  1867. Files.SplitPath(archiveName, path, name);
  1868. Codecs.JoinName(name, entryName, pages[currentPageNr].name);
  1869. ELSE
  1870. Files.SplitPath(fullname, path, pages[currentPageNr].name);
  1871. END;
  1872. END;
  1873. tabs.SetTabCaption(tabList[currentPageNr], Strings.NewString(currentPage.name));
  1874. tabs.Invalidate;
  1875. Files.SplitExtension (fullname, backName, ext);
  1876. Files.SplitExtension (currentPage.filename, backName, backExt);
  1877. IF ext # backExt THEN
  1878. currentPage.compilerSettings := settings.GetCompilerSettings(name);
  1879. currentPage.options := currentPage.compilerSettings.options;
  1880. optionsEdit.SetAsString(currentPage.options);
  1881. GetSyntaxHighlighterName(filename, syntaxHighlighterName);
  1882. IF (syntaxHighlighterName # "") THEN
  1883. currentPage.editor.highlighting.SetAOC(syntaxHighlighterName);
  1884. currentPage.editor.highlighting.SetAOC(syntaxHighlighterName);
  1885. END;
  1886. END;
  1887. COPY(fullname, currentPage.filename);
  1888. compileBtn.caption.SetAOC(currentPage.compilerSettings.caption);
  1889. findPCBtn.visible.Set(currentPage.compilerSettings.findPC);
  1890. optionsEdit.GetAsString(options); COPY(options, currentPage.options);
  1891. currentPage.modified := FALSE;
  1892. SetModified(FALSE);
  1893. IF HasModifiedPage() THEN
  1894. SetIcon(iconWorking);
  1895. ELSE
  1896. SetIcon(iconIdle);
  1897. END;
  1898. END
  1899. END Store;
  1900. PROCEDURE NewTab;
  1901. VAR pet : PETPanel;
  1902. i : LONGINT;
  1903. found : BOOLEAN;
  1904. BEGIN
  1905. found := FALSE;
  1906. NEW(pet, SELF); pet.alignment.Set(WMComponents.AlignClient); pet.fillColor.Set(0FFFFFFFFH); pet.takesFocus.Set(TRUE);
  1907. IF pet.editor.undoMgr # NIL THEN
  1908. pet.editor.undoMgr.nrUpdatesListener := NrUpdatesChanged;
  1909. NrUpdatesChanged(0, 0);
  1910. END;
  1911. IF (pet.scratchPanel # NIL) THEN
  1912. pet.scratchPanel.bounds.SetHeight(settings.scratchPanelHeight);
  1913. END;
  1914. (* find a free place *)
  1915. i := 0;
  1916. WHILE (i < MaxNbrOfTabs) & (~found) DO
  1917. IF pages[i] = NIL THEN pages[i] := pet; currentPageNr := i; found := TRUE; END;
  1918. INC(i)
  1919. END;
  1920. UpdatePages;
  1921. END NewTab;
  1922. (** Returns TRUE if at least one page has been modified, FALSE otherwise *)
  1923. PROCEDURE HasModifiedPage() : BOOLEAN;
  1924. VAR modified : BOOLEAN; i : LONGINT;
  1925. BEGIN
  1926. modified := FALSE;
  1927. i := 0;
  1928. WHILE ~modified & (i < MaxNbrOfTabs) DO
  1929. IF (pages[i] # NIL) & (pages[i].modified) THEN
  1930. modified := TRUE;
  1931. END;
  1932. INC(i);
  1933. END;
  1934. RETURN modified;
  1935. END HasModifiedPage;
  1936. (* Returns FALSE if the user declines to close all tabs *)
  1937. PROCEDURE CloseAllTabs() : BOOLEAN;
  1938. VAR res, i : LONGINT;
  1939. BEGIN
  1940. (* First check whether all pages are saved to disk *)
  1941. i := 0;
  1942. LOOP
  1943. IF i >= MaxNbrOfTabs THEN EXIT; END;
  1944. IF (pages[i] # NIL) & (pages[i].modified) THEN
  1945. res := WMDialogs.Confirmation(WindowTitle, "At least on page has not been stored. Continue?");
  1946. IF res = WMDialogs.ResNo THEN
  1947. RETURN FALSE;
  1948. ELSIF res = WMDialogs.ResYes THEN
  1949. EXIT;
  1950. END;
  1951. END;
  1952. INC(i);
  1953. END;
  1954. i := 0;
  1955. WHILE (i < MaxNbrOfTabs) DO
  1956. IF (pages[i] # NIL) THEN pages[i].Finalize; pages[i] := NIL; END;
  1957. INC(i);
  1958. END;
  1959. UpdatePages;
  1960. form.Invalidate;
  1961. RETURN TRUE;
  1962. END CloseAllTabs;
  1963. PROCEDURE CloseHandler(sender, data: ANY);
  1964. VAR found : BOOLEAN; i : LONGINT;
  1965. BEGIN
  1966. (* close current tab, warn user if not saved *)
  1967. IF (currentPage = NIL) OR (currentPage.modified) & (
  1968. WMDialogs.Confirmation(WindowTitle, "The current text was not stored. Continue ?") = WMDialogs.ResNo)
  1969. THEN RETURN END;
  1970. (* remove current page *)
  1971. found := FALSE; i := 0;
  1972. WHILE (~found & (i < MaxNbrOfTabs)) DO
  1973. IF (currentPage = pages[i]) THEN pages[i].Finalize; pages[i] := NIL; found := TRUE END;
  1974. INC(i);
  1975. END;
  1976. IF found & (i >= 2) THEN currentPageNr := i-2; END;
  1977. UpdatePages;
  1978. form.Invalidate;
  1979. END CloseHandler;
  1980. PROCEDURE SplitHandler(sender, data: ANY);
  1981. BEGIN
  1982. IF (currentPage # NIL) THEN
  1983. IF currentPage.splitted THEN
  1984. currentPage.splitPanel.visible.Set(FALSE);
  1985. currentPage.editor.SetFocus;
  1986. ELSE
  1987. currentPage.splitPanel.visible.Set(TRUE);
  1988. END;
  1989. currentPage.splitted := ~currentPage.splitted
  1990. END
  1991. END SplitHandler;
  1992. PROCEDURE LinkClickedHandler(sender, data : ANY);
  1993. BEGIN
  1994. IF data IS WMTextView.LinkWrapper THEN
  1995. KernelLog.String("Link: "); KernelLog.String(data(WMTextView.LinkWrapper).link^); KernelLog.Ln
  1996. END;
  1997. END LinkClickedHandler;
  1998. PROCEDURE FindPC(sender, data : ANY);
  1999. VAR a, b : LONGINT;
  2000. pcStr : ARRAY 128 OF CHAR;
  2001. selectionText: Texts.Text;
  2002. from, to: Texts.TextPosition;
  2003. options : CompilerOptions;
  2004. BEGIN
  2005. IF currentPage = NIL THEN RETURN; END;
  2006. IF Texts.GetLastSelection(selectionText, from, to) THEN
  2007. selectionText.AcquireRead;
  2008. a := MIN(from.GetPosition(), to.GetPosition());
  2009. b := MAX(from.GetPosition(), to.GetPosition());
  2010. TextUtilities.SubTextToStr(selectionText, a, b - a, pcStr);
  2011. selectionText.ReleaseRead;
  2012. Strings.Trim(pcStr, " ");
  2013. END;
  2014. optionsEdit.GetAsString(options);
  2015. IF pcStr = "" THEN
  2016. IF WMDialogs.QueryString("Enter PC to locate", pcStr) = WMDialogs.ResOk THEN
  2017. currentPage.DoCompile(TRUE, pcStr, options)
  2018. END
  2019. ELSE
  2020. currentPage.DoCompile(TRUE, pcStr, options)
  2021. END
  2022. END FindPC;
  2023. PROCEDURE UnloadModule;
  2024. VAR
  2025. path, filename : Files.FileName;
  2026. name, extension, msg : ARRAY 128 OF CHAR;
  2027. tw : TextUtilities.TextWriter; res : WORD;
  2028. BEGIN
  2029. ASSERT(currentPage # NIL);
  2030. Files.SplitPath(currentPage.filename, path, filename);
  2031. Strings.GetExtension(filename, name, extension);
  2032. IF (name # "PET") THEN
  2033. Modules.FreeModule(name, res, msg);
  2034. ELSE
  2035. res := -1; msg := "Unloading module PET not allowed! PET is running.";
  2036. END;
  2037. IF res = 0 THEN
  2038. msg := "Module "; Strings.Append(msg, name); Strings.Append(msg, " unloaded.");
  2039. END;
  2040. currentPage.ClearLog;
  2041. NEW(tw, currentPage.logEdit.text); tw.String (msg); tw.Update;
  2042. IF currentPage.logEdit.visible.Get() = FALSE THEN currentPage.logEdit.visible.Set(TRUE); END;
  2043. END UnloadModule;
  2044. PROCEDURE Close*;
  2045. VAR page : LONGINT;
  2046. BEGIN
  2047. Close^;
  2048. FOR page := 0 TO LEN(pages)-1 DO
  2049. IF pages[page] # NIL THEN pages[page].Finalize; END;
  2050. END;
  2051. IF projectTextModified THEN
  2052. StoreText(projectTextFilename, projectText);
  2053. END;
  2054. DecCount;
  2055. END Close;
  2056. (* XML scanner/parser error handler *)
  2057. PROCEDURE Error(pos, line, row: LONGINT; CONST msg: ARRAY OF CHAR);
  2058. BEGIN
  2059.  xmlHasErrors := TRUE;
  2060. END Error;
  2061. PROCEDURE LoadState(CONST filename : ARRAY OF CHAR) : BOOLEAN;
  2062. VAR
  2063. file : Files.File;
  2064. scanner : XMLScanner.Scanner;
  2065. parser : XMLParser.Parser;
  2066. reader : Files.Reader;
  2067. doc : XML.Document;
  2068. elem : XML.Element;
  2069. string : XML.String;
  2070. msg : ARRAY 128 OF CHAR;
  2071. BEGIN
  2072. xmlHasErrors := FALSE;
  2073. file := Files.Old(filename);
  2074. IF file # NIL THEN
  2075. NEW(reader, file, 0);
  2076. NEW(scanner, reader); scanner.reportError := Error;
  2077. NEW(parser, scanner); parser.reportError := Error;
  2078. doc := parser.Parse();
  2079. IF xmlHasErrors THEN
  2080. msg := "Could not load state: "; Strings.Append(msg, filename); Strings.Append(msg, " could not be parsed");
  2081. WMDialogs.Error(WindowTitle, msg);
  2082. RETURN FALSE;
  2083. END;
  2084. elem := doc.GetRoot();
  2085. IF elem # NIL THEN string := elem.GetName(); END;
  2086. IF (string # NIL) & (string^ = "PETData") THEN
  2087. DisableUpdate;
  2088. LoadPages(doc.GetRoot());
  2089. EnableUpdate;
  2090. ELSE
  2091. msg := "Could not load state: "; Strings.Append(msg, filename); Strings.Append(msg, " not valid");
  2092. WMDialogs.Error(WindowTitle, msg);
  2093. RETURN FALSE;
  2094. END;
  2095. ELSE
  2096. msg := "Could not load state: XML file "; Strings.Append(msg, filename); Strings.Append(msg, " not found");
  2097. WMDialogs.Error(WindowTitle, msg);
  2098. RETURN FALSE;
  2099. END;
  2100. RETURN TRUE;
  2101. END LoadState;
  2102. (* Store the current editor settings into a file *)
  2103. PROCEDURE StoreState(CONST filename : ARRAY OF CHAR);
  2104. VAR state : XML.Element; file : Files.File; w : Files.Writer;
  2105. BEGIN
  2106. file := Files.New(filename);
  2107. IF file # NIL THEN
  2108. Files.OpenWriter(w, file, 0);
  2109. state := StorePages();
  2110. state.Write(w, NIL, 0);
  2111. w.Update;
  2112. Files.Register(file);
  2113. KernelLog.String("PET state saved into "); KernelLog.String(filename); KernelLog.Ln;
  2114. ELSE
  2115. WMDialogs.Error(WindowTitle, "Could not create file");
  2116. END;
  2117. END StoreState;
  2118. PROCEDURE LoadPages(pages : XML.Element);
  2119. VAR
  2120. elem : XML.Element; enum : XMLObjects.Enumerator; ptr : ANY; s : XML.String;
  2121. selectedPageNr : LONGINT;
  2122. BEGIN
  2123. selectedPageNr := -1;
  2124. enum := pages.GetContents(); enum.Reset;
  2125. WHILE (enum.HasMoreElements()) DO
  2126. ptr := enum.GetNext();
  2127. IF ptr IS XML.Element THEN
  2128. elem := ptr(XML.Element);
  2129. s := elem.GetName();
  2130. IF (s # NIL) & (s^ = "Tab") THEN
  2131. LoadPage(elem);
  2132. ELSIF (s # NIL) & (s^ = "General") THEN
  2133. WMRestorable.LoadLongint(elem, "SelectedPageNr", selectedPageNr);
  2134. WMRestorable.LoadString(elem, "ProjectTextFile", projectTextFilename);
  2135. IF projectTextFilename # "" THEN
  2136. projectText := LoadText(projectTextFilename);
  2137. projectText.onTextChanged.Add(ProjectTextModified);
  2138. END;
  2139. END;
  2140. END;
  2141. END;
  2142. IF (selectedPageNr >= 0) & (selectedPageNr < LEN(SELF.pages)) & (SELF.pages[selectedPageNr] # NIL) THEN
  2143. TabSelected(NIL, tabList[selectedPageNr]);
  2144. tabs.Select(tabList[selectedPageNr]);
  2145. END;
  2146. END LoadPages;
  2147. PROCEDURE StorePages() : XML.Element;
  2148. VAR data, elem : WMRestorable.XmlElement; i : LONGINT;
  2149. BEGIN
  2150. NEW(data); data.SetName("PETData");
  2151. NEW(elem); elem.SetName("General");
  2152. WMRestorable.StoreLongint(elem, "SelectedPageNr", currentPageNr);
  2153. WMRestorable.StoreString(elem, "ProjectTextFile", projectTextFilename);
  2154. data.AddContent(elem);
  2155. WHILE (i < MaxNbrOfTabs) DO
  2156. IF (pages[i] # NIL) THEN
  2157. elem := StorePage(pages[i]);
  2158. data.AddContent(elem);
  2159. END;
  2160. INC(i)
  2161. END;
  2162. RETURN data;
  2163. END StorePages;
  2164. PROCEDURE LoadPage(page : WMRestorable.XmlElement);
  2165. VAR
  2166. entries: XMLObjects.Enumerator;
  2167. entry : XML.Element;
  2168. s : Strings.String;
  2169. firstLine, cursorPos, width, height : LONGINT;
  2170. options : CompilerOptions;
  2171. showLabels, wordWrap, visible, wrap, caseSensitive, backwards, highlightAll : BOOLEAN;
  2172. searchString, replaceString : WMSearchComponents.SearchString;
  2173. ptr : ANY;
  2174. BEGIN
  2175. WMRestorable.LoadString(page, "codecFormat", codecFormat);
  2176. WMRestorable.LoadString(page, "compilerOptions", options);
  2177. WMRestorable.LoadBoolean(page, "showLabels", showLabels);
  2178. WMRestorable.LoadBoolean(page, "wordWrap", wordWrap);
  2179. WMRestorable.LoadStringPtr(page, "file", s);
  2180. IF (s # NIL) THEN
  2181. Load(s^, codecFormat);
  2182. COPY(options, currentPage.options);
  2183. optionsEdit.SetAsString(options);
  2184. IF showLabels THEN currentPage.ToggleLabels; labelsBtn.SetPressed(TRUE); END;
  2185. IF wordWrap THEN currentPage.ToggleWrap; wrapBtn.SetPressed(TRUE); END;
  2186. entries := page.GetContents(); entries.Reset;
  2187. WHILE(entries.HasMoreElements()) DO
  2188. ptr := entries.GetNext();
  2189. IF ptr IS XML.Element THEN
  2190. entry := ptr (XML.Element);
  2191. s := entry.GetName();
  2192. IF (s # NIL) THEN
  2193. IF (s^ = "Editor") THEN
  2194. WMRestorable.LoadLongint(entry, "firstLine", firstLine);
  2195. WMRestorable.LoadLongint(entry, "cursorPos", cursorPos);
  2196. currentPage.editor.tv.firstLine.Set(firstLine);
  2197. currentPage.editor.tv.cursor.SetPosition(cursorPos);
  2198. ELSIF (s^ = "SplitEditor") THEN
  2199. WMRestorable.LoadLongint(entry, "firstLine", firstLine);
  2200. WMRestorable.LoadLongint(entry, "cursorPos", cursorPos);
  2201. WMRestorable.LoadBoolean(entry, "visible", visible);
  2202. WMRestorable.LoadLongint(entry, "height", height);
  2203. currentPage.splitEditor.tv.firstLine.Set(firstLine);
  2204. currentPage.splitEditor.tv.cursor.SetPosition(cursorPos);
  2205. currentPage.splitPanel.visible.Set(visible);
  2206. currentPage.splitted := visible;
  2207. currentPage.splitPanel.bounds.SetHeight(height);
  2208. ELSIF (s^ = "SidePanel") THEN
  2209. WMRestorable.LoadBoolean(entry, "visible", visible);
  2210. WMRestorable.LoadLongint(entry, "width", width);
  2211. WMRestorable.LoadLongint(entry, "scratchHeight", height);
  2212. currentPage.sidePanel.visible.Set(visible);
  2213. currentPage.sidePanel.bounds.SetWidth(width);
  2214. currentPage.scratchPanel.bounds.SetHeight(height);
  2215. ELSIF (s^ = "SearchPanel") THEN
  2216. WMRestorable.LoadBoolean(entry, "visible", visible);
  2217. WMRestorable.LoadBoolean(entry, "wrap", wrap);
  2218. WMRestorable.LoadBoolean(entry, "casesensitive", caseSensitive);
  2219. WMRestorable.LoadBoolean(entry, "backwards", backwards);
  2220. WMRestorable.LoadBoolean(entry, "highlight", highlightAll);
  2221. WMRestorable.LoadString(entry, "searchString", searchString);
  2222. WMRestorable.LoadString(entry, "replaceString", replaceString);
  2223. currentPage.searchPanel.visible.Set(visible);
  2224. currentPage.searchPanel.SetSettings(wrap, caseSensitive, backwards, highlightAll);
  2225. currentPage.searchPanel.searchEdit.SetAsString(searchString);
  2226. currentPage.searchPanel.replEdit.SetAsString(replaceString);
  2227. ELSIF (s^ = "LogPanel") THEN
  2228. WMRestorable.LoadLongint(entry, "height", height);
  2229. currentPage.logPanel.bounds.SetHeight(height);
  2230. END;
  2231. END;
  2232. END;
  2233. END; (* WHILE (entries.HasMoreElements() *)
  2234. END;
  2235. END LoadPage;
  2236. PROCEDURE StorePage(page : PETPanel) : WMRestorable.XmlElement;
  2237. VAR
  2238. elem, entry : WMRestorable.XmlElement;
  2239. wrap, caseSensitive, backwards, highlightAll : BOOLEAN;
  2240. string : WMSearchComponents.SearchString;
  2241. BEGIN
  2242. ASSERT(page # NIL);
  2243. NEW(elem); elem.SetName("Tab");
  2244. WMRestorable.StoreString(elem, "file", page.filename);
  2245. WMRestorable.StoreString(elem, "codecFormat", page.codecFormat);
  2246. WMRestorable.StoreString(elem, "compilerOptions", page.options);
  2247. WMRestorable.StoreBoolean(elem, "showLabels", page.editor.tv.showLabels.Get());
  2248. WMRestorable.StoreBoolean(elem, "wordWrap", page.editor.tv.wrapMode.Get() = WMTextView.WrapWord);
  2249. NEW(entry); entry.SetName("Editor");
  2250. WMRestorable.StoreLongint(entry, "firstLine", page.editor.tv.firstLine.Get());
  2251. WMRestorable.StoreLongint(entry, "cursorPos", page.editor.tv.cursor.GetPosition());
  2252. elem.AddContent(entry);
  2253. NEW(entry); entry.SetName("SplitEditor");
  2254. WMRestorable.StoreBoolean(entry, "visible", page.splitPanel.visible.Get());
  2255. WMRestorable.StoreLongint(entry, "firstLine", page.splitEditor.tv.firstLine.Get());
  2256. WMRestorable.StoreLongint(entry, "cursorPos", page.splitEditor.tv.cursor.GetPosition());
  2257. WMRestorable.StoreLongint(entry, "height", page.splitPanel.bounds.GetHeight());
  2258. elem.AddContent(entry);
  2259. NEW(entry); entry.SetName("SearchPanel");
  2260. page.searchPanel.GetSettings(wrap, caseSensitive, backwards, highlightAll);
  2261. WMRestorable.StoreBoolean(entry, "visible", page.searchPanel.visible.Get());
  2262. WMRestorable.StoreBoolean(entry, "wrap", wrap);
  2263. WMRestorable.StoreBoolean(entry, "casesensitive", caseSensitive);
  2264. WMRestorable.StoreBoolean(entry, "backwards", backwards);
  2265. WMRestorable.StoreBoolean(entry, "highlight", highlightAll);
  2266. page.searchPanel.searchEdit.GetAsString(string);
  2267. WMRestorable.StoreString(entry, "searchString", string);
  2268. page.searchPanel.replEdit.GetAsString(string);
  2269. WMRestorable.StoreString(entry, "replaceString", string);
  2270. elem.AddContent(entry);
  2271. NEW(entry); entry.SetName("LogPanel");
  2272. WMRestorable.StoreLongint(entry, "height", page.logPanel.bounds.GetHeight());
  2273. elem.AddContent(entry);
  2274. NEW(entry); entry.SetName("SidePanel");
  2275. WMRestorable.StoreBoolean(entry, "visible", page.sidePanel.visible.Get());
  2276. WMRestorable.StoreLongint(entry, "width", page.sidePanel.bounds.GetWidth());
  2277. WMRestorable.StoreLongint(entry, "scratchHeight", page.scratchPanel.bounds.GetHeight());
  2278. elem.AddContent(entry);
  2279. RETURN elem;
  2280. END StorePage;
  2281. PROCEDURE HandleShortcut(ucs : LONGINT; flags : SET; keysym : LONGINT) : BOOLEAN;
  2282. VAR filename : Filename; options : CompilerOptions;
  2283. BEGIN
  2284. modifierFlags := flags;
  2285. IF DisableShortcuts THEN RETURN FALSE; END;
  2286. IF (keysym = 13H) & ControlKeyDown(flags) THEN (* CTRL-S *)
  2287. StoreHandler(NIL, NIL);
  2288. ELSIF (keysym = 20H) & ControlKeyDown(flags) THEN (* CTRL-<space> *)
  2289. CompleteHandler(NIL, NIL);
  2290. ELSIF (keysym = 08H) & ControlKeyDown(flags) THEN (* CTRL-H *)
  2291. IF currentPage # NIL THEN
  2292. optionsEdit.GetAsString(options);
  2293. currentPage.DoCompile(FALSE, "", options);
  2294. END;
  2295. ELSIF (keysym = 0FH) & ControlKeyDown(flags) THEN (* CTRL-O *)
  2296. filenameEdit.SetAsString("");
  2297. filenameEdit.SetFocus;
  2298. ELSIF (keysym = Inputs.KsPageDown) & ControlKeyDown(flags) THEN (* CTRL-PgDn *)
  2299. IF (WMDialogs.QueryString("Save PET state into (.pet extension is appended)", filename) = WMDialogs.ResOk) & (filename # "") THEN
  2300. Strings.Append(filename, StateFileExtension);
  2301. StoreState(filename);
  2302. END;
  2303. ELSIF (keysym = Inputs.KsPageUp) & ControlKeyDown(flags) THEN (* CTRL-PgUp *)
  2304. IF (WMDialogs.QueryString("Load PET state from (.pet extension is appended)", filename) = WMDialogs.ResOk) & (filename # "") THEN
  2305. DisableUpdate;
  2306. IF CloseAllTabs() THEN
  2307. Strings.Append(filename, StateFileExtension);
  2308. IF LoadState(filename) THEN
  2309. UpdatePages;
  2310. UpdateState;
  2311. END;
  2312. END;
  2313. EnableUpdate;
  2314. form.Invalidate;
  2315. END;
  2316. ELSIF (keysym = Inputs.KsTab) & ControlKeyDown(flags) THEN (* CTRL-Tab *)
  2317. DisableUpdate; SelectNextTab; EnableUpdate;
  2318. ELSIF (keysym = Inputs.KsTab) & (flags * Inputs.Ctrl # {}) & (flags * Inputs.Shift # {}) &
  2319. (flags - Inputs.Ctrl - Inputs.Shift = {}) THEN (* CTRL-SHIFT-Tab *)
  2320. DisableUpdate; SelectPreviousTab; EnableUpdate;
  2321. ELSIF (keysym = 015H) & ControlKeyDown(flags) THEN (* CTRL-U *)
  2322. IF (currentPage # NIL) THEN UnloadModule; END;
  2323. (* relay hot key to current page *)
  2324. ELSIF (currentPage = NIL) OR ((currentPage # NIL) & (~currentPage.HandleShortcut(ucs, flags, keysym))) THEN
  2325. RETURN FALSE; (* Key not handled *)
  2326. END;
  2327. RETURN TRUE;
  2328. END HandleShortcut;
  2329. PROCEDURE Handle*(VAR m: WMMessages.Message);
  2330. VAR data : WMRestorable.XmlElement;
  2331. BEGIN
  2332. IF m.msgType = WMMessages.MsgKey THEN
  2333. IF ~HandleShortcut(m.x, m.flags, m.y) THEN
  2334. Handle^(m);
  2335. END;
  2336. ELSIF (m.msgType = WMMessages.MsgExt) & (m.ext # NIL) THEN
  2337. IF (m.ext IS KillerMsg) THEN Close
  2338. ELSIF (m.ext IS WMRestorable.Storage) THEN
  2339. data := StorePages();
  2340. m.ext(WMRestorable.Storage).Add("TFPET", "TFPET.Restore", SELF, data)
  2341. ELSE Handle^(m)
  2342. END
  2343. ELSE Handle^(m)
  2344. END
  2345. END Handle;
  2346. END Window;
  2347. VAR
  2348. nofWindows : LONGINT;
  2349. scratchText : Texts.Text;
  2350. scratchModified : BOOLEAN;
  2351. settings : Settings;
  2352. StrScratchPanel, StrPETPanel : Strings.String;
  2353. (** Open document *)
  2354. PROCEDURE Open*(context : Commands.Context); (** [Options] {filename['@'position]} ~ *)
  2355. VAR
  2356. window : Window; count, index, temp, position : LONGINT;
  2357. filename : Filename; format : ARRAY 32 OF CHAR;
  2358. options: Options.Options;
  2359. BEGIN
  2360. NEW(options);
  2361. options.Add("e","external",Options.Flag);
  2362. options.Add("f", "format", Options.String);
  2363. IF options.Parse(context.arg, context.error) THEN
  2364. IF (context.caller # NIL) & (context.caller IS Window) & ~options.GetFlag("external") THEN
  2365. window := context.caller(Window);
  2366. ELSE
  2367. NEW(window, NIL);
  2368. END;
  2369. IF ~options.GetString("format", format) THEN format := "AUTO"; END;
  2370. count := 0;
  2371. WHILE context.arg.GetString(filename) DO
  2372. position := 0; index := Strings.Find(filename, 0, '@');
  2373. IF index >= 0 THEN temp := index + 1; Strings.StrToIntPos(filename, position, temp); ASSERT (position # 0); Strings.Truncate(filename, index) END;
  2374. IF filename # "" THEN window.Load(filename, format); window.SetCursorPosition(position); INC(count) END
  2375. END;
  2376. IF count = 0 THEN window.Load("Untitled.Mod", "AUTO") END;
  2377. END;
  2378. END Open;
  2379. PROCEDURE OpenState*(context : Commands.Context); (** filename ~ *)
  2380. VAR filename : Filename; window : Window;
  2381. BEGIN
  2382. context.arg.SkipWhitespace; context.arg.String(filename);
  2383. NEW(window, NIL);
  2384. IF ~window.LoadState(filename) THEN
  2385. context.error.String("PET: Could not state from file "); context.error.String(filename); context.error.Ln;
  2386. END;
  2387. END OpenState;
  2388. PROCEDURE Restore*(context : WMRestorable.Context);
  2389. VAR w : Window;
  2390. BEGIN
  2391. NEW(w, context)
  2392. END Restore;
  2393. (** Comment the currently selected text *)
  2394. PROCEDURE CommentSelection*(text : Texts.Text; from, to : Texts.TextPosition);
  2395. VAR a, b : LONGINT; string : ARRAY 4 OF Texts.Char32;
  2396. BEGIN
  2397. ASSERT((text # NIL) & (from # NIL) & (to # NIL));
  2398. text.AcquireWrite;
  2399. a := MIN(from.GetPosition(), to.GetPosition());
  2400. b := MAX(from.GetPosition(), to.GetPosition());
  2401. string[0] := ORD(" "); string[1] := ORD("*"); string[2] := ORD(")"); string[3] := 0;
  2402. text.InsertUCS32(b, string);
  2403. string[0] := ORD("("); string[1] := ORD("*"); string[2] := ORD(" "); string[3] := 0;
  2404. text.InsertUCS32(a, string);
  2405. IF (a <= b) THEN from.SetPosition(a); ELSE to.SetPosition(a); END;
  2406. text.ReleaseWrite;
  2407. Texts.SetLastSelection(text, from, to);
  2408. END CommentSelection;
  2409. (** Uncomment the currently selected text if it is commented *)
  2410. PROCEDURE UncommentSelection*(text : Texts.Text; from, to : Texts.TextPosition);
  2411. VAR
  2412. reader : Texts.TextReader; ch : Texts.Char32;
  2413. a, b : LONGINT;
  2414. openPos, closePos, openLen, closeLen : LONGINT;
  2415. BEGIN
  2416. text.AcquireWrite;
  2417. a := MIN(from.GetPosition(), to.GetPosition());
  2418. b := MAX(from.GetPosition(), to.GetPosition());
  2419. NEW(reader, text);
  2420. (* find open *)
  2421. openPos := -1; openLen := 2;
  2422. reader.SetPosition(a);
  2423. REPEAT reader.ReadCh(ch); UNTIL reader.eot OR ~TextUtilities.IsWhiteSpace(ch, FALSE) OR (reader.GetPosition() >= b);
  2424. IF (ch = ORD("(")) THEN
  2425. reader.ReadCh(ch);
  2426. IF (ch = ORD("*")) THEN
  2427. openPos := reader.GetPosition() - 2;
  2428. reader.ReadCh(ch);
  2429. IF (ch = ORD(" ")) THEN INC(openLen); END; (* delete the space character right to the open comment string *)
  2430. END;
  2431. END;
  2432. (* find close *)
  2433. closePos := -1; closeLen := 2;
  2434. IF (openPos > 0) THEN
  2435. reader.SetDirection(-1);
  2436. reader.SetPosition(b - 1);
  2437. REPEAT reader.ReadCh(ch); UNTIL reader.eot OR ~TextUtilities.IsWhiteSpace(ch, FALSE) OR (reader.GetPosition() <= a);
  2438. IF (ch = ORD(")")) THEN
  2439. reader.ReadCh(ch);
  2440. IF (ch = ORD("*")) THEN
  2441. closePos := reader.GetPosition() + 1;
  2442. reader.ReadCh(ch);
  2443. IF (ch = ORD(" ")) & (openPos + openLen - 1 < closePos - closeLen + 2) THEN
  2444. (* delete the space character left to the close comment string *)
  2445. INC(closeLen); DEC(closePos);
  2446. END;
  2447. END;
  2448. END;
  2449. END;
  2450. IF (openPos + openLen - 1 < closePos) THEN
  2451. text.Delete(closePos, closeLen);
  2452. text.Delete(openPos, openLen);
  2453. END;
  2454. text.ReleaseWrite;
  2455. END UncommentSelection;
  2456. (** Comment the currently selected text *)
  2457. PROCEDURE Comment*;
  2458. VAR text : Texts.Text; from, to : Texts.TextPosition;
  2459. BEGIN
  2460. IF Texts.GetLastSelection(text, from, to) THEN
  2461. CommentSelection(text, from, to);
  2462. END;
  2463. END Comment;
  2464. (** Uncomment the currently selected text if it is commented *)
  2465. PROCEDURE Uncomment*;
  2466. VAR text : Texts.Text; from, to : Texts.TextPosition;
  2467. BEGIN
  2468. IF Texts.GetLastSelection(text, from, to) THEN
  2469. UncommentSelection(text, from, to);
  2470. END;
  2471. END Uncomment;
  2472. PROCEDURE GetSyntaxHighlighterName*(fullname : ARRAY OF CHAR; VAR name : ARRAY OF CHAR);
  2473. VAR filename, extension, config : Files.FileName; res : WORD;
  2474. BEGIN
  2475. name := "";
  2476. Strings.UpperCase(fullname);
  2477. Strings.GetExtension(fullname, filename, extension);
  2478. IF (extension # "") THEN
  2479. config := "Applications.PET.SyntaxHighlighter.";
  2480. Strings.AppendX(config, extension);
  2481. Configuration.Get(config, name, res);
  2482. IF (res # Configuration.Ok) THEN name := ""; END;
  2483. END;
  2484. END GetSyntaxHighlighterName;
  2485. PROCEDURE ControlKeyDown(flags : SET) : BOOLEAN;
  2486. BEGIN
  2487. RETURN (flags * Inputs.Ctrl # {}) & (flags - Inputs.Ctrl = {});
  2488. END ControlKeyDown;
  2489. PROCEDURE EitherShiftOrControlDown(flags : SET) : BOOLEAN;
  2490. BEGIN
  2491. RETURN ((flags * Inputs.Shift # {}) & (flags * Inputs.Ctrl = {})) OR ((flags * Inputs.Ctrl # {}) & (flags * Inputs.Shift = {}));
  2492. END EitherShiftOrControlDown;
  2493. PROCEDURE ContainsFileExtension(filename , extension : ARRAY OF CHAR) : BOOLEAN;
  2494. BEGIN
  2495. Strings.UpperCase(filename);
  2496. Strings.UpperCase(extension);
  2497. RETURN Strings.Pos(extension, filename) > 0;
  2498. END ContainsFileExtension;
  2499. PROCEDURE ScratchModified(sender, data : ANY);
  2500. BEGIN {EXCLUSIVE}
  2501. scratchModified := TRUE
  2502. END ScratchModified;
  2503. PROCEDURE StoreScratchText;
  2504. BEGIN (* caller holds module lock *)
  2505. IF scratchModified THEN
  2506. StoreText(ScratchTextFilename, scratchText);
  2507. scratchModified := FALSE;
  2508. END;
  2509. END StoreScratchText;
  2510. PROCEDURE LoadScratchText;
  2511. BEGIN (* caller holds module lock *)
  2512. scratchText := LoadText(ScratchTextFilename);
  2513. scratchText.onTextChanged.Add(ScratchModified);
  2514. END LoadScratchText;
  2515. PROCEDURE StoreText(CONST filename : ARRAY OF CHAR; text : Texts.Text);
  2516. VAR res : WORD;
  2517. BEGIN
  2518. text.AcquireRead;
  2519. TextUtilities.StoreOberonText(text, filename, res);
  2520. text.ReleaseRead
  2521. END StoreText;
  2522. PROCEDURE LoadText(CONST filename : ARRAY OF CHAR) : Texts.Text;
  2523. VAR text : Texts.Text; res : WORD;
  2524. BEGIN
  2525. NEW(text);
  2526. text.AcquireWrite;
  2527. TextUtilities.LoadOberonText(text, filename, res);
  2528. text.ReleaseWrite;
  2529. RETURN text;
  2530. END LoadText;
  2531. PROCEDURE IncCount;
  2532. BEGIN {EXCLUSIVE}
  2533. INC(nofWindows);
  2534. IF (nofWindows = 1) THEN
  2535. NEW(settings); settings.Load;
  2536. LoadScratchText;
  2537. END;
  2538. END IncCount;
  2539. PROCEDURE DecCount;
  2540. BEGIN {EXCLUSIVE}
  2541. DEC(nofWindows);
  2542. IF (nofWindows = 0) THEN
  2543. StoreScratchText;
  2544. scratchText := NIL;
  2545. settings := NIL;
  2546. END;
  2547. END DecCount;
  2548. PROCEDURE Cleanup;
  2549. VAR die : KillerMsg;
  2550. msg : WMMessages.Message;
  2551. m : WMWindowManager.WindowManager;
  2552. BEGIN {EXCLUSIVE}
  2553. NEW(die); msg.ext := die; msg.msgType := WMMessages.MsgExt;
  2554. m := WMWindowManager.GetDefaultManager();
  2555. m.Broadcast(msg);
  2556. AWAIT(nofWindows = 0);
  2557. END Cleanup;
  2558. PROCEDURE LoadModule(CONST moduleName : ARRAY OF CHAR);
  2559. VAR module : Modules.Module; msg : ARRAY 128 OF CHAR; res : WORD;
  2560. BEGIN
  2561. module := Modules.ThisModule(moduleName, res, msg);
  2562. END LoadModule;
  2563. PROCEDURE InitStrings;
  2564. BEGIN
  2565. StrScratchPanel := Strings.NewString("ScratchPanel");
  2566. StrPETPanel := Strings.NewString("PETPanel");
  2567. END InitStrings;
  2568. BEGIN
  2569. nofWindows := 0;
  2570. scratchText := NIL; scratchModified := FALSE;
  2571. Modules.InstallTermHandler(Cleanup);
  2572. InitStrings;
  2573. END TFPET.
  2574. System.Free TFPET ~
  2575. WMMacros.ReadMacros Macros.XML ~
  2576. TFPET.Open TFAOParser.Mod~
  2577. TFPET.Open TFPET.Mod ~
  2578. System.Free TFPET WMXMLTree ~
  2579. PC.Compile TFPET.Mod ~
  2580. System.Free TFXRef TFPET TFModuleTrees TFAOParser TFDumpTS TFCheck TFScopeTools TFTypeSys BimboScanner TFStringPool~
  2581. Compiler.Compile TFStringPool.Mod BimboScanner.Mod TFTypeSys.Mod TFScopeTools.Mod TFCheck.Mod TFDumpTS.Mod TFAOParser.Mod TFModuleTrees.Mod TFPET.Mod~
  2582. TFPET.OpenState a.pet ~
  2583. (* Create .xym files for all modules in a directory *)
  2584. TFAOParser.MakeSymbolFiles "Strings" "Oberon*"~ (* main *.Mod*)
  2585. TFAOParser.MakeSymbolFiles "Trunk/" ~ (* main *.Mod*)
  2586. TFAOParser.MakeSymbolFiles "D:\Aos\trunk\source\" "*Oberon*"~ (* d:/release/*.Mod *)
  2587. TFAOParser.MakeSymbolFiles "D:\Aos\trunk\WinAos\Work\" "*Oberon*"~
  2588. AosTar.Create TFPET20061118.tar TextUtilities.Mod WMTextView.Mod TFStringPool.Mod BimboScanner.Mod TFScopeTools.Mod TFTypeSys.Mod TFCheck.Mod TFDumpTS.Mod TFAOParser.Mod
  2589. TFModuleTrees.Mod TFPET.Mod ~
  2590. TFPET.Open TFModuleTrees.Mod~
  2591. TFPET.Open PET.Mod~
  2592. TFPET.Open TFPET.Mod ~
  2593. TFPET.Open WMComponents.Mod~
  2594. PET.Open TFPET.Mod ~
  2595. WMTextView.Mod
  2596. Changed Highlight and TextMarker to use TextPositionKeeper instead of Texts.TextPosition