<> <> <> <> <> <> 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 { <> 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)]]]]; }; 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, lockViewers: BOOLEAN _ TRUE, displayCursor: BOOLEAN _ FALSE, displayCarets: BOOLEAN _ FALSE] 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-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]]; <> 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]; <<>> 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[]; <<>> <> 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 displayCarets THEN { IF Carets.pCaretViewer # NIL THEN InvertCaret[context, primary]; IF Carets.sCaretViewer # NIL THEN InvertCaret[context, secondary]; Carets.ResumeCarets[]; }; <<>> <> 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] = { <> 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] = { <> 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 = { <> <> 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"]; <<>> <> <<>> 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]; <<>> <> 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]; <<>> <> 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"]; <<>> <> psTool.magnificationChoice _ ChoiceButtons.BuildEnumTypeSelection[ viewer: self, x: indent, y: NextY[], title: "Magnification:", buttonNames: CONS["FullPage", CONS["HalfPage", CONS["UseFactorBelow", NIL]]], default: "FullPage", style: menuSelection]; <<>> <> button _ MyButton["MagnificationFactor: ", MagnificationFactorButton, "Set the magnification factor"]; psTool.magnificationViewer _ LabelledTextViewer["%"]; <<>> <> psTool.formatViewer _ ChoiceButtons.BuildEnumTypeSelection[ viewer: self, x: indent, y: NextY[], title: "Page Format:", buttonNames: CONS["Portrait", CONS["Landscape", NIL]], default: "Portrait", style: menuSelection]; <<>> <> button _ MyButton["BlackBorder: ", BlackBorderButton, "Set the black border width surrounding the identified image area."]; psTool.borderViewer _ LabelledTextViewer["pixels"]; <<>> <> button _ MyButton["PageMargin: ", PageMarginButton, "Set the white space provided around the page"]; psTool.pageMarginViewer _ LabelledTextViewer["inches"]; <<>> <> 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]; <<>> <> 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"]; <<>> <> Containers.ChildXBound[self, Rules.Create[info: [wx: 0, wy: NextY[], wh: 1, parent: self]]]; <<>> <> 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]; <<>> <> 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.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.