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. π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 February 21, 1984 10:13:20 am PST Last Edited by: Beach, October 31, 1983 11:46 am Last Edited by: Wyatt, December 9, 1983 3:09 pm 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) 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) IF displayCursor THEN ViewerOps.PaintEverything will fix cursor up finish the rectangle and close the file Returns a file name like "Screen1.ais", "Screen2.ais", etc. Κ – "cedar" style˜JšΟc™Jš)™)Jš6™6Jš6™6Jš!œ!™CJš0™0Jš/™/J˜šΟk ˜ Jšœžœ˜Jšœ žœ˜*J˜Jšœ˜Jšœ˜Jšœ ˜ Jšœ ˜ J˜J˜ J˜Jšœ˜Jšœ ˜ Jšœ ˜ Jšœ˜Jšœ ˜ J˜ Jšœ ˜ J˜—šœž ˜Jšžœu˜|Jšžœ ˜Jšžœ˜Jšžœ ˜J˜—Jšžœžœžœ˜Jšœ žœ/˜DJ˜unitš Οn œžœžœžœžœ˜KJ™P˜.J˜%J˜3Jšœ˜—J˜@Jšœžœ˜*Jšœžœ˜'Jšœ žœžœ8˜OJš™šžœžœ˜JšœA˜A˜J˜ J˜#J˜Jšœ ˜ J˜—J˜—šž˜šœ˜J˜ J˜#Jšœ.˜.J˜——JšB™Bšžœžœžœž˜)Jšœžœžœ˜'Jšžœžœ1˜HJšœ*˜*Jšžœ˜—Jš'™'J˜J˜Jšœ˜J˜—šœžœ˜)JšœA™A—šœžœ˜J˜—šŸ œžœžœžœ˜KJšœ?™?Jšžœžœžœ˜Jšœžœ,˜2šœžœžœ˜/Jšžœ[˜_—Jšœ˜J˜—šŸœžœž œ˜2Jšœk™kJ˜—šŸœžœž œ˜1Jšœ`™`J˜—š,Ÿœžœž œžœžœ%žœ&žœžœžœ_žœžœžœžœžœžœžœžœžœžœžœ žœžœ˜ιJ™]J™BJšœΈ™ΈJš œžœžœžœžœžœ˜WJ˜2Jšœžœžœ$˜;Jšœ žœ˜J˜J˜AJšœžœ˜0Jšœžœžœ$˜@Jšœžœžœ5˜RJš œ žœžœ žœ žœ ˜Jšžœ ˜ Jšœ˜Jšž˜—šž˜Jšœžœ˜—J˜J˜—J˜šœ˜J˜RJ˜ŠJ˜J˜hJ˜AJ˜“J˜;J˜T——…—"`2b