<> <> <> <> <> <> <> DIRECTORY Carets USING [ResumeCarets], CaretsExtras USING [SuspendVisibleCarets], CGAIS, Convert, FS, Graphics, GraphicsOps, IO, PressScreen, Real, Rope, SirPress, Terminal, ViewerClasses, ViewerLocks, ViewerSpecs, ViewerOps; PressScreenImpl: CEDAR MONITOR IMPORTS Carets, CaretsExtras, Convert, FS, Graphics, GraphicsOps, IO, Real, Rope, SirPress, Terminal, ViewerLocks, ViewerOps EXPORTS PressScreen SHARES 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: FS.StreamOpen[pressFileName, $create] ]; screenBitMap: GraphicsOps.BitmapRef_ GraphicsOps.ScreenBitmap[]; widthInWords: INT _ screenBitMap.width/16; halfWidthInWords: NAT _ widthInWords/2; screenPtr: LONG POINTER _ Terminal.GetBitBltTable[Terminal.Current[]].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.RopeFromInt[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 _ FS.StreamOpen[trueName, $create]; 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 _ Terminal.GetBitBltTable[Terminal.Current[]].dst.word; 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: 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]]; aisHeaderPtr: LONG POINTER TO AISHeader _ @aisHeader; aisBlock: IO.UnsafeBlock _ [ base: LOOPHOLE[aisHeaderPtr], startIndex: 0, count: 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; <> 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[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 { CaretsExtras.SuspendVisibleCarets[]; }; IF lockViewers THEN ViewerLocks.LockViewerTree[]; 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]]; IF displayCursor THEN { vt: Terminal.Virtual _ Terminal.Current[]; cursorArray: Terminal.BWCursorBitmap _ Terminal.GetBWCursorPattern[vt]; position: Terminal.Position _ Terminal.GetMousePosition[vt]; [] _ context.Save[]; [] _ context.SetPaintMode[transparent]; context.SetColor[Graphics.black]; context.SetCP[position.x, vt.bwHeight-position.y]; context.procs.DrawBits[context, @cursorArray, 1, 0, 0, 0, 16, 16, 0, 0]; context.Restore[]; }; <<>> <> 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 { Carets.ResumeCarets[]; }; <<>> <> screen.EndScannedRectangle[]; screen.ClosePress[]; ViewerOps.PaintEverything[]; RETURN [trueName]; }; 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; }; }. 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.