PET.Mod 95 KB

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