PET.Mod 95 KB

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