DIRECTORY Carets USING [ResumeCarets, SuspendCarets], AISFileFormat, Convert, Cursors, FS, Imager, ImagerArtwork, ImagerInterpress, ImagerTerminal, InterminalBackdoor, IO, MessageWindow, PressScreen, Real, Rope, SirPress, Terminal, ViewerClasses, ViewerLocks, ViewerSpecs, ViewerOps; PressScreenImpl: CEDAR MONITOR IMPORTS Carets, Convert, Cursors, FS, Imager, ImagerArtwork, ImagerInterpress, ImagerTerminal, InterminalBackdoor, IO, MessageWindow, Real, Rope, SirPress, Terminal, ViewerLocks, ViewerOps EXPORTS PressScreen = { 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: FS.StreamOpen[pressFileName, $create] ]; vt: Terminal.Virtual _ InterminalBackdoor.terminal; frameBuffer: Terminal.FrameBuffer _ Terminal.GetBWFrameBuffer[vt]; widthInWords: INT _ frameBuffer.wordsPerLine; halfWidthInWords: NAT _ widthInWords/2; screenPtr: LONG POINTER _ frameBuffer.base; IF which=bothSides THEN { screen.SetPageSize[height: 85, width: 110, unit: SirPress.in/10]; screen.BeginScannedRectangle[ x: 1, y: 1, numberOfLines: frameBuffer.height, dotsPerLine: widthInWords*16, height: 8*4, unit: SirPress.in/4] } ELSE screen.BeginScannedRectangle[ x: 1, y: 1, numberOfLines: frameBuffer.height, dotsPerLine: (halfWidthInWords+extraWords)*16, unit: SirPress.in/4]; FOR i: INT IN [0..frameBuffer.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.RopeFromInt[count _ count + 1]]; }; MagnificationFactorTooLarge: PUBLIC SIGNAL = CODE; AISPageAlignmentHackFailed: PUBLIC SIGNAL = CODE; ScreenWorker: TYPE = PROC [screenParms: ScreenParameters, vt: Terminal.Virtual, context: Imager.Context, frameBuffer: Terminal.FrameBuffer, screenWidthInWords, clippedWidth: NAT, screenPtr: LONG POINTER]; DoScreenWork: PROC [screenParms: ScreenParameters, Prepare, WithLock, Finish: ScreenWorker] = { OPEN screenParms; vt: Terminal.Virtual _ InterminalBackdoor.terminal; context: Imager.Context _ ImagerTerminal.BWContext[vt: vt, pixelUnits: TRUE]; frameBuffer: Terminal.FrameBuffer _ Terminal.GetBWFrameBuffer[vt]; screenWidthInWords: NAT _ frameBuffer.wordsPerLine; clippedWidth: NAT _ MIN[frameBuffer.width-sourceLeft, sourceWidth]; screenPtr: LONG POINTER _ frameBuffer.base; sourceHeight _ MIN[sourceHeight, frameBuffer.height-sourceBottom]; Prepare[screenParms: screenParms, vt: vt, context: context, frameBuffer: frameBuffer, screenWidthInWords: screenWidthInWords, clippedWidth: clippedWidth, screenPtr: screenPtr]; IF displayCarets THEN { Carets.SuspendCarets[visible: TRUE]; }; { Locked: SAFE PROC ~ TRUSTED { context.MaskBox[[sourceLeft, sourceBottom, sourceLeft+borderWidth, sourceBottom+sourceHeight]]; context.MaskBox[[sourceLeft+clippedWidth-borderWidth, sourceBottom, sourceLeft+clippedWidth, sourceBottom+sourceHeight]]; context.MaskBox[[sourceLeft, sourceBottom, sourceLeft+clippedWidth, sourceBottom+borderWidth]]; context.MaskBox[[sourceLeft, sourceBottom+sourceHeight-borderWidth, sourceLeft+clippedWidth, sourceBottom+sourceHeight]]; context.SetColor[Imager.white]; context.MaskBox[[sourceLeft-16, sourceBottom, sourceLeft, sourceBottom+sourceHeight]]; context.MaskBox[[sourceLeft+clippedWidth, sourceBottom, sourceLeft+clippedWidth+16, sourceBottom+sourceHeight]]; IF displayCursor THEN { vt: Terminal.Virtual _ Terminal.Current[]; cursorArray: Terminal.BWCursorBitmap _ Terminal.GetBWCursorPattern[vt]; position: Terminal.Position _ Terminal.GetMousePosition[vt]; cursorInfo: Cursors.CursorInfo = Cursors.GetCursorInfo[]; context.SetColor[Imager.black]; context.MaskBits[base: @cursorArray, wordsPerLine: 1, sMin: 0, fMin: 0, sSize: 16, fSize: 16, tx: position.x+cursorInfo.hotX, ty: vt.bwHeight-(position.y+cursorInfo.hotY)]; }; WithLock[screenParms: screenParms, vt: vt, context: context, frameBuffer: frameBuffer, screenWidthInWords: screenWidthInWords, clippedWidth: clippedWidth, screenPtr: screenPtr]; }; IF lockViewers THEN ViewerLocks.CallUnderViewerTreeLock[Locked] ELSE Locked[]; }; IF displayCarets THEN { Carets.ResumeCarets[]; }; ViewerOps.PaintEverything[]; Finish[screenParms: screenParms, vt: vt, context: context, frameBuffer: frameBuffer, screenWidthInWords: screenWidthInWords, clippedWidth: clippedWidth, screenPtr: screenPtr]; }; pixelsPerWord: REAL = 16.0; micasPerPoint: REAL = 32.0; --not 2540/72.0, so we can print these press files with SPRUCE; at least, that's what Michael Plass alleged in the presence of Rick Beach and Mike Spreitzer on February 4, 1986, although experiments that day show it doesn't work. micasPerWord: REAL = micasPerPoint * pixelsPerWord; AISPressScreen: PUBLIC PROCEDURE [ pressFileName: ROPE, screenParms: ScreenParameters _ [], pageParms: PageParameters _ [] ] RETURNS [fileName: ROPE] = TRUSTED { OPEN screenParms, pageParms; trueName: Rope.ROPE _ IF pressFileName = NIL THEN NewAISPressName[] ELSE pressFileName; outputStream: IO.STREAM _ FS.StreamOpen[trueName, $create]; bytesSoFar: INT; screen: SirPress.PressHandle; sourceLeftInWords, sourceRightInWords: NAT; paperHeight, paperWidth, pageBorder, x, y: REAL; bytesPerPage: INT = 2048; wordsOfPressCommands: INT = 8; -- count of Press commands generated before dots so that the AIS image starts on a page boundary AISHeader: TYPE = RECORD [ header: AISFileFormat.AttributeHeader, partHeader: AISFileFormat.PartHeader, rasterPart: AISFileFormat.RasterPart, uca: AISFileFormat.UCACoding]; aisHeader: AISHeader _ [ header: [ password: AISFileFormat.passwordValue, length: 0], partHeader: [type: raster, length: SIZE[AISFileFormat.RasterPart]+SIZE[AISFileFormat.PartHeader]+SIZE[AISFileFormat.UCACoding]], rasterPart: [ scanCount: 0, scanLength: 0, scanDirection: 3, samplesPerPixel: 1, codingType: uca], uca: [ bitsPerSample: 0, wordsPerScanLine: 0, scanLinesPerBlock: 177777B, paddingPerBlock: 177777B ]]; aisHeaderPtr: LONG POINTER TO AISHeader _ @aisHeader; aisBlock: IO.UnsafeBlock _ [ base: LOOPHOLE[aisHeaderPtr], startIndex: 0, count: 2*SIZE[AISHeader]]; Prepare: ScreenWorker = CHECKED { OPEN screenParms; sourceLeftInWords _ MIN[sourceLeft/16, screenWidthInWords]; sourceRightInWords _ MIN[(sourceLeft+clippedWidth+15)/16, screenWidthInWords]; paperHeight _ IF landscape THEN 8.5*2540 ELSE 11*2540; paperWidth _ (11+8.5)*2540 - paperHeight; pageBorder _ (leftMarginInches + rightMarginInches)*2540; SELECT scaleToFit FROM fullPage => magnification _ MIN[ (paperWidth-pageBorder) / (micasPerWord*(sourceRightInWords-sourceLeftInWords)), (paperHeight-pageBorder)/(micasPerPoint*sourceHeight)]; halfPage => magnification _ MIN[ (paperWidth-pageBorder) / (micasPerWord*(sourceRightInWords-sourceLeftInWords)), (paperHeight-2*pageBorder) / (2.0*micasPerPoint*sourceHeight)]; useMagnification => NULL; ENDCASE; x _ (paperWidth-micasPerWord*(sourceRightInWords-sourceLeftInWords)*magnification)/2.0; y _ (paperHeight-micasPerPoint*sourceHeight*magnification)/2.0; IF x<0 OR y<0 OR x+micasPerWord*(sourceRightInWords-sourceLeftInWords)*magnification > paperWidth OR y+micasPerPoint*sourceHeight*magnification > paperHeight THEN SIGNAL MagnificationFactorTooLarge; aisHeader.uca.wordsPerScanLine _ sourceRightInWords-sourceLeftInWords; aisHeader.rasterPart.scanLength _ aisHeader.uca.wordsPerScanLine*16; aisHeader.rasterPart.scanCount _ sourceHeight; IO.UnsafePutBlock[outputStream, aisBlock]; IO.PutChar[outputStream, '\000]; IO.PutChar[outputStream, '\000]; THROUGH [0..bytesPerPage - IO.GetIndex[outputStream] - 2*wordsOfPressCommands) DO IO.PutChar[outputStream, '$]; ENDLOOP; 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[micasPerPoint*sourceHeight*magnification], unit: SirPress.mica]; bytesSoFar _ IO.GetIndex[outputStream]; IF bytesSoFar # bytesPerPage THEN SIGNAL AISPageAlignmentHackFailed; aisHeader.header.length _ bytesSoFar/2; IO.SetIndex[outputStream, 0]; IO.UnsafePutBlock[outputStream, aisBlock]; IO.SetIndex[outputStream, bytesSoFar]; }; WithLock: ScreenWorker = TRUSTED { OPEN screenParms; FOR i: INT IN [0..sourceHeight) DO offset: LONG CARDINAL _ (i+frameBuffer.height-sourceHeight-sourceBottom)*screenWidthInWords+sourceLeftInWords; screen.UnsafeShowLine[screenPtr + offset]; ENDLOOP; }; Finish: ScreenWorker = CHECKED { OPEN screenParms; screen.EndScannedRectangle[]; screen.ClosePress[]; }; DoScreenWork[screenParms, Prepare, WithLock, Finish]; RETURN [trueName]; }; pointsPerInch: REAL = 72.0; --not 72.27, because these are "screen points" metersPerPoint: REAL = Imager.metersPerInch/pointsPerInch; IPScreen: PUBLIC PROCEDURE [ipFileName: ROPE, screenParms: ScreenParameters _ [], pageParms: PageParameters _ []] RETURNS [fileName: ROPE] = { OPEN screenParms, pageParms; r: ImagerInterpress.Ref; paperWidth: REAL = (IF landscape THEN 11.0 ELSE 8.5)*pointsPerInch; paperHeight: REAL = (IF landscape THEN 8.5 ELSE 11.0)*pointsPerInch; pageBorder: REAL = (leftMarginInches + rightMarginInches)*pointsPerInch; x0, y0: REAL; Prepare: ScreenWorker = { SELECT scaleToFit FROM fullPage => magnification _ MIN[ (paperWidth-pageBorder) / sourceWidth, (paperHeight-pageBorder) / sourceHeight]; halfPage => magnification _ MIN[ (paperWidth-pageBorder) / sourceWidth, (paperHeight-2*pageBorder) / 2.0*sourceHeight]; useMagnification => NULL; ENDCASE; x0 _ (paperWidth-sourceWidth*magnification)/2.0; y0 _ (paperHeight-sourceHeight*magnification)/2.0; IF x0<0 OR y0<0 OR x0+sourceWidth*magnification > paperWidth OR y0+sourceHeight*magnification > paperHeight THEN SIGNAL MagnificationFactorTooLarge; }; WithLock: ScreenWorker = { OPEN screenParms; DoIPMaster: PROC [context: Imager.Context] = { context.ScaleT[metersPerPoint]; IF landscape THEN {context.TranslateT[t: [paperHeight, 0]]; context.RotateT[90]}; context.TranslateT[t: [x0, y0]]; context.ScaleT[magnification]; context.TranslateT[t: [-sourceLeft, -sourceBottom]]; context.ClipRectangle[[sourceLeft, sourceBottom, sourceWidth, sourceHeight]]; context.MaskBits[ base: screenPtr, wordsPerLine: frameBuffer.wordsPerLine, sMin: frameBuffer.height-sourceHeight-sourceBottom, fMin: sourceLeft, sSize: sourceHeight, fSize: sourceWidth, tx: sourceLeft, ty: sourceBottom+sourceHeight ]; }; ImagerInterpress.DoPage[self: r, action: DoIPMaster ! Imager.Error => { MessageWindow.Append[ message: Rope.Concat[error.explanation, " creating IPMaster"], clearFirst: TRUE]; CONTINUE} ]; }; Finish: ScreenWorker = { }; fileName _ IF ipFileName = NIL THEN NewIPName[] ELSE ipFileName; r _ ImagerInterpress.Create[fileName: fileName ! FS.Error => { MessageWindow.Append[message: error.explanation, clearFirst: TRUE]; GOTO Quit; }]; DoScreenWork[screenParms, Prepare, WithLock, Finish]; ImagerInterpress.Close[r]; EXITS Quit => NULL; }; StuffScreen: PUBLIC PROCEDURE [screenParms: ScreenParameters _ []] = { OPEN screenParms; Prepare: ScreenWorker = { }; WithLock: ScreenWorker = { OPEN screenParms; DoStuff: PROC [context: Imager.Context] = { context.TranslateT[t: [-sourceLeft, -sourceBottom]]; context.MaskBits[ base: screenPtr, wordsPerLine: frameBuffer.wordsPerLine, sMin: frameBuffer.height-sourceHeight-sourceBottom, fMin: sourceLeft, sSize: sourceHeight, fSize: sourceWidth, tx: sourceLeft, ty: sourceBottom+sourceHeight ]; }; ImagerArtwork.PasteArtwork[action: DoStuff, bounds: [0, 0, sourceWidth, sourceHeight], m: ImagerArtwork.Points[], clip: TRUE]; }; Finish: ScreenWorker = { }; DoScreenWork[screenParms, Prepare, WithLock, Finish]; }; aisFileNameTemplate: ROPE = "Screen#.AIS"; NewAISPressName: PUBLIC ENTRY PROCEDURE RETURNS [pressFileName: ROPE] = { ENABLE UNWIND => NULL; NextName: PROCEDURE RETURNS [ROPE] = { RETURN [aisFileNameTemplate.Replace[start: i, len: 1, with: Convert.RopeFromInt[count _ count + 1]]]; }; i: INT = Rope.Find[s1: aisFileNameTemplate, s2: "#"]; pressFileName _ IF i = -1 THEN aisFileNameTemplate ELSE NextName[]; DO s: FS.OpenFile; s _ FS.Open[pressFileName ! FS.Error => GO TO ThisNameIsOkay]; FS.Close[s]; pressFileName _ NextName[]; ENDLOOP; EXITS ThisNameIsOkay => NULL; }; ipFileNameTemplate: ROPE = "Screen#.IP"; NewIPName: PUBLIC ENTRY PROCEDURE RETURNS [ipFileName: ROPE] = { ENABLE UNWIND => NULL; NextName: PROCEDURE RETURNS [ROPE] = { RETURN [ipFileNameTemplate.Replace[start: i, len: 1, with: Convert.RopeFromInt[count _ count + 1]]]; }; i: INT = Rope.Find[s1: ipFileNameTemplate, s2: "#"]; ipFileName _ IF i = -1 THEN ipFileNameTemplate ELSE NextName[]; DO s: FS.OpenFile; s _ FS.Open[ipFileName ! FS.Error => GO TO ThisNameIsOkay]; FS.Close[s]; ipFileName _ NextName[]; ENDLOOP; EXITS ThisNameIsOkay => NULL; }; }. 6-Apr-82 12:01:31 Teitelman fixed PressScreenButton to clear message window first. May 4, 1982 4:39 pm Cattell: print msg saying whether half or full screen. Also, no longer need config 'cause SirPressPackage is external. June 18, 1982 1:58 pm Cattell: convert to 3.2; leave a little left margin to avoid printer truncation. November 15, 1982 12:30 pm Plass: Made client-callable interface. November 15, 1982 2:30 pm Plass: Made rightSide work, removed button interface, made half-screen resolution match what Spruce can sometimes handle. November 16, 1982 10:57 am Plass: Tracked SirPress changes. February 21, 1984 10:12:39 am PST Plass: Fixed AIS header to make a proper AIS file. April 25, 1985 11:05:01 am PST: Imager conversion. ΌPressScreenImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. 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 April 25, 1985 11:29:36 am PST Last Edited by: Beach, October 31, 1983 11:46 am Last Edited by: Wyatt, December 9, 1983 3:09 pm Michael Plass, June 2, 1985 4:26:26 pm PDT Spreitzer, February 4, 1986 3:43:45 pm PST Old interface to convert part or all of the bit mapped screen into a press file. define the screen rectangle call ShowLine for each line of screen (or half-line, if left side) finish the rectangle and close the file count is incremented by one and substituted for # in the template Returns a file name like "Screen1.press", "Screen2.press", etc. The specified rectangle will not fit on an 8.5 by 11 inch page with the supplied margins and magnifications An internal error expected when the size of SirPress record definitions change (low probability) IF displayCursor THEN ViewerOps.PaintEverything will fix cursor up 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). Create the AIS Header from the screen rectangle information define the screen rectangle in the Press file Stuff the current position of the Press file into the AIS Header call ShowLine for each line of screen (or half-line, if left side) finish the rectangle and close the file Returns a file name like "Screen1.ais", "Screen2.ais", etc. Returns a file name like "Screen1.IP", "Screen2.IP", etc. Κ|– "cedar" style˜šΟc™Icodešœ Οmœ1™˜>Kšœ Ÿœ˜—KšŸœ˜ —Kšœ˜—K˜—K™šœ˜K˜—K˜Kš œ ŸœŸœŸœ Ÿœ ˜@šœ>˜>Kšœ=Ÿœ˜CKšŸœ˜ Kšœ˜—Kšœ5˜5Kšœ˜šŸ˜KšœŸœ˜ —Kšœ˜J˜—š‘ œŸœŸ œ)˜FJšŸœ ˜J˜šœ˜J˜—J˜šœ˜JšŸœ ˜š‘œŸœ˜+Kšœ4˜4˜Kšœ˜Kšœ'˜'Kšœ3˜3Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜—K˜—KšœxŸœ˜~J˜—J™šœ˜J˜—J˜Jšœ5˜5Jšœ˜J˜—JšœŸœ˜*š‘œŸœŸœŸœ˜IJšœ;™;JšŸœŸœŸœ˜š‘œŸ œŸœŸœ˜&JšŸœ_˜eJ˜—JšœŸœ/˜5šœŸœŸœ˜2JšŸœ ˜—šŸ˜JšœŸœ ˜Jš œŸœŸœ ŸœŸœ˜>JšŸœ ˜ Jšœ˜JšŸ˜—šŸ˜JšœŸœ˜—J˜J˜—JšœŸœ˜(š‘ œŸœŸœŸœ˜@Jšœ9™9JšŸœŸœŸœ˜š‘œŸ œŸœŸœ˜&JšŸœ^˜dJ˜—JšœŸœ.˜4šœ ŸœŸœ˜.JšŸœ ˜—šŸ˜JšœŸœ ˜Jš œŸœŸœ ŸœŸœ˜;JšŸœ ˜ Jšœ˜JšŸ˜—šŸ˜JšœŸœ˜—J˜J˜—J˜šœ˜J˜RJ˜ŠJ˜J˜hJ˜AJ˜“J˜;J˜TJ˜2——…—7@Mx