CKViewerOps.mesa
Last edited by Ken Pier, August 12, 1983 10:23 am
DIRECTORY
BitBlt,
Buttons,
ViewerOps,
CKViewerPanel,
CKViewerButtons,
ColorDisplay,
GraphicsColor,
MessageWindow,
Inline, Real,
Process USING [MsecToTicks, Pause];
CKViewerOps: PROGRAM
IMPORTS BitBlt, Buttons, ColorDisplay, Inline, Real, Process, MessageWindow, CKViewerButtons, ViewerOps
EXPORTS CKViewerButtons, CKViewerPanel = BEGIN
OPEN MW: MessageWindow;
CKViewer: TYPE = CKViewerButtons.CKViewer;
CKViewerState: TYPE = CKViewerButtons.CKViewerState;
sym: BOOLEANFALSE;
bbspace: BitBlt.BBTableSpace;
bb: BitBlt.BBptr ← InitBB[@bbspace];
grayword: CARDINAL ← 0;
bitmap,bitmapB: LONG POINTERNIL;
wpl,wplB: CARDINAL ← 0;
width,height: CARDINAL ← 0;
lbpp,lbppB: CARDINAL ← 0; -- log (base 2) bits per pixel
bpp,bppB: CARDINAL ← 0; -- bits per pixel
full: BOOLEANFALSE;
ashow,bshow: BOOLEANTRUE;
splat: BOOLEANTRUE;
cornerSize: CARDINAL ← 4;
cornerColor: CARDINAL ← 8;
Triple: TYPE = RECORD[r,g,b: [0..256)];
testmap: ARRAY[0..8] OF Triple ← [
[127,127,127], -- gray (background)
[ 0, 0, 0], -- black
[255, 0, 0], -- red
[ 0,255, 0], -- green
[255,255, 0], -- yellow
[ 0, 0,255], -- blue
[255, 0,255], -- magenta
[ 0,255,255], -- cyan
[255,255,255] -- white
];
Diag: PROC [] = {
draw a set of diagonal lines
Bham: PROC [fx,fy,lx,ly: INTEGER, color: [0..8]] = {
draw a line from (fx,fy) to (lx,ly)
yt: REAL; xx, xi: INTEGER; yy, yi: INTEGER;
dx: INTEGER ← lx-fx;
dy: INTEGER ← ly-fy;
IF dy>dx OR dx<=0 OR dy<=0 THEN ERROR;
FOR xi IN [0..dx) DO
yt ← (Real.Float[dy]/Real.Float[dx])*Real.Float[xi];
yi ← Real.FixI[yt+0.5];
xx𡤏x+xi; yy𡤏y+yi;
TestRect[xx,yy,1,1,color];
TestRect[iWidth-xx,yy,1,1,color];
TestRect[xx,iHeight-yy,1,1,color];
TestRect[iWidth-xx,iHeight-yy,1,1,color];
ENDLOOP;
};
black: [0..8] = 1; --testmap[1] is black
white: [0..8] = 8; --testmap[8] is white
iWidth: INTEGER ← width;
iHeight: INTEGER ← height;
deltaX: INTEGER ← iWidth/40;
deltaY: INTEGER ← (deltaX*iHeight)/iWidth;
xi: INTEGER ← 0;
yi: INTEGER ← 0;
IF full THEN Positive[] ELSE {
FOR i: CARDINAL IN[0..9) DO
ColorDisplay.SetColor[pixelA: i, r: testmap[i].r, g: testmap[i].g, b: testmap[i].b];
ENDLOOP;
SetShowButtons[TRUE,FALSE,FALSE];
};
TestRect[0,0,width,height,black]; --black background
FOR n: INTEGER ← 0, n+1 UNTIL xi >=iWidth DO
Bham[fx: xi, fy: 0, lx: iWidth-1, ly: iHeight-n*deltaY, color: white];
xi←xi+deltaX;
ENDLOOP;
};
ShowTPat: PROC = {
x: CARDINAL = 60;
h: CARDINAL = 60;
w: CARDINAL = 50;
gap: CARDINAL = 15;
IF full THEN Positive[] ELSE {
FOR i: CARDINAL IN[0..9) DO
ColorDisplay.SetColor[pixelA: i, r: testmap[i].r, g: testmap[i].g, b: testmap[i].b];
ENDLOOP;
SetShowButtons[TRUE,FALSE,FALSE];
};
gray background
TestRect[0,0,width,height,0];
four corners
{ s: CARDINAL = cornerSize;
c: CARDINAL = cornerColor; -- color
TestRect[0,0,s,s,c];
TestRect[width-s,0,s,s,c];
TestRect[0,height-s,s,s,c];
TestRect[width-s,height-s,s,s,c];
};
various colors at left edge
FOR i: CARDINAL IN[0..8) DO
r,g,b: [0..256);
r ← (i MOD 2)*255;
g ← ((i/2) MOD 2)*255;
b ← ((i/4) MOD 2)*255;
TestRect[4,i*h+10,x,h-20,i+1];
ENDLOOP;
a bunch of stripes
FOR i: CARDINAL IN[0..8) DO
r,g,b: [0..256);
r ← (i MOD 2)*255;
g ← ((i/2) MOD 2)*255;
b ← ((i/4) MOD 2)*255;
TestRect[x+i*w+gap,0,w-gap,8*h,i+1];
ENDLOOP;
};
TestRect: PROC[x,y,w,h: CARDINAL, i: [0..8]] = {
IF NOT (x<width AND y<height) THEN RETURN;
w ← MIN[w,width-x]; h ← MIN[h,height-y];
IF full THEN FullRect[x,y,w,h,testmap[i].r,testmap[i].g,testmap[i].b]
ELSE ARect[x,y,w,h,i];
};
Rect: PROC[x,y,w,h: CARDINAL, i: [0..256)] = { --formerly i: [0..8]
IF NOT (x<width AND y<height) THEN RETURN;
w ← MIN[w,width-x]; h ← MIN[h,height-y];
IF full THEN FullRect[x,y,w,h,i,i,i] --gray value
ELSE ARect[x,y,w,h,i];
};
SetUpColors: PROCEDURE = BEGIN
OPEN ColorDisplay;
k: CARDINAL ← Inline.BITSHIFT[1,bpp]; -- number of pixel values
r,g,b: [0..256);
Alter: PROC[c: [0..256)] RETURNS[[0..256)] = INLINE { RETURN[255-(255-c)/2] };
IF full THEN {
FOR n: CARDINAL IN [0..256) DO
r ← MyRandom[256]; g ← MyRandom[256]; b ← MyRandom[256];
SetRedMap[g,r]; SetGreenMap[b,g]; SetBlueMap[r,b]; --scrambler
ENDLOOP;
}
ELSE {
FOR n: CARDINAL IN [0..k) DO
r ← MyRandom[256]; g ← MyRandom[256]; b ← MyRandom[256];
ColorDisplay.SetColor[pixelA: n, pixelB: 0, r: r, g: g, b: b];
ColorDisplay.SetColor[pixelA: n, pixelB: 1, r: Alter[r], g: Alter[g], b: Alter[b]];
ENDLOOP;
};
END;
Positive: PROC = {
IF NOT full THEN RETURN;
FOR i: CARDINAL IN[0..256) DO
ColorDisplay.SetRedMap[i,i];
ColorDisplay.SetGreenMap[i,i];
ColorDisplay.SetBlueMap[i,i];
ENDLOOP;
};
HalfPositive: PROC = {
i: [0..256] ← 0;
IF NOT full THEN RETURN;
FOR j: CARDINAL IN[128..256) DO
ColorDisplay.SetRedMap[j,i];
ColorDisplay.SetGreenMap[j,i];
ColorDisplay.SetBlueMap[j,i];
i← i+2;
ENDLOOP;
};
MyRandom: PROCEDURE [max: CARDINAL] RETURNS [CARDINAL] = INLINE BEGIN
RETURN[Random[] MOD max];
END;
SetGray: PROC[g: [0..256)] = { grayword ← MakeGray[g] };
MakeGray: PROC[g: [0..256)] RETURNS[CARDINAL] = {
grayword: CARDINAL ← 0;
IF bpp#0 THEN {
ppw: CARDINAL ← 16/bpp; -- pixels per word
mask: CARDINAL ← Inline.BITNOT[Inline.BITSHIFT[-1,bpp]];
g ← Inline.BITAND[g,mask];
THROUGH [0..ppw) DO grayword ← Inline.BITSHIFT[grayword,bpp] + g ENDLOOP;
};
RETURN[grayword];
};
InitBB: PROC[bbs: POINTER TO BitBlt.BBTableSpace] RETURNS[BitBlt.BBptr] = INLINE {
bb: BitBlt.BBptr ← BitBlt.AlignedBBTable[bbs];
bb^ ← [
dst: [word: NIL, bit: 0],
dstBpl: 0,
src: [word: @grayword, bit: 0],
srcDesc: [gray[[yOffset: 0, widthMinusOne: 0, heightMinusOne: 0]]],
width: 0, height: 0,
flags: [disjoint: TRUE, gray: TRUE]
];
RETURN[bb];
};
FullRect: PROC[x,y,w,h: CARDINAL, r,g,b: [0..256)] = {
rgword: CARDINAL ← 256*r + g;
bbword: CARDINAL ← 256*b + b;
IF NOT full THEN RETURN;
bitmap A
bb.dst ← [word: ColorDisplay.baseA + LONG[y]*ColorDisplay.wplA + x, bit: 0];
bb.dstBpl ← 16*ColorDisplay.wplA;
bb.src ← [word: @rgword, bit: 0];
bb.width ← 16*w;
bb.height ← h;
bb.flags.dstFunc ← null;
BitBlt.BITBLT[bb];
bitmap B
bb.dst ← [word: ColorDisplay.baseB + LONG[y]*ColorDisplay.wplB + x/2, bit: 8*(x MOD 2)];
bb.dstBpl ← 16*ColorDisplay.wplB;
bb.src ← [word: @bbword, bit: bb.dst.bit];
bb.width ← 8*w;
bb.height ← h;
bb.flags.dstFunc ← null;
BitBlt.BITBLT[bb];
};
ARect: PROC[x,y,w,h: CARDINAL, i: [0..256), fn: BitBlt.DstFunc ← null] = {
iword: CARDINAL ← MakeGray[i];
xbit: CARDINAL ← Inline.BITSHIFT[x,lbpp];
bb.dst ← [word: ColorDisplay.baseA + LONG[y]*ColorDisplay.wplA + xbit/16, bit: xbit MOD 16];
bb.dstBpl ← 16*ColorDisplay.wplA;
bb.src ← [word: @iword, bit: bb.dst.bit];
bb.width ← Inline.BITSHIFT[w,lbpp];
bb.height ← h;
bb.flags.dstFunc ← fn;
BitBlt.BITBLT[bb];
};
index: [0..256) ← 0;
Rectangle: PROC[lx,ty,rx,by: CARDINAL, fn: BitBlt.DstFunc ← null, clear: BOOLEANFALSE] = {
IF full THEN {
r,g,b: [0..256);
IF clear THEN r←g𡤋𡤀 ELSE {r ← MyRandom[256]; g ← MyRandom[256]; b ← MyRandom[256];};
FullRect[lx,ty,rx-lx,by-ty,r,g,b];
}
ELSE {
index ← IF clear THEN 0 ELSE (index + 1) MOD 256;
ARect[lx,ty,rx-lx,by-ty,index,fn];
IF clear AND bitmapB#NIL THEN BRectangle[lx,ty,rx,by,null,TRUE];
};
};
BRectangle: PROC[lx,ty,rx,by: CARDINAL, fn: BitBlt.DstFunc ← xor, clear: BOOLEANFALSE] = {
xbit: CARDINAL ← Inline.BITSHIFT[lx,lbppB];
black: CARDINALIF clear THEN 0 ELSE 177777B;
bb.dst ← [word: bitmapB + LONG[ty]*wplB + xbit/16, bit: xbit MOD 16];
bb.dstBpl ← 16*wplB;
bb.src ← [word: @black, bit: 0];
bb.width ← Inline.BITSHIFT[(rx-lx),lbppB];
bb.height ← by-ty;
bb.flags.dstFunc ← fn;
BitBlt.BITBLT[bb];
};
RandomSplat: PROCEDURE [ckViewer: CKViewer] = {
screenX: CARDINAL = width;
screenY: CARDINAL = height;
XorRatio: CARDINAL = 3;
ty, ty2, lx, w, h: CARDINAL;
fn: BitBlt.DstFunc ← (IF MyRandom[XorRatio]=0 THEN xor ELSE null);
SetGray[MyRandom[256]];
IF sym THEN {
ty ← ty2 ← MyRandom[screenY/2];
lx ← MyRandom[screenX/2];
w ← MyRandom[screenX/2-lx];
h ← MyRandom[screenY/2-ty];
Rectangle[lx, ty, lx+w, ty+h, fn];
ty ← screenY/2+(screenY/2-ty)-h;
Rectangle[lx, ty, lx+w, ty+h, fn];
lx ← screenX/2+(screenX/2-lx)-w;
Rectangle[lx, ty, lx+w, ty+h, fn];
Rectangle[lx, ty2, lx+w, ty2+h, fn];
}
ELSE {
ty ← MyRandom[screenY];
lx ← MyRandom[screenX];
w ← MyRandom[screenX-lx];
h ← MyRandom[screenY-ty];
Rectangle[lx, ty, lx+w, ty+h, fn];
};
IF bitmapB#NIL THEN {
ty ← MyRandom[screenY];
lx ← MyRandom[screenX];
w ← MyRandom[screenX-lx];
h ← MyRandom[screenY-ty];
BRectangle[lx, ty, lx+w, ty+h];
};
IF ckViewer.state.slow THEN Wait[200]; -- slow mode
};
ShowConverge: PROCEDURE = {
black: [0..8] = 1; --testmap[1] is black
white: [0..8] = 8; --testmap[8] is white
hThick: CARDINAL ← height/300;
hStep: CARDINAL ← height/30;
vThick: CARDINAL ← height/300;
vStep: CARDINAL ← height/30;
IF full THEN Positive[] ELSE {
FOR i: CARDINAL IN[0..9) DO
ColorDisplay.SetColor[pixelA: i, r: testmap[i].r, g: testmap[i].g, b: testmap[i].b];
ENDLOOP;
SetShowButtons[TRUE,FALSE,FALSE];
};
TestRect[0,0,width,height,black]; --black background
FOR xx: CARDINAL ← 0, xx+hStep UNTIL xx > width DO
TestRect[xx, 0, vThick, height, white];
ENDLOOP;
FOR v: CARDINAL ← 0, v+vStep UNTIL v > height DO
TestRect[0, v, width, hThick ,white];
ENDLOOP;
};
ShowBig: PROCEDURE [big: BOOLEAN, color: GraphicsColor.Color] = {
r,g,b: CARDINAL;
rectheight: CARDINAL ← height/16; --sixteen rectangles
cInc: CARDINALIF big THEN 20B ELSE 1;
maxIntensity: CARDINALIF full THEN 400B ELSE (Inline.BITSHIFT[1,bpp]);
groupSize: CARDINALMAX[16/maxIntensity,1];
groupIndex: CARDINAL ← 16/groupSize;
IF NOT full THEN SetShowButtons[TRUE,FALSE,FALSE] ELSE SetShowButtons[TRUE,TRUE,TRUE];
FOR gI: CARDINAL IN [0..groupIndex) DO
inten: CARDINAL ← gI*cInc;
SELECT color FROM
GraphicsColor.red => {r←inten; b←g𡤀};
GraphicsColor.green => {g←inten; b←r𡤀};
GraphicsColor.blue => {b←inten; r←g𡤀};
ENDCASE => ERROR;
IF full THEN {
OPEN ColorDisplay; SetRedMap[gI,r]; SetGreenMap[gI,g]; SetBlueMap[gI,b];}
ELSE ColorDisplay.SetColor[pixelA: gI, pixelB: 0, r: r, g: g, b: b];
FOR x: CARDINAL IN [0..groupSize) DO
nextRect: CARDINAL ← gI*groupSize + x;
Rect[0,nextRect*rectheight,width,rectheight, gI];
ENDLOOP;
ENDLOOP;
};
ShowBigRed: PROCEDURE [big: BOOLEAN] = {
ShowBig[big, GraphicsColor.red];
};
ShowBigGreen: PROCEDURE [big: BOOLEAN] = {
ShowBig[big, GraphicsColor.green];
};
ShowBigBlue: PROCEDURE [big: BOOLEAN] = {
ShowBig[big, GraphicsColor.blue];
};
ShowCBars: PROCEDURE = {
graywidth: CARDINAL ← width/128; --this must integer divide evenly
grayheight: CARDINAL ← height/2; --this must integer divide evenly
cbarwidth: CARDINAL ← (width)/9; --this may truncate
cbarheight: CARDINAL ← height/2; --this must integer divide evenly
IF full THEN HalfPositive[] ELSE { --set up gray map
k: CARDINAL ← (Inline.BITSHIFT[1,bpp])/2; -- half the number of pixel values
FOR n: CARDINAL IN [0..k) DO
ColorDisplay.SetColor[pixelA: n+200B, pixelB: 0, r: n*2, g: n*2, b: n*2]; --use top half of colormap. Only makes sense for 8 BPP
ENDLOOP;
};
FOR i: CARDINAL IN[0..9) DO --set up color bars
IF full THEN {ColorDisplay.SetRedMap[i,testmap[i].r]; ColorDisplay.SetGreenMap[i,testmap[i].g]; ColorDisplay.SetBlueMap[i,testmap[i].b];}
ELSE ColorDisplay.SetColor[pixelA: i, r: testmap[i].r, g: testmap[i].g, b: testmap[i].b]
ENDLOOP;
FOR x: CARDINAL IN [0..128) DO --gray wedge
Rect[x*graywidth, 0, graywidth, grayheight, x+128];
ENDLOOP;
FOR x: CARDINAL IN [0..8] DO --colorbars
Rect[x*cbarwidth, cbarheight, cbarwidth, cbarheight, x];
ENDLOOP;
SetShowButtons[TRUE,full,full];
};
NextRoll: PROCEDURE [] = {
OPEN ColorDisplay;
r,g,b,r0,g0,b0: [0..256);
IF full THEN {
r0←GetRedMap[0]; g0←GetGreenMap[0]; b0←GetBlueMap[0];
FOR i: CARDINAL IN[0..255) DO
r ← GetRedMap[i+1]; g ← GetGreenMap[i+1]; b ← GetBlueMap[i+1];
SetRedMap[i,r]; SetGreenMap[i,g]; SetBlueMap[i,b];
ENDLOOP;
SetRedMap[255,r0]; SetGreenMap[255,g0]; SetBlueMap[255,b0];
}
ELSE {
[r0,g0,b0] ← ColorDisplay.GetColor[0];
FOR i: CARDINAL IN[0..255) DO
[r,g,b] ← ColorDisplay.GetColor[i+1];
ColorDisplay.SetColor[i,0,r,g,b];
ENDLOOP;
ColorDisplay.SetColor[255,0,r0,g0,b0];
};
Wait[100];
};
NextScramble: PROCEDURE [] = {
SetUpColors[]; Wait[200];
};
background: INTEGER ← 0; -- initially black
ClearScreen: PROCEDURE = {
IF NOT full THEN {
ColorDisplay.SetColor[0, 0, background, background, background];
SetGray[0] }
ELSE {ColorDisplay.SetGreenMap[0,0]; ColorDisplay.SetBlueMap[0,0]; ColorDisplay.SetRedMap[0,0];};
Rectangle[lx: 0, ty: 0, rx: width, by: height, fn: null, clear: TRUE];
};
Wait: PROCEDURE[millisecs: CARDINAL] = INLINE {
Process.Pause[Process.MsecToTicks[millisecs]] };
Constant definitions (meanings described in InitRandom below)
defaultSeed: CARDINAL = 27183;
numCalls: INTEGER = 3;
Module state
a: ARRAY [0..55] OF CARDINAL;
Holds 55 random cardinals, to be returned by Random. (A[0] is wasted to make the
code generator produce better array accesses.)
p: INTEGER [0..55];
a[1..p-1] has not yet been returned by Random; p is [1..55] except within Random.
Procedures
InitRandom: PUBLIC PROC[seed: INTEGER] RETURNS[INTEGER] = {
The parameter seed determines the sequence generated by procedure Random below.
If seed=0, a default seed value is used to determine the starting point of the
sequence; if seed>0, seed is scaled if necessary and then used; if seed<0, a seed
value is derived from the system clock. In any case, the seed value actually used
(after scaling) is the integer value returned.
minSeed: CARDINAL = LAST[CARDINAL]/10;
g, gPrev, gSave: CARDINAL;
IF seed<=0 THEN seed ← defaultSeed;
Now scale the seed into the proper range (no log routine available...)
WHILE seed<minSeed DO seed ← seed*3 ENDLOOP;
Seed can't be too big since LAST[INTEGER] < LAST[CARDINAL]*(9/10)
The array a is initialized by placing seed in a[55], and scattering the values
(-1)**(i-1) * (F(i) - seed*F(i-1)) MOD maxRand, 0<i<55,
(where F(i) denotes the i-th Fibonacci number) throughout the rest of a. Then
the generating procedure RandomGen is called, numCalls times, to make things
sufficiently random.
a[55] ← gPrev ← seed;
g ← 1;
FOR i: INTEGER IN [1..54] DO
p ← (21*i) MOD 55;
a[p] ← gSave ← g; g ← gPrev-g; gPrev ← gSave;
ENDLOOP;
THROUGH [1..numCalls) DO
RandomGen[];
ENDLOOP;
Show a as being empty; first call to Random will call RandomGen again.
p ← 1;
RETURN[seed]
};--InitRandom
Random: PUBLIC PROC RETURNS[CARDINAL] = INLINE {
p ← p-1;
IF p=0 THEN { RandomGen[]; p ← 55 };
RETURN[a[p]]
};--Random
RandomGen: PROC = INLINE {
Additive random number generator using the recurrence y(n) = y(n-55) - y(n-24)
mod maxRand. See John F. Reiser, "Analysis of Additive Random Number Generators",
STAN-CS-77-601, March 1977, or Knuth Volume 2 (second edition.)
FOR i: INTEGER IN [1..24] DO
a[i] ← a[i] - a[i+31];
ENDLOOP;
FOR i: INTEGER IN [25..55] DO
a[i] ← a[i] - a[i-24];
ENDLOOP;
};--RandomGen
Choose: PUBLIC PROC[min, max: CARDINAL] RETURNS[CARDINAL--[min..max]--] = {
intervalLen: CARDINAL;
IF min > max THEN ERROR;
intervalLen ← max - min + 1; --is 0 when min=0, max=LAST[CARDINAL]
IF intervalLen = 0 THEN RETURN[Random[]];
DO
Draw a number in [0..LAST[CARDINAL]]. We want to reject this number if it lies in the
"odd interval" at the high end of this range (there is no odd interval if intervalLen
divides 2^16). The funny test below does it (claim). The average number of numbers drawn
is less than 2, and much closer to 1 for small intervalLen.
r, rem: CARDINAL;
Inline expansion of Random[];
p ← p-1;
IF p=0 THEN { RandomGen[]; p ← 55 };
r ← a[p];
rem ← r MOD intervalLen;
IF (r - rem) > LOOPHOLE[-LOOPHOLE[intervalLen,INTEGER],CARDINAL] THEN LOOP;
RETURN[min + rem];
ENDLOOP;
};--Choose
SetLogBitsPerPixel: PROC[n: [0..4)] RETURNS[BOOLEAN] = {
b: CARDINAL ← Inline.BITSHIFT[1,n];
mode: ColorDisplay.Mode ← [FALSE,b,1];
IF NOT ColorDisplay.HasMode[mode] THEN {
mode.bitsPerPixelB ← 0;
IF NOT ColorDisplay.HasMode[mode] THEN RETURN[FALSE];
};
IF NOT ColorDisplay.SetMode[mode] THEN ERROR;
lbpp ← n; bpp ← b; full ← FALSE;
lbppB ← 0; bppB ← 1;
SetShowButtons[TRUE, TRUE, FALSE];
width ← ColorDisplay.width; height ← ColorDisplay.height;
bitmap ← ColorDisplay.baseA; wpl ← ColorDisplay.wplA;
bitmapB ← ColorDisplay.baseB; wplB ← ColorDisplay.wplB;
ClearScreen;
SetUpColors;
ColorDisplay.TurnOn[];
RETURN[TRUE];
};
Set24BitsPerPixel: PROC = {
mode: ColorDisplay.Mode ← [TRUE,0,0];
IF NOT ColorDisplay.HasMode[mode] THEN RETURN;
IF NOT ColorDisplay.SetMode[mode] THEN ERROR;
lbpp ← 0; bpp ← 0; full ← TRUE;
bitmap ← NIL; bitmapB ← NIL; wpl ← 0;
SetShowButtons[TRUE, TRUE, FALSE];
width ← ColorDisplay.width; height ← ColorDisplay.height;
ClearScreen[];
ColorDisplay.TurnOn[];
};
Go: PUBLIC PROC [ckViewer: CKViewer] = {
[] ← InitRandom[0];
public ← ckViewer;
SELECT TRUE FROM
SetLogBitsPerPixel[3] => NULL;
SetLogBitsPerPixel[2] => NULL;
ENDCASE => {
MW.Append[message: "NO COLOR DISPLAY !!", clearFirst: TRUE];
MW.Blink[];
RETURN;
};
DO
IF ckViewer.state.quit THEN {
ClearScreen; ViewerOps.DestroyViewer[ckViewer.container];
[]𡤌olorDisplay.SetMode[ColorDisplay.disconnected]; EXIT;
};
IF ckViewer.state.testingPanel THEN LOOP; --turned off by FinalizeTest
IF ckViewer.state.bpp=1 AND bpp#1 THEN { [] ← SetLogBitsPerPixel[0];
SetSplat[] };
IF ckViewer.state.bpp=2 AND bpp#2 THEN { [] ← SetLogBitsPerPixel[1];
SetSplat[] };
IF ckViewer.state.bpp=4 AND bpp#4 THEN { [] ← SetLogBitsPerPixel[2];
SetSplat[] };
IF ckViewer.state.bpp=8 AND bpp#8 THEN { [] ← SetLogBitsPerPixel[3];
SetSplat[] };
IF ckViewer.state.bpp=24 AND NOT full THEN { Set24BitsPerPixel[];
SetSplat[] };
IF ckViewer.state.aToggle THEN {
SetShowButtons[NOT ashow, bshow,FALSE];
ckViewer.state.aToggle ← FALSE};
IF ckViewer.state.bToggle THEN {
SetShowButtons[ashow, NOT bshow,FALSE];
ckViewer.state.bToggle ← FALSE};
IF ckViewer.state.random THEN {
sym ← FALSE; SetSplat[];
ClearScreen[];
ckViewer.state.random ← FALSE};
IF ckViewer.state.symmetric THEN {
sym ← TRUE; SetSplat[];
ClearScreen[];
ckViewer.state.symmetric ← FALSE};
IF NOT ckViewer.state.freeze THEN {
ckViewer.state.roll ← ckViewer.state.scramble ← FALSE; --only TRUE when frozen
SELECT TRUE FROM
ckViewer.state.testPattern => {
splat ← FALSE; ShowTPat[]; ckViewer.state.testPattern ← FALSE;
};
ckViewer.state.cbars => {ShowCBars[]; splat ← ckViewer.state.cbars ← FALSE};
ckViewer.state.converge => {ShowConverge[]; splat ← ckViewer.state.converge ← FALSE};
ckViewer.state.diag => {Diag[]; splat ← ckViewer.state.diag ← FALSE};
ckViewer.state.bigRed => {ShowBigRed[big: TRUE]; splat ← ckViewer.state.bigRed ← FALSE};
ckViewer.state.bigGreen => {ShowBigGreen[big: TRUE]; splat ← ckViewer.state.bigGreen ← FALSE};
ckViewer.state.bigBlue => {ShowBigBlue[big: TRUE]; splat ← ckViewer.state.bigBlue ← FALSE};
ckViewer.state.smallRed => {ShowBigRed[big: FALSE]; splat ← ckViewer.state.smallRed ← FALSE};
ckViewer.state.smallGreen => {ShowBigGreen[big: FALSE]; splat ← ckViewer.state.smallGreen ← FALSE};
ckViewer.state.smallBlue => {ShowBigBlue[big: FALSE]; splat ← ckViewer.state.smallBlue ← FALSE};
ENDCASE => IF splat THEN RandomSplat[ckViewer];
}
ELSE {
SELECT TRUE FROM
ckViewer.state.scramble => NextScramble[];
ckViewer.state.roll => NextRoll[];
ENDCASE => NULL;
};
ENDLOOP;
IF NOT ColorDisplay.SetMode[ColorDisplay.disconnected] THEN ERROR;
};
SetSplat: PROCEDURE [] = {
splat ← TRUE; SetShowButtons[ashow,bshow,FALSE];
CKViewerButtons.SetStaticButtons[public, IF sym THEN public.buttons.symmetricButton ELSE public.buttons.randomButton]
};
SetShowButtons: PROCEDURE [a, b, c: BOOL] = {
ashow𡤊 bshow𡤋 ColorDisplay.Show[a,b,c];
Buttons.SetDisplayStyle[public.buttons.aChanButtton, IF ashow THEN $WhiteOnBlack ELSE $BlackOnWhite];
Buttons.SetDisplayStyle[public.buttons.bChanButton, IF bshow THEN $WhiteOnBlack ELSE $BlackOnWhite];
};
SetUpPanelTest: PUBLIC PROCEDURE [ckViewer: CKViewer] = {
ckViewer.state.testingPanel ← TRUE;
Wait[2000]; --stupid synchronizer so main loop in Go will quit messing with screen
ClearScreen []; --FILL FIFOS WITH Zeroes
ColorDisplay.Show[TRUE,TRUE,TRUE]; --so when ChannelOn glitches nothing bad will happen
Wait[36]; --be sure both a and b actually show
SetShowButtons[ashow,bshow,TRUE]; --restore ashow/bshow
};
public: CKViewer←NIL;
END.