-- Kaleidoscope.mesa -- Last Edited -- Gobbel 28-Feb-82 16:39:08 -- Yamamoto 19-Sep-83 10:08:58 -- Copyright (C) 1984 by Xerox Corporation. All rights reserved. DIRECTORY Display USING [Bitmap, Black, replaceFlags], Environment USING [bitsPerWord, wordsPerPage], Exec USING [AddCommand, ExecProc], Heap USING [Create], Inline USING [BITAND, BITSHIFT, BITXOR, LongCOPY], Mopcodes USING [zLI4, zSHIFT, zWLFS], MSegment USING [Address, Create, Handle], Process USING [Abort, Detach, DisableTimeout, EnableAborts, priorityBackground, priorityNormal, SecondsToTicks, SetPriority, Yield], Profile USING [initialToolStateDefault], ToolWindow USING [Activate, AdjustProcType, Box, Create, CreateSubwindow, Deactivate, Show, TransitionProcType], UserInput USING [AttentionProcType, ClearInputFocusOnMatch, SetAttention, SetInputFocus], UserTerminal USING [Background, hasBorder, screenHeight, screenWidth, SetBackground, SetBorder], Window USING [Box, GetBox, GetParent, Handle]; Kaleidoscope: MONITOR IMPORTS Display, Exec, Heap, Inline, Process, Profile, MSegment, ToolWindow, UserInput, UserTerminal, Window = BEGIN Bit: TYPE = MACHINE DEPENDENT {on(0), off(1)}; BitDesc: TYPE = MACHINE DEPENDENT RECORD [offset(0: 0..7): [0..377B] _ 0, pos(0: 8..11): [0..17B] _ 0, size(0: 12..15): [0..17B] _ 1]; z: UNCOUNTED ZONE _ Heap.Create[2]; Generator: TYPE = RECORD[a, b, c: INTEGER, periodCount: CARDINAL]; period: CARDINAL; persistence: CARDINAL; windowSide: CARDINAL _ 256; screenWidthWords: CARDINAL = EVEN[(windowSide+15)/16]; screenAreaWords: CARDINAL = screenWidthWords*windowSide; screenAreaPages: CARDINAL = (screenAreaWords+Environment.wordsPerPage-1)/Environment.wordsPerPage; spotShift: INTEGER = -(Environment.bitsPerWord - Log2[windowSide/2]); boxEdge: INTEGER = windowSide + 2; toolBox: Window.Box _ [[50, 50], [boxEdge, boxEdge]]; bigBox: Window.Box _ [[0, 0], [4*windowSide+2, 3*windowSide+2]]; xStateB: Generator _ [1, -1849,3,]; xStateE: Generator _ TRASH; yStateB: Generator _ [1, -1809,3,]; yStateE: Generator _ TRASH; pBitmap: LONG POINTER TO UNSPECIFIED _ NIL; bitmapSeg: MSegment.Handle _ NIL; toolWindow, subWindow: Window.Handle _ NIL; wait: CONDITION _ [timeout: Process.SecondsToTicks[1]]; finished: CONDITION; bouncer: PROCESS; running: BOOLEAN _ FALSE; stop: BOOLEAN _ FALSE; MakeDesc: PROCEDURE [UNSPECIFIED] RETURNS [BitDesc] = MACHINE CODE {Mopcodes.zLI4; Mopcodes.zSHIFT}; Log2: PROCEDURE [n: CARDINAL] RETURNS [log: INTEGER] = BEGIN log _ SELECT n FROM >= 100000B => 15, >= 40000B => 14, >= 20000B => 13, >= 10000B => 12, >= 4000B => 11, >= 2000B => 10, >= 1000B => 9, >= 400B => 8, >= 200B => 7, >= 100B => 6, >= 40B => 5, >= 20B => 4, >= 10B => 3, >= 4 => 2, >= 2 => 1, ENDCASE => 0; END; Set: PROCEDURE [value: Bit, word: LONG POINTER, desc: BitDesc] = MACHINE CODE {Mopcodes.zWLFS}; EVEN: PROCEDURE [v: UNSPECIFIED] RETURNS [UNSPECIFIED] = INLINE {RETURN[v+Inline.BITAND[v, 1]]}; Advance: ENTRY PROCEDURE [state: LONG POINTER TO Generator] = BEGIN OPEN state; a _ Inline.BITXOR[(a+b), b]; periodCount _ periodCount - 1; IF periodCount = 0 THEN {b _ Inline.BITXOR[(b+c), c]; periodCount _ period}; END; Spots: PROCEDURE [x, y: INTEGER] = BEGIN -- Draw 8 spots with kaleidoscopic symmetry x0: CARDINAL = Inline.BITSHIFT[x, spotShift]; y0: CARDINAL = Inline.BITSHIFT[y, spotShift]; IF x0 < y0 THEN -- Discard points in other triangle BEGIN x1: CARDINAL = (windowSide-1)-x0; y1: CARDINAL = (windowSide-1)-y0; Set[on, pBitmap+x0*screenWidthWords, MakeDesc[y0]]; Set[on, pBitmap+y0*screenWidthWords, MakeDesc[x0]]; Set[on, pBitmap+x1*screenWidthWords, MakeDesc[y0]]; Set[on, pBitmap+y0*screenWidthWords, MakeDesc[x1]]; Set[on, pBitmap+x1*screenWidthWords, MakeDesc[y1]]; Set[on, pBitmap+y1*screenWidthWords, MakeDesc[x1]]; Set[on, pBitmap+x0*screenWidthWords, MakeDesc[y1]]; Set[on, pBitmap+y1*screenWidthWords, MakeDesc[x0]]; END; END; Erases: PROCEDURE [x, y: INTEGER] = BEGIN -- Same as Spots except this erases. x0: CARDINAL = Inline.BITSHIFT[x, spotShift]; y0: CARDINAL = Inline.BITSHIFT[y, spotShift]; IF x0 < y0 THEN BEGIN x1: CARDINAL = (windowSide-1)-x0; y1: CARDINAL = (windowSide-1)-y0; Set[off, pBitmap+x0*screenWidthWords, MakeDesc[y0]]; Set[off, pBitmap+y0*screenWidthWords, MakeDesc[x0]]; Set[off, pBitmap+x1*screenWidthWords, MakeDesc[y0]]; Set[off, pBitmap+y0*screenWidthWords, MakeDesc[x1]]; Set[off, pBitmap+x1*screenWidthWords, MakeDesc[y1]]; Set[off, pBitmap+y1*screenWidthWords, MakeDesc[x1]]; Set[off, pBitmap+x0*screenWidthWords, MakeDesc[y1]]; Set[off, pBitmap+y1*screenWidthWords, MakeDesc[x0]]; END; END; PaintKals: ENTRY PROCEDURE = { FOR i: CARDINAL IN [0..4) DO FOR j: CARDINAL IN [0..3) DO Display.Bitmap[ window: subWindow, box: [[i*windowSide, j*windowSide], [windowSide, windowSide]], address: [pBitmap,0,0], bitmapBitWidth: windowSide, flags: Display.replaceFlags]; ENDLOOP; ENDLOOP; }; NotifyQuit: ENTRY PROC = {NOTIFY finished}; Run: PROCEDURE = BEGIN ENABLE UNWIND => NULL; oldBackground: UserTerminal.Background _ UserTerminal.SetBackground[white]; IF UserTerminal.hasBorder THEN UserTerminal.SetBorder[377B, 377B]; Process.SetPriority[Process.priorityBackground]; running _ TRUE; xStateB.periodCount _ period; yStateB.periodCount _ period; xStateE _ xStateB; yStateE _ yStateB; FOR i: CARDINAL IN[1..persistence] DO -- Run the b(egin) generators ahead [] _ Advance[@xStateB]; [] _ Advance[@yStateB]; [] _ Spots[xStateB.a, yStateB.a]; ENDLOOP; DO -- Main loop ENABLE ABORTED => EXIT; THROUGH [0..16) DO Advance[@xStateE]; Advance[@yStateE]; -- Advance and erase 8 spots Erases[xStateE.a, yStateE.a]; Advance[@xStateB]; Advance[@yStateB]; -- Advance and put 8 spots Spots[xStateB.a, yStateB.a]; ENDLOOP; PaintKals[]; Process.Yield[]; IF stop THEN {NotifyQuit[]; EXIT}; ENDLOOP; running _ FALSE; [] _ UserTerminal.SetBackground[oldBackground]; IF UserTerminal.hasBorder THEN UserTerminal.SetBorder[210B, 42B]; END; MyDisplay: PROC[Window.Handle] = { Display.Black[subWindow, [[0,0], subWindow.GetBox[].dims]]; PaintKals[]; }; AttentionProc: UserInput.AttentionProcType = { Process.Detach[FORK StopRunning[toolWindow]]}; StopRunning: ENTRY PROCEDURE [w: Window.Handle] = { Process.SetPriority[Process.priorityNormal]; stop _ TRUE; WAIT finished; [] _ ToolWindow.Deactivate[w]}; StartRunning: ENTRY PROC [window: Window.Handle] = { IF running THEN RETURN; IF subWindow = NIL THEN subWindow _ ToolWindow.CreateSubwindow[ parent: window, display: MyDisplay, box: [[0,0], toolWindow.GetBox[].dims]]; UserInput.SetInputFocus[subWindow, NIL, FALSE]; UserInput.SetAttention[subWindow.GetParent[], AttentionProc]; UserInput.SetAttention[subWindow, AttentionProc]; pBitmap^ _ 177777B; Inline.LongCOPY[ from: pBitmap, to: pBitmap+1, nwords: screenAreaPages*256 - 1]; stop _ FALSE; bouncer _ FORK Run; running _ TRUE}; WaitTilFinished: ENTRY PROC = {WAIT finished}; TransitionProc: ToolWindow.TransitionProcType = { ENABLE UNWIND => NULL; SELECT new FROM inactive, tiny => { IF old = active THEN { UserInput.ClearInputFocusOnMatch[subWindow]; IF ~stop THEN {stop _ TRUE; WaitTilFinished[]}; Process.Abort[bouncer]; JOIN bouncer}; IF new = inactive THEN subWindow _ NIL}; active => IF old # active THEN StartRunning[window]; ENDCASE}; KalCommand: Exec.ExecProc = {ToolWindow.Activate[toolWindow]}; AdjustProc: ENTRY ToolWindow.AdjustProcType = {}; Init: PROCEDURE = BEGIN i,j: CARDINAL _ 0; period _ 10000; persistence _ 5000; bitmapSeg _ MSegment.Create[file: NIL, release: [], fileBase: 0, pages: screenAreaPages]; pBitmap _ MSegment.Address[bitmapSeg]; toolWindow _ ToolWindow.Create[ name: "Kaleidoscope"L, adjust: AdjustProc, transition: TransitionProc, box: [place: [0,0], dims: [w: UserTerminal.screenWidth, h: UserTerminal.screenHeight]], initialState: Profile.initialToolStateDefault, named: FALSE]; IF Profile.initialToolStateDefault # inactive THEN { TransitionProc[ window: toolWindow, old: inactive, new: Profile.initialToolStateDefault]; ToolWindow.Show[toolWindow]}; Exec.AddCommand["Kaleidoscope.~"L, KalCommand]; Process.EnableAborts[@wait]; Process.DisableTimeout[@finished]; END; Init[]; END...