-- Author: John Maxwell -- Last Edited by: Maxwell, November 22, 1983 10:52 am 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: 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: BOOLEAN ← TRUE; WaitRunning: ENTRY PROCEDURE = INLINE {WHILE ~running DO UserTerminal.WaitForScanLine[0]; ENDLOOP}; Notifier: TerminalMultiplex.TerminalSwapNotifier = BEGIN SELECT action FROM coming => running ← TRUE; going => running ← FALSE; ENDCASE; END; -- ****************************************************************** -- User Commands -- ****************************************************************** main: PROCESS ← NIL; Initialize: PROCEDURE = BEGIN 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[]; END; ForkMain: PROCEDURE = {main ← FORK Main[]}; Main: PROCEDURE = BEGIN ENABLE { Piece.Overflow => {DisplayMessage["Piece.Overflow"]; RESUME}; ANY => DisplayMessage["UNCAUGHT SIGNAL"]}; DisplayMessage["Mockingbird of November 22, 1983"]; DO IF badCommand THEN BEGIN WHILE TTY.GetChar[keyboard] # 177C DO NULL; ENDLOOP; EraseMessage[]; badCommand ← FALSE; END; 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; END; badCommand: BOOLEAN ← FALSE; Command: PROCEDURE RETURNS[BOOLEAN] = BEGIN 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]; END; HandleRed: PROCEDURE = BEGIN 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]; END; HandleBlue: PROCEDURE[w: CARDINAL] = BEGIN 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]; END; HandleYellow: PROCEDURE = BEGIN 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]; END; ReadKeyboard: PROCEDURE = BEGIN ENABLE BEGIN String.InvalidNumber => BEGIN DisplayMessage["illegal number- type DEL to continue"]; badCommand ← TRUE; CONTINUE; END; TTY.Rubout => BEGIN DisplayMessage["command terminated"]; CONTINUE; END; Piece.Overflow => IF windows[selectedWindow].score = old THEN windows[selectedWindow].score ← new; END; EraseMessage[]; windows[selectedWindow].command.keyboard[windows[selectedWindow].score]; END; ChangeCursor: PROCEDURE = BEGIN 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; END; oldCursor: Cursor ← textCursor; CursorState: TYPE = {window, scroll, command, screen, commandwindow}; currentState: CursorState ← screen; Scroll: PROCEDURE[w: CARDINAL, y: INTEGER] = BEGIN IF y > 0 THEN SetCursorPattern[scrollUpCursor]; IF y < 0 THEN SetCursorPattern[scrollDownCursor]; windows[w].command.scroll[windows[w].score, y]; SetCursorPattern[scrollUpDownCursor]; END; MousePoint: PROCEDURE = BEGIN x, y: REAL = 1; MousePX ← x*mouse.x; MousePY ← y*mouse.y; END; MousePX, MousePY: REAL; ScreenPX, ScreenPY: REAL; -- ****************************************************************** -- Window & Subwindow procedures -- ****************************************************************** DrawScreen: PROCEDURE = BEGIN i: CARDINAL; FOR i IN [0..noWindows) DO windows[i].command.display[windows[i].score, TRUE] ENDLOOP; END; MoveWindow: PROCEDURE[y: REAL] = BEGIN 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 BEGIN dist ← ABS[windows[i].top-y]; w ← i; END; 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]; END; NewWindow: PROCEDURE[w: CARDINAL, y: REAL] = BEGIN -- called by bluebug in the righthand margin SetCursorPattern[newWindowCursor]; WHILE BlueBug[] AND NOT YellowBug[] DO NULL; ENDLOOP; IF YellowBug[] THEN BEGIN DeleteWindow[w]; RETURN; END; DefaultWindow[noWindows, y, windows[w].bottom]; windows[w].bottom ← y; Select[noWindows]; DisplayHeader[black, noWindows]; SetClipper[w]; SetClipper[noWindows]; noWindows ← noWindows + 1; END; SubWindow: PROCEDURE[w: CARDINAL, y: REAL] = BEGIN -- yellowbug in the righthand margin SetCursorPattern[subWindowCursor]; WHILE NOT BlueBug[] AND YellowBug[] DO NULL; ENDLOOP; IF BlueBug[] THEN BEGIN DeleteWindow[w]; RETURN; END; Flash[NIL]; END; FindWindow: PROCEDURE[y: REAL] RETURNS[CARDINAL] = BEGIN i: CARDINAL; FOR i IN [0..noWindows) DO IF y < windows[i].top AND y > windows[i].bottom THEN RETURN[i]; ENDLOOP; RETURN[0]; END; DeleteWindow: PROCEDURE[w: CARDINAL] = BEGIN 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 BEGIN windows[neighbor].bottom ← windows[w].bottom; DisplayHeader[white, w]; END ELSE BEGIN neighbor ← FindWindow[windows[w].bottom - 1]; IF neighbor # 0 THEN BEGIN MoveContext[neighbor, windows[w].top]; DisplayHeader[white, neighbor]; windows[neighbor].top ← windows[w].top; DisplayHeader[black, neighbor]; END; END; IF neighbor = 0 THEN BEGIN DisplayMessage["cannot delete that window"]; RETURN; END; noWindows ← noWindows - 1; Heap.FreeMDSString[, windows[w].file]; windows[w] ← windows[noWindows]; SetClipper[neighbor]; Select[neighbor]; windows[neighbor].command.display[windows[neighbor].score, TRUE]; END; Invert: PROCEDURE[dc: Context] = BEGIN SetStipple[dc, black]; [] ← SetPaintMode[dc, invert]; DrawBox[dc, [0, 0, 1024, 808]]; [] ← SetPaintMode[dc, opaque]; END; MoveContext: PROCEDURE[w: CARDINAL, y: REAL] = BEGIN 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]; END; Select: PROCEDURE[w: CARDINAL] = BEGIN 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; END; selectedWindow: CARDINAL ← 1; listenWindow: CARDINAL ← 1; DefaultWindow: PROCEDURE[w: CARDINAL, top, bottom: REAL] = BEGIN 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]; END; -- ****************************************************************** -- Command Window procedures -- ****************************************************************** DisplayCommandWindow: PROCEDURE[score: ScorePTR, erase: BOOLEAN] = BEGIN 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]; END; DisplayCommand: PROCEDURE[s: LONG STRING, x, y: REAL, proc: PROCEDURE[r: Box]] = BEGIN 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]; END; DisplayHeader: PROCEDURE[color: CARDINAL, w: CARDINAL] = BEGIN 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]; END; EraseMessage: PROCEDURE = BEGIN SetBrush[white, opaque]; DrawBox[screen, [0, 763, 620, 780]]; SetBrush[black, invert]; END; DisplayMessage: PUBLIC PROCEDURE[s: STRING] = BEGIN 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]]; END; AddCommand: PROCEDURE[r: Box, proc: PROCEDURE[r: Box]] = BEGIN 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; END; DeleteCommand: PROCEDURE[x, y: REAL] = BEGIN i: CARDINAL; FOR i IN [0..mIndex) DO IF manager[i].rect.xmin = x THEN BEGIN mIndex ← mIndex - 1; manager[i] ← manager[mIndex]; END; ENDLOOP; END; FindCommand: PROCEDURE[x, y: REAL] RETURNS[m: Image] = BEGIN i: CARDINAL; FOR i IN [0..mIndex) DO BEGIN 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]; END; ENDLOOP; m.command ← NullProc; RETURN[m]; END; Flash: PROCEDURE[score: ScorePTR] = BEGIN Invert[windows[selectedWindow].context]; Invert[windows[selectedWindow].context]; END; Erase: PROCEDURE[score: ScorePTR, erase: BOOLEAN] = BEGIN SetStipple[screen, white]; [] ← SetPaintMode[screen, opaque]; DrawBox[screen, GetBounds[screen]]; SetStipple[screen, black]; [] ← SetPaintMode[screen, transparent]; END; -- ****************************************************************** -- Commands -- ****************************************************************** Confirm: PROCEDURE[w: CARDINAL, s: STRING] RETURNS[BOOLEAN] = BEGIN confirm: BOOLEAN; IF windows[w].command.count = 0 THEN RETURN[TRUE]; DisplayMessage[s]; confirm ← TTY.GetChar[keyboard] = CR; EraseMessage[]; RETURN[confirm]; END; FileIn: PROCEDURE[r: Box] = BEGIN ENABLE Directory.Error => BEGIN DisplayMessage["no such file"]; DrawBox[screen, r]; CONTINUE; END; 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 BEGIN 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; END; DrawBox[screen, r]; END; FileOut: PROCEDURE[r: Box] = BEGIN ENABLE Directory.Error => BEGIN DisplayMessage["illegal file name"]; DrawBox[screen, r]; CONTINUE; END; 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]; END; BackUp: PROCEDURE[w: CARDINAL] = BEGIN 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[]; END; Play: PROCEDURE[r: Box] = BEGIN ENABLE Piece.Overflow => IF windows[selectedWindow].score = old THEN windows[selectedWindow].score ← new; windows[selectedWindow].command.play[windows[selectedWindow].score]; END; InvertPlay: PUBLIC PROCEDURE = BEGIN r: Box = manager[playIndex].rect; SetBrush[black, invert]; DrawBox[screen, r]; END; Listen: PROCEDURE[r: Box] = BEGIN ENABLE Piece.Overflow => IF windows[listenWindow].score = old THEN windows[listenWindow].score ← new; windows[listenWindow].command.listen[windows[listenWindow].score]; listenWindow ← selectedWindow; END; InvertListen: PUBLIC PROCEDURE = BEGIN r: Box = manager[listenIndex].rect; SetBrush[black, invert]; DrawBox[screen, r]; END; playIndex: CARDINAL ← 0; listenIndex: CARDINAL ← 0; Hardcopy: PROCEDURE[r: Box] = BEGIN 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[]; END; EditFileName: PROCEDURE[r: Box] = BEGIN 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 BEGIN c ← TTY.GetChar[keyboard]; IF c = 177C OR c = 010C THEN BEGIN IF windows[w].file.length = 0 THEN LOOP; windows[w].file.length ← windows[w].file.length- 1; DisplayHeader[black, w]; LOOP; END; IF c = ' THEN BEGIN windows[w].file.length ← 0; DisplayHeader[black, w]; LOOP; END; IF c # CR AND c # '. AND c # 033C THEN BEGIN String.AppendChar[windows[w].file, c]; DrawChar[screen, c]; LOOP; END; String.AppendString[windows[w].file, ".music"]; windows[w].type ← logical; EXIT; END; ENDLOOP; DisplayHeader[black, w]; EraseMessage[]; Select[w]; END; Quit: PROCEDURE[r: Box] = BEGIN IF NOT Confirm[1, "type CR to confirm Quit"] THEN RETURN; -- Score.StopPlaying[]; -- Score.StopListening[]; END; ClearManager: PROCEDURE = BEGIN mIndex ← 0; END; manager: ARRAY [0..20) OF Image; Image: TYPE = RECORD[rect: Box, command: PROCEDURE[r: Box]]; mIndex: CARDINAL ← 0; mMax: CARDINAL = 20; -- ****************************************************************** -- Assorted -- ****************************************************************** SetBrush: PROCEDURE[tex: CARDINAL, pnt: Graphics.PaintMode] = INLINE {Graphics.SetStipple[screen, tex]; [] ← Graphics.SetPaintMode[screen, pnt]}; SetClipper: PROCEDURE[w: CARDINAL] = BEGIN 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]; END; Wait: PROCEDURE[t: CARDINAL] = BEGIN -- now: LONG CARDINAL ← MiscDefs.CurrentTime[]; -- WHILE MiscDefs.CurrentTime[] < now + t DO NULL; ENDLOOP; END; 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: PROCEDURE[r: Box] = BEGIN END; Initialize[]; END. ReadCommandLine: PROCEDURE = BEGIN ENABLE Directory.Error => BEGIN DisplayMessage["no such file"]; CONTINUE; END; char: CHARACTER; CR: CHARACTER = 015C; filename: STRING ← [40]; ending: STRING ← [12]; test, error: BOOLEAN ← FALSE; hardcopy: BOOLEAN ← FALSE; command, second, period: BOOLEAN ← FALSE; 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]]]; END;