PressScreenImpl.mesa
Program to make AIS/press file of display
Last edited by: Rick Cattell on June 18, 1982 1:58 pm
Last edited by: Warren Teitelman on 6-Apr-82 12:02:06
Last edited by: Michael Plass on February 21, 1984 10:13:20 am PST
Last Edited by: Beach, October 31, 1983 11:46 am
Last Edited by: Wyatt, December 9, 1983 3:09 pm
DIRECTORY
Carets USING [ResumeCarets],
CaretsExtras USING [SuspendVisibleCarets],
CGAIS,
Convert,
FS,
Graphics,
GraphicsOps,
IO,
PressScreen,
Real,
Rope,
SirPress,
Terminal,
ViewerClasses,
ViewerLocks,
ViewerSpecs,
ViewerOps;
PressScreenImpl: CEDAR MONITOR
IMPORTS Carets, CaretsExtras, Convert, FS, Graphics, GraphicsOps, IO, Real, Rope, SirPress, Terminal, ViewerLocks, ViewerOps
EXPORTS PressScreen
SHARES ViewerLocks = {
OPEN PressScreen;
ROPE: TYPE = Rope.ROPE;
extraWords: NAT ← 6; -- Half-screen prints are widened by this much.
PressScreen: PUBLIC PROC[pressFileName: Rope.ROPE, which: Side] = TRUSTED {
Old interface to convert part or all of the bit mapped screen into a press file.
screen: SirPress.PressHandle← SirPress.Create[
fileNameForHeaderPage: pressFileName,
outputStream: FS.StreamOpen[pressFileName, $create]
];
screenBitMap: GraphicsOps.BitmapRef← GraphicsOps.ScreenBitmap[];
widthInWords: INT ← screenBitMap.width/16;
halfWidthInWords: NAT ← widthInWords/2;
screenPtr: LONG POINTER ← Terminal.GetBitBltTable[Terminal.Current[]].dst.word;
define the screen rectangle
IF which=bothSides THEN {
screen.SetPageSize[height: 85, width: 110, unit: SirPress.in/10];
screen.BeginScannedRectangle[
x: 1, y: 1,
numberOfLines: screenBitMap.height,
dotsPerLine: widthInWords*16,
height: 8*4,
unit: SirPress.in/4]
}
ELSE
screen.BeginScannedRectangle[
x: 1, y: 1,
numberOfLines: screenBitMap.height,
dotsPerLine: (halfWidthInWords+extraWords)*16,
unit: SirPress.in/4];
call ShowLine for each line of screen (or half-line, if left side)
FOR i: INT IN [0..screenBitMap.height) DO
offset: LONG CARDINAL ← i*widthInWords;
IF which=rightSide THEN offset ← offset + halfWidthInWords - extraWords;
screen.UnsafeShowLine[screenPtr + offset];
ENDLOOP;
finish the rectangle and close the file
screen.EndScannedRectangle[];
screen.ClosePress[];
};
fileNameTemplate: ROPE ← "Screen#.press";
count is incremented by one and substituted for # in the template
count: INT ← 0;
NewPressName: PUBLIC ENTRY PROCEDURE RETURNS [pressFileName: Rope.ROPE] = {
Returns a file name like "Screen1.press", "Screen2.press", etc.
ENABLE UNWIND => NULL;
i: INT = Rope.Find[s1: fileNameTemplate, s2: "#"];
pressFileName ← IF i = -1 THEN fileNameTemplate
ELSE fileNameTemplate.Replace[start: i, len: 1, with: Convert.RopeFromInt[count ← count + 1]];
};
MagnificationFactorTooLarge: PUBLIC SIGNAL = CODE;
The specified rectangle will not fit on an 8.5 by 11 inch page with the supplied margins and magnifications
AISPageAlignmentHackFailed: PUBLIC SIGNAL = CODE;
An internal error expected when the size of SirPress record definitions change (low probability)
AISPressScreen: PUBLIC PROCEDURE [pressFileName: ROPE,
sourceHeight: NAT ← ViewerSpecs.screenH,
sourceWidth: NAT ← ViewerSpecs.screenW,
sourceBottom: NAT ← 0,
sourceLeft: NAT ← 0,
magnification: REAL ← 0.5,
scaleToFit: MagnificationType ← useMagnification,
leftMarginInches, rightMarginInches: REAL ← 0.75,
landscape: BOOLEANFALSE,
borderWidth: REAL ← 2.0,
lockViewers: BOOLEANTRUE,
displayCursor: BOOLEANFALSE,
displayCarets: BOOLEANFALSE] RETURNS [fileName: ROPE] = TRUSTED {
Converts the specified region of the bit mapped screen into a combination AIS and Press file.
Such files can be used by CedarGraphics or printed by the TSetter.
AISPressScreen can raise two signals: MagnificationFactorTooLarge when the specified rectangle will not fit on an 8.5 by 11 inch page with the supplied margins and magnifications; and AISPageAlignmentHackFailed for an internal error expected when the size of SirPress record definitions change (low probability).
trueName: Rope.ROPEIF pressFileName = NIL THEN NewAISPressName[] ELSE pressFileName;
context: Graphics.Context ← Graphics.NewContext[];
outputStream: IO.STREAM ← FS.StreamOpen[trueName, $create];
bytesSoFar: INT;
screen: SirPress.PressHandle;
screenBitMap: GraphicsOps.BitmapRef ← GraphicsOps.ScreenBitmap[];
screenWidthInWords: NAT ← screenBitMap.width/16;
sourceLeftInWords: NATMIN[sourceLeft/16, screenWidthInWords];
sourceRightInWords: NATMIN[(sourceLeft+sourceWidth+15)/16, screenWidthInWords];
paperHeight: REALIF landscape THEN 8.5*2540 ELSE 11*2540;
paperWidth: REAL ← (11+8.5)*2540 - paperHeight;
pageBorder: REAL ← (leftMarginInches + rightMarginInches)*2540;
x: REAL;
y: REAL;
screenPtr: LONG POINTER ← Terminal.GetBitBltTable[Terminal.Current[]].dst.word;
bytesPerPage: INT = 2048;
wordsOfPressCommands: INT = 8; -- count of Press commands generated before dots so that the AIS image starts on a page boundary
AISHeader: TYPE = RECORD [
header: CGAIS.Header,
rasterPart: CGAIS.RasterPart,
uca: CGAIS.UCA];
aisHeader: AISHeader ← [
header: [
password: CGAIS.password,
attributeLength: 0],
rasterPart: [
aph: [
type: raster,
length: SIZE[CGAIS.RasterPart]],
scanCount: 0,
scanLength: 0,
scanDirection: 3,
samplesPerPixel: 1,
codingType: CGAIS.UCACodingType],
uca: [
bitsPerSample: 0,
wordsPerScanLine: 0,
scanLinesPerBlock: 177777B]];
aisHeaderPtr: LONG POINTER TO AISHeader ← @aisHeader;
aisBlock: IO.UnsafeBlock ← [
base: LOOPHOLE[aisHeaderPtr],
startIndex: 0,
count: 2*SIZE[AISHeader]];
SELECT scaleToFit FROM
fullPage => {
magnification ← MIN[ (paperWidth-pageBorder)/(32.0*16.0*(sourceRightInWords-sourceLeftInWords)),
(paperHeight-pageBorder)/(32.0*sourceHeight)];
};
halfPage => {
magnification ← MIN[ (paperWidth-pageBorder)/(32.0*16.0*(sourceRightInWords-sourceLeftInWords)),
(paperHeight-2*pageBorder)/(2.0*32.0*sourceHeight)];
};
useMagnification => NULL;
ENDCASE;
x ← (paperWidth-32.0*16.0*(sourceRightInWords-sourceLeftInWords)*magnification)/2.0;
y ← (paperHeight-32.0*sourceHeight*magnification)/2.0;
IF x<0 OR y<0 OR x+32.0*16.0*(sourceRightInWords-sourceLeftInWords)*magnification>paperWidth OR y+32.0*sourceHeight*magnification>paperHeight THEN
SIGNAL MagnificationFactorTooLarge;
Create the AIS Header from the screen rectangle information
aisHeader.uca.wordsPerScanLine ← sourceRightInWords-sourceLeftInWords;
aisHeader.rasterPart.scanLength ← aisHeader.uca.wordsPerScanLine*16;
aisHeader.rasterPart.scanCount ← sourceHeight;
IO.UnsafePutBlock[outputStream, aisBlock];
IO.PutChar[outputStream, '\000];
IO.PutChar[outputStream, '\000];
THROUGH [0..bytesPerPage - IO.GetIndex[outputStream] - 2*wordsOfPressCommands) DO
IO.PutChar[outputStream, '$];
ENDLOOP;
define the screen rectangle in the Press file
screen ← SirPress.Create[
fileNameForHeaderPage: trueName,
outputStream: outputStream
];
IF landscape THEN screen.SetPageSize[height: 85, width: 110, unit: SirPress.in/10];
screen.BeginScannedRectangle[
x: Real.RoundLI[x], y: Real.RoundLI[y],
numberOfLines: sourceHeight,
dotsPerLine: (sourceRightInWords-sourceLeftInWords)*16,
height: Real.RoundLI[32.0*sourceHeight*magnification],
unit: SirPress.mica];
Stuff the current position of the Press file into the AIS Header
bytesSoFar ← IO.GetIndex[outputStream];
IF bytesSoFar # bytesPerPage THEN SIGNAL AISPageAlignmentHackFailed;
aisHeader.header.attributeLength ← bytesSoFar/2;
IO.SetIndex[outputStream, 0];
IO.UnsafePutBlock[outputStream, aisBlock];
IO.SetIndex[outputStream, bytesSoFar];
IF displayCarets THEN {
CaretsExtras.SuspendVisibleCarets[];
};
IF lockViewers THEN ViewerLocks.LockViewerTree[];
context.DrawBox[[sourceLeft, sourceBottom, sourceLeft+borderWidth, sourceBottom+sourceHeight]];
context.DrawBox[[sourceLeft+sourceWidth-borderWidth, sourceBottom, sourceLeft+sourceWidth, sourceBottom+sourceHeight]];
context.DrawBox[[sourceLeft, sourceBottom, sourceLeft+sourceWidth, sourceBottom+borderWidth]];
context.DrawBox[[sourceLeft, sourceBottom+sourceHeight-borderWidth, sourceLeft+sourceWidth, sourceBottom+sourceHeight]];
context.SetColor[Graphics.white];
context.DrawBox[[sourceLeft-16, sourceBottom, sourceLeft, sourceBottom+sourceHeight]];
context.DrawBox[[sourceLeft+sourceWidth, sourceBottom, sourceLeft+sourceWidth+16, sourceBottom+sourceHeight]];
IF displayCursor THEN {
vt: Terminal.Virtual ← Terminal.Current[];
cursorArray: Terminal.BWCursorBitmap ← Terminal.GetBWCursorPattern[vt];
position: Terminal.Position ← Terminal.GetMousePosition[vt];
[] ← context.Save[];
[] ← context.SetPaintMode[transparent];
context.SetColor[Graphics.black];
context.SetCP[position.x, vt.bwHeight-position.y];
context.procs.DrawBits[context, @cursorArray, 1, 0, 0, 0, 16, 16, 0, 0];
context.Restore[];
};
call ShowLine for each line of screen (or half-line, if left side)
FOR i: INT IN [0..sourceHeight) DO
offset: LONG CARDINAL ← (i+screenBitMap.height-sourceHeight-sourceBottom)*screenWidthInWords+sourceLeftInWords;
screen.UnsafeShowLine[screenPtr + offset];
ENDLOOP;
IF lockViewers THEN ViewerLocks.ReleaseViewerTree[];
IF displayCursor THEN ViewerOps.PaintEverything will fix cursor up
IF displayCarets THEN {
Carets.ResumeCarets[];
};
finish the rectangle and close the file
screen.EndScannedRectangle[];
screen.ClosePress[];
ViewerOps.PaintEverything[];
RETURN [trueName];
};
aisFileNameTemplate: ROPE = "Screen#.AIS";
NewAISPressName: PUBLIC ENTRY PROCEDURE RETURNS [pressFileName: ROPE] = {
Returns a file name like "Screen1.ais", "Screen2.ais", etc.
ENABLE UNWIND => NULL;
NextName: PROCEDURE RETURNS [ROPE] = {
RETURN [aisFileNameTemplate.Replace[start: i, len: 1, with: Convert.RopeFromInt[count ← count + 1]]];
};
i: INT = Rope.Find[s1: aisFileNameTemplate, s2: "#"];
pressFileName ← IF i = -1 THEN aisFileNameTemplate
ELSE NextName[];
DO
s: FS.OpenFile;
s ← FS.Open[pressFileName ! FS.Error => GO TO ThisNameIsOkay];
FS.Close[s];
pressFileName ← NextName[];
ENDLOOP;
EXITS
ThisNameIsOkay => NULL;
};
}.
6-Apr-82 12:01:31 Teitelman fixed PressScreenButton to clear message window first.
May 4, 1982 4:39 pm Cattell: print msg saying whether half or full screen. Also, no longer need config 'cause SirPressPackage is external.
June 18, 1982 1:58 pm Cattell: convert to 3.2; leave a little left margin to avoid printer truncation.
November 15, 1982 12:30 pm Plass: Made client-callable interface.
November 15, 1982 2:30 pm Plass: Made rightSide work, removed button interface, made half-screen resolution match what Spruce can sometimes handle.
November 16, 1982 10:57 am Plass: Tracked SirPress changes.
February 21, 1984 10:12:39 am PST Plass: Fixed AIS header to make a proper AIS file.