ThymeViewers.mesa
Copyright (C) 1985 by Xerox Corporation. All rights reserved.
Last Edited by:
Sweetsun Chen, October 21, 1985 4:10:23 pm PDT
DIRECTORY
Buttons USING [Button, ButtonProc, Create, SetDisplayStyle],
Commander USING [CommandProc, Register],
Containers USING [ChildXBound, ChildYBound, Create],
FileNames USING [CurrentWorkingDirectory],
FS USING [Close, GetInfo, Open, OpenFile, Read],
Icons USING [IconFlavor, IconFileFormat],
Imager USING [Context, DoSave, MaskBox, SetColor, SetXY],
ImagerBackdoor USING [DrawBits, invert],
IO USING [Close, Flush, PutF, time],
Labels USING [Create, Label],
Menus
USING [AppendMenuEntry, ChangeNumberOfLines, CreateMenu, CreateEntry,
GetLine, SetLine, MenuEntry
GetNumberOfLines, Menu, MenuLine, MenuProc],
MessageWindow USING [Append, Blink],
Rope USING [ROPE],
Rules USING [Create, Rule],
spGlobals USING[ConRec, DumpIt, EchoInput, FuncTable, Handle, Level2Model, ModelTable, NodeRec, NormalRun, RefConRec, RefNodeRec, RefR, RefUnReal, ResistorBody, ShowDetails, spFunctions, spModels, Stages, StopIt, ThymeToolRec, ToggleEchoInput, 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, FetchProp, PaintViewer, RegisterViewerClass, RestoreViewer, SaveViewer, --SetMenu, --SetOpenHeight],
ViewerPrivate USING [selectedIcon],
ViewerTools USING [GetContents, MakeNewTextViewer, SetContents, SetSelection],
VM USING [AddressForPageNumber, Allocate, Free, Interval];
ThymeViewers:
CEDAR
MONITOR
IMPORTS Buttons, Commander, Containers, FileNames, FS, Imager, ImagerBackdoor, IO, Labels, Menus, MessageWindow, 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;
local constants
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
menus
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]
];
typescript menus
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 => {
Menus.SetLine[menu, 1, tsMenuEntry];
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.Blink[];
MessageWindow.Append[msg, TRUE];
}; -- BlinkMsg
MakeMainViewer:
PROC [handle: spGlobals.Handle, workingDir: Rope.
ROPE ←
NIL] = {
entryHeight: CARDINAL = 12;
entryVSpace: CARDINAL = 6;
entryHSpace: CARDINAL = 10;
initialOutputName: Rope.ROPE = "<Output file name(s) will be set automatically.>";
outLabel, progressLabel, timeLabel, stepLabel: Labels.Label;
wDirButton, inputButton: Buttons.Button;
openInput: Buttons.Button;
initialInputName: Rope.ROPE = "<Specify input file name here.>";
handle.height ← handle.height + entryVSpace;
working directory
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,
scrollable: FALSE,
border: FALSE],
paint: FALSE];
handle.height ← handle.height + entryHeight + entryVSpace;
input file
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,
scrollable: FALSE,
border: FALSE],
paint: FALSE];
handle.height ← handle.height + entryHeight + entryVSpace;
output file
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;
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,
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];
echo input switch
handle.echoInputButton ← Buttons.Create[
info: [
name: "Echo input",
parent: handle.outer,
wx: handle.step.wx + handle.step.ww + entryHSpace + 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.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 = {
force the selection into the user input field
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 = {
echo input when parsing
handle: spGlobals.Handle ← NARROW[clientData];
IF handle #
NIL
THEN {
spGlobals.ToggleEchoInput[handle];
Buttons.SetDisplayStyle[handle.echoInputButton,
IF spGlobals.EchoInput[handle] THEN $WhiteOnBlack ELSE $BlackOnWhite];
};
}; -- InputPrompt
MakeMsgViewer:
PROC [handle: spGlobals.Handle] = {
divider
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;
the typescript
handle.message← TypeScript.Create[
info: [
parent: handle.outer,
wy: handle.height,
ww: handle.outer.cw,
wh: 800,
border: FALSE,
file: "Thyme.log"],
paint: FALSE
];
IF ViewerOps.FetchProp[handle.message, $ThymeHandle] =
NIL
THEN ViewerOps.AddProp[handle.message, $ThymeHandle, handle];
[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
destroy proc
MyDestroy: ViewerEvents.EventProc = {
h: spGlobals.Handle ← NARROW[ViewerOps.FetchProp[viewer, $ThymeToolData]];
IF h=NIL THEN RETURN;
IF event=destroy
AND before
THEN {
h.msgStream.Close[];
};
}; -- MyDestroy
painting
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 = {
context.SetXY[[25, 39]];
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
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]
];
MakeThyme: Commander.CommandProc = {[] ← MakeThymeViewers[];};
MakeBitmaps[];
ViewerOps.RegisterViewerClass[$ThymeCursor, thymeCursorClass];
Commander.Register[
key: "Thyme",
proc: MakeThyme,
doc: "Start an instance of the circuit simulator Thyme." ];
[] ← ViewerEvents.RegisterEventProc[proc: MyDestroy, event: destroy];
build the library functions and models
START spGlobals.spModels;
START spGlobals.Level2Model;
START spGlobals.spFunctions;
}.
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.)