-- Pupwatch: non-scrolling display -- [Indigo]<Grapevine>PupWatch>FunnyDisplay.mesa -- Andrew Birrell 20-Nov-81 15:30:15 DIRECTORY AltoDisplay, Ascii USING[ CR, SP ], BitBltDefs, FrameDefs USING[ GlobalFrame, IsBound, SwapInCode ], ImageDefs USING[ AddCleanupProcedure, CleanupItem, CleanupMask, CleanupProcedure ], LookerDefs USING[ PupwatchFont ], MiscDefs USING[ DestroyFakeModule ], SegmentDefs USING[ FileSegmentHandle, SegmentAddress, SwapIn ], SystemDefs; FunnyDisplay: MONITOR IMPORTS BitBltDefs, FrameDefs, ImageDefs, LookerDefs, MiscDefs, SegmentDefs, SystemDefs EXPORTS LookerDefs = BEGIN -- Layout of an "AL" font -- Font: TYPE = MACHINE DEPENDENT RECORD [ maxHeight: CARDINAL, -- height of tallest char in font (scan lines) variableWidth: BOOLEAN, -- IF TRUE, proportionally spaced font blank: [0..177B], -- not used maxWidth: [0..377B], -- width of widest char in font (raster units). FCDptrs: FontArray, -- array of self-relative pointers to -- FCD's. Indexed by char value. extFCDptrs: FontArray -- array of self-relative pointers to -- FCD's for extentions. As large an -- array as needed. ]; FontArray: TYPE = ARRAY CHARACTER OF CARDINAL; FCDptr: TYPE = POINTER TO FCD; FCD: TYPE = MACHINE DEPENDENT RECORD [ widthORext: [0..77777B], -- width or extention index hasNoExtension: BOOLEAN, -- TRUE=> no ext.;prevfield=width height: [0..377B], -- # scan lines to skip for char displacement: [0..377B] -- displacement back to char bitmap ]; GetFont: PROC RETURNS[POINTER TO Font] = BEGIN IF FrameDefs.IsBound[MiscDefs.DestroyFakeModule] THEN BEGIN seg: SegmentDefs.FileSegmentHandle; offset: CARDINAL; [seg,offset] ← MiscDefs.DestroyFakeModule[LOOPHOLE[LookerDefs.PupwatchFont]]; SegmentDefs.SwapIn[seg]; RETURN[SegmentDefs.SegmentAddress[seg]+offset] END ELSE BEGIN -- running in boot file? -- FrameDefs.SwapInCode[LOOPHOLE[LookerDefs.PupwatchFont]]; RETURN[ -- assume it came into the MDS! -- FrameDefs.GlobalFrame[LookerDefs.PupwatchFont].code.shortbase] END END; myFont: POINTER TO Font = GetFont[]; fontdesc: POINTER TO FontArray = @myFont.FCDptrs; -- Cursor and mouse -- CursorData: TYPE = ARRAY [0..16) OF WORD; cursor: POINTER TO CursorData = LOOPHOLE[431B]; mouseX: POINTER TO CARDINAL = LOOPHOLE[424B]; mouseY: POINTER TO CARDINAL = LOOPHOLE[425B]; cursorX: POINTER TO CARDINAL = LOOPHOLE[426B]; cursorY: POINTER TO CARDINAL = LOOPHOLE[427B]; -- Screen layout -- top: CARDINAL = 32; --unused screen at top-- bottom: CARDINAL = 32; --unused screen at bottom-- margin: CARDINAL = 4; --bitmap-relative margin, sides and bottom-- wPerLine: CARDINAL = 2*( 11 ); bPerLine: CARDINAL = wPerLine * 16; scanLines: CARDINAL = (AltoDisplay.MaxScanLines-top-bottom)/2*2; lineHeight: CARDINAL = myFont.maxHeight; nLines: CARDINAL = (scanLines-2*margin)/lineHeight; topY: CARDINAL = 1+lineHeight+margin; -- top of typescript -- bitmapWords: CARDINAL = wPerLine * scanLines; myBitmap: POINTER = EvenAlloc[bitmapWords]; myDCB: AltoDisplay.DCBHandle = EvenAlloc[SIZE[AltoDisplay.DCB]]; padDCB: AltoDisplay.DCBHandle = EvenAlloc[SIZE[AltoDisplay.DCB]]; whiteBBT: BitBltDefs.BBptr = EvenAlloc[SIZE[BitBltDefs.BBTable]]; blackBBT: BitBltDefs.BBptr = EvenAlloc[SIZE[BitBltDefs.BBTable]]; PaintRectangle: PROC[x,y: CARDINAL, w,h: CARDINAL, color: {white, black, invert}] = BEGIN bbt: POINTER TO BitBltDefs.BBTable = IF color = white THEN whiteBBT ELSE blackBBT; bbt.dlx ← x; bbt.dty ← y; bbt.dw ← w; bbt.dh ← h; bbt.function ← IF color = invert THEN invert ELSE replace; BitBltDefs.BITBLT[ bbt ]; END; -- Access to Font: character painting and width -- bbtSpace: BitBltDefs.BBTableSpace; InitBBTSpace: PROC RETURNS[bbt:BitBltDefs.BBptr] = BEGIN bbt ← BitBltDefs.AlignedBBTable[@bbtSpace]; bbt↑ ← [sourcetype: block, function: paint, dbca: myBitmap, dbmr: wPerLine, sbmr: 1, slx: 0, sty: 0]; END; bbt: BitBltDefs.BBptr = InitBBTSpace[]; -- BBT for character painting -- bmState: RECORD[x, y: CARDINAL] ← [x: 0, y: 0 ]; -- pos for next char -- PaintChar: PROCEDURE[char: CHARACTER] = INLINE BEGIN -- extensions are not supported! cw: FCDptr = LOOPHOLE[@fontdesc[char]+fontdesc[char]]; bbt.sbca ← cw - (bbt.dh ← cw.displacement); bbt.dty ← bmState.y + cw.height; bmState.x ← (bbt.dlx ← bmState.x) + (bbt.dw ← cw.widthORext); BitBltDefs.BITBLT[bbt]; END; CharWidth: PROCEDURE[char: CHARACTER] RETURNS[CARDINAL] = BEGIN -- extensions are not supported! cw: FCDptr = LOOPHOLE[@fontdesc[char]+fontdesc[char]]; RETURN[cw.widthORext] END; EvenAlloc: PROC[words: CARDINAL] RETURNS[res: POINTER] = BEGIN mem: POINTER = SystemDefs.AllocateHeapNode[words+1]; res ← LOOPHOLE[ ((LOOPHOLE[mem,CARDINAL]+1)/2)*2, POINTER ]; END; charWidth: ARRAY CHARACTER OF CARDINAL; GetLength: PUBLIC PROC[s: STRING] RETURNS[ length: CARDINAL ] = BEGIN length ← 0; FOR index: CARDINAL IN [0..s.length) DO length ← length + charWidth[s[index]] ENDLOOP; END; SetPos: PUBLIC ENTRY PROC[pos: CARDINAL] = -- set to raster position relative to start of current line -- { bmState.x ← margin + pos }; Clear: PUBLIC ENTRY PROC = -- Whiten text area of display, and reset next character position -- BEGIN bmState.x ← margin; bmState.y ← topY; PaintRectangle[x: 1, y: lineHeight+2, w: bPerLine-2, h: scanLines - (lineHeight+2) - 1, color: white]; END; -- Publictext displaying procedures -- WriteChar: PUBLIC PROC[c: CHARACTER] = BEGIN IF c < Ascii.SP THEN BEGIN IF c = Ascii.CR THEN BEGIN bmState.x ← margin; bmState.y ← bmState.y + lineHeight; IF bmState.y >= nLines * lineHeight THEN bmState.y ← topY; BEGIN nextY: CARDINAL ← bmState.y + lineHeight; IF nextY >= nLines * lineHeight THEN nextY ← topY; PaintRectangle[x: margin, y: nextY, w: bPerLine-2*margin, h: lineHeight, color: white]; END; RETURN END ELSE c ← '?; END; IF bmState.x + charWidth[c] <= bPerLine-margin THEN PaintChar[c] ELSE bmState.x ← bPerLine-margin; END; WriteMultiple: PUBLIC PROC[desc: DESCRIPTOR FOR PACKED ARRAY OF CHARACTER]= BEGIN FOR i: CARDINAL IN [0..LENGTH[desc]) DO c: CHARACTER ← desc[i]; IF c < Ascii.SP THEN c ← '?; -- including CR -- IF bmState.x + charWidth[c] <= bPerLine-margin THEN PaintChar[c] ELSE { bmState.x ← bPerLine-margin; EXIT }; ENDLOOP; END; EraseChar: PUBLIC ENTRY PROC[c: CHARACTER] = BEGIN IF c < Ascii.SP THEN BEGIN IF c = Ascii.CR THEN RETURN ELSE c ← '?; END; bmState.x ← bmState.x - charWidth[c]; PaintRectangle[x: bmState.x, y: bmState.y, w: charWidth[c], h: lineHeight, color: white]; END; WriteTitle: PUBLIC PROC[s: STRING] = BEGIN oldY: CARDINAL = bmState.y; oldX: CARDINAL = bmState.x; bmState.y ← 1; bmState.x ← margin; PaintRectangle[x:margin, y: 1, w: bPerLine-2*margin, h: lineHeight, color: white]; FOR index: CARDINAL IN [0..s.length) DO WriteChar[s[index]]; ENDLOOP; PaintRectangle[x:margin, y: 1, w: bPerLine-2*margin, h: lineHeight, color: invert]; bmState.y ← oldY; bmState.x ← oldX; END; -- Cleanup mechanism -- cleanupDisplay: ImageDefs.CleanupItem ← [link:, proc: Cleanup, mask: ImageDefs.CleanupMask[Finish] + ImageDefs.CleanupMask[Abort] + ImageDefs.CleanupMask[Save] + ImageDefs.CleanupMask[Restore] + ImageDefs.CleanupMask[Checkpoint] + ImageDefs.CleanupMask[Restart] + ImageDefs.CleanupMask[Continue] + ImageDefs.CleanupMask[InLd] + ImageDefs.CleanupMask[OutLd] ]; Cleanup: ImageDefs.CleanupProcedure = BEGIN SELECT why FROM Finish, Abort, Save, Checkpoint, OutLd => BEGIN realTime: POINTER TO CARDINAL = LOOPHOLE[430B]; delayStart: CARDINAL = realTime↑; AltoDisplay.DCBchainHead↑ ← NIL; UNTIL realTime↑ - delayStart > 2 DO NULL ENDLOOP; END; Restore, Restart, Continue, InLd => AltoDisplay.DCBchainHead↑ ← padDCB; ENDCASE; END; -- Initialisation -- cursor↑ ← [ 0, 400B, 4440B, 44444B, 23710B, 17361B, 130032B, 61614B, 143706B, 143706B, 61614B, 30030B, 17360B, 3700B, 0, 0 ]; mouseX↑ ← cursorX↑ ← 16--indent-- + bPerLine/2 - 8; mouseY↑ ← cursorY↑ ← top - 16; padDCB↑ ← [next: myDCB, resolution: high, background: white, indenting: 0, width: 0, bitmap: NIL, height: top/2]; myDCB↑ ← [next: NIL, resolution: high, background: white, indenting: 1, width: wPerLine, bitmap: myBitmap, height: scanLines/2]; whiteBBT↑ ← [ pad: 0, sourcealt: FALSE, destalt: FALSE, sourcetype: gray, function: , unused: 0, dbca: myBitmap, dbmr: wPerLine, dlx:, dty:, dw:, dh:, sbca:, sbmr:, slx:, sty:, gray0: 0, gray1: 0, gray2: 0, gray3: 0 ]; blackBBT↑ ← [ pad: 0, sourcealt: FALSE, destalt: FALSE, sourcetype: gray, function: , unused: 0, dbca: myBitmap, dbmr: wPerLine, dlx:, dty:, dw:, dh:, sbca:, sbmr:, slx:, sty:, gray0: 177777B, gray1: 177777B, gray2: 177777B, gray3: 177777B ]; -- Paint black border -- PaintRectangle[x: 0, y: 0, w: bPerLine, h: scanLines, color: black]; -- Initialise text area -- Clear[]; FOR c: CHARACTER IN CHARACTER DO charWidth[c] ← CharWidth[c]; ENDLOOP; -- Turn on screen -- IF FrameDefs.IsBound[ImageDefs.AddCleanupProcedure] THEN ImageDefs.AddCleanupProcedure[@cleanupDisplay]; AltoDisplay.DCBchainHead↑ ← padDCB; END.