<> <> <> <> <> <> DIRECTORY Buttons, ChoiceButtons, CGAIS, Commander, Containers, Convert, FileIO, Graphics, GraphicsOps, IO, Labels, LFUtil, Menus, PressScreen, Process, Real, Rope, Rules, SirPress, TSViewerImpl, UserTerminal, ViewerClasses, ViewerLocks, ViewerOps, ViewerSpecs, ViewerTools; PressScreenImpl: CEDAR MONITOR IMPORTS Buttons, ChoiceButtons, Commander, Containers, Convert, FileIO, Graphics, GraphicsOps, IO, Labels, LFUtil, Menus, Process, Real, Rope, Rules, SirPress, UserTerminal, ViewerSpecs, ViewerLocks, ViewerOps, ViewerTools EXPORTS PressScreen SHARES 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 { <> 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; <> 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]; <> 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; <> screen.EndScannedRectangle[]; screen.ClosePress[]; }; fileNameTemplate: ROPE _ "Screen#.press"; <> count: INT _ 0; NewPressName: PUBLIC ENTRY PROCEDURE RETURNS [pressFileName: Rope.ROPE] = { <> 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)]]]]; }; PressScreenTool: PUBLIC TYPE = REF PressScreenToolRec; PressScreenToolRec: PUBLIC TYPE = RECORD[ 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, logViewer: ViewerClasses.Viewer, logMessage: ROPE ]; indent: INTEGER ~ TSViewerImpl.indent; baseline: INTEGER ~ TSViewerImpl.baseline; NewPressScreenTool: PUBLIC PROCEDURE [serverName: ROPE] RETURNS[psTool: PressScreenTool _ NEW[PressScreenToolRec]] = { <> ENABLE UNWIND => NULL; curY: INTEGER _ indent/2; NextY: PROCEDURE RETURNS [y:NAT] = {y _ curY _ curY+baseline}; container: ViewerClasses.Viewer _ Containers.Create[ info: [ name: IF serverName.Length = 0 THEN "PressScreen" ELSE Rope.Concat["PressScreen to ", serverName], column: right, scrollable: FALSE ], paint: FALSE ]; 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: container, scrollable: FALSE, border: TRUE], paint: FALSE ]; button _ Labels.Create[ info: [name: name, wx: v.wx + v.ww, wy: curY+1, wh: button.wh, parent: container, scrollable: FALSE, border: FALSE], paint: FALSE ]; }; MyButton: PROCEDURE [name: ROPE, proc: Buttons.ButtonProc, doc: ROPE] RETURNS [Buttons.Button] = { RETURN [Buttons.Create[ info: [name: name, wx: indent, wy: NextY[], parent: container, border: FALSE], clientData: psTool, proc: proc, fork: TRUE, paint: FALSE, documentation: doc ]]}; InsertMenu["FlashImage", FlashImageButton, "Flashes the selected area of the screen for the AIS/Press file"]; InsertMenu["SelectedImage", SelectedImageButton, "Converts the selected area of the screen into an AIS/Press file"]; InsertMenu["WholeScreen", WholeScreenButton, "Converts the whole screen into an AIS/Press file"]; InsertMenu["RightColumn", RightColumnButton, "Converts the right column of the screen into an AIS/Press file"]; InsertMenu["LeftColumn", LeftColumnButton, "Converts the left column of the screen into an AIS/Press file"]; ViewerOps.SetMenu[container, menu]; <> psTool.magnificationChoice _ ChoiceButtons.BuildEnumTypeSelection[ viewer: container, x: indent, y: curY, title: "Magnification: ", buttonNames: CONS["UseFactor", CONS["HalfPage", CONS["FullPage", NIL]]], default: "FullPage", style: menuSelection]; <> button _ MyButton["MagnificationFactor: ", MagnificationFactorButton, "Set the magnification factor"]; psTool.magnificationViewer _ LabelledTextViewer["%"]; <> button _ MyButton["SetCorners: ", SetCornersButton, "Set the corners of the selection image area of the screen"]; psTool.ulx _ LabelledTextViewer["x "]; psTool.uly _ LabelledTextViewer["y "]; psTool.lrx _ LabelledTextViewer["x "]; psTool.lry _ LabelledTextViewer["y"]; <> psTool.formatViewer _ ChoiceButtons.BuildEnumTypeSelection[ viewer: container, x: indent, y: NextY[], title: "Format: ", buttonNames: CONS["Landscape", CONS["Portrait", NIL]], default: "Landscape", style: menuSelection]; <> button _ MyButton["BlackBorder: ", SetCornersButton, "Set the corners of the selection image area of the screen"]; psTool.borderViewer _ LabelledTextViewer["pixels"]; <> button _ MyButton["PageMargin: ", PageMarginButton, "Set the white space provided around the page"]; psTool.pageMarginViewer _ LabelledTextViewer["inches"]; <> Containers.ChildXBound[container, Rules.Create[info: [wx: 0, wy: NextY[], wh: 1, parent: container]]]; <> psTool.logViewer _ ViewerTools.MakeNewTextViewer[ info: [wx: 0, wy: curY+2, parent: container, scrollable: TRUE, border: FALSE] ]; Containers.ChildXBound[container, psTool.logViewer]; Containers.ChildYBound[container, psTool.logViewer]; <> ChoiceButtons.UpdateChoiceButtons[container, 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[container, psTool.formatViewer, "Portrait"]; ViewerTools.SetContents[psTool.borderViewer, IO.PutFR["%g", IO.int[2]]]; ViewerTools.SetContents[psTool.pageMarginViewer, IO.PutFR["%g", IO.real[0.75]]]; ViewerOps.PaintViewer[container, all]; }; MagnificationFactorTooLarge: PUBLIC SIGNAL = CODE; <> AISPageAlignmentHackFailed: PUBLIC SIGNAL = CODE; <> 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] RETURNS[fileName: ROPE] = TRUSTED { <> <> <> 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-3*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]]; <> 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; <> 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]; <> 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]; <<>> ViewerLocks.LockViewerTree[]; <<>> <> FOR i: INT IN [0..sourceHeight) DO offset: LONG CARDINAL _ (i+screenBitMap.height-sourceHeight-sourceBottom)*screenWidthInWords+sourceLeftInWords; screen.UnsafeShowLine[screenPtr + offset]; ENDLOOP; ViewerLocks.ReleaseViewerTree[]; <<>> <> screen.EndScannedRectangle[]; screen.ClosePress[]; ViewerOps.PaintEverything[]; RETURN [trueName]; }; aisFileNameTemplate: ROPE = "Screen#.AIS"; NewAISPressName: PUBLIC ENTRY PROCEDURE RETURNS [pressFileName: ROPE] = { <> ENABLE UNWIND => NULL; i: INT = Rope.Find[s1: aisFileNameTemplate, s2: "#"]; pressFileName _ IF i = -1 THEN aisFileNameTemplate ELSE aisFileNameTemplate.Replace[start: i, len: 1, with: Convert.ValueToRope[[signed[(count _ count + 1)]]]]; }; 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]]; }; SelectedImageButton: Buttons.ButtonProc = { psTool: PressScreenTool _ NARROW[clientData]; ulx, uly, lrx, lry: REAL; magnificationRope: ROPE _ ChoiceButtons.GetSelectedButton[psTool.magnificationChoice]; fileName: ROPE; [ulx, uly, lrx, lry] _ ReadScreenCorners[psTool]; fileName _ AISPressScreen[ pressFileName: NewAISPressName[], sourceHeight: Real.Fix[uly - lry + 1], sourceWidth: Real.Fix[lrx - ulx + 1], sourceBottom: Real.Fix[lry], sourceLeft: Real.Fix[ulx], 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: ConvertRopeToReal[ViewerTools.GetContents[psTool.borderViewer]], rightMarginInches: ConvertRopeToReal[ViewerTools.GetContents[psTool.borderViewer]], landscape: Rope.Equal[ChoiceButtons.GetSelectedButton[psTool.formatViewer], "Landscape"], borderWidth: ConvertRopeToReal[ViewerTools.GetContents[psTool.pageMarginViewer]] ! MagnificationFactorTooLarge => GOTO ReportError]; AppendLogMessage[psTool, Rope.Concat[fileName, " written."]]; EXITS ReportError => AppendLogMessage[NARROW[clientData], "Magnification factor too large for selected image"]; }; WholeScreenButton: Buttons.ButtonProc = { psTool: PressScreenTool _ NARROW[clientData]; magnificationRope: ROPE _ ChoiceButtons.GetSelectedButton[psTool.magnificationChoice]; fileName: ROPE _ AISPressScreen[ pressFileName: NewAISPressName[], sourceHeight: ViewerSpecs.screenH, sourceWidth: ViewerSpecs.screenW, sourceBottom: 0, sourceLeft: 0, 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: ConvertRopeToReal[ViewerTools.GetContents[psTool.borderViewer]], rightMarginInches: ConvertRopeToReal[ViewerTools.GetContents[psTool.borderViewer]], landscape: SELECT ChoiceButtons.GetSelectedButton[psTool.formatViewer] FROM "Landscape" => TRUE, ENDCASE => FALSE, borderWidth: ConvertRopeToReal[ViewerTools.GetContents[psTool.pageMarginViewer]] ! MagnificationFactorTooLarge => GOTO ReportError]; AppendLogMessage[psTool, Rope.Concat[fileName, " written."]]; EXITS ReportError => AppendLogMessage[NARROW[clientData], "Magnification factor too large for the whole screen"]; }; RightColumnButton: Buttons.ButtonProc = { psTool: PressScreenTool _ NARROW[clientData]; magnificationRope: ROPE _ ChoiceButtons.GetSelectedButton[psTool.magnificationChoice]; fileName: ROPE _ AISPressScreen[ pressFileName: NewAISPressName[], sourceHeight: ViewerSpecs.screenH, sourceWidth: ViewerSpecs.openRightWidth, sourceBottom: 0, sourceLeft: ViewerSpecs.openRightLeftX, 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: ConvertRopeToReal[ViewerTools.GetContents[psTool.borderViewer]], rightMarginInches: ConvertRopeToReal[ViewerTools.GetContents[psTool.borderViewer]], landscape: SELECT ChoiceButtons.GetSelectedButton[psTool.formatViewer] FROM "Landscape" => TRUE, ENDCASE => FALSE, borderWidth: ConvertRopeToReal[ViewerTools.GetContents[psTool.pageMarginViewer]] ! MagnificationFactorTooLarge => GOTO ReportError]; AppendLogMessage[psTool, Rope.Concat[fileName, " written."]]; EXITS ReportError => AppendLogMessage[NARROW[clientData], "Magnification factor too large for the right column"]; }; LeftColumnButton: Buttons.ButtonProc = { psTool: PressScreenTool _ NARROW[clientData]; magnificationRope: ROPE _ ChoiceButtons.GetSelectedButton[psTool.magnificationChoice]; fileName: ROPE _ AISPressScreen[ pressFileName: NewAISPressName[], sourceHeight: ViewerSpecs.screenH, sourceWidth: ViewerSpecs.openLeftWidth, sourceBottom: 0, sourceLeft: ViewerSpecs.openLeftLeftX, 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: ConvertRopeToReal[ViewerTools.GetContents[psTool.borderViewer]], rightMarginInches: ConvertRopeToReal[ViewerTools.GetContents[psTool.borderViewer]], landscape: SELECT ChoiceButtons.GetSelectedButton[psTool.formatViewer] FROM "Landscape" => TRUE, ENDCASE => FALSE, borderWidth: ConvertRopeToReal[ViewerTools.GetContents[psTool.pageMarginViewer]] ! MagnificationFactorTooLarge => GOTO ReportError]; AppendLogMessage[psTool, Rope.Concat[fileName, " written."]]; EXITS ReportError => AppendLogMessage[NARROW[clientData], "Magnification factor too large for the right column"]; }; MagnificationFactorButton: Buttons.ButtonProc = { psTool: PressScreenTool _ NARROW[clientData]; IF mouseButton = blue THEN ViewerTools.SetContents[psTool.magnificationViewer, ""]; ViewerTools.SetSelection[psTool.magnificationViewer]; }; SetCornersButton: Buttons.ButtonProc = { psTool: PressScreenTool _ NARROW[clientData]; IF mouseButton=red THEN { 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]]]; }; FlashScreenArea[psTool]; EXITS DoNothing => NULL; }; BlackBorder: 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]; }; 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[Real.ReadReal[Get]]; }; PressScreenExecCommand: Commander.CommandProc = TRUSTED { stream: IO.STREAM _ IO.RIS[cmd.commandLine]; serverName: ROPE _ IO.GetToken[stream, IO.IDProc]; [] _ NewPressScreenTool[serverName]; }; 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.