<> <> <> <> <> <> <> <<>> 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.0 - Oct 1985"; 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; }. <> <<>> <> <> < Cedar6.0. (Cedar Graphics -> Imager, etc.)>> <>