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
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:
BOOLEAN ←
FALSE,
borderWidth:
REAL ← 2.0,
lockViewers:
BOOLEAN ←
TRUE,
displayCursor:
BOOLEAN ←
FALSE,
displayCarets:
BOOLEAN ←
FALSE]
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.ROPE ← IF 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: NAT ← MIN[sourceLeft/16, screenWidthInWords];
sourceRightInWords: NAT ← MIN[(sourceLeft+sourceWidth+15)/16, screenWidthInWords];
paperHeight: REAL ← IF 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:
BOOL ←
FALSE] =
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];
};
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.STREAM ← IO.RIS[cmd.commandLine];
serverName: ROPE ← IO.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.