DIRECTORY InputFocus USING [inputEnabled, InputFocusImpl], Interminal USING [SetCursorPattern], Process USING [Detach, Pause, MsecToTicks, Ticks], Runtime USING [SelfDestruct], WindowManager USING [RestoreCursor]; Begin: PROGRAM IMPORTS InputFocus, Interminal, Process, Runtime, --SafeStorage,-- WindowManager SHARES InputFocus = BEGIN WaitingCursor: PROC = BEGIN aWhile: Process.Ticks = Process.MsecToTicks[100]; InitializeHourglass[56]; UNTIL InputFocus.inputEnabled DO TickHourglass[]; Process.Pause[aWhile]; ENDLOOP; WindowManager.RestoreCursor[]; Runtime.SelfDestruct[]; -- flush this module END; X: BOOL = TRUE; O: BOOL = FALSE; theHGBits: PACKED ARRAY [0..16*16) OF BOOL; theHG: POINTER TO PACKED ARRAY [0..16*16) OF BOOL _ @theHGBits; initialHourglass: PACKED ARRAY [0..16*16) OF BOOL = [ X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, O, X, X, X, X, X, X, X, X, X, X, X, X, X, X, O, O, O, X, X, X, X, X, X, X, X, X, X, X, X, O, O, O, O, O, X, X, X, X, X, X, X, X, X, X, O, O, O, O, O, O, O, X, X, X, X, X, X, X, X, O, O, O, O, O, O, O, O, O, X, X, X, X, X, X, O, O, O, O, O, O, O, O, O, O, O, X, X, X, X, O, O, O, O, O, O, O, O, O, O, O, O, X, O, O, X, O, O, O, O, O, O, O, O, O, O, O, X, O, O, O, O, X, O, O, O, O, O, O, O, O, O, X, O, O, O, O, O, O, X, O, O, O, O, O, O, O, X, O, O, O, O, O, O, O, O, X, O, O, O, O, O, X, O, O, O, O, O, O, O, O, O, O, X, O, O, O, X, O, O, O, O, O, O, O, O, O, O, O, O, X, O, X, O, O, O, O, O, O, O, O, O, O, O, O, O, O, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X ]; grains: CARDINAL = 56; initGrains: CARDINAL = 3; invertSand: BOOL _ TRUE; sand: BOOL _ TRUE; sandArray: ARRAY [1..15) OF CARDINAL; sandUsed, tick, totalTicks, savedTicks: CARDINAL; InitializeHourglass: PUBLIC PROCEDURE [ticks: CARDINAL] = TRUSTED BEGIN savedTicks _ ticks; sandUsed _ tick _ 0; totalTicks _ ticks; theHG^ _ initialHourglass; sandArray _ [14, 12, 10, 8, 6, 4, 2, 2, 3, 6, 7, 10, 11, 14]; sand _ TRUE; END; TickHourglass: PUBLIC PROCEDURE = TRUSTED BEGIN incr: INTEGER; n, m: CARDINAL; topSlope: CARDINAL = 3; bottomSlope: CARDINAL = 2; IF (tick_tick+1) > totalTicks THEN BEGIN -- wrap around IF invertSand THEN sand _ ~sand ELSE theHG^ _ initialHourglass; sandUsed _ tick _ 0; totalTicks _ savedTicks; sandArray _ [14, 12, 10, 8, 6, 4, 2, 2, 3, 6, 7, 10, 11, 14]; RETURN; END ELSE THROUGH [sandUsed..MIN[tick*grains/totalTicks, grains]) DO FOR n DECREASING IN [2..8) DO IF sandArray[n] >= sandArray[n-1]+topSlope THEN EXIT; REPEAT FINISHED => FOR n IN [1..8) DO IF sandArray[n]#0 THEN EXIT; ENDLOOP; ENDLOOP; sandArray[n] _ sandArray[n]-1; m _ (n*16)+7; incr _ 1; UNTIL theHG[m]=sand DO m _ m+incr; incr _ -incr + (IF incr<0 THEN 1 ELSE -1); ENDLOOP; theHG[m] _ ~sand; IF sandUsed < initGrains THEN theHG[SELECT sandUsed FROM 0 => (9*16)+7, 1 => (11*16)+7, ENDCASE => (13*16)+7] _ sand ELSE BEGIN FOR n IN [8..14) DO IF sandArray[n] >= sandArray[n+1]+bottomSlope THEN EXIT; REPEAT FINISHED => FOR n DECREASING IN [8..15) DO IF sandArray[n]#0 THEN EXIT; ENDLOOP; ENDLOOP; sandArray[n] _ sandArray[n]-1; m _ (n*16)+7; incr _ 1; WHILE theHG[m]=sand DO m _ m+incr; incr _ -incr + (IF incr<0 THEN 1 ELSE -1); ENDLOOP; theHG[m] _ sand; END; sandUsed _ sandUsed+1; ENDLOOP; Interminal.SetCursorPattern[LOOPHOLE[theHGBits]]; -- update displayed cursor END; START InputFocus.InputFocusImpl; TRUSTED {Process.Detach[FORK WaitingCursor]}; -- cursor for amusement during start-up END. Begin.mesa; Written by S. McGregor Last Edited by McGregor, July 14, 1983 1:47 pm Last Edited by: Maxwell, January 3, 1983 1:37 pm SafeStorage USING [SetCollectionInterval], Here's how to modify the hourglass cursor: change the initialHourglass array below to anything you like for an initial cursor. Count the number of bits (of sand) contained in the top and change the constant grains to this number. sandArray will also need to be changed in InitializeHourglass. The first seven numbers tell how many grains there are to start in the top rows of the hourglass (not counting the sides). The last seven numbers tell how many empty places (slots for sand grains) there are in the bottom rows of the hourglass. The algorithm that moves the grains will carefully skip over any grains you initially put in the bottom. Other fun things to play with are the constants that control how steep (slope) the sand piles up in the bottom, or drains from the top. Happy hacking, /Scott. take a grain out of the top non-empty row of sand, favoring the middle. put a grain in one of the top non-empty rows of sand, favoring the middle, and using the slope as a determinant of the sand stacking angle. [] _ SafeStorage.SetCollectionInterval[16384]; -- rumor of better performance Κν– "cedar" style˜JšΟc#™#Jš.™.Jšœ0™0J˜šΟk ˜ Jšœ žœ ˜0Jšœ žœ˜$Jšœžœ%˜2Jšœ˜Jšœ žœ™*Jšœžœ˜$J˜—Jšœž˜J˜Jšžœ+œ˜PJšžœ ˜J˜Jšž˜J˜šΟn œžœž˜J˜1J˜Jšžœžœ)žœ˜QJ˜Jšœ˜,Jšžœ˜J˜—Jš©™©J˜Jšžœžœžœ˜Jšžœžœžœ˜J˜Jš œ žœžœ žœžœ˜+Jš œžœžœžœžœ žœžœ˜?J˜š œžœžœ žœžœ˜5Jš žœžœžœžœžœžœžœžœžœžœžœžœžœžœžœžœ˜/Jš žœžœžœžœžœžœžœžœžœžœžœžœžœžœžœžœ˜/Jš žœžœžœžœžœžœžœžœžœžœžœžœžœžœžœžœ˜/Jš žœžœžœžœžœžœžœžœžœžœžœžœžœžœžœžœ˜/Jš žœžœžœžœžœžœžœžœžœžœžœžœžœžœžœžœ˜/Jš žœžœžœžœžœžœžœžœžœžœžœžœžœžœžœžœ˜/Jš žœžœžœžœžœžœžœžœžœžœžœžœžœžœžœžœ˜/Jš žœžœžœžœžœžœžœžœžœžœžœžœžœžœžœžœ˜/Jš žœžœžœžœžœžœžœžœžœžœžœžœžœžœžœžœ˜/Jš žœžœžœžœžœžœžœžœžœžœžœžœžœžœžœžœ˜/Jš žœžœžœžœžœžœžœžœžœžœžœžœžœžœžœžœ˜/Jš žœžœžœžœžœžœžœžœžœžœžœžœžœžœžœžœ˜/Jš žœžœžœžœžœžœžœžœžœžœžœžœžœžœžœžœ˜/Jš žœžœžœžœžœžœžœžœžœžœžœžœžœžœžœžœ˜/Jš žœžœžœžœžœžœžœžœžœžœžœžœžœžœžœžœ˜/Jšžœžœžœžœžœžœžœžœžœžœžœžœžœžœžœž˜.J˜J˜—Jšœžœ˜Jšœ žœ˜J˜Jšœ žœžœ˜Jšœžœžœ˜J˜Jšœ žœ žœžœ˜%Jšœ(žœ˜1J˜š Ÿœžœž œ žœž ˜GJ˜J˜J˜J˜J˜=Jšœžœ˜ Jšžœ˜J˜—šŸ œžœž œž ˜/Jšœžœ˜Jšœžœ˜Jšœ žœ˜Jšœ žœ˜J˜šžœžœžœ˜7Jšžœ žœžœ˜?J˜J˜J˜=Jšžœ˜Jšž˜J˜—Jšžœžœ žœ"ž˜?˜JšG™Gšžœž œžœž˜Jšžœ)žœžœ˜5š žœžœžœžœž˜%Jšžœžœžœ˜Jšžœ˜—Jšžœ˜—J˜J˜ J˜ šžœž˜J˜ Jšœžœžœžœ˜*Jšžœ˜—J˜J˜JšJ™JJš@™@šžœžœžœ ž˜8J˜J˜Jšžœ˜—šžœž˜ šžœžœ ž˜Jšžœ,žœžœ˜8š žœžœžœž œžœ ž˜1Jšžœžœžœ˜Jšžœ˜—Jšžœ˜—J˜J˜ J˜ šžœž˜J˜ Jšœžœžœžœ˜*Jšžœ˜—J˜Jšžœ˜J˜—J˜J˜Jšžœ˜J˜—Jšœžœ˜LJšžœ˜—J˜Jšžœ˜ J˜Jšžœžœ'˜UJ˜Jšœ/™MJ™Jšžœ˜J˜J˜J˜—…— œ‹