DIRECTORY Buttons USING [Button, ButtonProc, Create, SetDisplayStyle], Commander USING [CommandProc, Register], CommandTool USING [ParseToList], Containers USING [ChildXBound, ChildYBound, Create], Convert USING [CardFromRope, Error], FileNames USING [CurrentWorkingDirectory], FS USING [Close, EnumerateForNames, GetInfo, NameProc, Open, OpenFile, Read], Icons USING [IconFlavor, IconFileFormat], Imager USING [Context, DoSave, MaskBox, SetColor, SetXY], ImagerBackdoor USING [DrawBits, invert], IO USING [Close, Flush, int, PutF, PutFR, rope, time], Labels USING [Create, Label], List USING [DReverse], Menus USING [AppendMenuEntry, ChangeNumberOfLines, CreateMenu, CreateEntry, GetNumberOfLines, Menu, MenuLine, MenuProc], MessageWindow USING [Append, Blink], Rope USING [Equal, Fetch, Find, Length, ROPE, Substr], Rules USING [Create, Rule], spGlobals USING[BatchRun, ConRec, DumpIt, EchoInput, EnsureExtension, FuncTable, Handle, Level2Model, ModelTable, NodeRec, NormalRun, RefConRec, RefNodeRec, RefR, RefUnReal, ResistorBody, ShowDetails, spFunctions, spModels, SaveAll, Stages, StopIt, ThymeToolRec, ToggleEchoInput, ToggleSaveAll, ToggleShowDetails, UnReal], TerminalDefs USING [Cursor], TiogaOps USING [FindDef, FindText, FindWord, SearchDir], TypeScript USING [Create, TS], VFonts USING[CharWidth, StringWidth], ViewerBLT USING[ChangeNumberOfLines], ViewerClasses USING [PaintProc, Viewer, ViewerClass, ViewerClassRec], ViewerEvents USING [EventProc, RegisterEventProc], ViewerIO USING [CreateViewerStreams], ViewerOps USING [AddProp, CreateViewer, EnumerateViewers, EnumProc, FetchProp, PaintViewer, RegisterViewerClass, RestoreViewer, SaveViewer, SetViewer, --SetMenu, --SetOpenHeight], ViewerPrivate USING [selectedIcon], ViewerTools USING [GetContents, MakeNewTextViewer, SetContents, SetSelection], VM USING [AddressForPageNumber, Allocate, Free, Interval]; ThymeViewers: CEDAR MONITOR IMPORTS Buttons, Commander, CommandTool, Containers, Convert, FileNames, FS, Imager, ImagerBackdoor, IO, Labels, List, Menus, MessageWindow, Rope, Rules, spGlobals, TiogaOps, TypeScript, ViewerEvents, ViewerIO, ViewerOps, VFonts, ViewerBLT, ViewerPrivate, ViewerTools, VM EXPORTS spGlobals = { version: PUBLIC Rope.ROPE_ "Thyme - Cedar6.1 - June 1986"; refNodeRec: PUBLIC spGlobals.RefNodeRec= NEW[spGlobals.NodeRec]; refConRec: PUBLIC spGlobals.RefConRec= NEW[spGlobals.ConRec]; refR: PUBLIC spGlobals.RefR= NEW[spGlobals.ResistorBody]; refUnReal: PUBLIC spGlobals.RefUnReal= NEW[spGlobals.UnReal]; modelTable: PUBLIC spGlobals.ModelTable_ NIL; functionTable: PUBLIC spGlobals.FuncTable_ NIL; msgViewerH: CARDINAL = 100; MakeThymeViewers: PUBLIC PROC[wDir: Rope.ROPE _ NIL] RETURNS [handle: spGlobals.Handle _ NIL] = { thymeMenus: Menus.Menu; handle _ NEW[spGlobals.ThymeToolRec _ []]; thymeMenus _ MakeThymeMenus[handle]; TRUSTED{ handle.outer _ Containers.Create[ info: [ name: version, iconic: TRUE, icon: private, menu: thymeMenus, column: left, scrollable: FALSE], paint: FALSE]; }; IF ViewerOps.FetchProp[handle.outer, $ThymeHandle] = NIL THEN ViewerOps.AddProp[handle.outer, $ThymeHandle, handle]; IF ThymeNormalPaint = NIL THEN ThymeNormalPaint _ handle.outer.class.paint; handle.outer.class.paint _ ThymeViewerPaint; Menus.ChangeNumberOfLines[thymeMenus, 1]; MakeMainViewer[ handle: handle, workingDir: IF wDir = NIL THEN FileNames.CurrentWorkingDirectory[] ELSE wDir]; MakeMsgViewer[handle]; ViewerOps.SetOpenHeight[handle.outer, handle.height + msgViewerH]; ViewerOps.PaintViewer[handle.outer, all]; }; -- MakeThymeViewers MakeThymeMenus: PROC[handle: spGlobals.Handle] RETURNS[menu: Menus.Menu] = { requestConfirmMsg: Rope.ROPE = "Please confirm by clicking at it again."; menu _ Menus.CreateMenu[]; Menus.AppendMenuEntry[ menu: menu, entry: Menus.CreateEntry[ name: "Stop", proc: Stop, clientData: handle, guarded: TRUE, documentation: requestConfirmMsg] ]; Menus.AppendMenuEntry[ menu: menu, entry: Menus.CreateEntry[ name: "Dump", proc: Dump, clientData: handle, guarded: TRUE, documentation: requestConfirmMsg] ]; Menus.AppendMenuEntry[ menu: menu, entry: Menus.CreateEntry[name: "Run", proc: Run, clientData: handle] ]; Menus.AppendMenuEntry[ menu: menu, entry: Menus.CreateEntry[name: "New", proc: New, clientData: handle] ]; Menus.AppendMenuEntry[ menu: menu, entry: Menus.CreateEntry[name: "TypeScriptMenus", proc: TypeScriptMenus, clientData: handle] ]; Menus.AppendMenuEntry[ menu: menu, entry: Menus.CreateEntry[ name: "Save", proc: Save, clientData: handle, guarded: TRUE, documentation: requestConfirmMsg], line: 1 ]; Menus.AppendMenuEntry[ menu: menu, entry: Menus.CreateEntry[ name: "Reset", proc: Reset, clientData: handle, guarded: TRUE, documentation: requestConfirmMsg], line: 1 ]; Menus.AppendMenuEntry[ menu: menu, entry: Menus.CreateEntry[name: "Find", proc: Find, clientData: handle], line: 1 ]; Menus.AppendMenuEntry[ menu: menu, entry: Menus.CreateEntry[name: "Word", proc: Word, clientData: handle], line: 1 ]; Menus.AppendMenuEntry[ menu: menu, entry: Menus.CreateEntry[name: "Def", proc: Def, clientData: handle], line: 1 ]; Menus.AppendMenuEntry[ menu: menu, entry: Menus.CreateEntry[name: "FindError", proc: FindError, clientData: handle], line: 1 ]; }; -- MakeThymeMenus Stop: ENTRY Menus.MenuProc = { ENABLE UNWIND => NULL; handle: spGlobals.Handle _ NARROW[clientData]; spGlobals.StopIt[handle]; }; -- Stop Run: ENTRY Menus.MenuProc = { ENABLE UNWIND => NULL; handle: spGlobals.Handle _ NARROW[clientData]; spGlobals.NormalRun[handle]; }; -- Run Dump: ENTRY Menus.MenuProc = { ENABLE UNWIND => NULL; handle: spGlobals.Handle _ NARROW[clientData]; spGlobals.DumpIt[handle]; }; -- Dump New: Menus.MenuProc = { handle: spGlobals.Handle _ NARROW[clientData]; []_ MakeThymeViewers[ViewerTools.GetContents[handle.wDir]]; }; TypeScriptMenus: ENTRY Menus.MenuProc = { ENABLE UNWIND => NULL; viewer: ViewerClasses.Viewer _ NARROW[parent]; menu: Menus.Menu _ viewer.menu; numLines: Menus.MenuLine _ Menus.GetNumberOfLines[menu]; SELECT numLines FROM 1 => { numLines _ numLines + 1; }; 2 => numLines _ numLines - 1; ENDCASE => ERROR; ViewerBLT.ChangeNumberOfLines[viewer, numLines]; }; -- TypeScriptMenus Save: ENTRY Menus.MenuProc = { ENABLE UNWIND => NULL; handle: spGlobals.Handle _ NARROW[clientData]; IF handle # NIL THEN { IF handle.simulation # NIL THEN MessageWindow.Append["Thyme.log could NOT be saved when a circuit is being simulated.", TRUE] ELSE IF handle.msgStream # NIL THEN { handle.msgStream.PutF["\nSaved: %g\n", IO.time[]]; handle.msgStream.Flush[]; ViewerOps.SaveViewer[handle.message]; }; }; }; -- Save Reset: ENTRY Menus.MenuProc = { ENABLE UNWIND => NULL; handle: spGlobals.Handle _ NARROW[clientData]; IF handle # NIL THEN { IF handle.simulation # NIL THEN MessageWindow.Append["Thyme.log could NOT be reset when a circuit is being simulated.", TRUE] ELSE IF handle.msgStream # NIL THEN { ViewerOps.RestoreViewer[handle.message]; handle.msgStream.PutF["File: Thyme.log\nCreated: %g\n", IO.time[]]; }; }; }; -- Reset Find: ENTRY Menus.MenuProc = { ENABLE UNWIND => NULL; handle: spGlobals.Handle _ NARROW[clientData]; IF handle # NIL THEN { IF handle.msgStream # NIL AND handle.message # NIL THEN { dir: TiogaOps.SearchDir = SELECT mouseButton FROM red => forwards, yellow => anywhere, ENDCASE => backwards; case: BOOL = NOT shift; found: BOOL _ TiogaOps.FindText[ viewer: handle.message, rope: NIL, -- automatically uses contents of primary selection whichDir: dir, which: primary, case: case]; IF NOT found THEN BlinkMsg["Text not found."]; }; }; }; -- Find Word: ENTRY Menus.MenuProc = { ENABLE UNWIND => NULL; handle: spGlobals.Handle _ NARROW[clientData]; IF handle # NIL THEN { IF handle.msgStream # NIL AND handle.message # NIL THEN { dir: TiogaOps.SearchDir = SELECT mouseButton FROM red => forwards, yellow => anywhere, ENDCASE => backwards; case: BOOL = NOT shift; found: BOOL _ TiogaOps.FindWord[ viewer: handle.message, rope: NIL, -- automatically uses contents of primary selection whichDir: dir, which: primary, case: case]; IF NOT found THEN BlinkMsg["Text not found."]; }; }; }; -- Word Def: ENTRY Menus.MenuProc = { ENABLE UNWIND => NULL; handle: spGlobals.Handle _ NARROW[clientData]; IF handle # NIL THEN { IF handle.msgStream # NIL AND handle.message # NIL THEN { dir: TiogaOps.SearchDir = SELECT mouseButton FROM red => forwards, yellow => anywhere, ENDCASE => backwards; case: BOOL = NOT shift; found: BOOL _ TiogaOps.FindDef[ viewer: handle.message, rope: NIL, -- automatically uses contents of primary selection whichDir: dir, which: primary, case: case]; IF NOT found THEN BlinkMsg["Text not found."]; }; }; }; -- Def FindError: ENTRY Menus.MenuProc = { ENABLE UNWIND => NULL; handle: spGlobals.Handle _ NARROW[clientData]; IF handle # NIL THEN { IF handle.msgStream # NIL AND handle.message # NIL THEN { dir: TiogaOps.SearchDir = SELECT mouseButton FROM red => forwards, yellow => anywhere, ENDCASE => backwards; case: BOOL = NOT shift; found: BOOL _ TiogaOps.FindText[ viewer: handle.message, rope: "g Error ", whichDir: dir, which: primary, case: case]; IF NOT found THEN BlinkMsg["Text not found."]; }; }; }; -- FindError BlinkMsg: PROC[msg: Rope.ROPE] = { MessageWindow.Append[msg, TRUE]; MessageWindow.Blink[]; }; -- BlinkMsg MakeMainViewer: PROC [handle: spGlobals.Handle, workingDir: Rope.ROPE _ NIL] = { entryHeight: CARDINAL = 12; entryVSpace: CARDINAL = 6; entryHSpace: CARDINAL = 10; initialOutputName: Rope.ROPE = ""; outLabel, progressLabel, timeLabel, stepLabel: Labels.Label; wDirButton, inputButton: Buttons.Button; initialInputName: Rope.ROPE = ""; handle.height _ handle.height + entryVSpace; wDirButton _ Buttons.Create[ info: [ name: "Working Directory:", parent: handle.outer, wy: handle.height + 2, wh: entryHeight, -- default the width so that it will be computed for us border: FALSE ], clientData: handle, proc: DirPrompt, paint: FALSE]; handle.wDir _ ViewerTools.MakeNewTextViewer[ info: [ parent: handle.outer, wx: wDirButton.wx + wDirButton.ww + entryHSpace, wy: handle.height, ww: 80*VFonts.CharWidth['M], wh: entryHeight + 2, data: workingDir, border: FALSE], paint: FALSE]; handle.height _ handle.height + entryHeight + entryVSpace; inputButton _ Buttons.Create[ info: [ name: "Input File:", parent: handle.outer, wy: handle.height + 2, wh: entryHeight, border: FALSE ], clientData: handle, proc: InputPrompt, paint: FALSE]; handle.input _ ViewerTools.MakeNewTextViewer[ info: [ parent: handle.outer, wx: inputButton.wx + inputButton.ww + entryHSpace, wy: handle.height, ww: 80*VFonts.CharWidth['M], wh: entryHeight + 2, data: initialInputName, border: FALSE], paint: FALSE]; handle.height _ handle.height + entryHeight + entryVSpace; outLabel _ Labels.Create[ info: [ name: "Output File:", parent: handle.outer, wy: handle.height, border: FALSE ], paint: FALSE]; handle.output _ Labels.Create[ info: [ name: initialOutputName, parent: handle.outer, wx: VFonts.StringWidth["Output File:"] + entryHSpace, wy: handle.height + 2, ww: 80*VFonts.CharWidth['W], wh: entryHeight, border: FALSE], paint: FALSE]; handle.height _ handle.height + entryHeight + entryVSpace; progressLabel _ Labels.Create[ info: [name: "Progress:", parent: handle.outer, wy: handle.height, border: FALSE ], paint: FALSE]; handle.progress _ ViewerOps.CreateViewer[ flavor: $ThymeCursor, info: [ parent: handle.outer, wx: progressLabel.wx + progressLabel.ww + entryHSpace, wy: handle.height, ww: 16, wh: 16, data: idleBitmap, border: FALSE], paint: FALSE]; handle.showDetailsButton _ Buttons.Create[ info: [ name: "details:", parent: handle.outer, wx: handle.progress.wx + handle.progress.ww + entryHSpace + entryHSpace, wy: handle.height, wh: entryHeight + 3, border: TRUE ], clientData: handle, proc: ShowDetailsProc, paint: FALSE]; Buttons.SetDisplayStyle[handle.showDetailsButton, IF spGlobals.ShowDetails[handle] THEN $WhiteOnBlack ELSE $BlackOnWhite]; timeLabel _ Labels.Create[ info: [ name: "time:", parent: handle.outer, wx: handle.showDetailsButton.wx + handle.showDetailsButton.ww + entryHSpace, wy: handle.height + 2, wh: entryHeight, border: FALSE ], paint: FALSE]; handle.time _ Labels.Create[ info: [ parent: handle.outer, wx: timeLabel.wx + timeLabel.ww + entryHSpace, wy: handle.height + 2, ww: 8*VFonts.StringWidth["M"], wh: entryHeight, border: FALSE], paint: FALSE]; stepLabel _ Labels.Create[ info: [ name: "step:", parent: handle.outer, wx: handle.time.wx + handle.time.ww + entryHSpace, wy: handle.height + 2, wh: entryHeight, border: FALSE ], paint: FALSE]; handle.step _ Labels.Create[ info: [ parent: handle.outer, wx: stepLabel.wx + stepLabel.ww + entryHSpace, wy: handle.height + 2, ww: 8*VFonts.StringWidth["M"], wh: entryHeight, border: FALSE], paint: FALSE]; handle.echoInputButton _ Buttons.Create[ info: [ name: "Echo input", parent: handle.outer, wx: handle.step.wx + handle.step.ww + entryHSpace, wy: handle.height, wh: entryHeight + 3, border: TRUE ], clientData: handle, proc: EchoInputProc, paint: FALSE]; Buttons.SetDisplayStyle[handle.echoInputButton, IF spGlobals.EchoInput[handle] THEN $WhiteOnBlack ELSE $BlackOnWhite]; handle.saveAllButton _ Buttons.Create[ info: [ name: "Save All", parent: handle.outer, wx: handle.echoInputButton.wx + handle.echoInputButton.ww + entryHSpace, wy: handle.height, wh: entryHeight + 3, border: TRUE ], clientData: handle, proc: SaveAllProc, paint: FALSE]; Buttons.SetDisplayStyle[handle.saveAllButton, IF spGlobals.SaveAll[handle] THEN $WhiteOnBlack ELSE $BlackOnWhite]; handle.height _ handle.height + entryHeight + entryVSpace; }; -- MakeMainViewer DirPrompt: Buttons.ButtonProc = { handle: spGlobals.Handle _ NARROW[clientData]; IF handle # NIL THEN ViewerTools.SetSelection[handle.wDir]; }; -- InputPrompt InputPrompt: Buttons.ButtonProc = { handle: spGlobals.Handle _ NARROW[clientData]; IF handle # NIL THEN ViewerTools.SetSelection[handle.input]; }; -- InputPrompt ShowDetailsProc: Buttons.ButtonProc = { handle: spGlobals.Handle _ NARROW[clientData]; IF handle # NIL THEN { spGlobals.ToggleShowDetails[handle]; Buttons.SetDisplayStyle[handle.showDetailsButton, IF spGlobals.ShowDetails[handle] THEN $WhiteOnBlack ELSE $BlackOnWhite]; IF NOT spGlobals.ShowDetails[handle] THEN { ViewerTools.SetContents[handle.time, NIL]; ViewerTools.SetContents[handle.step, NIL]; }; }; }; -- InputPrompt EchoInputProc: Buttons.ButtonProc = { handle: spGlobals.Handle _ NARROW[clientData]; IF handle # NIL THEN { spGlobals.ToggleEchoInput[handle]; Buttons.SetDisplayStyle[handle.echoInputButton, IF spGlobals.EchoInput[handle] THEN $WhiteOnBlack ELSE $BlackOnWhite]; }; }; -- EchoInputProc SaveAllProc: Buttons.ButtonProc = { handle: spGlobals.Handle _ NARROW[clientData]; IF handle # NIL THEN { spGlobals.ToggleSaveAll[handle]; Buttons.SetDisplayStyle[handle.saveAllButton, IF spGlobals.SaveAll[handle] THEN $WhiteOnBlack ELSE $BlackOnWhite]; }; }; -- SaveAllProc MakeMsgViewer: PROC [handle: spGlobals.Handle] = { rule: Rules.Rule _ Rules.Create[ info: [ parent: handle.outer, wy: handle.height, ww: handle.outer.cw, wh: 1], paint: FALSE]; Containers.ChildXBound[handle.outer, rule]; handle.height_ handle.height + 2; handle.message_ TypeScript.Create[ info: [ parent: handle.outer, wy: handle.height, ww: handle.outer.cw, wh: 800, border: FALSE, file: "Thyme.log"], paint: FALSE ]; [in: , out: handle.msgStream] _ ViewerIO.CreateViewerStreams[ name: "Thyme.log", viewer: handle.message, backingFile: "Thyme.log"]; IO.PutF[handle.msgStream, "File: Thyme.log\nCreated: %g\n", IO.time[]]; Containers.ChildXBound[handle.outer, handle.message]; Containers.ChildYBound[handle.outer, handle.message]; }; -- MakeMsgViewer ThymeDestroy: ViewerEvents.EventProc = { IF (event = destroy) AND before THEN { h: spGlobals.Handle _ NARROW[ViewerOps.FetchProp[viewer, $ThymeHandle]]; IF h # NIL THEN {OPEN h; outer _ NIL; wDir _ input _ NIL; output _ time _ step _ NIL; message _ NIL; msgStream.Flush[]; msgStream.Close[]; msgStream _ NIL; showDetailsButton _ echoInputButton _ saveAllButton _ NIL; }; }; }; -- ThymeDestroy iconW: INTEGER = 64; iconH: INTEGER = 64; StatusBitmap: TYPE = REF StatusPattern; StatusPattern: TYPE = TerminalDefs.Cursor; -- ARRAY [0..16) OF WORD thymeIconBitmap: REF IconPattern; IconPattern: TYPE = ARRAY [0..iconH*iconW/16) OF WORD; idleBitmap, inputBitmap, bombBitmap, topoBitmap: StatusBitmap; runBitmap: ARRAY [0..4) OF StatusBitmap; ThymeViewerPaint: ViewerClasses.PaintProc = { IF self.iconic THEN [] _ ThymeIconPaint[self, context, whatChanged, clear] ELSE [] _ ThymeNormalPaint[self, context, whatChanged, clear]; }; -- ThymeViewerPaint ThymeNormalPaint: ViewerClasses.PaintProc _ NIL; -- will be assigned Containers PaintProc ThymeIconPaint: ViewerClasses.PaintProc = { handle: spGlobals.Handle; bitmap: StatusBitmap; drawFace: PROC = { context.SetXY[[0, iconH]]; ImagerBackdoor.DrawBits[context: context, base: LOOPHOLE[thymeIconBitmap], wordsPerLine: iconW/16, sMin: 0, fMin: 0, sSize: iconH, fSize: iconW, tx: 0, ty: iconH]; }; drawStatus: PROC = { ImagerBackdoor.DrawBits[context: context, base: LOOPHOLE[bitmap], wordsPerLine: 1, sMin: 0, fMin: 0, sSize: 15, fSize: 15, tx: 25, ty: 39]; }; invertProc: PROC = { context.SetColor[ImagerBackdoor.invert]; context.MaskBox[[0, 0, iconW, iconH]]; }; handle _ NARROW[ViewerOps.FetchProp[self, $ThymeHandle]]; bitmap _ NARROW[handle.progress.data]; IF whatChanged # $ThymeStatus THEN context.DoSave[drawFace]; context.DoSave[drawStatus]; IF ViewerPrivate.selectedIcon = self THEN context.DoSave[invertProc]; }; -- ThymeIconPaint MakeBitmaps: PROC[file: Rope.ROPE _ "Thyme.icons"]= TRUSTED { iconRaster: INTEGER = 4; fh: FS.OpenFile _ FS.Open[file]; pages: INT _ FS.GetInfo[fh].pages; space: VM.Interval _ VM.Allocate[count: pages]; iconBase: LONG POINTER TO Icons.IconFileFormat _ VM.AddressForPageNumber[space.page]; cursorsBase: LONG POINTER TO Icons.IconFileFormat _ iconBase + SIZE[Icons.IconFileFormat]; MakeCursorBitmap: PROC[offset: INTEGER] RETURNS [bitmap: StatusBitmap] = TRUSTED{ bitmap _ NEW[StatusPattern]; FOR i: INTEGER IN [0..16) DO bitmap[i] _ cursorsBase.bits[offset + i * iconRaster]; ENDLOOP; }; -- MakeBitmap FS.Read[file: fh, from: 0, nPages: pages, to: iconBase]; thymeIconBitmap _ NEW[IconPattern _ iconBase.bits]; idleBitmap _ MakeCursorBitmap[0]; inputBitmap _ MakeCursorBitmap[1]; bombBitmap _ MakeCursorBitmap[2]; topoBitmap _ MakeCursorBitmap[3]; FOR ir: CARDINAL IN [0..4) DO runBitmap[ir] _ MakeCursorBitmap[16 * iconRaster + ir]; ENDLOOP; VM.Free[space]; FS.Close[fh]; }; -- MakeBitmaps SetCursor: PUBLIC PROC [handle: spGlobals.Handle] = { ENABLE UNWIND => NULL; d: REF ANY; IF handle = NIL THEN RETURN; IF handle.progress = NIL THEN RETURN; SELECT handle.stage FROM idle => d _ idleBitmap; input => d _ inputBitmap; bomb => d _ bombBitmap; topo => d _ topoBitmap; run => d _ IF handle.vars = NIL THEN runBitmap[0] ELSE runBitmap[handle.vars.runState]; ENDCASE => BlinkMsg["* Weird situation at SetCursor detected. Please inform Thyme implementor."]; handle.progress.data _ d; IF handle.outer.iconic THEN ViewerOps.PaintViewer[handle.outer, client, FALSE, $ThymeStatus] ELSE ViewerOps.PaintViewer[handle.progress, client, FALSE, $ThymeStatus]; }; -- SetCursor SetWorkingDirectory: PUBLIC PROC [wDir: Rope.ROPE, handle: spGlobals.Handle] = { ViewerOps.SetViewer[handle.wDir, wDir]; }; ThymeCursorPaint: ViewerClasses.PaintProc = { ctx: Imager.Context _ context; bitmap: StatusBitmap _ NARROW[self.data]; proc: PROC = { ctx.SetXY[[0, 16]]; ImagerBackdoor.DrawBits[context: ctx, base: LOOPHOLE[bitmap], wordsPerLine: 1, sMin: 0, fMin: 0, sSize: 15, fSize: 15, tx: 0, ty: 16]; }; ctx.DoSave[proc]; }; -- ThymeCursorPaint thymeCursorClass: ViewerClasses.ViewerClass _ NEW[ViewerClasses.ViewerClassRec _ [ paint: ThymeCursorPaint, tipTable: NIL] ]; RopeList: TYPE = LIST OF Rope.ROPE; MakeThyme: Commander.CommandProc = { argList: RopeList; length: NAT; msg _ NIL; [argList, length] _ CommandTool.ParseToList[cmd]; IF length <= 0 THEN [] _ MakeThymeViewers[] ELSE { wDir: Rope.ROPE _ FileNames.CurrentWorkingDirectory[]; nCircuits: NAT _ 0; maxCircuits: NAT _ 12; allVersions: BOOL _ FALSE; FOR arg: RopeList _ argList, arg.rest UNTIL arg = NIL OR msg # NIL DO IF arg.first.Fetch[0] = '- THEN { IF arg.first.Length[] >= 2 THEN SELECT arg.first.Fetch[1] FROM 'A, 'a => allVersions _ TRUE; 'H, 'h => allVersions _ FALSE; IN ['0..'9] => { max: NAT _ Convert.CardFromRope[arg.first.Substr[1] ! Convert.Error => max _ maxCircuits]; -- don't change it maxCircuits _ max; }; ENDCASE; -- simply ignors illegal switches } ELSE { fileList: RopeList _ FileListFromPattern[ spGlobals.EnsureExtension[arg.first, "thy"], wDir, allVersions]; IF fileList = NIL THEN msg _ "No such file." ELSE FOR file: RopeList _ fileList, file.rest UNTIL file = NIL OR msg # NIL DO IF nCircuits >= maxCircuits THEN msg _ IO.PutFR[ "Note: max. %g circuits for each command. You may change it by a switch.", IO.int[maxCircuits]] ELSE { handle: spGlobals.Handle; create: BOOL _ TRUE; EnumThymeViewers: ViewerOps.EnumProc = { handle _ NARROW[ViewerOps.FetchProp[v, $ThymeHandle]]; IF handle = NIL THEN RETURN; IF NOT handle.outer.inhibitDestroy THEN { cmd.out.PutF[" Forking simulation of %g ....\n", IO.rope[file.first]]; create _ FALSE; spGlobals.BatchRun[handle, wDir, file.first]; RETURN[FALSE]; }; }; -- EnumThymeViewers ViewerOps.EnumerateViewers[EnumThymeViewers]; IF create THEN { handle _ MakeThymeViewers[wDir]; spGlobals.BatchRun[handle, wDir, file.first]; cmd.out.PutF[" Forking simulation of %g ....\n", IO.rope[file.first]]; }; }; nCircuits _ nCircuits + 1; ENDLOOP; }; ENDLOOP; }; }; -- GraphFiles FileListFromPattern: PROC [pattern, wDir: Rope.ROPE _ NIL, allVersions: BOOL _ FALSE] RETURNS [fileList: RopeList _ NIL] = { root, lastRoot: Rope.ROPE _ NIL; LinkIt: FS.NameProc -- PROC [fullFName] RETURNS [continue: BOOL] -- = { excl: INT _ fullFName.Find["!"]; continue _ TRUE; IF ~allVersions THEN { root _ fullFName.Substr[0, excl]; IF root.Equal[lastRoot, FALSE] THEN { fileList.first _ fullFName; RETURN; }; lastRoot _ root; }; fileList _ CONS[fullFName, fileList]; }; -- LinkIt FS.EnumerateForNames[pattern, LinkIt, wDir]; TRUSTED {fileList _ LOOPHOLE[List.DReverse[LOOPHOLE[fileList]]]}; }; -- FileListFrom MakeBitmaps[]; ViewerOps.RegisterViewerClass[$ThymeCursor, thymeCursorClass]; Commander.Register[ key: "Thyme", proc: MakeThyme, doc: "Syntax: Thyme [switch(es)] Start instance(s) of the circuit simulator Thyme. switches: -a all versions, -h highest version only, -# start at most # instances." ]; [] _ ViewerEvents.RegisterEventProc[proc: ThymeDestroy, event: destroy, before: TRUE]; START spGlobals.spModels; START spGlobals.Level2Model; START spGlobals.spFunctions; }. ŒThymeViewers.mesa Copyright (C) 1985 by Xerox Corporation. All rights reserved. Last Edited by: Last Edited by: Jacobi June 10, 1986 6:55:47 pm PDT Last Edited by: Neil Gunther June 24, 1986 6:57:58 pm PDT Pradeep Sindhu April 29, 1986 0:45:42 am PDT Sweetsun Chen, April 26, 1986 7:30:58 pm PST Christian Jacobi, June 10, 1986 6:54:59 pm PDT GetLine, SetLine, MenuEntry public global variables local constants menus typescript menus Menus.SetLine[menu, 1, tsMenuEntry]; openInput: Buttons.Button; working directory scrollable: FALSE, input file scrollable: FALSE, output file progress cursor echo input switch saveAll switch force the selection into the user input field echo input when parsing echo input when parsing message viewer divider the typescript IF ViewerOps.FetchProp[handle.message, $ThymeHandle] = NIL THEN ViewerOps.AddProp[handle.message, $ThymeHandle, handle]; destroy proc progress _ NIL; -- NOT nil'd for fear that ThymeIconPaint may be called after this. checkProcess, simulation and vars should have been nil'd. painting context.SetXY[[25, 39]]; build the library functions and models CHANGE LOG Chen, June 12, 1984 11:21:28 am PDT, created. Chen, May 14, 1985 8:05:48 pm PDT, implemented custom icon that shows status. Chen, July 19, 1985 2:59:06 pm PDT, => Cedar6.0. (Cedar Graphics -> Imager, etc.) Christian Jacobi, June 10, 1986 6:55:20 pm PDT, Messages blink only afterwards Κλ˜Jšœ™Jšœ>™>™Icode™3K™9K™,K™,K™.—J™šΟk ˜ Jšœœ/˜Jšœ œœ˜-Jšœœœ˜/J˜J™J˜Jšœ œ˜J™š Οnœœœ œœ˜4Jšœœ˜,Jšœ˜J˜Jšœ œ˜*Jšœ$˜$J˜šœ˜šœ!˜!šœ˜Jšœ˜Jšœœ˜ Jšœ˜Jšœ˜Jšœ ˜ Jšœ œ˜—Jšœœ˜—J˜—J˜šœ3˜8Jšœ7˜;—Jšœœœ-˜KJšœ,˜,J˜Jšœ)˜)šœ˜Jšœ˜Jš œ œœœ%œ˜N—Jšœ˜J˜JšœB˜BJšœ)˜)Jšœž˜—J˜J™J˜šŸœœœ˜LJšœœ-˜IJšœ˜J˜šœ˜Jšœ ˜ šœ˜Jšœ ˜ Jšœ ˜ Jšœ˜Jšœ œ˜Jšœ!˜!—Jšœ˜—emphasisšœ˜Jšœ ˜ šœ˜Jšœ ˜ Jšœ ˜ Jšœ˜Jšœ œ˜Jšœ!˜!—Jšœ˜—šœ˜Jšœ ˜ JšœD˜DJšœ˜—šœ˜Jšœ ˜ JšœD˜DJšœ˜—šœ˜Jšœ ˜ šœH˜HJšœ˜—Jšœ˜—J˜Jšœ™šœ˜Jšœ ˜ šœ˜Jšœ ˜ Jšœ ˜ Jšœ˜Jšœ œ˜Jšœ"˜"—J˜Jšœ˜—šœ˜Jšœ ˜ šœ˜Jšœ˜Jšœ ˜ Jšœ˜Jšœ œ˜Jšœ"˜"—J˜Jšœ˜—šœ˜Jšœ ˜ JšœG˜GJ˜Jšœ˜—šœ˜Jšœ ˜ JšœG˜GJ˜Jšœ˜—šœ˜Jšœ ˜ JšœE˜EJ˜Jšœ˜—šœ˜Jšœ ˜ JšœQ˜QJ˜Jšœ˜—Jšœž˜—J˜šœœ˜Jšœœœ˜Jšœœ ˜.Jšœ˜Jšœž˜ —J˜šœœ˜Jšœœœ˜Jšœœ ˜.Jšœ˜Jšœž˜ —J˜šœœ˜Jšœœœ˜Jšœœ ˜.Jšœ˜Jšœž˜ —J˜šœ˜Jšœœ ˜.Jšœ;˜;Jšœ˜—J™šœœ˜)Jšœœœ˜Jšœœ ˜.Jšœ˜Jšœ8˜8šœ ˜šœ˜Jšœ$™$Jšœ˜J˜—Jšœ˜Jšœœ˜—Jšœ0˜0Jšœž˜—J˜šœœ˜Jšœœœ˜Jšœœ ˜.šœ œœ˜JšœœœYœ˜}šœœœœ˜%Jšœ'œ ˜2Jšœ˜Jšœ%˜%J˜—J˜—Jšœž˜ —J˜šœœ˜Jšœœœ˜Jšœœ ˜.šœ œœ˜JšœœœYœ˜}šœœœœ˜%Jšœ(˜(Jšœ8œ ˜CJ˜—J˜—Jšœž˜ J˜—šœœ˜Jšœœœ˜Jšœœ ˜.šœ œœ˜š œœœœœ˜9šœœ ˜1Jšœ%œ˜:—Jšœœœ˜šœœ˜ Jšœ˜Jšœœž3˜>Jšœ˜Jšœ˜Jšœ ˜ —Jšœœœ˜.J˜—J˜—Jšœž˜ —J˜šœœ˜Jšœœœ˜Jšœœ ˜.šœ œœ˜š œœœœœ˜9šœœ ˜1Jšœ%œ˜:—Jšœœœ˜šœœ˜ Jšœ˜Jšœœž3˜>Jšœ˜Jšœ˜Jšœ ˜ —Jšœœœ˜.J˜—J˜—Jšœž˜ J˜—šœœ˜Jšœœœ˜Jšœœ ˜.šœ œœ˜š œœœœœ˜9šœœ ˜1Jšœ%œ˜:—Jšœœœ˜šœœ˜Jšœ˜Jšœœž3˜>Jšœ˜Jšœ˜Jšœ ˜ —Jšœœœ˜.J˜—J˜—Jšœž˜ —J˜šœ œ˜#Jšœœœ˜Jšœœ ˜.šœ œœ˜š œœœœœ˜9šœœ ˜1Jšœ%œ˜:—Jšœœœ˜šœœ˜ Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ ˜ —Jšœœœ˜.J˜—J˜—Jšœž ˜—J˜šŸœœ œ˜"Jšœœ˜ J˜Jšœž ˜—J˜šŸœœ-œœ˜PJšœ œ˜Jšœ œ˜Jšœ œ˜Jšœœ6˜RIunit˜˜>Jšœ œœ˜(J˜šœ-˜-Jšœ œ7˜JJšœ:˜>Jšœž˜J˜—Jšœ,œž(˜YJ˜šœ+˜+Jšœ˜Jšœ˜šœ œ˜J˜šœ0œ˜JJšœX˜X—J˜—šœ œ˜Jšœ™šœ0œ ˜AJšœI˜I—J˜—šœ œ˜J˜(Jšœ&˜&J˜J˜—Jšœ œ*˜9Jšœ œ˜&J˜Jšœœ˜Jšœœ˜Jšœœ˜šœ˜šœœ+˜3Jšœ'ž˜9—J˜J˜—Jšœž!˜*—J˜—šœ˜šœ)˜)Jšœ@˜@—Jšœ œœ˜,š œœ&œœœœ˜Nšœœœ˜0JšœJ˜JJšœ˜—šœ˜Jšœ˜Jšœœœ˜šŸœ˜(Jšœ œ'˜6Jšœ œœœ˜šœœœ˜)Jšœ2œ˜GJšœ œ˜Jšœ-˜-Jšœœ˜J˜—Jšœž˜—Jšœ-˜-šœœ˜Jšœ ˜ Jšœ-˜-Jšœ3œ˜HJ˜—J˜—Jšœ˜Jšœ˜—J˜—Jšœ˜—J˜—Jšœž ˜J˜šŸœœœœœœœœ˜|Jšœœœ˜ š œœ žΠckž  ž  žœ˜GJšœœ˜ Jšœ œ˜šœœ˜J˜!šœœœ˜%Jšœ˜Jšœ˜J˜—Jšœ˜J˜—Jšœ œ˜%Jšœžœ˜ —J˜Jšœ*˜,Jšœ œœ˜AJšœž˜——J˜J˜J™Jšœ>˜>J˜šœ˜Jšœ ˜ Jšœ˜JšœΉ˜ΉJ˜—JšœPœ˜VJ˜J™&J˜Jšœ˜Jšœ˜Jšœ˜J˜Jšœ˜J˜J™ ™J™-J™MJ™QJ™N——…—Y {—