DIRECTORY Buttons USING [Button, ButtonProc, Create, SetDisplayStyle], Commander USING [CommandProc, Register], CommandTool USING [ParseToList], Containers USING [Create], Convert USING [CardFromRope, Error], FileNames USING [CurrentWorkingDirectory], FS USING [EnumerateForNames, NameProc], Icons USING [IconFlavor, NewIconFromFile], IO USING [Close, Flush, int, PutF, PutFR, rope], Labels USING [Create, Label], List USING [DReverse], Menus USING [AppendMenuEntry, ChangeNumberOfLines, CreateMenu, CreateEntry, Menu, MenuProc], Rope USING [Equal, Fetch, Find, Length, ROPE, Substr], ThymeGlobals USING[BatchRun, ConRec, DumpIt, EchoInput, EnsureExtension, FuncTable, Handle, ModelTable, NodeRec, NormalRun, RefConRec, RefNodeRec, RefR, RefUnReal, ResistorBody, ShowDetails, SaveAll, Stages, StopIt, ThymeToolRec, ToggleEchoInput, ToggleSaveAll, ToggleShowDetails, UnReal], TerminalIO USING [TOS], VFonts USING[CharWidth, StringWidth], ViewerClasses USING [Viewer, ViewerClass, ViewerClassRec], ViewerEvents USING [EventProc, RegisterEventProc], ViewerOps USING [AddProp, EnumerateViewers, EnumProc, FetchProp, PaintViewer, SetViewer, SetOpenHeight], ViewerTools USING [GetContents, MakeNewTextViewer, SetContents, SetSelection]; ThymeViewers: CEDAR MONITOR IMPORTS Buttons, Commander, CommandTool, Containers, Convert, FileNames, FS, Icons, IO, Labels, List, Menus, Rope, TerminalIO, ThymeGlobals, ViewerEvents, ViewerOps, VFonts, ViewerTools EXPORTS ThymeGlobals = { version: PUBLIC Rope.ROPE_ "NewThyme - Cedar6.1 - January 1987"; refNodeRec: PUBLIC ThymeGlobals.RefNodeRec= NEW[ThymeGlobals.NodeRec]; refConRec: PUBLIC ThymeGlobals.RefConRec= NEW[ThymeGlobals.ConRec]; refR: PUBLIC ThymeGlobals.RefR= NEW[ThymeGlobals.ResistorBody]; refUnReal: PUBLIC ThymeGlobals.RefUnReal= NEW[ThymeGlobals.UnReal]; modelTable: PUBLIC ThymeGlobals.ModelTable_ NIL; functionTable: PUBLIC ThymeGlobals.FuncTable_ NIL; MakeThymeViewers: PUBLIC PROC[wDir: Rope.ROPE _ NIL] RETURNS [handle: ThymeGlobals.Handle _ NIL] = { thymeMenus: Menus.Menu; handle _ NEW[ThymeGlobals.ThymeToolRec _ []]; thymeMenus _ MakeThymeMenus[handle]; handle.outer _ Containers.Create[ info: [ name: version, iconic: TRUE, icon: Icons.NewIconFromFile["Thyme.icons", 0], menu: thymeMenus, column: left, scrollable: FALSE], paint: FALSE]; IF ViewerOps.FetchProp[handle.outer, $ThymeHandle] = NIL THEN ViewerOps.AddProp[handle.outer, $ThymeHandle, handle]; Menus.ChangeNumberOfLines[thymeMenus, 1]; MakeMainViewer[ handle: handle, workingDir: IF wDir = NIL THEN FileNames.CurrentWorkingDirectory[] ELSE wDir]; handle.msgStream _ TerminalIO.TOS[]; ViewerOps.SetOpenHeight[handle.outer, handle.height]; ViewerOps.PaintViewer[handle.outer, all]; }; -- MakeThymeViewers MakeThymeMenus: PROC[handle: ThymeGlobals.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] ]; }; -- MakeThymeMenus Stop: ENTRY Menus.MenuProc = { ENABLE UNWIND => NULL; handle: ThymeGlobals.Handle _ NARROW[clientData]; ThymeGlobals.StopIt[handle]; }; -- Stop Run: ENTRY Menus.MenuProc = { ENABLE UNWIND => NULL; handle: ThymeGlobals.Handle _ NARROW[clientData]; ThymeGlobals.NormalRun[handle]; }; -- Run Dump: ENTRY Menus.MenuProc = { ENABLE UNWIND => NULL; handle: ThymeGlobals.Handle _ NARROW[clientData]; ThymeGlobals.DumpIt[handle]; }; -- Dump New: Menus.MenuProc = { handle: ThymeGlobals.Handle _ NARROW[clientData]; [] _ MakeThymeViewers[ViewerTools.GetContents[handle.wDir]]; }; MakeMainViewer: PROC [handle: ThymeGlobals.Handle, workingDir: Rope.ROPE _ NIL] = { entryHeight: CARDINAL = 12; entryVSpace: CARDINAL = 6; entryHSpace: CARDINAL = 10; initialOutputName: Rope.ROPE = ""; outLabel, 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; handle.showDetailsButton _ Buttons.Create[ info: [ name: "details:", parent: handle.outer, wx: entryHSpace + entryHSpace, wy: handle.height, wh: entryHeight + 3, border: TRUE ], clientData: handle, proc: ShowDetailsProc, paint: FALSE]; Buttons.SetDisplayStyle[handle.showDetailsButton, IF ThymeGlobals.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 ThymeGlobals.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 ThymeGlobals.SaveAll[handle] THEN $WhiteOnBlack ELSE $BlackOnWhite]; handle.height _ handle.height + entryHeight + entryVSpace; }; -- MakeMainViewer DirPrompt: Buttons.ButtonProc = { handle: ThymeGlobals.Handle _ NARROW[clientData]; IF handle # NIL THEN ViewerTools.SetSelection[handle.wDir]; }; -- InputPrompt InputPrompt: Buttons.ButtonProc = { handle: ThymeGlobals.Handle _ NARROW[clientData]; IF handle # NIL THEN ViewerTools.SetSelection[handle.input]; }; -- InputPrompt ShowDetailsProc: Buttons.ButtonProc = { handle: ThymeGlobals.Handle _ NARROW[clientData]; IF handle # NIL THEN { ThymeGlobals.ToggleShowDetails[handle]; Buttons.SetDisplayStyle[handle.showDetailsButton, IF ThymeGlobals.ShowDetails[handle] THEN $WhiteOnBlack ELSE $BlackOnWhite]; IF NOT ThymeGlobals.ShowDetails[handle] THEN { ViewerTools.SetContents[handle.time, NIL]; ViewerTools.SetContents[handle.step, NIL]; }; }; }; -- InputPrompt EchoInputProc: Buttons.ButtonProc = { handle: ThymeGlobals.Handle _ NARROW[clientData]; IF handle # NIL THEN { ThymeGlobals.ToggleEchoInput[handle]; Buttons.SetDisplayStyle[handle.echoInputButton, IF ThymeGlobals.EchoInput[handle] THEN $WhiteOnBlack ELSE $BlackOnWhite]; }; }; -- EchoInputProc SaveAllProc: Buttons.ButtonProc = { handle: ThymeGlobals.Handle _ NARROW[clientData]; IF handle # NIL THEN { ThymeGlobals.ToggleSaveAll[handle]; Buttons.SetDisplayStyle[handle.saveAllButton, IF ThymeGlobals.SaveAll[handle] THEN $WhiteOnBlack ELSE $BlackOnWhite]; }; }; -- SaveAllProc ThymeDestroy: ViewerEvents.EventProc = { IF (event = destroy) AND before THEN { h: ThymeGlobals.Handle _ NARROW[ViewerOps.FetchProp[viewer, $ThymeHandle]]; IF h # NIL THEN {OPEN h; outer _ NIL; wDir _ input _ NIL; output _ time _ step _ NIL; IF msgStream#NIL THEN { msgStream.Flush[]; msgStream.Close[]; msgStream _ NIL; }; showDetailsButton _ echoInputButton _ saveAllButton _ NIL; }; }; }; -- ThymeDestroy SetWorkingDirectory: PUBLIC PROC [wDir: Rope.ROPE, handle: ThymeGlobals.Handle] = { ViewerOps.SetViewer[handle.wDir, wDir]; }; 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[ ThymeGlobals.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: ThymeGlobals.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; ThymeGlobals.BatchRun[handle, wDir, file.first]; RETURN[FALSE]; }; }; -- EnumThymeViewers ViewerOps.EnumerateViewers[EnumThymeViewers]; IF create THEN { handle _ MakeThymeViewers[wDir]; ThymeGlobals.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 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]; }. 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 Barth, July 8, 1988 10:48:53 am PDT Christian Le Cocq April 29, 1987 10:26:50 am 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 public global variables IF ThymeNormalPaint = NIL THEN ThymeNormalPaint _ handle.outer.class.paint; handle.outer.class.paint _ ThymeViewerPaint; menus working directory input file scrollable: FALSE, output file progress cursor 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, data: NIL, border: FALSE], paint: FALSE]; wx: handle.progress.wx + handle.progress.ww + entryHSpace + entryHSpace, echo input switch saveAll switch force the selection into the user input field echo input when parsing echo input when parsing message viewer destroy proc painting ThymeViewerPaint: ViewerClasses.PaintProc = { IF ~self.iconic THEN [] _ ThymeNormalPaint[self, context, whatChanged, clear]; }; -- ThymeViewerPaint ThymeNormalPaint: ViewerClasses.PaintProc _ NIL; -- will be assigned Containers PaintProc 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 Κ˜Icodešœ™Kšœ>™>™Kšœ0Οk™3Kšœ6™9K™#K™0Kšœ)™,Kšœ)™,Kšœ+™.—K™š ˜ Kšœœ/˜Kšœœ˜Kšœœ˜šœ˜šœœ+˜3Kšœ'Ÿ˜9—K˜K˜—KšœŸ!˜*—K˜—šœ˜šœ)˜)KšœC˜C—Kšœ œœ˜,š œœ&œœœœ˜Nšœœœ˜0KšœJ˜JKšœ˜—šœ˜Kšœ˜Kšœœœ˜šžœ˜(Kšœ œ'˜6Kšœ œœœ˜šœœœ˜)Kšœ2œ˜GKšœ œ˜Kšœ0˜0Kšœœ˜K˜—KšœŸ˜—Kšœ-˜-šœœ˜Kšœ ˜ Kšœ0˜0Kšœ3œ˜HK˜—K˜—Kšœ˜Kšœ˜—K˜—Kšœ˜—K˜—KšœŸ ˜K˜šžœœœœœœœœ˜|Kšœœœ˜ šžœœ Ÿ/œ˜GKšœœ˜ Kšœ œ˜šœœ˜K˜!šœœœ˜%Kšœ˜Kšœ˜K˜—Kšœ˜K˜—Kšœ œ˜%KšœŸ ˜ —K˜Kšœ*˜,Kšœ œœ˜AKšœŸ˜——K˜šœ˜Kšœ ˜ Kšœ˜KšœΉ˜ΉK˜—KšœPœ˜VK˜Kšœ˜K˜Kšœ™ ™Kšœ œ ™-Kšœœ,™MKšœœ/™QK™N——…—1šIΓ