ScreenImpl.mesa
Copyright (C) 1983, 1984 Xerox Corporation. All rights reserved.
Author: John Maxwell
Last Edited by: Maxwell, November 22, 1983 10:52 am
Edited by Doug Wyatt, June 15, 1984 11:26:20 am PDT
DIRECTORY
CursorDefs,
Directory USING [Error],
DisplayDefs USING [DisplayOff],
Graphics USING [
Box, CopyContext, DrawChar,
Context, DrawRope, DrawBox, FontRef, GetBounds,
MakeFont, Map, NewContext, PaintMode, RopeBox, RopeWidth,
ClipBox, SetCP, SetDefaultFont, SetFat, SetPaintMode, SetStipple,
Translate, WorldToUser],
Heap USING [MakeMDSString, FreeMDSString],
MusicDefs USING [AnyBug, black, BlueBug, Control, grey, RedBug, Shift, ScorePTR,
white, YellowBug],
MusicProcess,
Piece USING [Free, Overflow],
Real USING [FixI],
Score USING [InitializeSynthesizer, StopListening, StopPlaying, Test],
Screen USING [commands, CommandProcs],
String USING [AppendChar, AppendString, InvalidNumber],
TerminalMultiplex USING [RegisterNotifier, TerminalSwapNotifier],
TTY USING [CharsAvailable, Create, GetChar, Handle, Rubout, SetEcho],
UserTerminal USING [mouse, GetCursorPattern, SetCursorPattern, WaitForScanLine];
ScreenImpl: CEDAR MONITOR
IMPORTS
Directory, Graphics, Heap, MusicDefs, -- Music: MusicProcess, --
Piece, Real, Screen, String, TerminalMultiplex, TTY, UserTerminal
EXPORTS Screen =
BEGIN
OPEN Graphics, CursorDefs, MusicDefs, Screen, UserTerminal;
keyboard: TTY.Handle;
font: Graphics.FontRef;
******************************************************************
Multiplexing code
******************************************************************
running: BOOLTRUE;
WaitRunning: ENTRY PROC = INLINE
{WHILE ~running DO UserTerminal.WaitForScanLine[0]; ENDLOOP};
Notifier: TerminalMultiplex.TerminalSwapNotifier = {
SELECT action FROM
coming => running ← TRUE;
going => running ← FALSE;
ENDCASE;
};
******************************************************************
User Commands
******************************************************************
main: PROCESSNIL;
Initialize: PROC = {
TerminalMultiplex.RegisterNotifier[Notifier];
DisplayDefs.DisplayOff[white];
DisplayDefs.SetSystemDisplaySize[0, 0];
[] ← TTY.SetEcho[keyboard, FALSE];
keyboard ← TTY.Create[NIL];
screen ← NewContext[NIL];
[] ← SetFat[screen, TRUE];
windows[0] ← [screen, , , command, @commandProcs, 800, 740];
DefaultWindow[1, 740, 0];
font ← MakeFont["TimesRoman12"];
SetDefaultFont[screen, font];
commandProcs.display ← DisplayCommandWindow;
FrameDefs.MakeCodeResident[FrameDefs.GlobalFrame[Music]];
Score.InitializeSynthesizer[];
DrawScreen[];
ReadCommandLine[];
SetCursorPattern[textCursor];
main ← FORK Main[];
};
ForkMain: PROC = {main ← FORK Main[]};
Main: PROC = {
ENABLE {
Piece.Overflow => {DisplayMessage["Piece.Overflow"]; RESUME};
ANY => DisplayMessage["UNCAUGHT SIGNAL"]};
DisplayMessage["Mockingbird of November 22, 1983"];
DO IF badCommand THEN {
WHILE TTY.GetChar[keyboard] # 177C DO NULL; ENDLOOP;
EraseMessage[]; badCommand ← FALSE; };
badCommand ← FALSE;
WaitRunning[];
SELECT TRUE FROM
RedBug[] => HandleRed[];
BlueBug[] => HandleBlue[FindWindow[ScreenPY]];
YellowBug[] => HandleYellow[];
TTY.CharsAvailable[keyboard] # 0 => ReadKeyboard[];
ENDCASE => ChangeCursor[];
FOR w: CARDINAL IN [1..noWindows) DO
IF windows[w].command.count > 50 THEN BackUp[w];
ENDLOOP;
ENDLOOP;
};
badCommand: BOOLFALSE;
Command: PROC RETURNS[BOOL] = {
image: Image;
EraseMessage[];
MousePoint[];
[ScreenPX, ScreenPY] ← WorldToUser[screen, MousePX, 808 - MousePY];
image ← FindCommand[ScreenPX, ScreenPY];
IF image.command # NullProc THEN {
image.command[image.rect];
WHILE AnyBug[] DO NULL; ENDLOOP;
RETURN[TRUE]};
RETURN[FALSE];
};
HandleRed: PROC = {
w: CARDINAL;
top: REAL;
IF Command[] THEN RETURN;
w ← FindWindow[ScreenPY];
IF w = 0 THEN RETURN;
Select[w];
top ← windows[w].top-header-40;
IF ScreenPX > 606 THEN RETURN;
SELECT TRUE FROM
Control[] => windows[w].command.redbug[windows[w].score];
Shift[] => windows[w].command.redbug[windows[w].score];
ScreenPX < leftMargin => Scroll[w, Real.FixI[top-ScreenPY]];
ScreenPX > rightMargin => NULL; -- MoveWindow[ScreenPY];
ENDCASE => windows[w].command.redbug[windows[w].score];
};
HandleBlue: PROC[w: CARDINAL] = {
ENABLE Piece.Overflow => IF windows[w].score = old THEN windows[w].score ← new;
top: REAL;
IF Command[] THEN RETURN;
IF w = 0 THEN RETURN;
Select[w];
IF ScreenPX > 606 THEN RETURN;
top ← windows[w].top-header-40;
SELECT TRUE FROM
Control[] => windows[w].command.bluebug[windows[w].score];
Shift[] => windows[w].command.bluebug[windows[w].score];
ScreenPX < leftMargin => Scroll[w, Real.FixI[ScreenPY-top]];
ScreenPX > rightMargin => NULL; -- NewWindow[w, ScreenPY];
ENDCASE => windows[w].command.bluebug[windows[w].score];
};
HandleYellow: PROC = {
w: CARDINAL;
IF Command[] THEN RETURN;
w ← FindWindow[ScreenPY];
IF w = 0 THEN RETURN;
Select[w];
IF ScreenPX > 606 THEN RETURN;
SELECT TRUE FROM
Control[] => windows[w].command.yellowbug[windows[w].score];
Shift[] => windows[w].command.yellowbug[windows[w].score];
ScreenPX < leftMargin => windows[w].command.thumb[windows[w].score];
ScreenPX > rightMargin => NULL; -- SubWindow[w, ScreenPY];
ENDCASE => windows[w].command.yellowbug[windows[w].score];
};
ReadKeyboard: PROC = {
ENABLE {
String.InvalidNumber => {
DisplayMessage["illegal number- type DEL to continue"];
badCommand ← TRUE;
CONTINUE; };
TTY.Rubout => {
DisplayMessage["command terminated"];
CONTINUE; };
Piece.Overflow => IF windows[selectedWindow].score = old
THEN windows[selectedWindow].score ← new;
};
EraseMessage[];
windows[selectedWindow].command.keyboard[windows[selectedWindow].score];
};
ChangeCursor: PROC = {
newState: CursorState;
MousePoint[];
[ScreenPX, ScreenPY] ← WorldToUser[screen, MousePX, 808 - MousePY];
IF ScreenPX > 606 THEN RETURN;
SELECT TRUE FROM
FindCommand[ScreenPX, ScreenPY].command # NullProc => newState ← command;
ScreenPY > windows[0].bottom => newState ← commandwindow;
ScreenPX > rightMargin => newState ← window;
ScreenPX < leftMargin => newState ← scroll;
ENDCASE => newState ← screen;
IF newState = currentState THEN RETURN;
IF currentState = screen THEN oldCursor ← GetCursorPattern[];
SELECT newState FROM
window => SetCursorPattern[windowCursor];
command => SetCursorPattern[bullseyeCursor];
scroll => SetCursorPattern[scrollUpDownCursor];
commandwindow => SetCursorPattern[textCursor];
ENDCASE => SetCursorPattern[oldCursor];
currentState ← newState;
};
oldCursor: Cursor ← textCursor;
CursorState: TYPE = {window, scroll, command, screen, commandwindow};
currentState: CursorState ← screen;
Scroll: PROC[w: CARDINAL, y: INTEGER] = {
IF y > 0 THEN SetCursorPattern[scrollUpCursor];
IF y < 0 THEN SetCursorPattern[scrollDownCursor];
windows[w].command.scroll[windows[w].score, y];
SetCursorPattern[scrollUpDownCursor];
};
MousePoint: PROC = {
x, y: REAL = 1;
MousePX ← x*mouse.x;
MousePY ← y*mouse.y;
};
MousePX, MousePY: REAL;
ScreenPX, ScreenPY: REAL;
******************************************************************
Window & Subwindow procedures
******************************************************************
DrawScreen: PROC = {
i: CARDINAL;
FOR i IN [0..noWindows) DO windows[i].command.display[windows[i].score, TRUE] ENDLOOP;
};
MoveWindow: PROC[y: REAL] = {
i, a, w: CARDINAL ← 0;
dist, last: REAL ← 1000;
SetCursorPattern[moveWindowCursor];
FOR i IN [1..noWindows) DO
IF (windows[i].top-y < dist OR y-windows[i].top < dist)
AND FindWindow[windows[i].top +1] # 0
THEN { dist ← ABS[windows[i].top-y]; w ← i; };
ENDLOOP;
IF w = 0 THEN RETURN;
a ← FindWindow[windows[w].top +1];
DisplayHeader[white, w];
WHILE RedBug[] DO NULL; ENDLOOP;
MousePoint[];
[ScreenPX, ScreenPY] ← WorldToUser[screen, MousePX, 808 - MousePY];
y ← ScreenPY;
last ← windows[w].top;
IF y > windows[a].top - 16 THEN y ← windows[a].top - 16;
IF y < windows[w].bottom + 16 THEN y ← windows[w].bottom + 16;
MoveContext[w, y];
windows[a].bottom ← y;
windows[w].top ← y;
SetClipper[a];
SetClipper[w];
DisplayHeader[black, w];
IF last > windows[w].top THEN windows[a].command.display[windows[a].score, TRUE];
windows[w].command.display[windows[w].score, TRUE];
Select[w];
};
NewWindow: PROC[w: CARDINAL, y: REAL] = {
called by bluebug in the righthand margin
SetCursorPattern[newWindowCursor];
WHILE BlueBug[] AND NOT YellowBug[] DO NULL; ENDLOOP;
IF YellowBug[] THEN { DeleteWindow[w]; RETURN; };
DefaultWindow[noWindows, y, windows[w].bottom];
windows[w].bottom ← y;
Select[noWindows];
DisplayHeader[black, noWindows];
SetClipper[w];
SetClipper[noWindows];
noWindows ← noWindows + 1;
};
SubWindow: PROC[w: CARDINAL, y: REAL] = {
yellowbug in the righthand margin
SetCursorPattern[subWindowCursor];
WHILE NOT BlueBug[] AND YellowBug[] DO NULL; ENDLOOP;
IF BlueBug[] THEN { DeleteWindow[w]; RETURN; };
Flash[NIL];
};
FindWindow: PROC[y: REAL] RETURNS[CARDINAL] = {
i: CARDINAL;
FOR i IN [0..noWindows) DO
IF y < windows[i].top AND y > windows[i].bottom THEN RETURN[i];
ENDLOOP;
RETURN[0];
};
DeleteWindow: PROC[w: CARDINAL] = {
neighbor: CARDINAL;
SetCursorPattern[windowCursor];
Invert[windows[w].context];
WHILE BlueBug[] AND YellowBug[] DO NULL; ENDLOOP;
Wait[1];
Invert[windows[w].context];
IF BlueBug[] OR YellowBug[] THEN RETURN;
neighbor ← FindWindow[windows[w].top + 1];
IF neighbor # 0
THEN {
windows[neighbor].bottom ← windows[w].bottom;
DisplayHeader[white, w];
}
ELSE {
neighbor ← FindWindow[windows[w].bottom - 1];
IF neighbor # 0 THEN {
MoveContext[neighbor, windows[w].top];
DisplayHeader[white, neighbor];
windows[neighbor].top ← windows[w].top;
DisplayHeader[black, neighbor];
};
};
IF neighbor = 0
THEN {
DisplayMessage["cannot delete that window"];
RETURN;
};
noWindows ← noWindows - 1;
Heap.FreeMDSString[, windows[w].file];
windows[w] ← windows[noWindows];
SetClipper[neighbor];
Select[neighbor];
windows[neighbor].command.display[windows[neighbor].score, TRUE];
};
Invert: PROC[dc: Context] = {
SetStipple[dc, black];
[] ← SetPaintMode[dc, invert];
DrawBox[dc, [0, 0, 1024, 808]];
[] ← SetPaintMode[dc, opaque];
};
MoveContext: PROC[w: CARDINAL, y: REAL] = {
siy, soy, tiy, toy: REAL;
siy ← y;
tiy ← windows[w].top;
[, soy] ← Map[screen, windows[w].context, 0, siy];
[, toy] ← Map[screen, windows[w].context, 0, tiy];
Translate[windows[w].context, 0, soy- toy];
};
Select: PROC[w: CARDINAL] = {
SetBrush[black, transparent];
DrawBox[screen, [20, windows[selectedWindow].top- header- 10,
28, windows[selectedWindow].top- header]];
SetBrush[grey, opaque];
DrawBox[screen, [20, windows[w].top- header- 10, 28, windows[w].top- header]];
selectedWindow ← w;
};
selectedWindow: CARDINAL ← 1;
listenWindow: CARDINAL ← 1;
DefaultWindow: PROC[w: CARDINAL, top, bottom: REAL] = {
windows[w] ← [, , , unknown, @unknownProcs, top, bottom];
windows[w].context ← CopyContext[screen];
windows[w].file ← Heap.MakeMDSString[, 40];
Translate[windows[w].context, 30, top - header - 40]; -- 30 regular, 45 for videotaping
SetClipper[w];
SetStipple[windows[w].context, black];
[] ← SetPaintMode[windows[w].context, opaque];
DrawBox[windows[w].context, GetBounds[windows[w].context]];
windows[w].type ← logical;
windows[w].command ← @Screen.commands;
windows[w].score ← windows[w].command.initialize[windows[w].context];
};
******************************************************************
Command Window procedures
******************************************************************
DisplayCommandWindow: PROC[score: ScorePTR, erase: BOOL] = {
i: CARDINAL;
Erase[NIL, TRUE];
SetBrush[black, opaque];
ClearManager[];
DisplayCommand["FileIn", 30, 750, FileIn];
DisplayCommand["PlayBack", 110, 750, Play];
DisplayCommand["Print", 215, 750, Hardcopy];
DisplayCommand["Quit", 300, 750, Quit];
DisplayCommand["Record", 385, 750, Listen];
DisplayCommand["FileOut", 480, 750, FileOut];
FOR i IN [1..noWindows) DO DisplayHeader[black, i] ENDLOOP;
Select[1];
};
DisplayCommand: PROC[s: LONG STRING, x, y: REAL, proc: PROC[r: Box]] = {
box: Box;
SetCP[screen, x, y];
SetBrush[black, invert];
DrawRope[screen, LOOPHOLE[s]];
[box.xmin, box.ymin, box.xmax, box.ymax] ← RopeBox[font, LOOPHOLE[s]];
box.xmin ← box.xmin + x;
box.ymin ← box.ymin + y;
box.xmax ← box.xmax + x;
box.ymax ← box.ymax + y;
IF box.xmax - box.xmin < 30 THEN box.xmax ← box.xmin + 30;
IF box.ymax - box.ymin < 10 THEN box.ymax ← box.ymin + 10;
AddCommand[box, proc];
};
DisplayHeader: PROC[color: CARDINAL, w: CARDINAL] = {
top: REAL ← windows[w].top;
px, py: REAL;
px ← 30;
py ← windows[w].top - 16;
SetBrush[color, opaque];
DrawBox[screen, [0, top-header, 620, top]];
DeleteCommand[px, py];
IF color = grey THEN SetBrush[grey, invert];
IF color = black THEN SetBrush[black, invert];
IF color = white THEN RETURN;
DisplayCommand[windows[w].file, 30, top-12, EditFileName];
};
EraseMessage: PROC = {
SetBrush[white, opaque];
DrawBox[screen, [0, 763, 620, 780]];
SetBrush[black, invert];
};
DisplayMessage: PUBLIC PROC[s: STRING] = {
ls: LONG STRING ← s;
IF s = NIL THEN {EraseMessage[]; RETURN};
SetBrush[black, opaque];
DrawBox[screen, [0, 765, 620, 780]];
SetBrush[black, invert];
SetCP[screen, 300 - RopeWidth[font, LOOPHOLE[ls]].xw/2, 767];
DrawRope[screen, LOOPHOLE[ls]];
};
AddCommand: PROC[r: Box, proc: PROC[r: Box]] = {
FOR i: CARDINAL IN [0..mIndex) DO
IF manager[i].command = proc THEN RETURN;
ENDLOOP;
manager[mIndex] ← [r, proc];
IF proc = Play THEN playIndex ← mIndex;
IF proc = Listen THEN listenIndex ← mIndex;
mIndex ← mIndex + 1;
};
DeleteCommand: PROC[x, y: REAL] = {
i: CARDINAL;
FOR i IN [0..mIndex) DO
IF manager[i].rect.xmin = x THEN
{
mIndex ← mIndex - 1;
manager[i] ← manager[mIndex];
}; ENDLOOP;
};
FindCommand: PROC[x, y: REAL] RETURNS[m: Image] = {
i: CARDINAL;
FOR i IN [0..mIndex) DO
{
m ← manager[i];
IF x > m.rect.xmin AND x < m.rect.xmax AND
y > m.rect.ymin AND y < m.rect.ymax
THEN RETURN[m];
}; ENDLOOP;
m.command ← NullProc;
RETURN[m];
};
Flash: PROC[score: ScorePTR] = {
Invert[windows[selectedWindow].context];
Invert[windows[selectedWindow].context];
};
Erase: PROC[score: ScorePTR, erase: BOOL] = {
SetStipple[screen, white];
[] ← SetPaintMode[screen, opaque];
DrawBox[screen, GetBounds[screen]];
SetStipple[screen, black];
[] ← SetPaintMode[screen, transparent];
};
******************************************************************
Commands
******************************************************************
Confirm: PROC[w: CARDINAL, s: STRING] RETURNS[BOOL] = {
confirm: BOOL;
IF windows[w].command.count = 0 THEN RETURN[TRUE];
DisplayMessage[s];
confirm ← TTY.GetChar[keyboard] = CR;
EraseMessage[];
RETURN[confirm];
};
FileIn: PROC[r: Box] = {
ENABLE Directory.Error => {
DisplayMessage["no such file"];
DrawBox[screen, r];
CONTINUE; };
s: CARDINAL ← selectedWindow;
SetBrush[black, invert];
DrawBox[screen, r];
IF Confirm[s, "the current file has not been filed out-- type CR to confirm"] THEN
{
IF windows[s].score # NIL THEN Piece.Free[windows[s].score];
windows[s].score ← windows[s].command.fileIn[windows[s].file];
EraseMessage[];
windows[s].command.display[windows[s].score, TRUE];
windows[s].command.count ← 0;
};
DrawBox[screen, r];
};
FileOut: PROC[r: Box] = {
ENABLE Directory.Error => {
DisplayMessage["illegal file name"];
DrawBox[screen, r];
CONTINUE; };
s: CARDINAL ← selectedWindow;
SetBrush[black, invert];
DrawBox[screen, r];
windows[s].command.fileOut[windows[s].score, windows[s].file];
windows[s].command.count ← 0;
DrawBox[screen, r];
};
BackUp: PROC[w: CARDINAL] = {
DisplayMessage["Please wait... storing file on backup.music"];
windows[w].command.fileOut[windows[w].score, "backup.music"];
windows[w].command.count ← 1; -- so it will look dirty
EraseMessage[];
};
Play: PROC[r: Box] = {
ENABLE Piece.Overflow => IF windows[selectedWindow].score = old
THEN windows[selectedWindow].score ← new;
windows[selectedWindow].command.play[windows[selectedWindow].score];
};
InvertPlay: PUBLIC PROC = {
r: Box = manager[playIndex].rect;
SetBrush[black, invert];
DrawBox[screen, r];
};
Listen: PROC[r: Box] = {
ENABLE Piece.Overflow => IF windows[listenWindow].score = old
THEN windows[listenWindow].score ← new;
windows[listenWindow].command.listen[windows[listenWindow].score];
listenWindow ← selectedWindow;
};
InvertListen: PUBLIC PROC = {
r: Box = manager[listenIndex].rect;
SetBrush[black, invert];
DrawBox[screen, r];
};
playIndex: CARDINAL ← 0;
listenIndex: CARDINAL ← 0;
Hardcopy: PROC[r: Box] = {
SetBrush[black, invert];
DrawBox[screen, r];
DisplayMessage["Please wait... printing screen on music.press"];
windows[selectedWindow].command.hardcopy[windows[selectedWindow].score, "music.press"];
DrawBox[screen, r];
EraseMessage[];
};
EditFileName: PROC[r: Box] = {
w: CARDINAL ← FindWindow[ScreenPY];
c, last: CHARACTER ← 040C;
CR: CHARACTER ← 015C;
IF w = 0 THEN RETURN;
windows[w].file.length ← 0;
DisplayMessage["Please enter filename."];
DisplayHeader[white, w];
DisplayHeader[black, w];
DO {
c ← TTY.GetChar[keyboard];
IF c = 177C OR c = 010C THEN
{
IF windows[w].file.length = 0 THEN LOOP;
windows[w].file.length ← windows[w].file.length- 1;
DisplayHeader[black, w];
LOOP; };
IF c = ' THEN {
windows[w].file.length ← 0;
DisplayHeader[black, w];
LOOP; };
IF c # CR AND c # '. AND c # 033C THEN {
String.AppendChar[windows[w].file, c];
DrawChar[screen, c]; LOOP;
};
String.AppendString[windows[w].file, ".music"];
windows[w].type ← logical;
EXIT; };
ENDLOOP;
DisplayHeader[black, w];
EraseMessage[];
Select[w];
};
Quit: PROC[r: Box] = {
IF NOT Confirm[1, "type CR to confirm Quit"] THEN RETURN;
Score.StopPlaying[];
Score.StopListening[];
};
ClearManager: PROC = {
mIndex ← 0;
};
manager: ARRAY [0..20) OF Image;
Image: TYPE = RECORD[rect: Box, command: PROC[r: Box]];
mIndex: CARDINAL ← 0;
mMax: CARDINAL = 20;
******************************************************************
Assorted
******************************************************************
SetBrush: PROC[tex: CARDINAL, pnt: Graphics.PaintMode] = INLINE
{Graphics.SetStipple[screen, tex]; [] ← Graphics.SetPaintMode[screen, pnt]};
SetClipper: PROC[w: CARDINAL] = {
box: Box;
[box.xmin, box.ymin] ← Map[screen, windows[w].context, 0, windows[w].bottom];
[box.xmax, box.ymax] ← Map[screen, windows[w].context, 650, windows[w].top - header];
ClipBox[windows[w].context, box];
};
Wait: PROC[t: CARDINAL] = {
now: LONG CARDINAL ← MiscDefs.CurrentTime[];
WHILE MiscDefs.CurrentTime[] < now + t DO NULL; ENDLOOP;
};
screen: PUBLIC Context;
leftMargin: CARDINAL = 5;
rightMargin: CARDINAL = 585;
header: CARDINAL = 15;
CR: CHARACTER = 015C;
windows: ARRAY [0..10) OF Window;
noWindows: CARDINAL ← 2;
Window: TYPE = RECORD[
context: Context, file: STRING,
score: ScorePTR ← NIL,
type: WType, command: POINTER TO CommandProcs,
top, bottom: REAL
];
WType: TYPE = {physical, graphical, logical, command, unknown};
commandProcs: CommandProcs;
unknownProcs: CommandProcs ← [
Flash, Flash, Flash, Flash, Flash, Flash, , Flash, Erase, , , , , 0];
NullProc: PROC[r: Box] = { };
Initialize[];
END.
ReadCommandLine: PROC = {
ENABLE Directory.Error => {
DisplayMessage["no such file"];
CONTINUE; };
char: CHARACTER;
CR: CHARACTER = 015C;
filename: STRING ← [40];
ending: STRING ← [12];
test, error: BOOLFALSE;
hardcopy: BOOLFALSE;
command, second, period: BOOLFALSE;
inputStream: DiskHandle;
inputStream ← NewByteStream["com.cm", Read];
inputStream.reset[inputStream];
DO IF inputStream.endof[inputStream] THEN EXIT;
char ← inputStream.get[inputStream];
command processing
IF command THEN SELECT char FROM
'/ => EXIT;
'n => NULL;
't => test ← TRUE;
'h => hardcopy ← TRUE;
' => command ← FALSE;
ENDCASE => NULL;
IF char = '/ THEN command ← TRUE;
IF command THEN LOOP;
filename processing
SELECT TRUE FROM
char = CR OR char = ' => NULL;
inputStream.endof[inputStream] => NULL;
char = '. => IF period THEN EXIT ELSE {period ← TRUE; LOOP};
period => {AppendChar[ending, char]; LOOP};
ENDCASE => {AppendChar[filename, char]; LOOP};
we have a complete filename
IF filename.length # 0
AND ~EqualString[ending, "image"]
AND ~EqualString[ending, "bcd"] THEN {
AppendString[filename, ".music"];
windows[1].file.length ← 0;
AppendString[windows[1].file, filename];
DisplayHeader[black, 1];
DisplayMessage["Please wait-- retrieving file"];
IODefs.WriteLine[filename];
windows[1].command.fileIn[filename, second];
EraseMessage[];
windows[1].command.display[windows[1].score, TRUE];
command line switches (per file)
IF test AND Score.Test[] THEN {error ← TRUE; EXIT};
IF hardcopy THEN Hardcopy[[[215, 747], [249, 761]]];
second ← TRUE};
filename.length ← 0;
ending.length ← 0;
period ← FALSE;
ENDLOOP;
inputStream.destroy[inputStream];
command line switches (at completion)
IF test AND ~error THEN Quit[[[0, 0], [0, 0]]];
IF hardcopy THEN Quit[[[0, 0], [0, 0]]];
};