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 November 16, 1982 10:58 am
Last Edited by: Beach, October 25, 1983 12:51 pm
DIRECTORY
Buttons,
Carets,
CaretsImpl,
ChoiceButtons,
CGAIS,
Commander,
Containers,
Convert,
FileIO,
Graphics,
GraphicsOps,
IO,
Labels,
LFUtil,
Menus,
PieViewers,
PressScreen,
Process,
Real,
Rope,
Rules,
SirPress,
TSViewerImpl,
UserTerminal,
ViewerClasses,
ViewerLocks,
ViewerOps,
ViewerSpecs,
ViewerTools;
PressScreenImpl: CEDAR MONITOR
IMPORTS Buttons, Carets, CaretsImpl, ChoiceButtons, Commander, Containers, Convert, FileIO, Graphics, GraphicsOps, IO, Labels, LFUtil, Menus, PieViewers, Process, Real, Rope, Rules, SirPress, UserTerminal, ViewerSpecs, ViewerLocks, ViewerOps, ViewerTools
EXPORTS PressScreen
SHARES CaretsImpl, TSViewerImpl, 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: FileIO.Open[pressFileName, overwrite]
];
screenBitMap: GraphicsOps.BitmapRef← GraphicsOps.ScreenBitmap[];
widthInWords: INT ← screenBitMap.width/16;
halfWidthInWords: NAT ← widthInWords/2;
screenPtr: LONG POINTER ← UserTerminal.GetBitBltTable[].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.ValueToRope[[signed[(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 ← FileIO.Open[trueName, overwrite];
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 ← UserTerminal.GetBitBltTable[].dst.word;
bytesPerPage: INT = 512;
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]];
aisBlock: IO.UnsafeBlock ← [
base: @aisHeader,
startIndex: 0,
stopIndexPlusOne: 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;
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]];
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];
THROUGH [0..bytesPerPage - 2*(SIZE[AISHeader]+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 {
Carets.SuspendCarets[];
IF Carets.pCaretViewer # NIL THEN InvertCaret[context, primary];
IF Carets.sCaretViewer # NIL THEN InvertCaret[context, secondary];
};
IF displayCursor THEN {
cursorArray: UserTerminal.CursorArray ← UserTerminal.GetCursorPattern[];
[] ← context.Save[];
[] ← context.SetPaintMode[transparent];
context.SetColor[Graphics.black];
context.SetCP[UserTerminal.cursor.x, ViewerSpecs.screenH-UserTerminal.cursor.y];
context.procs.DrawBits[context, @cursorArray, 1, 0, 0, 0, 16, 16, 0, 0];
context.Restore[];
};
IF lockViewers THEN ViewerLocks.LockViewerTree[];
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 {
IF Carets.pCaretViewer # NIL THEN InvertCaret[context, primary];
IF Carets.sCaretViewer # NIL THEN InvertCaret[context, secondary];
Carets.ResumeCarets[];
};
finish the rectangle and close the file
screen.EndScannedRectangle[];
screen.ClosePress[];
ViewerOps.PaintEverything[];
RETURN [trueName];
};
aisFileNameTemplate: ROPE = "Screen#.AIS";
InvertCaret: PROC [context: Graphics.Context, id: Carets.CaretId, kill: BOOLFALSE] = TRUSTED BEGIN
OPEN CaretsImpl;
IF id=primary THEN BEGIN
IF (~kill OR pDark) AND pCaretViewer#NIL THEN BEGIN
IF pCaretViewer.column=color THEN RETURN;
[] ← context.Save[];
[] ← context.SetPaintMode[invert];
context.SetColor[Graphics.black];
context.SetCP[pCaretX-caretXOffset, pCaretY];
GraphicsOps.DrawBitmap[context, pCaret, caretW, caretH];
context.Restore[];
pDark ← ~pDark;
END;
IF kill THEN pCaretViewer ← NIL;
END
ELSE BEGIN
IF (~kill OR sDark) AND sCaretViewer#NIL THEN BEGIN
IF sCaretViewer.column=color THEN RETURN;
[] ← context.Save[];
[] ← context.SetPaintMode[invert];
context.SetColor[Graphics.black];
context.SetCP[sCaretX-caretXOffset, sCaretY];
GraphicsOps.DrawBitmap[context, sCaret, caretW, caretH];
context.Restore[];
sDark ← ~sDark;
END;
IF kill THEN sCaretViewer ← NIL;
END;
END;
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.ValueToRope[[signed[(count ← count + 1)]]]]];
};
i: INT = Rope.Find[s1: aisFileNameTemplate, s2: "#"];
s: IO.STREAM;
pressFileName ← IF i = -1 THEN aisFileNameTemplate
ELSE NextName[];
WHILE (s ← FileIO.Open[pressFileName !
FileIO.OpenFailed => GO TO ThisNameIsOkay]) # NIL DO
s.Close[];
pressFileName ← NextName[];
ENDLOOP;
EXITS
ThisNameIsOkay => NULL;
};
PressScreenTool: PUBLIC TYPE = REF PressScreenToolRec;
PressScreenToolRec: PUBLIC TYPE = RECORD[
screenAreaChoice: ChoiceButtons.EnumTypeRef,
magnificationChoice: ChoiceButtons.EnumTypeRef,
magnificationViewer: ViewerClasses.Viewer, -- magnification factor
ulx, uly, lrx, lry: ViewerClasses.Viewer, -- upper left, lower right coordinates
formatViewer: ChoiceButtons.EnumTypeRef,
borderViewer: ViewerClasses.Viewer, -- border width
pageMarginViewer: ViewerClasses.Viewer,
countDownTimerViewer: ViewerClasses.Viewer,
countDownPieViewer: PieViewers.PieViewer,
lockViewersTriState: ChoiceButtons.ThreeStateRef,
displayCursorTriState: ChoiceButtons.ThreeStateRef,
displayCaretsTriState: ChoiceButtons.ThreeStateRef,
logViewer: ViewerClasses.Viewer,
logMessage: ROPE
];
ScreenArea: TYPE = {leftColumn, rightColumn, wholeScreen, desiredArea};
indent: INTEGER ~ TSViewerImpl.indent;
baseline: INTEGER ~ TSViewerImpl.baseline;
NewPressScreenTool: PUBLIC PROCEDURE [serverName: ROPE] RETURNS[psTool: PressScreenTool] = {
Creates a PressScreen tool viewer.
ENABLE UNWIND => NULL;
viewer: ViewerClasses.Viewer ←
ViewerOps.CreateViewer[
flavor: $PressScreen,
info: [
name: IF serverName.Length = 0 THEN "PressScreen" ELSE Rope.Concat["PressScreen to ", serverName],
column: right,
scrollable: FALSE
],
paint: TRUE
];
psTool ← NARROW[ViewerOps.FetchProp[viewer, $PressScreenData]];
};
InitPressScreenViewer: ViewerClasses.InitProc = {
The only way this proc is called is to init a new $PressScreen viewer.
There is no reset menu entry posted.
psTool: PressScreenTool ← NEW[PressScreenToolRec];
nextX: INTEGER;
curY: INTEGER ← indent/2;
NextY: PROCEDURE RETURNS [y:NAT] = {y ← curY ← curY+baseline};
button: ViewerClasses.Viewer;
menu: Menus.Menu ← Menus.CreateMenu[];
InsertMenu: PROCEDURE [name: ROPE, proc: Menus.ClickProc, doc: ROPE] = {
Menus.InsertMenuEntry[menu, Menus.CreateEntry[
name: name,
proc: proc,
clientData: psTool,
documentation: doc
]];
};
LabelledTextViewer: PROCEDURE [name: ROPE] RETURNS [v: ViewerClasses.Viewer] = {
v ← ViewerTools.MakeNewTextViewer[
info:[wx: button.wx+button.ww, wy: curY, ww: 50, wh: button.wh,
parent: self, scrollable: FALSE, border: TRUE],
paint: TRUE
];
button ← Labels.Create[
info: [name: name, wx: v.wx + v.ww, wy: curY+1, wh: button.wh, parent: self, scrollable: FALSE, border: FALSE],
paint: TRUE
];
};
MyButton: PROCEDURE [name: ROPE, proc: Buttons.ButtonProc, doc: ROPE] RETURNS [Buttons.Button] = {
RETURN [Buttons.Create[
info: [name: name, wx: indent, wy: NextY[], parent: self, border: FALSE],
clientData: psTool,
proc: proc,
fork: TRUE,
paint: TRUE,
documentation: doc
]]};
triggerName: ROPE ← Atom.GetPName[Atom.Gensym['P]];
ViewerOps.AddProp[self, $PressScreenData, psTool];
containerInitProc[self]; -- since I know its really a $Container, I need to init it for him
self.name ← self.name.Cat[" ", triggerName];
[] ← Buttons.Create[info: [name: triggerName], proc: DoItButton, clientData: psTool, documentation: "Convert the identified area of the screen image into an AIS/Press file"];
Create the PressScreen menu
InsertMenu["GetSelectedViewer", GetSelectedViewerButton,
"Gets the corners of the selected viewer for PressScreening."];
InsertMenu["FlashImage", FlashImageButton,
"Flashes the identified area of the screen image."];
InsertMenu["SetCorners", SetCornersButton,
"Permits designation of a rectangular screen area"];
InsertMenu["DoIt", DoItButton,
"Convert the identified area of the screen image into an AIS/Press file"];
ViewerOps.SetMenu[self, menu];
Screen Area: DesiredArea WholeScreen LeftColumn RightColumn
psTool.screenAreaChoice ← ChoiceButtons.BuildEnumTypeSelection[
viewer: self,
x: indent,
y: curY,
title: "Screen Area:",
buttonNames: CONS["DesiredArea", CONS["WholeScreen", CONS["LeftColumn", CONS["RightColumn", NIL]]]],
default: "WholeScreen",
style: menuSelection];
Area Corners: #### x #### y #### x #### y
button ← MyButton["Area Corners: ", AreaCornersButton, "Set the corners of the identified area of the screen"];
psTool.ulx ← LabelledTextViewer["x "];
psTool.uly ← LabelledTextViewer["y "];
psTool.lrx ← LabelledTextViewer["x "];
psTool.lry ← LabelledTextViewer["y"];
Magnification: FullPage HalfPage UseFactorBelow
psTool.magnificationChoice ← ChoiceButtons.BuildEnumTypeSelection[
viewer: self,
x: indent,
y: NextY[],
title: "Magnification:",
buttonNames: CONS["FullPage", CONS["HalfPage", CONS["UseFactorBelow", NIL]]],
default: "FullPage",
style: menuSelection];
MagnificationFactor: xxxx %
button ← MyButton["MagnificationFactor: ", MagnificationFactorButton, "Set the magnification factor"];
psTool.magnificationViewer ← LabelledTextViewer["%"];
Page Format: Landscape Portrait
psTool.formatViewer ← ChoiceButtons.BuildEnumTypeSelection[
viewer: self,
x: indent,
y: NextY[],
title: "Page Format:",
buttonNames: CONS["Portrait", CONS["Landscape", NIL]],
default: "Portrait",
style: menuSelection];
BlackBorder: xxxx pixels
button ← MyButton["BlackBorder: ", BlackBorderButton, "Set the black border width surrounding the identified image area."];
psTool.borderViewer ← LabelledTextViewer["pixels"];
PageMargin: xxxx inches
button ← MyButton["PageMargin: ", PageMarginButton, "Set the white space provided around the page"];
psTool.pageMarginViewer ← LabelledTextViewer["inches"];
CountDownTimer: xxxx seconds
button ← MyButton["CountDownTimer: ", CountDownTimerButton, "Set the time before the screen is copied"];
psTool.countDownTimerViewer ← LabelledTextViewer["seconds "];
psTool.countDownPieViewer ← PieViewers.Create[parent: self, x: button.wx+button.ww, y: curY];
Viewer Controls: LockViewers DisplayCursor DisplayCarets
button ← Labels.Create[
info: [name: "Viewer Controls: ", wx: indent, wy: NextY[]+1, wh: button.wh, parent: self, scrollable: FALSE, border: FALSE],
paint: TRUE
];
[psTool.lockViewersTriState, nextX] ← ChoiceButtons.BuildTriStateButton[
viewer: self,
x: button.wx+button.ww,
y: curY,
name: "LockViewers"];
[psTool.displayCursorTriState, nextX] ← ChoiceButtons.BuildTriStateButton[
viewer: self,
x: nextX,
y: curY,
name: "DisplayCursor"];
[psTool.displayCaretsTriState, nextX] ← ChoiceButtons.BuildTriStateButton[
viewer: self,
x: nextX,
y: curY,
name: "DisplayCarets"];
Rule between buttons and log viewer
Containers.ChildXBound[self, Rules.Create[info: [wx: 0, wy: NextY[], wh: 1, parent: self]]];
Create log viewer for file completion messages
psTool.logViewer ← ViewerTools.MakeNewTextViewer[
info: [wx: 0, wy: curY+2, parent: self, scrollable: TRUE, border: FALSE]
];
Containers.ChildXBound[self, psTool.logViewer];
Containers.ChildYBound[self, psTool.logViewer];
AppendLogMessage[psTool, "To set the area corners: left-click SetCorners and cursor changes to cross-hair; left-click-and-hold to set first corner; drag mouse to second corner and release the mouse button."];
AppendLogMessage[psTool, "To use GetSelectedViewer: make a point selection within a viewer or make the selection the name of a viewer and left-click GetSelectedViewer."];
[] ← psTool.logViewer.class.scroll[psTool.logViewer, thumb, 0];
Display default settings
ChoiceButtons.UpdateChoiceButtons[self, psTool.screenAreaChoice, "WholeScreen"];
ChoiceButtons.UpdateChoiceButtons[self, psTool.magnificationChoice, "FullPage"];
ViewerTools.SetContents[psTool.magnificationViewer, IO.PutFR["%g", IO.real[100.0]]];
ViewerTools.SetContents[psTool.ulx, IO.PutFR["%g", IO.int[0]]];
ViewerTools.SetContents[psTool.uly, IO.PutFR["%g", IO.int[807]]];
ViewerTools.SetContents[psTool.lrx, IO.PutFR["%g", IO.int[1023]]];
ViewerTools.SetContents[psTool.lry, IO.PutFR["%g", IO.int[0]]];
ChoiceButtons.UpdateChoiceButtons[self, psTool.formatViewer, "Portrait"];
ViewerTools.SetContents[psTool.borderViewer, IO.PutFR["%g", IO.int[2]]];
ViewerTools.SetContents[psTool.pageMarginViewer, IO.PutFR["%g", IO.real[0.75]]];
ViewerTools.SetContents[psTool.countDownTimerViewer, IO.PutFR["%g", IO.int[0]]];
PieViewers.Set[psTool.countDownPieViewer, 100.0];
ViewerOps.PaintViewer[self, all];
};
GetSelectedViewerButton: Buttons.ButtonProc = {
psTool: PressScreenTool ← NARROW[clientData];
selectedViewer: ViewerClasses.Viewer ← ViewerTools.GetSelectedViewer[];
sourceName: ROPE
IF selectedViewer = NIL OR selectedViewer.class.get = NIL THEN NIL
ELSE NARROW[selectedViewer.class.get[selectedViewer, $SelChars]];
IF sourceName.Length <= 1 THEN {
IF (selectedViewer = NIL) THEN {
AppendLogMessage[psTool, "Selection not in text viewer"];
RETURN;
}
ELSE {
WHILE sourceName.Length <= 1 AND selectedViewer # NIL DO
sourceName ← selectedViewer.name;
selectedViewer ← selectedViewer.parent;
ENDLOOP;
};
};
IF sourceName.Length > 1 THEN {
selectedViewer ← ViewerOps.FindViewer[sourceName];
IF selectedViewer = NIL THEN
AppendLogMessage[psTool, Rope.Cat["Viewer \"", sourceName, "\" wasn't found."]]
ELSE {
ViewerTools.SetContents[psTool.ulx, IO.PutFR["%g", IO.int[selectedViewer.wx]]];
ViewerTools.SetContents[psTool.uly, IO.PutFR["%g", IO.int[selectedViewer.wy+selectedViewer.wh]]];
ViewerTools.SetContents[psTool.lrx, IO.PutFR["%g", IO.int[selectedViewer.wx+selectedViewer.ww]]];
ViewerTools.SetContents[psTool.lry, IO.PutFR["%g", IO.int[selectedViewer.wy]]];
ChoiceButtons.UpdateChoiceButtons[NARROW[parent], psTool.screenAreaChoice, "DesiredArea"];
FlashScreenArea[psTool];
};
};
};
FlashImageButton: Buttons.ButtonProc = {
psTool: PressScreenTool ← NARROW[clientData];
FlashScreenArea[psTool];
};
flashTime: Process.Milliseconds ~ 600;
FlashScreenArea: PROCEDURE [psTool: PressScreenTool] = {
ulx, uly, lrx, lry: REAL;
context: Graphics.Context ← Graphics.NewContext[];
[] ← context.SetPaintMode[invert];
[ulx, uly, lrx, lry] ← ReadScreenCorners[psTool];
context.DrawBox[[lrx, lry, ulx, uly]];
Process.Pause[Process.MsecToTicks[flashTime]];
context.DrawBox[[lrx, lry, ulx, uly]];
};
SetCornersButton: Buttons.ButtonProc = {
psTool: PressScreenTool ← NARROW[clientData];
sMin, fMin: INTEGER;
sSize, fSize: NAT;
[sMin, fMin, sSize, fSize] ← LFUtil.GetArea[ ! LFUtil.AbortAdjust => GOTO DoNothing];
ViewerTools.SetContents[psTool.ulx, IO.PutFR["%g", IO.int[fMin]]];
ViewerTools.SetContents[psTool.uly, IO.PutFR["%g", IO.int[sMin+sSize-1]]];
ViewerTools.SetContents[psTool.lrx, IO.PutFR["%g", IO.int[fMin+fSize-1]]];
ViewerTools.SetContents[psTool.lry, IO.PutFR["%g", IO.int[sMin]]];
ChoiceButtons.UpdateChoiceButtons[NARROW[parent], psTool.screenAreaChoice, "DesiredArea"];
FlashScreenArea[psTool];
EXITS
DoNothing => NULL;
};
DoItButton: Buttons.ButtonProc = {
psTool: PressScreenTool ← NARROW[clientData];
screenAreaChoice: ROPE ← ChoiceButtons.GetSelectedButton[psTool.screenAreaChoice];
magnificationRope: ROPE ← ChoiceButtons.GetSelectedButton[psTool.magnificationChoice];
pageMargin: REAL ← ConvertRopeToReal[ViewerTools.GetContents[psTool.pageMarginViewer]];
countDownTimer: Process.Ticks ← Process.SecondsToTicks[MIN[100000, MAX[0, Real.FixC[ConvertRopeToReal[ViewerTools.GetContents[psTool.countDownTimerViewer]]]]]];
sourceHeight, sourceWidth, sourceBottom, sourceLeft: NAT ← 0;
fileName: ROPE;
SELECT TRUE FROM
screenAreaChoice.Equal["LeftColumn"] => {
sourceHeight ← ViewerSpecs.screenH;
sourceWidth ← ViewerSpecs.openLeftWidth;
sourceBottom ← 0;
sourceLeft ← ViewerSpecs.openLeftLeftX;
};
screenAreaChoice.Equal["RightColumn"] => {
sourceHeight ← ViewerSpecs.screenH;
sourceWidth ← ViewerSpecs.openRightWidth;
sourceBottom ← 0;
sourceLeft ← ViewerSpecs.openRightLeftX;
};
screenAreaChoice.Equal["WholeScreen"] => {
sourceHeight ← ViewerSpecs.screenH;
sourceWidth ← ViewerSpecs.screenW;
sourceBottom ← 0;
sourceLeft ← 0;
};
screenAreaChoice.Equal["DesiredArea"] => {
ulx, uly, lrx, lry: REAL;
[ulx, uly, lrx, lry] ← ReadScreenCorners[psTool];
sourceHeight ← Real.Fix[uly - lry + 1];
sourceWidth ← Real.Fix[lrx - ulx + 1];
sourceBottom ← Real.Fix[lry];
sourceLeft ← Real.Fix[ulx];
};
ENDCASE => {
sourceHeight ← ViewerSpecs.screenH;
sourceWidth ← ViewerSpecs.screenW;
sourceBottom ← 0;
sourceLeft ← 0;
};
IF countDownTimer > 0 THEN {
FOR i: CARDINAL IN [1..25] DO
Process.Pause[countDownTimer/25];
PieViewers.Set[psTool.countDownPieViewer, 100.0-4*i];
ENDLOOP;
};
fileName ← AISPressScreen[
pressFileName: NewAISPressName[],
sourceHeight: sourceHeight,
sourceWidth: sourceWidth,
sourceBottom: sourceBottom,
sourceLeft: sourceLeft,
magnification: ConvertRopeToReal[ViewerTools.GetContents[psTool.magnificationViewer]]/100.0,
scaleToFit: SELECT TRUE FROM
magnificationRope.Equal["UseFactor"] => useMagnification,
magnificationRope.Equal["HalfPage"] => halfPage,
magnificationRope.Equal["FullPage"] => fullPage,
ENDCASE => halfPage,
leftMarginInches: pageMargin,
rightMarginInches: pageMargin,
landscape: SELECT ChoiceButtons.GetSelectedButton[psTool.formatViewer] FROM
"Landscape" => TRUE,
ENDCASE => FALSE,
borderWidth: ConvertRopeToReal[ViewerTools.GetContents[psTool.borderViewer]],
lockViewers: psTool.lockViewersTriState.state = on,
displayCursor: psTool.displayCursorTriState.state = on,
displayCarets: psTool.displayCaretsTriState.state = on
! MagnificationFactorTooLarge => GOTO ReportError];
AppendLogMessage[psTool, Rope.Concat[fileName, " written."]];
PieViewers.Set[psTool.countDownPieViewer, 100.0];
EXITS
ReportError =>
AppendLogMessage[NARROW[clientData], "Magnification factor too large for identified area"];
};
MagnificationFactorButton: Buttons.ButtonProc = {
psTool: PressScreenTool ← NARROW[clientData];
IF mouseButton = blue THEN ViewerTools.SetContents[psTool.magnificationViewer, ""];
ViewerTools.SetSelection[psTool.magnificationViewer];
};
AreaCornersButton: Buttons.ButtonProc = {
psTool: PressScreenTool ← NARROW[clientData];
sourceHeight, sourceWidth, sourceBottom, sourceLeft: NAT ← 0;
screenAreaChoice: ROPE ← ChoiceButtons.GetSelectedButton[psTool.screenAreaChoice];
SELECT TRUE FROM
screenAreaChoice.Equal["LeftColumn"] => {
sourceHeight ← ViewerSpecs.screenH;
sourceWidth ← ViewerSpecs.openLeftWidth;
sourceBottom ← 0;
sourceLeft ← ViewerSpecs.openLeftLeftX;
};
screenAreaChoice.Equal["RightColumn"] => {
sourceHeight ← ViewerSpecs.screenH;
sourceWidth ← ViewerSpecs.openRightWidth;
sourceBottom ← 0;
sourceLeft ← ViewerSpecs.openRightLeftX;
};
screenAreaChoice.Equal["WholeScreen"] => {
sourceHeight ← ViewerSpecs.screenH;
sourceWidth ← ViewerSpecs.screenW;
sourceBottom ← 0;
sourceLeft ← 0;
};
screenAreaChoice.Equal["DesiredArea"] => {
sourceHeight ← sourceWidth ← sourceBottom ← sourceLeft ← 0;
};
ENDCASE => {
sourceHeight ← ViewerSpecs.screenH;
sourceWidth ← ViewerSpecs.screenW;
sourceBottom ← 0;
sourceLeft ← 0;
};
ViewerTools.SetContents[psTool.ulx, IO.PutFR["%g", IO.int[sourceLeft]]];
ViewerTools.SetContents[psTool.uly, IO.PutFR["%g", IO.int[sourceBottom+sourceHeight-1]]];
ViewerTools.SetContents[psTool.lrx, IO.PutFR["%g", IO.int[sourceLeft+sourceWidth-1]]];
ViewerTools.SetContents[psTool.lry, IO.PutFR["%g", IO.int[sourceBottom]]];
ViewerTools.SetSelection[psTool.ulx];
};
BlackBorderButton: Buttons.ButtonProc = {
psTool: PressScreenTool ← NARROW[clientData];
IF mouseButton = blue THEN ViewerTools.SetContents[psTool.borderViewer, ""];
ViewerTools.SetSelection[psTool.borderViewer];
};
PageMarginButton: Buttons.ButtonProc = {
psTool: PressScreenTool ← NARROW[clientData];
IF mouseButton = blue THEN ViewerTools.SetContents[psTool.pageMarginViewer, ""];
ViewerTools.SetSelection[psTool.pageMarginViewer];
};
CountDownTimerButton: Buttons.ButtonProc = {
psTool: PressScreenTool ← NARROW[clientData];
IF mouseButton = blue THEN ViewerTools.SetContents[psTool.countDownTimerViewer, "0"];
ViewerTools.SetSelection[psTool.countDownTimerViewer];
};
AppendLogMessage: PROCEDURE [psTool: PressScreenTool, msg: ROPE] = {
psTool.logMessage ← psTool.logMessage.Cat[msg, "\n"];
ViewerTools.SetContents[psTool.logViewer, psTool.logMessage];
[] ← psTool.logViewer.class.scroll[psTool.logViewer, thumb, 100];
};
ReadScreenCorners: PROCEDURE [psTool: PressScreenTool] RETURNS [ulx, uly, lrx, lry: REAL] = {
ulx ← ConvertRopeToReal[ViewerTools.GetContents[psTool.ulx]];
uly ← ConvertRopeToReal[ViewerTools.GetContents[psTool.uly]];
lrx ← ConvertRopeToReal[ViewerTools.GetContents[psTool.lrx]];
lry ← ConvertRopeToReal[ViewerTools.GetContents[psTool.lry]];
};
ConvertRopeToReal: PROCEDURE [rope: ROPE] RETURNS [value: REAL] = {
i : INT ← 0;
Get: PROCEDURE RETURNS [c: CHARACTER] = {
c ← IF i >= rope.Length THEN ' ELSE rope.Fetch[i];
i ← i + 1;
RETURN[c];
};
RETURN[IF rope.Length = 0 THEN 0.0 ELSE Real.ReadReal[Get]];
};
PressScreenExecCommand: Commander.CommandProc = TRUSTED {
stream: IO.STREAMIO.RIS[cmd.commandLine];
serverName: ROPEIO.GetToken[stream, IO.IDProc];
[] ← NewPressScreenTool[serverName];
};
pressScreenViewerClass: ViewerClasses.ViewerClass ~
NEW[ViewerClasses.ViewerClassRec ← ViewerOps.FetchViewerClass[$Container]^];
containerInitProc: ViewerClasses.InitProc ← pressScreenViewerClass.init;
pressScreenViewerClass.init ← InitPressScreenViewer;
ViewerOps.RegisterViewerClass[$PressScreen, pressScreenViewerClass];
Commander.Register[
key: "PressScreen",
proc: PressScreenExecCommand,
doc: "Create a tool to make AIS/Press files of portions of the bitmap display screen"
];
}.
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.