MakeDoAux2Impl.Mesa
Last Edited by: Spreitzer, March 30, 1986 3:10:27 pm PST
Carl Hauser, April 11, 1985 3:43:34 pm PST
DIRECTORY BackStop, BasicTime, Carets, Imager, ImagerFont, ImagerPixelMap, ImagerRaster, Process, Random, Rope, Terminal, ViewerLocks;
MakeDoAux2Impl: CEDAR PROGRAM
IMPORTS BackStop, BasicTime, Carets, Imager, ImagerFont, ImagerPixelMap, ImagerRaster, Process, Random, Terminal, ViewerLocks
=
BEGIN
ROPE: TYPE = Rope.ROPE;
PixelMap: TYPE = ImagerPixelMap.PixelMap;
Context: TYPE = Imager.Context;
rs: Random.RandomStream = Random.Create[seed: -1];
font: ImagerFont.Font ← ImagerFont.Find["Xerox/PressFonts/TimesRoman-MRR"];
Drain: PROC [subject, replaceWith: PixelMap, divS, divF: INTEGER--the drain, in device coordinates--] = {
bounds: ImagerPixelMap.DeviceRectangle ← subject.Window[];
WHILE bounds.sSize > 0 AND bounds.fSize > 0 DO
n: INT = rs.ChooseInt[0, bounds.sSize + bounds.fSize - 1];
IF n < bounds.sSize THEN {
doomedS: NAT = n + bounds.sMin;
IF doomedS < divS THEN {
moveSize: NAT = doomedS - bounds.sMin;
IF moveSize > 0 THEN {
move: PixelMap = subject.Clip[[bounds.sMin, bounds.fMin, moveSize+1, bounds.fSize]];
move.Transfer[move.ShiftMap[1, 0]];
};
subject.Clip[[bounds.sMin, bounds.fMin, 1, bounds.fSize]].Transfer[replaceWith];
bounds.sMin ← bounds.sMin + 1;
}
ELSE {
last: NAT = bounds.sMin + bounds.sSize - 1;
moveSize: NAT = last - doomedS;
IF moveSize > 0 THEN {
move: PixelMap = subject.Clip[[doomedS, bounds.fMin, moveSize+1, bounds.fSize]];
move.ShiftMap[1, 0].Transfer[move];
};
subject.Clip[[last, bounds.fMin, 1, bounds.fSize]].Transfer[replaceWith];
};
bounds.sSize ← bounds.sSize - 1;
}
ELSE {
doomedF: NAT = n - bounds.sSize + bounds.fMin;
IF doomedF < divF THEN {
moveSize: NAT = doomedF - bounds.fMin;
IF moveSize > 0 THEN {
move: PixelMap = subject.Clip[[bounds.sMin, bounds.fMin, bounds.sSize, moveSize+1]];
move.Transfer[move.ShiftMap[0, 1]];
};
subject.Clip[[bounds.sMin, bounds.fMin, bounds.sSize, 1]].Transfer[replaceWith];
bounds.fMin ← bounds.fMin + 1;
}
ELSE {
last: NAT = bounds.fMin + bounds.fSize - 1;
moveSize: NAT = last - doomedF;
IF moveSize > 0 THEN {
move: PixelMap = subject.Clip[[bounds.sMin, doomedF, bounds.sSize, moveSize+1]];
move.ShiftMap[0, 1].Transfer[move];
};
subject.Clip[[bounds.sMin, last, bounds.sSize, 1]].Transfer[replaceWith];
};
bounds.fSize ← bounds.fSize - 1;
};
ENDLOOP;
};
GetCurrentFrameBuffer: PROC RETURNS [pm: PixelMap] = TRUSTED {
fb: Terminal.FrameBuffer = Terminal.Current[].GetBWFrameBuffer[];
pm ← ImagerPixelMap.CreateFrameBuffer[
pointer: fb.base,
words: LONG[fb.wordsPerLine]*fb.height,
lgBitsPerPixel: Lg[fb.bitsPerPixel],
rast: fb.wordsPerLine,
lines: fb.height,
ref: fb];
};
Lg: PROC [n: NAT] RETURNS [lg: [0 .. 4]] = {
lg ← SELECT n FROM
1 => 0,
2 => 1,
4 => 2,
8 => 3,
16 => 4,
ENDCASE => ERROR;
};
AllocSame: PROC [pattern: PixelMap] RETURNS [same: PixelMap] = {
same ← ImagerPixelMap.Create[pattern.refRep.lgBitsPerPixel, pattern.BufferBounds[]].Clip[pattern.Window[]];
};
PMContext: PROC [pm: PixelMap] RETURNS [context: Context] = {
context ← ImagerRaster.Create[ImagerRaster.NewBitmapDevice[pm], TRUE];
};
screen: PixelMap ← GetCurrentFrameBuffer[];
bounds: ImagerPixelMap.DeviceRectangle = screen.BoundedWindow[];
screenCopy: PixelMap ← AllocSame[screen];
mine: PixelMap ← AllocSame[screen];
Setup: PROC = {
myContext: Context = PMContext[mine];
scaledFont: ImagerFont.Font = font.Scale[bounds.sSize/2.2];
ae: ImagerFont.Extents = scaledFont.RopeBoundingBox["April"];
fe: ImagerFont.Extents = scaledFont.RopeBoundingBox["Fool!"];
Imager.SetColor[myContext, Imager.black];
Imager.MaskRectangle[myContext, [0, 0, bounds.fSize, bounds.sSize]];
Imager.SetColor[myContext, Imager.white];
Imager.SetFont[myContext, scaledFont];
Imager.SetXY[myContext, [
x: (bounds.fSize - (fe.rightExtent + fe.leftExtent))/2,
y: (bounds.sSize/2 - (fe.ascent + fe.descent))/2]];
Imager.ShowRope[myContext, "Fool!"];
Imager.TranslateT[myContext, [bounds.fSize, bounds.sSize]];
Imager.ScaleT[myContext, -1];
Imager.SetXY[myContext, [
x: (bounds.fSize - (ae.rightExtent + ae.leftExtent))/2,
y: (bounds.sSize/2 - (ae.ascent + ae.descent))/2]];
Imager.ShowRope[myContext, "April"];
};
GiveMsg: PROC = {
Inner: PROC = {
ReallyInner: PROC = {
screenCopy.Transfer[screen];
Drain[screen, mine, bounds.sMin + bounds.sSize/2, bounds.fMin + bounds.fSize/2];
Drain[screen, screenCopy, bounds.sMin + bounds.sSize/2, bounds.fMin + bounds.fSize/2];
};
errorMessage ← BackStop.Call[ReallyInner];
};
screen ← GetCurrentFrameBuffer[];
Carets.SuspendCarets[];
ViewerLocks.CallUnderViewerTreeLock[Inner];
Carets.ResumeCarets[];
};
errorMessage: ROPENIL;
Messenger: PROC = {
DO
unpacked: BasicTime.Unpacked = BasicTime.Unpack[BasicTime.Now[]];
IF unpacked.month > April OR (unpacked.month = April AND unpacked.day > 1) THEN EXIT;
IF unpacked.month < April THEN {Process.Pause[halfAnHour]; LOOP};
Process.Pause[Process.SecondsToTicks[rs.ChooseInt[minPause, maxPause]]];
GiveMsg[];
ENDLOOP;
};
halfAnHour: Process.Ticks ← Process.SecondsToTicks[1800];
minPause: INTEGER ← 1000;
maxPause: INTEGER ← 2000;
ForkMessenger: PROC = TRUSTED {Process.Detach[FORK Messenger[]]};
Setup[];
ForkMessenger[];
END.