(FILECREATED " 3-Apr-86 18:16:05" {ERIS}<LISPCORE>LIBRARY>C150STREAM.;15 139806 

      changes to:  (FNS CREATEC150BUFFER)
                   (VARS C150COLORMAP C150FONTDIRECTORIES)

      previous date: " 3-Apr-86 16:05:11" {ERIS}<LISPCORE>LIBRARY>C150STREAM.;14)


(* Copyright (c) 1985, 1986 by Xerox Corporation. All rights reserved.)

(PRETTYCOMPRINT C150STREAMCOMS)

(RPAQQ C150STREAMCOMS 
       ((CONSTANTS \C150PointsPerInch \C150RealBPP)
        (FNS C150.SEPARATOR C150.SETMARGINS \C150.ALLWHITESPACE \C150.BUFFER.DOT \C150.MICROLINEFEED 
             \C150.SENDLINE \C150.SENDLINEINFO \C150INIT \CREATECHARSET.C150)
        (FNS CREATEC150BUFFER NEWLINE.C150 NEWPAGE.C150 OPENC150STREAM C150.RESET SEND.TO.C150 
             STARTPAGE.C150 \BITBLT.C150 \BLTCHAR.C150 \BLTSHADE.C150 \C150.CRLF \CHANGECHARSET.C150 
             \CHARWIDTH.C150 \CLOSEFN.C150 \CREATEC150FONT \READC150FONTFILE \DRAWCIRCLE.C150 
             \DRAWCURVE.C150 \DRAWELLIPSE.C150 \DRAWLINE.C150 \DSPBACKCOLOR.C150 
             \DSPCLIPPINGREGION.C150 \DSPCOLOR.C150 \C150.ASSURE.COLOR \C150.LOOKUPRGB \DSPFONT.C150 
             \DSPLEFTMARGIN.C150 \DSPLINEFEED.C150 \DSPOPERATION.C150 \DSPPRINTCHAR.C150 
             \DSPPRINTCR/LF.C150 \DSPRESET.C150 \DSPRIGHTMARGIN.C150 \DSPXPOSITION.C150 
             \DSPYPOSITION.C150 \DUMPPAGEBUFFER.C150 \FILLCIRCLE.C150 \OUTCHARFN.C150 
             \SEARCHC150FONTFILES \STRINGWIDTH.C150)
        (VARS MISSINGC150FONTCOERCIONS (\C150COLORTABLE)
              (\C150.FRAMEBUFFER)
              (\C150STREAM)
              C150COLORMAP C150FONTCOERCIONS C150FONTDIRECTORIES C150FONTEXTENSIONS)
        (INITVARS (C150.CLIPBUFFER T)
               (\C150DEFAULTDEVICE (QUOTE CENTRONICS)))
        (FNS COLORMAP.TO.C150TABLE)
        (FILES COLOR XXGEOM XXFILL)
        [P (IF (NOT (GETD (QUOTE POLYSHADE.BLT)))
               THEN
               (* A fix for KOTO, which is not necessary in <lc>n>)
               (MOVD (QUOTE POLYSHADE.DISPLAY)
                     (QUOTE POLYSHADE.BLT]
        (DECLARE: DONTEVAL@LOAD DOCOPY (P (\C150INIT))
               (FILES CENTRONICS))
        (DECLARE: EVAL@LOAD DONTCOPY (FILES (LOADFROM)
                                            ADISPLAY LLDISPLAY))
        (MACROS \C150BackingStream)))
(DECLARE: EVAL@COMPILE 

(RPAQQ \C150PointsPerInch 120)

(RPAQQ \C150RealBPP 4)

(CONSTANTS \C150PointsPerInch \C150RealBPP)
)
(DEFINEQ

(C150.SEPARATOR
  [LAMBDA (BACKINGSTREAM)                                                  (* hdj 
                                                                           " 5-Sep-85 12:12")
    (LET ((SEPR.LENGTH 30))
         (for C instring (CONCAT "g0" SEPR.LENGTH " ") do (BOUT BACKINGSTREAM C))
         (for DASH from 1 to SEPR.LENGTH do (BOUT BACKINGSTREAM 255])

(C150.SETMARGINS
  [LAMBDA (BACKINGSTREAM C150LEFT C150RIGHT)                               (* hdj 
                                                                           " 5-Sep-85 12:21")
            
            (* * Set the left and right margins for the C150 printer)

    (LET [[LEFTCODE (CONCAT (FIX (TIMES 10 (if (OR (EQ C150LEFT NIL)
                                                   (LESSP C150LEFT .5)
                                                   (GEQ C150LEFT 9.0)
                                                   (GEQ C150LEFT C150RIGHT))
                                               then .5
                                             else C150LEFT]
          (RIGHTCODE (CONCAT (FIX (TIMES 10 (if (OR (EQ C150RIGHT NIL)
                                                    (GREATERP C150RIGHT 9)
                                                    (LEQ C150RIGHT .5)
                                                    (LEQ C150RIGHT C150LEFT))
                                                then 9
                                              else C150RIGHT]              (* send the left margin)
         (BOUT BACKINGSTREAM (CHARCODE ESC))
         (BOUT BACKINGSTREAM (CHARCODE l))
         (for CHAR instring LEFTCODE do (BOUT BACKINGSTREAM CHAR))
         (BOUT BACKINGSTREAM (CHARCODE CR))                                (* send the right 
                                                                           margin)
         (BOUT BACKINGSTREAM (CHARCODE ESC))
         (BOUT BACKINGSTREAM (CHARCODE r))
         (for CHAR instring RIGHTCODE do (BOUT BACKINGSTREAM CHAR))
         (BOUT BACKINGSTREAM (CHARCODE CR])

(\C150.ALLWHITESPACE
  [LAMBDA (BITMAP TABLES STARTINGSCAN)                                     (* hdj 
                                                                           " 6-Aug-85 15:50")
                                                                           (* is there anything to 
                                                                           print on the next 4 
                                                                           scanlines?)
    (LET*((MaxX (SUB1 (BITMAPWIDTH BITMAP)))
          [MaxColor (SUB1 (EXPT 2 (BITSPERPIXEL BITMAP]
          (COLORUSED? (ARRAY (ADD1 MaxColor)
                             (QUOTE POINTER)
                             NIL 0))
          (BlackTable (ELT TABLES 0))
          (MagentaTable (ELT TABLES 1))
          (YellowTable (ELT TABLES 2))
          (CyanTable (ELT TABLES 3)))
     (for Scanline from STARTINGSCAN to (IDIFFERENCE STARTINGSCAN 3) by -1
        do (for X from 0 to MaxX do (SETA COLORUSED? (BITMAPBIT BITMAP X Scanline)
                                          T)))
     (for Value from 0 to MaxColor never (AND (ELT COLORUSED? Value)
                                              (OR (EQ (ELT BlackTable Value)
                                                      1)
                                                  (EQ (ELT MagentaTable Value)
                                                      1)
                                                  (EQ (ELT YellowTable Value)
                                                      1)
                                                  (EQ (ELT CyanTable Value)
                                                      1])

(\C150.BUFFER.DOT
  [LAMBDA (DOT X BUFFER)                                                   (* hdj 
                                                                           " 3-Aug-85 20:55")
    (SETA BUFFER X DOT])

(\C150.MICROLINEFEED
  [LAMBDA (BACKINGSTREAM)                                                  (* hdj 
                                                                           " 5-Sep-85 12:12")
    (for CHAR instring "k1" do (BOUT BACKINGSTREAM CHAR])

(\C150.SENDLINE
  [LAMBDA (BACKINGSTREAM LINE# COLOR BUFFER)                               (* hdj 
                                                                           " 5-Sep-85 12:13")
    (for CHAR instring (CONCAT "g" (CHARACTER (IPLUS (ITIMES 4 COLOR)
                                                      (IREMAINDER LINE# 4)
                                                      (CHARCODE 0)))
                              (FOLDHI (ARRAYSIZE BUFFER)
                                     8)
                              " ") do (BOUT BACKINGSTREAM CHAR))
    (bind (BYTE.TO.SEND ← 0) for BYTE from 0 to (SUB1 (ARRAYSIZE BUFFER)) by 8
       do [for BIT from 7 to 0 by -1 do (SETQ BYTE.TO.SEND (LOGOR BYTE.TO.SEND
                                                                  (LLSH (ELT BUFFER (IPLUS BYTE BIT))
                                                                        BIT]
          (BOUT BACKINGSTREAM BYTE.TO.SEND])

(\C150.SENDLINEINFO
  [LAMBDA (BACKINGSTREAM COLOR LENGTHINBYTES LINE#)                        (* hdj 
                                                                           " 5-Sep-85 12:13")
    (for CHAR instring (CONCAT "g" (CHARACTER (IPLUS (UNFOLD COLOR 4)
                                                      LINE#
                                                      (CHARCODE 0)))
                              LENGTHINBYTES " ") do (BOUT BACKINGSTREAM CHAR])

(\C150INIT
  [LAMBDA NIL                                                              (* gbn 
                                                                           " 5-Nov-85 19:34")
                                                                           (* Initializes global 
                                                                           variables for the C150)
    (DECLARE (GLOBALVARS \C150IMAGEOPS))
    (SETQ \C150IMAGEOPS (create IMAGEOPS
                               IMAGETYPE ←(QUOTE C150)
                               IMFONT ←(FUNCTION \DSPFONT.C150)
                               IMLEFTMARGIN ←(FUNCTION \DSPLEFTMARGIN.C150)
                               IMRIGHTMARGIN ←(FUNCTION \DSPRIGHTMARGIN.C150)
                               IMLINEFEED ←(FUNCTION \DSPLINEFEED.C150)
                               IMXPOSITION ←(FUNCTION \DSPXPOSITION.C150)
                               IMYPOSITION ←(FUNCTION \DSPYPOSITION.C150)
                               IMCLOSEFN ←(FUNCTION \CLOSEFN.C150)
                               IMDRAWCURVE ←(FUNCTION \DRAWCURVE.C150)
                               IMFILLCIRCLE ←(QUOTE \FILLCIRCLE.C150)
                               IMDRAWLINE ←(FUNCTION \DRAWLINE.C150)
                               IMDRAWELLIPSE ←(FUNCTION \DRAWELLIPSE.C150)
                               IMDRAWCIRCLE ←(FUNCTION \DRAWCIRCLE.C150)
                               IMBITBLT ←(FUNCTION \BITBLT.C150)
                               IMBLTSHADE ←(FUNCTION \BLTSHADE.C150)
                               IMNEWPAGE ←(FUNCTION NEWPAGE.C150)
                               IMSCALE ←[FUNCTION (LAMBDA NIL
                                                    (FQUOTIENT 120 72]
                               IMSPACEFACTOR ←(FUNCTION NILL)
                               IMFONTCREATE ←(QUOTE C150)
                               IMCOLOR ←(FUNCTION \DSPCOLOR.C150)
                               IMBACKCOLOR ←(FUNCTION \DSPBACKCOLOR.C150)
                               IMOPERATION ←(FUNCTION \DSPOPERATION.C150)
                               IMSTRINGWIDTH ←(FUNCTION \STRINGWIDTH.C150)
                               IMCHARWIDTH ←(FUNCTION \CHARWIDTH.C150)
                               IMCLIPPINGREGION ←(FUNCTION \DSPCLIPPINGREGION.C150)
                               IMRESET ←(FUNCTION \DSPRESET.C150)
                               IMFILLPOLYGON ←(FUNCTION POLYSHADE.BLT)))
    [push IMAGESTREAMTYPES (LIST (QUOTE C150)
                                 (LIST (QUOTE OPENSTREAM)
                                       (FUNCTION OPENC150STREAM))
                                 (LIST (QUOTE FONTCREATE)
                                       (FUNCTION \CREATEC150FONT))
                                 (LIST (QUOTE FONTSAVAILABLE)
                                       (FUNCTION \SEARCHC150FONTFILES))
                                 (LIST (QUOTE CREATECHARSET)
                                       (FUNCTION \CREATECHARSET.C150]
    (push PRINTERTYPES (LIST (LIST (QUOTE C150))
                             (LIST (QUOTE CANPRINT)
                                   (LIST (QUOTE C150)))
                             (LIST (QUOTE STATUS)
                                   (FUNCTION TRUE))
                             (LIST (QUOTE PROPERTIES)
                                   (FUNCTION NILL))
                             (LIST (QUOTE SEND)
                                   (FUNCTION SEND.TO.C150))
                             (LIST (QUOTE BITMAPSCALE)
                                   NIL)
                             (LIST (QUOTE BITMAPFILE)
                                   NIL)))
    (ADDTOVAR DEFAULTPRINTINGHOST (C150 C150))
    (PUTPROP (QUOTE C150)
           (QUOTE PRINTERTYPE)
           (QUOTE C150))
    [push PRINTFILETYPES (LIST (QUOTE C150)
                               (LIST (QUOTE TEST)
                                     (FUNCTION NILL))
                               (LIST (QUOTE EXTENSION)
                                     (LIST (QUOTE C150]
    (DEFAULTFONT (QUOTE C150)
           (QUOTE (CLASSIC 10 MRR))
           (QUOTE NEW))
    T])

(\CREATECHARSET.C150
  [LAMBDA (FAMILY SIZE FACE ROTATION DEVICE CHARSET FONTDESC NOSLUG?)      (* gbn 
                                                                           " 9-Jan-86 13:00")
            
            (* * tries to build the csinfo required for CHARSET.
            Does the necessary coercions. Returns NIL when unsuccessful
            (\CREATECHARSET will do the same))
            
            (* * NOSLUG? means don't create an empty
            (slug) csinfo if the charset is not found, just return NIL)

    (DECLARE (GLOBALVARS C150FONTCOERCIONS MISSINGC150FONTCOERCIONS))
            
            (* C150FONTCOERCIONS is a list of font coercions, in the form
            ((user-font real-font) (user-font real-font) ...)%.
            Each user-font is a list of FAMILY, and optionally SIZE and CHARSET,
            (e.g., (GACHA) or (GACHA 10) or (GACHA 10 143)), and each real-font is a 
            similar list.)

    (COND
       ((PROG1 (for TRANSL in C150FONTCOERCIONS bind NEWCSINFO USERFONT REALFONT
                  when (AND (SETQ USERFONT (CAR TRANSL))
                            (EQ FAMILY (CAR USERFONT))
                            (OR (NOT (CADR USERFONT))
                                (EQ SIZE (CADR USERFONT)))
                            (OR (NOT (CADDR USERFONT))
                                (EQ CHARSET (CADDR USERFONT)))
                            (SETQ REALFONT (CADR TRANSL))
                            (SETQ NEWCSINFO (\CREATECHARSET.C150 (OR (CAR REALFONT)
                                                                     FAMILY)
                                                   (OR (CADR REALFONT)
                                                       SIZE)
                                                   FACE ROTATION DEVICE (OR (CADDR REALFONT)
                                                                            CHARSET)
                                                   FONTDESC NOSLUG?))) do (RETURN NEWCSINFO))
                                                                           (* Just recursively 
                                                                           call ourselves to 
                                                                           handle entries in 
                                                                           C150FONTCOERCIONS)
               ))
       ((AND (EQ ROTATION 0)                                               (* If it is available, 
                                                                           this will force the 
                                                                           appropriate file to be 
                                                                           read to fill in the 
                                                                           charset entry)
             (\READC150FONTFILE FAMILY SIZE FACE ROTATION (QUOTE C150)
                    CHARSET)))
       (T   
            (* * if we get here, the font is not directly available, either it needs 
            to be rotated, boldified, or italicised "by hand")

          (PROG (NEWFONT XFONT XLATEDFAM)
                (RETURN (COND
                           [(NEQ ROTATION 0)
            
            (* to make a rotated font (even if it is bold or whatnot), recursively 
            call fontcreate to get the unrotated font
            (maybe bold, etc), then call \SFMAKEROTATEDFONT on the csinfo.)

                            (OR (MEMB ROTATION (QUOTE (90 270)))
                                (ERROR "only implemented rotations are 0, 90 and 270." ROTATION))
                            (COND
                               ((SETQ XFONT (FONTCREATE FAMILY SIZE FACE 0 (QUOTE C150)
                                                   T CHARSET))
            
            (* actually call FONTCREATE here, rather than \CREATEC150FONT or 
            \CREATECHARSET.C150 so that the vanilla font that is built in this process 
            will be cached and not repeated.)

                                (if (SETQ CSINFO (\GETCHARSETINFO CHARSET XFONT T))
                                    then (\SFROTATECSINFO CSINFO ROTATION)
                                  else NIL]
                           ((AND (EQ (fetch WEIGHT of FACE)
                                     (QUOTE BOLD))
                                 (SETQ XFONT (FONTCREATE FAMILY SIZE (create FONTFACE
                                                                        using FACE WEIGHT ←(QUOTE
                                                                                            MEDIUM))
                                                    0
                                                    (QUOTE C150)
                                                    T CHARSET)))           (* if we want a bold 
                                                                           font, and the medium 
                                                                           weight font is 
                                                                           available, build the 
                                                                           medium weight version 
                                                                           then call \SFMAKEBOLD 
                                                                           on the csinfo)
                            (if (SETQ CSINFO (\GETCHARSETINFO CHARSET XFONT T))
                                then (\SFMAKEBOLD CSINFO)
                              else NIL))
                           ((AND (EQ (fetch SLOPE of FACE)
                                     (QUOTE ITALIC))
                                 (SETQ XFONT (FONTCREATE FAMILY SIZE (create FONTFACE
                                                                        using FACE SLOPE ←(QUOTE
                                                                                           REGULAR))
                                                    0
                                                    (QUOTE C150)
                                                    T CHARSET)))
                            (if (SETQ CSINFO (\GETCHARSETINFO CHARSET XFONT T))
                                then (\SFMAKEITALIC CSINFO)
                              else NIL))
                           ((for TRANSL in MISSINGC150FONTCOERCIONS bind NEWCSINFO USERFONT REALFONT
                               when (AND (SETQ USERFONT (CAR TRANSL))
                                         (EQ FAMILY (CAR USERFONT))
                                         (OR (NOT (CADR USERFONT))
                                             (EQ SIZE (CADR USERFONT)))
                                         (OR (NOT (CADDR USERFONT))
                                             (EQ CHARSET (CADDR USERFONT)))
                                         (SETQ REALFONT (CADR TRANSL))
                                         (SETQ NEWCSINFO (\CREATECHARSET.C150 (OR (CAR REALFONT)
                                                                                  FAMILY)
                                                                (OR (CADR REALFONT)
                                                                    SIZE)
                                                                FACE ROTATION DEVICE
                                                                (OR (CADDR REALFONT)
                                                                    CHARSET)
                                                                FONTDESC NOSLUG?)))
                               do (RETURN NEWCSINFO)))
                           ((NOT NOSLUG?)
                            (\BUILDSLUGCSINFO (fetch (FONTDESCRIPTOR FONTAVGCHARWIDTH) of FONTDESC)
                                   (FONTPROP FONTDESC (QUOTE ASCENT))
                                   (FONTPROP FONTDESC (QUOTE DESCENT))
                                   (FONTPROP FONTDESC (QUOTE DEVICE])
)
(DEFINEQ

(CREATEC150BUFFER
  [LAMBDA (WIDTH HEIGHT)                                                   (* FS " 3-Apr-86 18:14")
    (LET*((BITWIDTH (ITIMES WIDTH \C150RealBPP))
          (RASTERWIDTH (FOLDHI BITWIDTH BITSPERWORD))
          (PAGES (FOLDHI (ITIMES RASTERWIDTH HEIGHT)
                        WORDSPERPAGE)))
            
            (* * (create BITMAP BITMAPBITSPERPIXEL ← \C150RealBPP BITMAPRASTERWIDTH ← 
            RASTERWIDTH BITMAPWIDTH ← BITWIDTH BITMAPHEIGHT ← HEIGHT BITMAPBASE ←
            (OR (\ALLOCPAGEBLOCK PAGES) (HELP 
            "Can't allocate C150 buffer - pages needed = " PAGES))))
            
            (* * Don't think code above is correct, commented out and added below, 
            changing BITMAPWIDTH, and ignoring \MaxBitMapWords
            (safe?????) * *)

     (create BITMAP
            BITMAPBITSPERPIXEL ← \C150RealBPP
            BITMAPRASTERWIDTH ← RASTERWIDTH
            BITMAPWIDTH ← WIDTH
            BITMAPHEIGHT ← HEIGHT
            BITMAPBASE ←(OR (\ALLOCPAGEBLOCK PAGES)
                            (HELP "Can't allocate C150 buffer - pages needed = " PAGES])

(NEWLINE.C150
  [LAMBDA (C150STREAM)                                                     (* hdj 
                                                                           " 6-Jun-85 14:01")
                                                                           (* Go to next line
                                                                           (or next page if on 
                                                                           last line))
    (LET*[(C150DATA (fetch IMAGEDATA of C150STREAM))
          (NEWYPOS (IPLUS (ffetch DDYPOSITION of C150DATA)
                          (ffetch DDLINEFEED of C150DATA]
     (COND
        ((ILESSP NEWYPOS (ffetch DDClippingBottom of C150DATA))
         (NEWPAGE.C150 C150STREAM))
        (T (\DSPXPOSITION.C150 C150STREAM (ffetch DDLeftMargin of C150DATA))
           (\DSPYPOSITION.C150 C150STREAM NEWYPOS])

(NEWPAGE.C150
  [LAMBDA (C150STREAM)                                                     (* hdj 
                                                                           " 7-Aug-85 16:48")
    (LET ((DD (fetch (STREAM IMAGEDATA) of C150STREAM)))
         [\DUMPPAGEBUFFER.C150 (fetch DDDestination of DD)
                C150STREAM
                (OR \C150COLORTABLE (SETQ \C150COLORTABLE (COLORMAP.TO.C150TABLE C150COLORMAP]
         (STARTPAGE.C150 C150STREAM])

(OPENC150STREAM
  [LAMBDA (C150FILE OPTIONS)                                               (* gbn 
                                                                           " 6-Nov-85 19:08")
                                                                           (* Opens a C150 stream)
            
            (* open a C150 stream. keep a permanent pointer to the frame buffer, 
            because it can never be gc'ed any way, and we want to recycle it --
            only allow one of them to be open at a time, due to global frame buffer)

    (DECLARE (GLOBALVARS \C150IMAGEOPS C150BAUDRATE \C150STREAM))
    (if (AND (STREAMP \C150STREAM)
             (OPENP \C150STREAM))
        then (ERROR "Sorry - you can only have one C150 stream open at one time" \C150STREAM)
      else (if (EQ (FILENAMEFIELD C150FILE (QUOTE HOST))
                   (QUOTE LPT))
               then                                                        (* if the hardcopy 
                                                                           interface is opening to 
                                                                           the LPT pseudodevice, 
                                                                           change it to be the 
                                                                           device that the printer 
                                                                           is actually connected 
                                                                           to.)
                    (SETQ C150FILE (PACKFILENAME (QUOTE HOST)
                                          \C150DEFAULTDEVICE
                                          (QUOTE BODY)
                                          C150FILE)))
           (LET*[(WIDTH (FIX (TIMES 8.5 \C150PointsPerInch)))
                 (HEIGHT (FIX (TIMES 11 \C150PointsPerInch)))
                 (BACKINGSTREAM (OPENSTREAM C150FILE (QUOTE OUTPUT)))
                 (C150STREAM (SETQ \C150STREAM (DSPCREATE (OR \C150.FRAMEBUFFER (SETQ 
                                                                                 \C150.FRAMEBUFFER
                                                                                 (CREATEC150BUFFER
                                                                                  WIDTH HEIGHT]
            (replace (STREAM F1) of C150STREAM with BACKINGSTREAM)
            (replace (STREAM OUTCHARFN) of C150STREAM with (FUNCTION \OUTCHARFN.C150))
            (replace (STREAM STRMBOUTFN) of C150STREAM with (FUNCTION \DSPPRINTCHAR.C150))
            (replace (STREAM USERCLOSEABLE) of C150STREAM with T)
            (replace (STREAM IMAGEOPS) of C150STREAM with \C150IMAGEOPS)
            (replace (\DISPLAYDATA DDClippingRegion) of (\GETDISPLAYDATA C150STREAM)
               with (CREATEREGION 0 0 WIDTH HEIGHT))
            (STREAMPROP C150STREAM (QUOTE COLORMAPCACHE)
                   (LIST NIL))
            (DSPLEFTMARGIN 0 C150STREAM)
            (DSPRIGHTMARGIN WIDTH C150STREAM)
            (DSPCOLOR 0 C150STREAM)
            (DSPBACKCOLOR 7 C150STREAM)
            (STARTPAGE.C150 C150STREAM)
            C150STREAM])

(C150.RESET
  [LAMBDA NIL                                                              (* gbn 
                                                                           " 7-Nov-85 22:42")
            
            (* * just does things that the user prob doesn't know about.)

    (SETQ \C150STREAM)
    (CLOSEF? (QUOTE {CENTRONICS}))
    (CENTRONICS.RESET])

(SEND.TO.C150
  [LAMBDA (HOST FILE PRINTOPTIONS)                                         (* hdj 
                                                                           " 6-Jun-85 15:37")
    (COPYFILE FILE (PACKFILENAME (QUOTE HOST)
                          (QUOTE LPT)
                          (QUOTE NAME)
                          HOST
                          (QUOTE EXTENSION)
                          (QUOTE C150])

(STARTPAGE.C150
  [LAMBDA (C150STREAM)                                                     (* hdj 
                                                                           " 6-Aug-85 11:20")
    (LET*((DD (\GETDISPLAYDATA C150STREAM))
          (CREG (fetch DDClippingRegion of DD))
          (FONTASCENT (FONTASCENT (fetch DDFONT of DD)))
          (PAGEBUFFER (fetch DDDestination of DD)))
     (BLTSHADE (DSPBACKCOLOR NIL C150STREAM)
            PAGEBUFFER)
     (\DSPXPOSITION.C150 C150STREAM (fetch DDLeftMargin of DD))
     (\DSPYPOSITION.C150 C150STREAM (ADD1 (IDIFFERENCE (fetch TOP of CREG)
                                                 FONTASCENT])

(\BITBLT.C150
  [LAMBDA (SOURCEBITMAP SOURCELEFT SOURCEBOTTOM DESTSTRM DESTINATIONLEFT DESTINATIONBOTTOM WIDTH 
                 HEIGHT SOURCETYPE OPERATION TEXTURE CLIPPINGREGION CLIPPEDSOURCELEFT 
                 CLIPPEDSOURCEBOTTOM)                                      (* hdj 
                                                                           " 6-Jun-85 16:17")
    (DECLARE (LOCALVARS . T))
    (PROG (stodx stody left top bottom right DESTBITMAP DESTINATIONNBITS (SOURCENBITS
                                                                          (fetch (BITMAP 
                                                                                   BITMAPBITSPERPIXEL
                                                                                        )
                                                                             of SOURCEBITMAP))
                 (DESTDD (fetch IMAGEDATA of DESTSTRM)))
          (SETQ DESTBITMAP (fetch DDDestination of DESTDD))
          [PROGN                                                           (* compute limits based 
                                                                           on clipping regions.)
                 (SETQ left (fetch DDClippingLeft of DESTDD))
                 (SETQ bottom (fetch DDClippingBottom of DESTDD))
                 (SETQ right (fetch DDClippingRight of DESTDD))
                 (SETQ top (fetch DDClippingTop of DESTDD))
                 (COND
                    (CLIPPINGREGION                                        (* hard case, two 
                                                                           destination clipping 
                                                                           regions: do 
                                                                           calculations to merge 
                                                                           them.)
                           (PROG (CRLEFT CRBOTTOM)
                                 [SETQ left (IMAX left (SETQ CRLEFT (fetch LEFT of CLIPPINGREGION]
                                 [SETQ bottom (IMAX bottom (SETQ CRBOTTOM (fetch BOTTOM of 
                                                                                       CLIPPINGREGION
                                                                                 ]
                                 [SETQ right (IMIN right (IPLUS CRLEFT (fetch WIDTH of CLIPPINGREGION
                                                                              ]
                                 (SETQ top (IMIN top (IPLUS CRBOTTOM (fetch HEIGHT of CLIPPINGREGION]
          (SETQ DESTINATIONNBITS (fetch (BITMAP BITMAPBITSPERPIXEL) of DESTBITMAP))
                                                                           (* left, right top and 
                                                                           bottom are the limits 
                                                                           in destination taking 
                                                                           into account Clipping 
                                                                           Regions. Clip to region 
                                                                           in the arguments of 
                                                                           this call.)
          [PROGN (SETQ left (IMAX DESTINATIONLEFT left))
                 (SETQ bottom (IMAX DESTINATIONBOTTOM bottom))
                 [COND
                    (WIDTH                                                 (* WIDTH is optional)
                           (SETQ right (IMIN (IPLUS DESTINATIONLEFT WIDTH)
                                             right]
                 (COND
                    (HEIGHT                                                (* HEIGHT is optional)
                           (SETQ top (IMIN (IPLUS DESTINATIONBOTTOM HEIGHT)
                                           top]                            (* Clip and translate 
                                                                           coordinates.)
          (SETQ stodx (IDIFFERENCE DESTINATIONLEFT SOURCELEFT))
          (SETQ stody (IDIFFERENCE DESTINATIONBOTTOM SOURCEBOTTOM))
            
            (* compute the source dimensions (left right bottom top) by intersecting 
            the source bit map, the source area to be moved with the limits of the 
            region to be moved in the destination coordinates.)

          [PROGN                                                           (* compute left margin)
                 (SETQ left (IMAX CLIPPEDSOURCELEFT (IDIFFERENCE left stodx)
                                  0))                                      (* compute bottom 
                                                                           margin)
                 (SETQ bottom (IMAX CLIPPEDSOURCEBOTTOM (IDIFFERENCE bottom stody)
                                    0))                                    (* compute right margin)
                 (SETQ right (IMIN (\PIXELOFBITADDRESS SOURCENBITS (ffetch BITMAPWIDTH of 
                                                                                         SOURCEBITMAP
                                                                          ))
                                   (IDIFFERENCE right stodx)
                                   (IPLUS CLIPPEDSOURCELEFT WIDTH)))       (* compute top margin)
                 (SETQ top (IMIN (ffetch BITMAPHEIGHT of SOURCEBITMAP)
                                 (IDIFFERENCE top stody)
                                 (IPLUS CLIPPEDSOURCEBOTTOM HEIGHT]
          (COND
             ((AND (IGREATERP right left)
                   (IGREATERP top bottom)))
             (T                                                            (* there is nothing to 
                                                                           move.)
                (RETURN)))
          (OR OPERATION (SETQ OPERATION (ffetch (\DISPLAYDATA DDOPERATION) of DESTDD)))
            
            (* We'd rather handle the slow case when we are interruptable, so we do it 
            here as a heuristic. But we might get interrupted before we go 
            interruptable, so we do it there too.)

          (COND
             [(EQ SOURCENBITS DESTINATIONNBITS)                            (* going from one to 
                                                                           another of the same 
                                                                           size.)
                                                                           (* use LLSH with 
                                                                           constant value rather 
                                                                           than multiple because 
                                                                           it compiles into 
                                                                           opcodes.)
              [COND
                 ((EQ DESTINATIONNBITS 4)
                  (SETQ left (LLSH left 2))
                  (SETQ right (LLSH right 2))
                  (SETQ stodx (LLSH stodx 2)))
                 (T (SETQ left (LLSH left 3))
                    (SETQ right (LLSH right 3))
                    (SETQ stodx (LLSH stodx 3]                             (* set texture if it 
                                                                           will ever get looked 
                                                                           at.)
              (AND (EQ SOURCETYPE (QUOTE MERGE))
                   (SETQ TEXTURE (COLORTEXTUREFROMCOLOR# TEXTURE DESTINATIONNBITS)))
                                                                           (* easy case of color 
                                                                           to color)
              (PROG ([PILOTBBT (COND
                                  ((type? PILOTBBT \SYSPILOTBBT)
                                   \SYSPILOTBBT)
                                  (T (SETQ \SYSPILOTBBT (create PILOTBBT]
                     (HEIGHT (IDIFFERENCE top bottom))
                     (WIDTH (IDIFFERENCE right left))
                     (DTY (\SFInvert DESTBITMAP (IPLUS top stody)))
                     (DLX (IPLUS left stodx))
                     (STY (\SFInvert SOURCEBITMAP top))
                     (SLX left))
                    (replace PBTWIDTH of PILOTBBT with WIDTH)
                    (replace PBTHEIGHT of PILOTBBT with HEIGHT)
                    (COND
                       ((EQ SOURCETYPE (QUOTE MERGE))
                        (\BITBLT.MERGE PILOTBBT SOURCEBITMAP SLX STY DESTBITMAP DLX DTY WIDTH HEIGHT 
                               OPERATION TEXTURE))
                       (T (\BITBLTSUB PILOTBBT SOURCEBITMAP SLX STY DESTBITMAP DLX DTY HEIGHT 
                                 SOURCETYPE OPERATION TEXTURE]
             [(EQ SOURCENBITS 1)                                           (* going from a black 
                                                                           and white bitmap to a 
                                                                           color map)
              (AND SOURCETYPE (NEQ SOURCETYPE (QUOTE INPUT))
                   (ERROR "SourceType not implemented from B&W to color bitmaps." SOURCETYPE))
              (PROG ((HEIGHT (IDIFFERENCE top bottom))
                     (WIDTH (IDIFFERENCE right left))
                     (DBOT (IPLUS bottom stody))
                     (DLFT (IPLUS left stodx)))
                    (SELECTQ OPERATION
                        ((NIL REPLACE) 
                             (\BWTOCOLORBLT SOURCEBITMAP left bottom DESTBITMAP DLFT DBOT WIDTH 
                                    HEIGHT (COLORNUMBERP (fetch (\DISPLAYDATA DDBACKGROUNDCOLOR)
                                                            of DESTDD))
                                    (COLORNUMBERP (fetch (\DISPLAYDATA DDFOREGROUNDCOLOR)
                                                     of DESTDD))
                                    DESTINATIONNBITS))
                        (PAINT)
                        (INVERT)
                        (ERASE)
                        (SHOULDNT]
             (T                                                            (* going from color map 
                                                                           into black and white 
                                                                           map.)
                (ERROR "not implemented to blt between bitmaps of different pixel size.")))
          (RETURN T])

(\BLTCHAR.C150
  [LAMBDA (CHARCODE C150STREAM C150DATA)                                   (* hdj 
                                                                           "19-Jul-85 13:32")
            
            (* * puts a character on a C150STREAM.
            Since a C150STREAM is based on a color bitmap stream, we can use 
            \SLOWBLTCHAR)

    [COND
       ((NEQ (ffetch DDCHARSET of C150DATA)
             (\CHARSET CHARCODE))                                          (* The charset has 
                                                                           changed.)
        (\CHANGECHARSET.C150 C150DATA (\CHARSET CHARCODE]
    (LET [(CHAR8CODE (\CHAR8CODE CHARCODE))
          (ROTATION (ffetch (FONTDESCRIPTOR ROTATION) of (ffetch DDFONT of C150DATA]
         (COND
            [(EQ 0 ROTATION)
             (PROG (NEWX LEFT RIGHT (CURX (ffetch DDXPOSITION of C150DATA)))
                   [COND
                      ((IGREATERP (SETQ NEWX (IPLUS CURX (\DSPGETCHARWIDTH CHAR8CODE C150DATA)))
                              (ffetch DDRightMargin of C150DATA))          (* past RIGHT margin, 
                                                                           force eol)
                       (\DSPPRINTCR/LF.C150 (CHARCODE EOL)
                              C150STREAM)
                       (SETQ CURX (ffetch DDXPOSITION of C150DATA))
                       (SETQ NEWX (IPLUS CURX (\DSPGETCHARWIDTH CHAR8CODE C150DATA]
                                                                           (* update the x 
                                                                           position.)
                   (freplace DDXPOSITION of C150DATA with NEWX)
                   (SETQ LEFT (IMAX (ffetch DDClippingLeft of C150DATA)
                                    CURX))
                   (SETQ RIGHT (IMIN (ffetch DDClippingRight of C150DATA)
                                     NEWX))
                   (COND
                      ((AND (ILESSP LEFT RIGHT)
                            (NEQ (ffetch PBTHEIGHT of (SETQ NEWX (ffetch DDPILOTBBT of C150DATA)))
                                 0))
                       (SELECTQ (ffetch (BITMAP BITMAPBITSPERPIXEL) of (ffetch (\DISPLAYDATA 
                                                                                      DDDestination)
                                                                          of C150DATA))
                           (1 (freplace PBTDESTBIT of NEWX with LEFT)
                              (freplace PBTWIDTH of NEWX with (IDIFFERENCE RIGHT LEFT))
                              (freplace PBTSOURCEBIT of NEWX with (IDIFFERENCE (IPLUS (
                                                                                    \DSPGETCHAROFFSET
                                                                                       CHAR8CODE 
                                                                                       C150DATA)
                                                                                      LEFT)
                                                                         CURX))
                              (\PILOTBITBLT NEWX 0))
                           (4 (freplace PBTDESTBIT of NEWX with (SETQ LEFT (LLSH LEFT 2)))
                              (freplace PBTWIDTH of NEWX with (IDIFFERENCE (LLSH RIGHT 2)
                                                                     LEFT))
                              (freplace PBTSOURCEBIT of NEWX
                                 with (IDIFFERENCE (IPLUS (LLSH (\DSPGETCHAROFFSET CHAR8CODE C150DATA
                                                                       )
                                                                2)
                                                          LEFT)
                                             (LLSH CURX 2)))
                              (\PILOTBITBLT NEWX 0))
                           (8 (freplace PBTDESTBIT of NEWX with (SETQ LEFT (LLSH LEFT 3)))
                              (freplace PBTWIDTH of NEWX with (IDIFFERENCE (LLSH RIGHT 3)
                                                                     LEFT))
                              (freplace PBTSOURCEBIT of NEWX
                                 with (IDIFFERENCE (IPLUS (LLSH (\DSPGETCHAROFFSET CHAR8CODE C150DATA
                                                                       )
                                                                3)
                                                          LEFT)
                                             (LLSH CURX 3)))
                              (\PILOTBITBLT NEWX 0))
                           (SHOULDNT))
                       T]
            (T                                                             (* handle rotated fonts)
               (LET [(YPOS (ffetch DDYPOSITION of C150DATA))
                     (HEIGHTMOVED (\DSPGETCHARWIDTH CHAR8CODE C150DATA))
                     (CSINFO (\GETCHARSETINFO (\CHARSET CHARCODE)
                                    (ffetch DDFONT of C150DATA]
                    (COND
                       ((EQ ROTATION 90)                                   (* don't force CR for 
                                                                           rotated fonts.)
                        (\DSPYPOSITION.C150 C150STREAM (IPLUS YPOS HEIGHTMOVED))
                                                                           (* update the display 
                                                                           stream x position.)
                        (BITBLT (ffetch (CHARSETINFO CHARSETBITMAP) of CSINFO)
                               0
                               (\DSPGETCHAROFFSET CHAR8CODE C150DATA)
                               C150STREAM
                               (ADD1 (IDIFFERENCE (ffetch DDXPOSITION of C150DATA)
                                            (ffetch (CHARSETINFO CHARSETASCENT) of CSINFO)))
                               YPOS
                               (IPLUS (ffetch (CHARSETINFO CHARSETASCENT) of CSINFO)
                                      (ffetch (CHARSETINFO CHARSETDESCENT) of CSINFO))
                               HEIGHTMOVED))
                       ((EQ ROTATION 270)
                        (\DSPYPOSITION.C150 C150STREAM (IDIFFERENCE YPOS HEIGHTMOVED))
                        (BITBLT (ffetch (CHARSETINFO CHARSETBITMAP) of CSINFO)
                               0
                               (\DSPGETCHAROFFSET CHAR8CODE C150DATA)
                               C150STREAM
                               (IDIFFERENCE (ffetch DDXPOSITION of C150DATA)
                                      (ffetch (CHARSETINFO CHARSETDESCENT) of CSINFO))
                               (ffetch DDYPOSITION of C150STREAM)
                               (IPLUS (ffetch (CHARSETINFO CHARSETASCENT) of CSINFO)
                                      (ffetch (CHARSETINFO CHARSETDESCENT) of CSINFO))
                               HEIGHTMOVED))
                       (T (ERROR "Not implemented to rotate by other than 0, 90 or 270"])

(\BLTSHADE.C150
  [LAMBDA (TEXTURE STREAM DESTINATIONLEFT DESTINATIONBOTTOM WIDTH HEIGHT OPERATION CLIPPINGREGION)
                                                                           (* gbn 
                                                                           " 5-Nov-85 18:42")
                                                                           (* BLTSHADE to C150 
                                                                           color printer)
    (DECLARE (LOCALVARS . T))
    (PROG (left top bottom right DESTINATIONNBITS DESTINATIONBITMAP (DESTDD (fetch IMAGEDATA
                                                                               of STREAM)))
          (SETQ DESTINATIONLEFT DESTINATIONLEFT)
          (SETQ DESTINATIONBOTTOM DESTINATIONBOTTOM)
          [PROGN                                                           (* compute limits based 
                                                                           on clipping regions.)
                 (SETQ left (fetch DDClippingLeft of DESTDD))
                 (SETQ bottom (fetch DDClippingBottom of DESTDD))
                 (SETQ right (fetch DDClippingRight of DESTDD))
                 (SETQ top (fetch DDClippingTop of DESTDD))
                 (COND
                    (CLIPPINGREGION                                        (* hard case, two 
                                                                           destination clipping 
                                                                           regions: do 
                                                                           calculations to merge 
                                                                           them.)
                           (PROG (CRLEFT CRBOTTOM)
                                 [SETQ left (IMAX left (SETQ CRLEFT (fetch LEFT of CLIPPINGREGION]
                                 [SETQ bottom (IMAX bottom (SETQ CRBOTTOM (fetch BOTTOM of 
                                                                                       CLIPPINGREGION
                                                                                 ]
                                 [SETQ right (IMIN right (IPLUS CRLEFT (fetch WIDTH of CLIPPINGREGION
                                                                              ]
                                 (SETQ top (IMIN top (IPLUS CRBOTTOM (fetch HEIGHT of CLIPPINGREGION]
          [SETQ DESTINATIONNBITS (fetch (BITMAP BITMAPBITSPERPIXEL) of (SETQ DESTINATIONBITMAP
                                                                        (fetch DDDestination
                                                                           of DESTDD]
                                                                           (* SETQ right
                                                                           (\PIXELOFBITADDRESS 
                                                                           DESTINATIONNBITS right))
                                                                           (* left, right top and 
                                                                           bottom are the limits 
                                                                           in destination taking 
                                                                           into account Clipping 
                                                                           Regions. Clip to region 
                                                                           in the arguments of 
                                                                           this call.)
          [PROGN (SETQ left (IMAX DESTINATIONLEFT left))
                 (SETQ bottom (IMAX DESTINATIONBOTTOM bottom))
                 [COND
                    (WIDTH                                                 (* WIDTH is optional)
                           (SETQ right (IMIN (IPLUS DESTINATIONLEFT WIDTH)
                                             right]
                 (COND
                    (HEIGHT                                                (* HEIGHT is optional)
                           (SETQ top (IMIN (IPLUS DESTINATIONBOTTOM HEIGHT)
                                           top]
          (COND
             ((OR (ILEQ right left)
                  (ILEQ top bottom))                                       (* there is nothing to 
                                                                           move.)
              (RETURN)))
          [SETQ TEXTURE (COND
                           ((NULL TEXTURE)
                            (DSPBACKCOLOR NIL STREAM))
                           [(FIXP TEXTURE)                                 (* if fixp use the low 
                                                                           order bits as a color 
                                                                           number. This picks up 
                                                                           the case of BLACKSHADE 
                                                                           being used to INVERT.)
                            (OR (COLORNUMBERP TEXTURE DESTINATIONNBITS T)
                                (LOGAND TEXTURE (COND
                                                   ((EQ DESTINATIONNBITS 4)
                                                    15)
                                                   (T 255]
                           (T (\C150.ASSURE.COLOR TEXTURE STREAM]          (* filling an area with 
                                                                           a texture.)
          (SETQ left (ITIMES DESTINATIONNBITS left))
          (SETQ right (ITIMES DESTINATIONNBITS right))
          (SETQ TEXTURE (COLORTEXTUREFROMCOLOR# TEXTURE DESTINATIONNBITS)) (* easy case of black 
                                                                           and white bitmap into 
                                                                           black and white or 
                                                                           color to color or 
                                                                           texture filling.)
            
            (* We'd rather handle the slow case when we are interruptable, so we do it 
            here as a heuristic. But we might get interrupted before we go 
            interruptable, so we do it there too.)

          (PROG ([PILOTBBT (COND
                              ((type? PILOTBBT \SYSPILOTBBT)
                               \SYSPILOTBBT)
                              (T (SETQ \SYSPILOTBBT (create PILOTBBT]
                 (HEIGHT (IDIFFERENCE top bottom)))
                (replace PBTWIDTH of PILOTBBT with (IDIFFERENCE right left))
                (replace PBTHEIGHT of PILOTBBT with HEIGHT)
                (\BITBLTSUB PILOTBBT NIL left NIL DESTINATIONBITMAP left (\SFInvert DESTINATIONBITMAP 
                                                                                top)
                       HEIGHT
                       (QUOTE TEXTURE)
                       (OR OPERATION (ffetch (\DISPLAYDATA DDOPERATION) of DESTDD))
                       TEXTURE))
          (RETURN T])

(\C150.CRLF
  [LAMBDA (STREAM)                                                         (* hdj 
                                                                           "25-Jan-85 17:11")
                                                                           (* Send a CRLF to the 
                                                                           printer)
    (BOUT STREAM (CHARCODE CR))
    (BOUT STREAM (CHARCODE LF])

(\CHANGECHARSET.C150
  [LAMBDA (DISPLAYDATA CHARSET)                                            (* hdj 
                                                                           "19-Jul-85 13:48")
                                                                           (* Called when the 
                                                                           character set 
                                                                           information cached in a 
                                                                           display stream doesn't 
                                                                           correspond to CHARSET)
    (PROG [BM (PBT (ffetch DDPILOTBBT of DISPLAYDATA))
              (CSINFO (COND
                         ((IEQP 1 (fetch (BITMAP BITMAPBITSPERPIXEL) of (fetch (\DISPLAYDATA 
                                                                                      DDDestination)
                                                                           of DISPLAYDATA)))
                          (\GETCHARSETINFO CHARSET (ffetch DDFONT of DISPLAYDATA)))
                         (T (\GETCOLORCSINFO (fetch (\DISPLAYDATA DDFONT) of DISPLAYDATA)
                                   (fetch DDFOREGROUNDCOLOR of DISPLAYDATA)
                                   (fetch DDBACKGROUNDCOLOR of DISPLAYDATA)
                                   (fetch (BITMAP BITMAPBITSPERPIXEL) of (fetch (\DISPLAYDATA 
                                                                                       DDDestination)
                                                                            of DISPLAYDATA))
                                   CHARSET]
          (UNINTERRUPTABLY
              (freplace DDWIDTHSCACHE of DISPLAYDATA with (ffetch (CHARSETINFO WIDTHS) of CSINFO))
              (freplace DDOFFSETSCACHE of DISPLAYDATA with (ffetch (CHARSETINFO OFFSETS) of CSINFO))
              (freplace DDCHARIMAGEWIDTHS of DISPLAYDATA with (ffetch (CHARSETINFO IMAGEWIDTHS)
                                                                 of CSINFO))
              (freplace DDCHARSET of DISPLAYDATA with CHARSET)
              (SETQ BM (ffetch CHARSETBITMAP of CSINFO))
              (freplace PBTSOURCEBPL of PBT with (UNFOLD (ffetch BITMAPRASTERWIDTH of BM)
                                                        BITSPERWORD))
              [if (OR (NEQ (ffetch DDCHARSETASCENT of DISPLAYDATA)
                           (ffetch CHARSETASCENT of CSINFO))
                      (NEQ (ffetch DDCHARSETDESCENT of DISPLAYDATA)
                           (ffetch CHARSETDESCENT of CSINFO)))
                  then (\SFFixY DISPLAYDATA CSINFO)
                else (freplace PBTSOURCE of PBT with (\ADDBASE (ffetch BITMAPBASE of BM)
                                                            (ITIMES (ffetch BITMAPRASTERWIDTH
                                                                       of BM)
                                                                   (ffetch DDCHARHEIGHTDELTA
                                                                      of DISPLAYDATA])])

(\CHARWIDTH.C150
  [LAMBDA (C150STREAM CHARCODE)                                            (* hdj 
                                                                           " 5-Jun-85 12:56")
                                                                           (* gets the width of a 
                                                                           character code in a 
                                                                           display stream.
                                                                           Need to fix up for 
                                                                           spacefactor.)
    (\FGETWIDTH (ffetch (\DISPLAYDATA DDWIDTHSCACHE) of (ffetch IMAGEDATA of C150STREAM))
           CHARCODE])

(\CLOSEFN.C150
  [LAMBDA (C150STREAM)                                                     (* hdj 
                                                                           " 4-Oct-85 12:31")
            
            (* * do cleanup prefatory to closing. dump last buffer and close the 
            backing stream)

    (LET ((DD (fetch (STREAM IMAGEDATA) of C150STREAM)))
         [\DUMPPAGEBUFFER.C150 (fetch DDDestination of DD)
                C150STREAM
                (OR \C150COLORTABLE (SETQ \C150COLORTABLE (COLORMAP.TO.C150TABLE C150COLORMAP]
         (CLOSEF (\C150BackingStream C150STREAM])

(\CREATEC150FONT
  [LAMBDA (FAMILY SIZE FACE ROTATION DEVICE CHARSET)                       (* gbn 
                                                                           " 8-Jan-86 17:09")
            
            (* * create a font for the C150, synthesizing it if we must)

    (PROG [(FONTDESC (create FONTDESCRIPTOR
                            FONTDEVICE ←(QUOTE C150)
                            FONTFAMILY ← FAMILY
                            FONTSIZE ← SIZE
                            FONTFACE ← FACE
                            \SFAscent ← 0
                            \SFDescent ← 0
                            \SFHeight ← 0
                            ROTATION ← ROTATION
                            FONTDEVICESPEC ←(LIST FAMILY SIZE FACE ROTATION (QUOTE C150]
          (if (\GETCHARSETINFO CHARSET FONTDESC T)
              then (RETURN FONTDESC)
            else (RETURN NIL])

(\READC150FONTFILE
  [LAMBDA (FAMILY SIZE FACE ROTATION DEVICE CHARSET)                       (* hdj 
                                                                           "26-Sep-85 21:49")
    (DECLARE (GLOBALVARS C150FONTEXTENSIONS C150FONTDIRECTORIES))
    (bind FONTFILE CSINFO STRM for EXT inside C150FONTEXTENSIONS
       when (SETQ FONTFILE (FINDFILE (\FONTFILENAME FAMILY SIZE FACE EXT CHARSET)
                                  T C150FONTDIRECTORIES))
       do (SETQ STRM (OPENSTREAM FONTFILE (QUOTE INPUT)))
          (RESETLST (SETQ CSINFO (\READACFONTFILE STRM FAMILY SIZE FACE))) 
            
            (* If not a recognizable format, I guess we should keep looking for 
            another possible extension, altho it would also be nice to tell the user 
            that he has a bogus file.)

          (RETURN CSINFO])

(\DRAWCIRCLE.C150
  [LAMBDA (C150STREAM CENTERX CENTERY RADIUS BRUSH DASHING)                (* gbn 
                                                                           " 9-Jan-86 13:36")
                                                                           (* \DRAWCIRCLE.C150 
                                                                           extended for color.
                                                                           Color is specified by 
                                                                           either BRUSH or the 
                                                                           DSPCOLOR of DS.)
            
            (* * how is a litatom passed in as brush?)

    (DECLARE (LOCALVARS . T))
    (COND
       ((OR (NOT (NUMBERP RADIUS))
            (ILESSP (SETQ RADIUS (FIXR RADIUS))
                   0))
        (\ILLEGAL.ARG RADIUS))
       ((EQ RADIUS 0)                                                      (* don't draw anything.)
        NIL)
       (T (GLOBALRESOURCE \BRUSHBBT
                 (PROG ((BRUSH (create BRUSH using BRUSH BRUSHCOLOR ←(\C150.ASSURE.COLOR (fetch
                                                                                          BRUSHCOLOR
                                                                                            of BRUSH)
                                                                            C150STREAM)))
                        (X 0)
                        (Y RADIUS)
                        (D (ITIMES 2 (IDIFFERENCE 1 RADIUS)))
                        DestinationBitMap LEFT RIGHTPLUS1 TOP BOTTOM BRUSHWIDTH BRUSHHEIGHT 
                        LEFTMINUSBRUSH BOTTOMMINUSBRUSH TOPMINUSBRUSH BRUSHBM DESTINATIONBASE 
                        BRUSHBASE RASTERWIDTH BRUSHRASTERWIDTH NBITSRIGHTPLUS1 OPERATION HEIGHTMINUS1 
                        CX CY (BBT \BRUSHBBT)
                        COLOR COLORBRUSHBASE NBITS (DISPLAYDATA (fetch IMAGEDATA of C150STREAM))
                        (USERFN (AND (LITATOM BRUSH)
                                     BRUSH)))                              (* many of these 
                                                                           variables are used by 
                                                                           the macro for \CURVEPT 
                                                                           that passes them to 
                                                                           \BBTCURVEPT and 
                                                                           .SETUP.FOR.\BBTCURVEPT.
                                                                           sets them up.)
                       (COND
                          (USERFN                                          (* if calling user fn, 
                                                                           don't bother with set 
                                                                           up and leave points in 
                                                                           stream coordinates.)
                                 (SETQ CX CENTERX)
                                 (SETQ CY CENTERY))
                          (T (.SETUP.FOR.\BBTCURVEPT.)
                             (SELECTQ NBITS
                                 (1 (SETQ CX (IDIFFERENCE CENTERX (FOLDLO BRUSHWIDTH 2))))
                                 (4 (SETQ CX (IDIFFERENCE CENTERX (FOLDLO (LRSH BRUSHWIDTH 2)
                                                                         2))))
                                 (8 (SETQ CX (IDIFFERENCE CENTERX (FOLDLO (LRSH BRUSHWIDTH 3)
                                                                         2))))
                                 (SHOULDNT))                               (* take into account 
                                                                           the brush thickness.)
                             (SETQ CY (IDIFFERENCE CENTERY (FOLDLO BRUSHHEIGHT 2)))
                                                                           (* Move the window to 
                                                                           top while 
                                                                           interruptable, but 
                                                                           verify that it is still 
                                                                           there uninterruptably 
                                                                           with drawing points)
                             ))
                       [COND
                          ((EQ RADIUS 1)                                   (* put a single brush 
                                                                           down.)
                                                                           (* draw the top and 
                                                                           bottom most points.)
                           (COND
                              (USERFN (APPLY* USERFN CX CY C150STREAM))
                              (T (\CURVEPT CX CY)))
                           (RETURN))
                          (T                                               (* draw the top and 
                                                                           bottom most points.)
                             (COND
                                (USERFN (APPLY* USERFN CX (IPLUS CY RADIUS)
                                               C150STREAM)
                                       (APPLY* USERFN CX (IDIFFERENCE CY RADIUS)
                                              C150STREAM))
                                (T (\CURVEPT CX (IPLUS CY RADIUS))
                                   (\CURVEPT CX (IDIFFERENCE CY RADIUS]
                   LP                                                      (* (UNFOLD x 2) is used 
                                                                           instead of (ITIMES x 2))
                       [COND
                          [(IGREATERP 0 D)
                           (SETQ X (ADD1 X))
                           (COND
                              ((IGREATERP (UNFOLD (IPLUS D Y)
                                                 2)
                                      1)
                               (SETQ D (IPLUS D (UNFOLD (IDIFFERENCE X Y)
                                                       2)
                                              4))
                               (SETQ Y (SUB1 Y)))
                              (T (SETQ D (IPLUS D (UNFOLD X 2)
                                                1]
                          ((OR (EQ 0 D)
                               (IGREATERP X D))
                           (SETQ X (ADD1 X))
                           (SETQ D (IPLUS D (UNFOLD (IDIFFERENCE X Y)
                                                   2)
                                          4))
                           (SETQ Y (SUB1 Y)))
                          (T (SETQ D (IPLUS (IDIFFERENCE D (UNFOLD Y 2))
                                            3))
                             (SETQ Y (SUB1 Y]
                       (COND
                          [(EQ Y 0)                                        (* left most and right 
                                                                           most points are drawn 
                                                                           specially so that they 
                                                                           are not duplicated 
                                                                           which leaves a hole in 
                                                                           XOR mode.)
                           (COND
                              (USERFN (APPLY* USERFN (IPLUS CX X)
                                             CY C150STREAM)
                                     (APPLY* USERFN (IDIFFERENCE CX X)
                                            CY C150STREAM))
                              (T (\CURVEPT (IPLUS CX X)
                                        CY)
                                 (\CURVEPT (IDIFFERENCE CX X)
                                        CY]
                          (T (COND
                                (USERFN (APPLY* USERFN (IPLUS CX X)
                                               (IPLUS CY Y)
                                               C150STREAM)
                                       (APPLY* USERFN (IDIFFERENCE CX X)
                                              (IPLUS CY Y)
                                              C150STREAM)
                                       (APPLY* USERFN (IPLUS CX X)
                                              (IDIFFERENCE CY Y)
                                              C150STREAM)
                                       (APPLY* USERFN (IDIFFERENCE CX X)
                                              (IDIFFERENCE CY Y)
                                              C150STREAM))
                                (T (\CIRCLEPTS CX CY X Y)))
                             (GO LP)))
                       (MOVETO CENTERX CENTERY C150STREAM)
                       (RETURN NIL])

(\DRAWCURVE.C150
  [LAMBDA (C150STREAM KNOTS CLOSED BRUSH DASHING)                          (* gbn 
                                                                           "12-Jan-86 15:03")
                                                                           (* draws a spline curve 
                                                                           with a given brush.)
    (GLOBALRESOURCE \BRUSHBBT (PROG ([DASHLST (AND DASHING
                                                   (OR (AND (LISTP DASHING)
                                                            (EVERY DASHING (FUNCTION FIXP))
                                                            DASHING)
                                                       (\ILLEGAL.ARG DASHING]
                                     (BBT \BRUSHBBT)
                                     (CBRUSH (CREATE BRUSH USING BRUSH BRUSHCOLOR ←(
                                                                                   \C150.ASSURE.COLOR
                                                                                    (FETCH BRUSHCOLOR
                                                                                       OF BRUSH)
                                                                                    C150STREAM)))
                                     LKNOT)
                                    (SELECTQ (LENGTH KNOTS)
                                        (0                                 (* No knots => empty 
                                                                           curve rather than 
                                                                           error?)
                                           NIL)
                                        (1                                 (* only one knot, put 
                                                                           down a brush shape)
                                           (OR (type? POSITION (CAR KNOTS))
                                               (ERROR "bad knot" (CAR KNOTS)))
                                           (DRAWPOINT (fetch XCOORD of (CAR KNOTS))
                                                  (fetch YCOORD of (CAR KNOTS))
                                                  BRUSH C150STREAM))
                                        (2 (OR (type? POSITION (CAR KNOTS))
                                               (ERROR "bad knot" (CAR KNOTS)))
                                           (OR (type? POSITION (CADR KNOTS))
                                               (ERROR "bad knot" (CADR KNOTS)))
                                           (\LINEWITHBRUSH (fetch XCOORD of (CAR KNOTS))
                                                  (fetch YCOORD of (CAR KNOTS))
                                                  (fetch XCOORD of (CADR KNOTS))
                                                  (fetch YCOORD of (CADR KNOTS))
                                                  BRUSH DASHLST C150STREAM BBT))
                                        (\CURVE2 (PARAMETRICSPLINE KNOTS CLOSED)
                                               CBRUSH DASHLST BBT C150STREAM))
                                    (RETURN C150STREAM])

(\DRAWELLIPSE.C150
  [LAMBDA (DISPLAYSTREAM CENTERX CENTERY SEMIMINORRADIUS SEMIMAJORRADIUS ORIENTATION BRUSH DASHING)
                                                                           (* hdj 
                                                                           " 6-Jun-85 16:17")
    (DECLARE (LOCALVARS . T))
            
            (* Draws an ellipse. At ORIENTATION 0, the semimajor axis is horizontal, 
            the semiminor axis vertical. Orientation is positive in the 
            counterclockwise direction. The current location in the stream is left at 
            the center of the ellipse.)

    (PROG ((CENTERX (FIXR CENTERX))
           (CENTERY (FIXR CENTERY))
           (SEMIMINORRADIUS (FIXR SEMIMINORRADIUS))
           (SEMIMAJORRADIUS (FIXR SEMIMAJORRADIUS)))
          (COND
             ((OR (EQ 0 SEMIMINORRADIUS)
                  (EQ 0 SEMIMAJORRADIUS))
              (MOVETO CENTERX CENTERY DISPLAYSTREAM)
              (RETURN)))
          (COND
             ((ILESSP SEMIMINORRADIUS 1)
              (\ILLEGAL.ARG SEMIMINORRADIUS))
             ((ILESSP SEMIMAJORRADIUS 1)
              (\ILLEGAL.ARG SEMIMAJORRADIUS))
             ((OR (NULL ORIENTATION)
                  (EQ SEMIMINORRADIUS SEMIMAJORRADIUS))
              (SETQ ORIENTATION 0))
             ((NULL (NUMBERP ORIENTATION))
              (\ILLEGAL.ARG ORIENTATION)))
            
            (* This function is the implementation of the algorithm given in 
            "Algorithm for drawing ellipses or hyperbolae with a digital plotter" by 
            Pitteway appearing in Computer Journal 10:
            (3) Nov 1967.0 The input parameters are used to determine the ellipse 
            equation (1/8) Ayy+ (1/8) Bxx+ (1/4) Gxy+
            (1/4) Ux+ (1/4) Vy= (1/4) K which specifies a translated version of the 
            desired ellipse. This ellipse passes through the mesh point
            (0,0), the initial point of the algorithm.
            The power of 2 factors reflect an implementation convenience.)

          (GLOBALRESOURCE \BRUSHBBT
                 (PROG (DestinationBitMap LEFT RIGHTPLUS1 BOTTOM TOP BOTTOMMINUSBRUSH TOPMINUSBRUSH 
                              LEFTMINUSBRUSH DESTINATIONBASE BRUSHBASE BRUSHHEIGHT BRUSHWIDTH 
                              RASTERWIDTH BRUSHRASTERWIDTH BRUSHBM OPERATION HEIGHTMINUS1
                              (BBT \BRUSHBBT)
                              (cosOrientation (COS ORIENTATION))
                              (sinOrientation (SIN ORIENTATION))
                              (SEMIMINORRADIUSSQUARED (ITIMES SEMIMINORRADIUS SEMIMINORRADIUS))
                              (SEMIMAJORRADIUSSQUARED (ITIMES SEMIMAJORRADIUS SEMIMAJORRADIUS))
                              (x 0)
                              (y 0)
                              (x2 1)
                              x1 y1 y2 k1 k2 k3 a b d w A B G U V K CX CY yOffset CYPlusOffset 
                              CYMinusOffset NBITSRIGHTPLUS1 COLORBRUSHBASE COLOR NBITS
                              (DISPLAYDATA (fetch IMAGEDATA of DISPLAYSTREAM))
                              (USERFN (AND (LITATOM BRUSH)
                                           BRUSH)))                        (* many of these 
                                                                           variables are used by 
                                                                           the macro for \CURVEPT 
                                                                           that passes them to 
                                                                           \BBTCURVEPT and 
                                                                           .SETUP.FOR.\BBTCURVEPT.
                                                                           sets them up.)
                       (COND
                          (USERFN                                          (* if calling user fn, 
                                                                           don't bother with set 
                                                                           up and leave points in 
                                                                           window coordinates.)
                                 (SETQ CX CENTERX)
                                 (SETQ CY CENTERY))
                          (T (.SETUP.FOR.\BBTCURVEPT.)                     (* take into account 
                                                                           the brush thickness.)
                             (SELECTQ NBITS
                                 (1 (SETQ CX (IDIFFERENCE CENTERX (FOLDLO BRUSHWIDTH 2))))
                                 (4 (SETQ CX (IDIFFERENCE CENTERX (FOLDLO (LRSH BRUSHWIDTH 2)
                                                                         2))))
                                 (8 (SETQ CX (IDIFFERENCE CENTERX (FOLDLO (LRSH BRUSHWIDTH 3)
                                                                         2))))
                                 (SHOULDNT))
                             (SETQ CY (IDIFFERENCE CENTERY (FOLDLO BRUSHHEIGHT 2)))
                                                                           (* Move the window to 
                                                                           top while 
                                                                           interruptable, but 
                                                                           verify that it is still 
                                                                           there uninterruptably 
                                                                           with drawing points)
                             ))
                       (SETQ A (FPLUS (FTIMES SEMIMAJORRADIUSSQUARED cosOrientation cosOrientation)
                                      (FTIMES SEMIMINORRADIUSSQUARED sinOrientation sinOrientation)))
                       (SETQ B (LSH (FIXR (FPLUS (FTIMES SEMIMINORRADIUSSQUARED cosOrientation 
                                                        cosOrientation)
                                                 (FTIMES SEMIMAJORRADIUSSQUARED sinOrientation 
                                                        sinOrientation)))
                                    3))
                       (SETQ G (FTIMES cosOrientation sinOrientation (LSH (IDIFFERENCE 
                                                                               SEMIMINORRADIUSSQUARED 
                                                                               SEMIMAJORRADIUSSQUARED
                                                                                 )
                                                                          1)))
                       [SETQ yOffset (FIXR (FQUOTIENT (ITIMES SEMIMINORRADIUS SEMIMAJORRADIUS)
                                                  (SQRT A]
                       (SETQ CYPlusOffset (IPLUS CY yOffset))
                       (SETQ CYMinusOffset (IDIFFERENCE CY yOffset))
                       (SETQ U (LSH (FIXR (FTIMES A (LSH yOffset 1)))
                                    2))
                       (SETQ V (LSH (FIXR (FTIMES G yOffset))
                                    2))
                       (SETQ K (LSH [FIXR (FDIFFERENCE (ITIMES SEMIMINORRADIUSSQUARED 
                                                              SEMIMAJORRADIUSSQUARED)
                                                 (FTIMES A (ITIMES yOffset yOffset]
                                    2))
                       (SETQ A (LSH (FIXR A)
                                    3))
                       (SETQ G (LSH (FIXR G)
                                    2))
            
            (* The algorithm is incremental and iterates through the octants of a 
            cartesian plane. The octants are labeled from 1 through 8 beginning above 
            the positive X axis and proceeding counterclockwise.
            Decisions in making the incremental steps are determined according to the 
            error term d which is updated according to the curvature terms a and b.
            k1, k2, and k3 are used to correct the error and curvature terms at octant 
            boundaries. The initial values of these terms depends on the octant in 
            which drawing begins. The initial move steps
            (x1,y1) and (x2,y2) also depend on the starting octant.)

                       [COND
                          [(ILESSP (ABS U)
                                  (ABS V))
                           (SETQ x1 0)
                           (COND
                              [(MINUSP V)                                  (* start in octant 2)
                               (SETQ y1 1)
                               (SETQ y2 1)
                               (SETQ k1 (IMINUS A))
                               (SETQ k2 (IDIFFERENCE k1 G))
                               (SETQ k3 (IDIFFERENCE k2 (IPLUS B G)))
                               (SETQ b (IPLUS U (RSH (IPLUS A G)
                                                     1)))
                               (SETQ a (IMINUS (IPLUS b V)))
                               (SETQ d (IPLUS b (RSH B 3)
                                              (RSH V 1)
                                              (IMINUS K]
                              (T                                           (* start in octant 7)
                                 (SETQ y1 -1)
                                 (SETQ y2 -1)
                                 (SETQ k1 A)
                                 (SETQ k2 (IDIFFERENCE k1 G))
                                 (SETQ k3 (IPLUS k2 B (IMINUS G)))
                                 (SETQ b (IPLUS U (RSH (IDIFFERENCE G A)
                                                       1)))
                                 (SETQ a (IDIFFERENCE V b))
                                 (SETQ d (IPLUS b K (IMINUS (IPLUS (RSH V 1)
                                                                   (RSH B 3]
                          (T (SETQ x1 1)
                             (SETQ y1 0)
                             (COND
                                [(MINUSP V)                                (* start in octant 1)
                                 (SETQ y2 1)
                                 (SETQ k1 B)
                                 (SETQ k2 (IPLUS k1 G))
                                 (SETQ k3 (IPLUS k2 A G))
                                 [SETQ b (IMINUS (IPLUS V (RSH (IPLUS B G)
                                                               1]
                                 (SETQ a (IDIFFERENCE U b))
                                 (SETQ d (IPLUS b K (IMINUS (IPLUS (RSH A 3)
                                                                   (RSH U 1]
                                (T                                         (* start in octant 8)
                                   (SETQ y2 -1)
                                   (SETQ k1 (IMINUS B))
                                   (SETQ k2 (IPLUS k1 G))
                                   (SETQ k3 (IPLUS k2 G (IMINUS A)))
                                   (SETQ b (IPLUS V (RSH (IDIFFERENCE B G)
                                                         1)))
                                   (SETQ a (IDIFFERENCE U b))
                                   (SETQ d (IPLUS b (RSH A 3)
                                                  (IMINUS (IPLUS K (RSH U 1]
            
            (* The ellipse equation describes an ellipse of the desired size and 
            ORIENTATION centered at (0,0) and then dropped yOffset mesh points so that 
            it will pass through (0,0)%. Thus, the intended starting point is
            (CX, CY+yOffset) where (CX, CY) is the center of the desired ellipse.
            Drawing is accomplished with point relative steps.
            In each octant, the error term d is used to choose between move 1
            (an axis move) and move 2 (a diagonal move)%.)

                   MOVE
                       [COND
                          ((MINUSP d)                                      (* move 1)
                           (SETQ x (IPLUS x x1))
                           (SETQ y (IPLUS y y1))
                           (SETQ b (IDIFFERENCE b k1))
                           (SETQ a (IPLUS a k2))
                           (SETQ d (IPLUS b d)))
                          (T                                               (* move 2)
                             (SETQ x (IPLUS x x2))
                             (SETQ y (IPLUS y y2))
                             (SETQ b (IDIFFERENCE b k2))
                             (SETQ a (IPLUS a k3))
                             (SETQ d (IDIFFERENCE d a]
                       (COND
                          ((MINUSP x)
                           (MOVETO CENTERX CENTERY DISPLAYSTREAM)
                           (RETURN NIL)))
                       [COND
                          (USERFN (APPLY* USERFN (IPLUS CX x)
                                         (IPLUS CYPlusOffset y)
                                         DISPLAYSTREAM)
                                 (APPLY* USERFN (IDIFFERENCE CX x)
                                        (IDIFFERENCE CYMinusOffset y)
                                        DISPLAYSTREAM))
                          (T (\CURVEPT (IPLUS CX x)
                                    (IPLUS CYPlusOffset y))
                             (\CURVEPT (IDIFFERENCE CX x)
                                    (IDIFFERENCE CYMinusOffset y]
                       (AND (MINUSP b)
                            (GO SQUARE))
                   DIAGONAL
                       (OR (MINUSP a)
                           (GO MOVE))                                      (* diagonal octant 
                                                                           change)
                       (SETQ x1 (IDIFFERENCE x2 x1))
                       (SETQ y1 (IDIFFERENCE y2 y1))
                       (SETQ w (IDIFFERENCE (LSH k2 1)
                                      k3))
                       (SETQ k1 (IDIFFERENCE w k1))
                       (SETQ k2 (IDIFFERENCE k2 k3))
                       (SETQ k3 (IMINUS k3))
                       [SETQ b (IPLUS b a (IMINUS (RSH (ADD1 k2)
                                                       1]
                       [SETQ d (IPLUS b (RSH (IPLUS k3 4)
                                             3)
                                      (IMINUS d)
                                      (IMINUS (RSH (ADD1 a)
                                                   1]
                       (SETQ a (IDIFFERENCE (RSH (ADD1 w)
                                                 1)
                                      a))
                       (OR (MINUSP b)
                           (GO MOVE))
                   SQUARE
                                                                           (* square octant change)
                       [COND
                          ((EQ 0 x1)
                           (SETQ x2 (IMINUS x2)))
                          (T (SETQ y2 (IMINUS y2]
                       (SETQ w (IDIFFERENCE k2 k1))
                       (SETQ k1 (IMINUS k1))
                       (SETQ k2 (IPLUS w k1))
                       (SETQ k3 (IDIFFERENCE (LSH w 2)
                                       k3))
                       (SETQ b (IDIFFERENCE (IMINUS b)
                                      w))
                       (SETQ d (IDIFFERENCE (IDIFFERENCE b a)
                                      d))
                       (SETQ a (IDIFFERENCE (IDIFFERENCE a w)
                                      (LSH b 1)))
                       (GO DIAGONAL])

(\DRAWLINE.C150
  [LAMBDA (C150STREAM X1 Y1 X2 Y2 WIDTH OPERATION COLOR)                   (* gbn 
                                                                           " 5-Nov-85 13:39")
                                                                           (* C150STREAM is 
                                                                           guaranteed to be a 
                                                                           C150STREAM Draws a line 
                                                                           from x1,y1 to x2,y2 
                                                                           leaving the position at 
                                                                           x2,y2)
    (PROG ((DD (fetch IMAGEDATA of C150STREAM)))
          (\CLIPANDDRAWLINE (OR (FIXP X1)
                                (FIXR X1))
                 (OR (FIXP Y1)
                     (FIXR Y1))
                 (OR (FIXP X2)
                     (FIXR X2))
                 (OR (FIXP Y2)
                     (FIXR Y2))
                 [COND
                    ((NULL WIDTH)
                     1)
                    ((OR (FIXP WIDTH)
                         (FIXR WIDTH]
                 (SELECTQ OPERATION
                     (NIL (ffetch DDOPERATION of DD))
                     ((REPLACE PAINT INVERT ERASE) 
                          OPERATION)
                     (\ILLEGAL.ARG OPERATION))
                 (ffetch DDDestination of DD)
                 (ffetch DDClippingLeft of DD)
                 (SUB1 (ffetch DDClippingRight of DD))
                 (ffetch DDClippingBottom of DD)
                 (SUB1 (ffetch DDClippingTop of DD))
                 C150STREAM
                 (\C150.ASSURE.COLOR COLOR C150STREAM)))                   (* the generic case of 
                                                                           MOVETO is used so that 
                                                                           the hardcopy streams 
                                                                           get handled as well.)
    (MOVETO X2 Y2 C150STREAM])

(\DSPBACKCOLOR.C150
  [LAMBDA (STREAM COLOR)                                                  (* rmk: 
                                                                          "12-Sep-84 09:54")
                                                                          (* sets and returns a 
                                                                          display stream's 
                                                                          background color.)
    (PROG (COLORCELL (DD (\GETDISPLAYDATA STREAM)))
          (SETQ COLORCELL (fetch DDCOLOR of DD))
          (RETURN (COND
                     (COLOR (OR (\POSSIBLECOLOR COLOR)
                                (\ILLEGAL.ARG COLOR))
                            (PROG1 (COND
                                      (COLORCELL (PROG1 (CDR COLORCELL)
                                                        (RPLACD COLORCELL COLOR)))
                                      (T                                  (* no color cell yet, 
                                                                          make one.)
                                         (replace DDCOLOR of DD with (CONS WHITECOLOR COLOR))
                                         BLACKCOLOR))
                                   (\SFFixFont STREAM DD)))
                     (T (OR (CDR COLORCELL)
                            BLACKCOLOR])

(\DSPCLIPPINGREGION.C150
  [LAMBDA (C150STREAM REGION)                                              (* hdj 
                                                                           " 5-Jun-85 12:56")
                                                                           (* sets the clipping 
                                                                           region of a display 
                                                                           stream.)
    (PROG ((DD (\GETDISPLAYDATA C150STREAM)))
          (RETURN (PROG1 (ffetch DDClippingRegion of DD)
                         (COND
                            (REGION (OR (type? REGION REGION)
                                        (ERROR REGION " is not a REGION."))
                                   (UNINTERRUPTABLY
                                       (freplace DDClippingRegion of DD with REGION)
                                       (\SFFixClippingRegion DD)
                                       (\SFFixY DD))])

(\DSPCOLOR.C150
  [LAMBDA (STREAM COLOR)                                                   (* gbn 
                                                                           "13-Jan-86 12:08")
                                                                           (* sets and returns a 
                                                                           display stream's 
                                                                           foreground color.)
    (LET (CURRENTCOLOR NEWCOLOR (DD (\GETDISPLAYDATA STREAM)))
         (SETQ CURRENTCOLOR (fetch DDCOLOR of DD))
         (COND
            (COLOR (SETQ NEWCOLOR (\C150.ASSURE.COLOR COLOR STREAM))
                   (PROG1 (COND
                             (CURRENTCOLOR (PROG1 (CAR CURRENTCOLOR)
                                                  (RPLACA CURRENTCOLOR NEWCOLOR)))
                             (T                                            (* no color cell yet, 
                                                                           make one.)
                                (replace DDCOLOR of DD with (CONS NEWCOLOR BLACKCOLOR))
                                WHITECOLOR))
                          (\SFFixFont STREAM DD)))
            (T (OR (CAR CURRENTCOLOR)
                   WHITECOLOR])

(\C150.ASSURE.COLOR
  [LAMBDA (COLOR# C150STREAM)                                              (* gbn 
                                                                           " 7-Jan-86 17:44")
    (PROG (LEVELS)
          (AND (COND
                  ((NULL COLOR)
                   (RETURN (DSPCOLOR NIL C150STREAM)))
                  [(FIXP COLOR#)
                   (RETURN (COND
                              ((AND (IGEQ COLOR# 0)
                                    (ILESSP COLOR# 8)
                                    COLOR#))
                              (T (\ILLEGAL.ARG COLOR#]
                  [(LITATOM COLOR#)
                   (RETURN (COND
                              ((SETQ LEVELS (\LOOKUPCOLORNAME COLOR#))     (* recursively look up 
                                                                           color number)
                               (\C150.ASSURE.COLOR (CDR LEVELS)
                                      C150STREAM))
                              (T (ERROR "Unknown color name" COLOR#]
                  ((EQ (LENGTH COLOR#)
                       2)                                                  (* temporarily, handle 
                                                                           the case of being given 
                                                                           a texture and a color, 
                                                                           by using the color)
                   (RETURN (\C150.ASSURE.COLOR (CADR COLOR#)
                                  C150STREAM)))
                  ((HLSP COLOR#)                                           (* HLS form convert to 
                                                                           RGB)
                   (SETQ LEVELS (HLSTORGB COLOR#)))
                  ((RGBP COLOR#)                                           (* check for RGB or HLS)
                   (SETQ LEVELS COLOR#))
                  ((TYPENAMEP COLOR# (QUOTE BITMAP))                       (* just a hack to not 
                                                                           blow up)
                   (RETURN (IMOD (for I from 1 to (BITMAPWIDTH COLOR#)
                                    sum (BITMAPBIT COLOR# I 1))
                                 8)))
                  (T (\ILLEGAL.ARG COLOR#)))
               (RETURN (COND
                          ((\C150.LOOKUPRGB LEVELS C150STREAM))
                          (T (ERROR COLOR# "not available in color map"])

(\C150.LOOKUPRGB
  [LAMBDA (RGB C150STREAM)                                                 (* gbn 
                                                                           " 5-Nov-85 15:47")
            
            (* * returns the colormap index whose value is RGB.
            Looks first in the cache, then runs through the colormap.
            Returns NIL if RGB NOT found)

    (DECLARE (GLOBALVARS C150COLORMAP))
    (PROG [INDEX (CACHE (STREAMPROP C150STREAM (QUOTE COLORMAPCACHE]
          (RETURN (if (SETQ INDEX (SASSOC RGB CACHE))
                      then (CDR INDEX)
                    else [SETQ INDEX (bind (CM ← C150COLORMAP) for I from 0
                                        to (SUB1 (EXPT 2 3))
                                        thereis (AND (EQ (\GENERIC.COLORLEVEL CM I (QUOTE RED))
                                                         (fetch (RGB RED) of LEVELS))
                                                     (EQ (\GENERIC.COLORLEVEL CM I (QUOTE GREEN))
                                                         (fetch (RGB GREEN) of LEVELS))
                                                     (EQ (\GENERIC.COLORLEVEL CM I (QUOTE BLUE))
                                                         (fetch (RGB BLUE) of LEVELS]
                         (if INDEX
                             then (PUTASSOC RGB INDEX CACHE))
                         INDEX])

(\DSPFONT.C150
  [LAMBDA (C150STREAM FONT)                                                (* hdj 
                                                                           " 4-Oct-85 11:55")
                                                                           (* sets the font that a 
                                                                           display stream uses to 
                                                                           print characters.
                                                                           C150STREAM is 
                                                                           guaranteed to be a 
                                                                           stream of type C150)
    (PROG (XFONT OLDFONT (DD (fetch IMAGEDATA of C150STREAM)))             (* save old value to 
                                                                           return, smash new value 
                                                                           and update the bitchar 
                                                                           portion of the record.)
          (RETURN (PROG1 (SETQ OLDFONT (fetch DDFONT of DD))
                         (COND
                            (FONT (SETQ XFONT (OR (\GETFONTDESC FONT (QUOTE C150)
                                                         T)
                                                  (FONTCOPY (ffetch DDFONT of DD)
                                                         FONT)))           (* color case, create a 
                                                                           font with the current 
                                                                           foreground and 
                                                                           background colors.)
            
            (* (SETQ XFONT (\GETCOLORFONT XFONT (DSPCOLOR NIL C150STREAM)
            (DSPBACKCOLOR NIL C150STREAM) (ffetch (BITMAP BITMAPBITSPERPIXEL) of
            (ffetch (\DISPLAYDATA DDDestination) of DD)))))
                                                                           (* updating font 
                                                                           information is fairly 
                                                                           expensive operation.
                                                                           Don't bother unless 
                                                                           font has changed.)
                                  (OR (EQ XFONT OLDFONT)
                                      (UNINTERRUPTABLY
                                          (freplace DDFONT of DD with XFONT)
                                          (freplace DDLINEFEED of DD
                                             with (IMINUS (fetch \SFHeight of XFONT)))
                                          (\SFFixFont C150STREAM DD))])

(\DSPLEFTMARGIN.C150
  [LAMBDA (C150STREAM XPOSITION)                                           (* hdj 
                                                                           " 5-Jun-85 12:56")
                                                                           (* sets the xposition 
                                                                           that a carriage return 
                                                                           returns to.)
    (PROG ((DD (fetch IMAGEDATA of C150STREAM)))
          (RETURN (PROG1 (ffetch DDLeftMargin of DD)
                         (AND XPOSITION (COND
                                           ((AND (SMALLP XPOSITION)
                                                 (IGREATERP XPOSITION -1))
                                            (UNINTERRUPTABLY
                                                (freplace DDLeftMargin of DD with XPOSITION)
                                                (\SFFIXLINELENGTH C150STREAM)))
                                           (T (\ILLEGAL.ARG XPOSITION])

(\DSPLINEFEED.C150
  [LAMBDA (C150STREAM DELTAY)                                              (* hdj 
                                                                           " 5-Jun-85 12:56")
                                                                           (* sets the amount that 
                                                                           a line feed increases 
                                                                           the y coordinate by.)
    (PROG ((DD (fetch IMAGEDATA of C150STREAM)))
          (RETURN (PROG1 (ffetch DDLINEFEED of DD)
                         (AND DELTAY (COND
                                        ((NUMBERP DELTAY)
                                         (freplace DDLINEFEED of DD with DELTAY))
                                        (T (\ILLEGAL.ARG DELTAY])

(\DSPOPERATION.C150
  [LAMBDA (C150STREAM OPERATION)                                           (* hdj 
                                                                           " 5-Jun-85 12:56")
                                                                           (* sets the operation 
                                                                           field of a display 
                                                                           stream)
    (PROG ((DD (\GETDISPLAYDATA C150STREAM)))
          (RETURN (PROG1 (fetch DDOPERATION of DD)
                         (COND
                            (OPERATION (OR (FMEMB OPERATION (QUOTE (PAINT REPLACE INVERT ERASE)))
                                           (LISPERROR "ILLEGAL ARG" OPERATION))
                                   (UNINTERRUPTABLY
                                       (freplace DDOPERATION of DD with OPERATION)
                                                                           (* update other fields 
                                                                           that depend on 
                                                                           operation.)
                                       (\SETPBTFUNCTION (fetch DDPILOTBBT of DD)
                                              (fetch DDSOURCETYPE of DD)
                                              OPERATION))])

(\DSPPRINTCHAR.C150
  [LAMBDA (STREAM CHARCODE)                                                (* hdj 
                                                                           " 5-Jun-85 12:56")
                                                                           (* Displays the 
                                                                           character and 
                                                                           increments the 
                                                                           Xposition. STREAM is 
                                                                           guaranteed to be of 
                                                                           type display.)
    (PROG ((DD (fetch IMAGEDATA of STREAM)))
          (SELCHARQ CHARCODE
               ((EOL CR LF) 
                    (\DSPPRINTCR/LF.C150 CHARCODE STREAM)
                    (replace CHARPOSITION of STREAM with 0))
               (LF (\DSPPRINTCR/LF.C150 CHARCODE STREAM))
               (TAB (PROG (TABWIDTH (SPACEWIDTH (CHARWIDTH (CHARCODE SPACE)
                                                       STREAM)))
                          (SETQ TABWIDTH (UNFOLD SPACEWIDTH 8))
                          (if (IGREATERP (\DISPLAYSTREAMINCRXPOSITION
                                          (SETQ TABWIDTH (IDIFFERENCE TABWIDTH
                                                                (MOD (IDIFFERENCE (fetch DDXPOSITION
                                                                                     of DD)
                                                                            (ffetch DDLeftMargin
                                                                               of DD))
                                                                     TABWIDTH)))
                                          DD)
                                     (ffetch DDRightMargin of DD))
                              then                                         (* tab was past 
                                                                           rightmargin, force cr.)
                                   (\DSPPRINTCR/LF.C150 (CHARCODE EOL)
                                          STREAM))                         (* return the number of 
                                                                           spaces taken.)
                          (add (fetch CHARPOSITION of STREAM)
                               (IQUOTIENT TABWIDTH SPACEWIDTH))))
               (add (fetch CHARPOSITION of STREAM)
                    (IPLUS (if (ILESSP CHARCODE 32)
                               then                                        (* CONTROL character)
                                    (\BLTCHAR.C150 CHARCODE STREAM DD)
                                    0
                             else (\BLTCHAR.C150 CHARCODE STREAM DD)
                                  1])

(\DSPPRINTCR/LF.C150
  [LAMBDA (CHARCODE DS)                                                    (* hdj 
                                                                           " 6-Jun-85 14:08")
                                                                           (* CHARCODE is EOL, CR, 
                                                                           or LF Assumes that DS 
                                                                           has been checked by 
                                                                           \DSPPRINTCHAR)
    (PROG (BTM AMOUNT/BELOW Y ROTATION FONT (DD (fetch IMAGEDATA of DS)))
          (COND
             ((AND (fetch DDSlowPrintingCase of DD)
                   (NEQ (SETQ ROTATION (fetch (FONTDESCRIPTOR ROTATION) of (fetch DDFONT of DD)))
                        0))
              (PROG ((CLIPREG (ffetch DDClippingRegion of DD))
                     X)
                    [COND
                       ((EQ CHARCODE (CHARCODE EOL))                       (* on LF, no change in 
                                                                           X)
                        (COND
                           ((SETQ Y (fetch DDEOLFN of DD))                 (* call the eol 
                                                                           function for ds.)
                            (APPLY* Y DS)))
                        (\DSPYPOSITION.C150 DS (SELECTQ ROTATION
                                                   (90 (fetch (REGION BOTTOM) of CLIPREG))
                                                   (270 (fetch (REGION TOP) of CLIPREG))
                                                   (ERROR 
                                                         "Only rotations supported are 0, 90 and 270"
                                                          ]
                    [SETQ X (IPLUS (fetch DDXPOSITION of DD)
                                   (SELECTQ ROTATION
                                       (90 (IMINUS (ffetch DDLINEFEED of DD)))
                                       (270 (ffetch DDLINEFEED of DD))
                                       (ERROR "Only rotations supported are 0, 90 and 270"]
                    (DSPXPOSITION X DS)))
             (T (COND
                   ((EQ CHARCODE (CHARCODE EOL))                           (* on LF, no change in 
                                                                           X)
                    (COND
                       ((SETQ Y (fetch DDEOLFN of DD))                     (* call the eol 
                                                                           function for ds.)
                        (APPLY* Y DS)))
                    (DSPXPOSITION (ffetch DDLeftMargin of DD)
                           DS)))
                (SETQ Y (IPLUS (ffetch DDYPOSITION of DD)
                               (ffetch DDLINEFEED of DD)))
                (DSPYPOSITION Y DS])

(\DSPRESET.C150
  [LAMBDA (C150STREAM)                                                     (* hdj 
                                                                           " 5-Aug-85 18:57")
    (DECLARE (GLOBALVARS \CURRENTDISPLAYLINE))                             (* resets a display 
                                                                           stream)
    (PROG (CREG FONT FONTASCENT (DD (\GETDISPLAYDATA C150STREAM)))
          (SETQ CREG (ffetch DDClippingRegion of DD))
          (SETQ FONT (fetch DDFONT of DD))
          (SETQ FONTASCENT (FONTASCENT FONT))
          (SELECTQ (fetch (FONTDESCRIPTOR ROTATION) of FONT)
              (0 (\DSPXPOSITION.C150 C150STREAM (ffetch DDLeftMargin of DD))
                 (\DSPYPOSITION.C150 C150STREAM (ADD1 (IDIFFERENCE (fetch TOP of CREG)
                                                             FONTASCENT))))
              (90 (\DSPXPOSITION.C150 C150STREAM (IPLUS (fetch LEFT of CREG)
                                                        FONTASCENT))
                  (\DSPYPOSITION.C150 C150STREAM (fetch BOTTOM of CREG)))
              (270 (\DSPXPOSITION.C150 C150STREAM (IDIFFERENCE (fetch RIGHT of CREG)
                                                         FONTASCENT))
                   (\DSPYPOSITION.C150 C150STREAM (fetch TOP of CREG)))
              (ERROR "only supported rotations are 0, 90 and 270"))
          (\CLEARBM (ffetch (\DISPLAYDATA DDDestination) of DD)
                 (DSPBACKCOLOR NIL C150STREAM)
                 CREG])

(\DSPRIGHTMARGIN.C150
  [LAMBDA (C150STREAM XPOSITION)                                           (* hdj 
                                                                           " 5-Jun-85 12:56")
                                                                           (* Sets the right 
                                                                           margin that determines 
                                                                           when a cr is inserted 
                                                                           by print.)
    (PROG (OLDRM (DD (fetch IMAGEDATA of C150STREAM)))
          (SETQ OLDRM (ffetch DDRightMargin of DD))
          (COND
             ((NULL XPOSITION))
             [(AND (SMALLP XPOSITION)
                   (IGREATERP XPOSITION -1))                               (* Avoid fixing 
                                                                           linelength if right 
                                                                           margin hasn't changed.)
              (OR (EQ XPOSITION OLDRM)
                  (UNINTERRUPTABLY
                      (freplace DDRightMargin of DD with XPOSITION)
                      (\SFFIXLINELENGTH C150STREAM))]
             (T (\ILLEGAL.ARG XPOSITION)))
          (RETURN OLDRM])

(\DSPXPOSITION.C150
  [LAMBDA (C150STREAM XPOSITION)                                           (* hdj 
                                                                           " 5-Jun-85 12:56")
                                                                           (* coordinate position 
                                                                           is stored in 15 bits in 
                                                                           the range -2↑15 to 
                                                                           +2↑15.)
    (PROG ((DD (fetch IMAGEDATA of C150STREAM)))
          (RETURN (PROG1 (fetch DDXPOSITION of DD)
                         (COND
                            ((NULL XPOSITION))
                            ((NUMBERP XPOSITION)
                             (freplace DDXPOSITION of DD with XPOSITION)   (* reset the 
                                                                           charposition field so 
                                                                           that PRINT etc.
                                                                           won't put out eols.)
                             (freplace (STREAM CHARPOSITION) of C150STREAM with 0))
                            (T (\ILLEGAL.ARG XPOSITION])

(\DSPYPOSITION.C150
  [LAMBDA (DISPLAYSTREAM YPOSITION)                                        (* hdj 
                                                                           " 3-Oct-85 17:57")
    (LET ((DD (fetch IMAGEDATA of DISPLAYSTREAM)))
         (PROG1 (ffetch DDYPOSITION of DD)
                (COND
                   ((NULL YPOSITION))
                   ((NUMBERP YPOSITION)
                    (UNINTERRUPTABLY
                        (freplace DDYPOSITION of DD with YPOSITION)
                        (\INVALIDATEDISPLAYCACHE DD)))
                   (T (\ILLEGAL.ARG YPOSITION])

(\DUMPPAGEBUFFER.C150
  [LAMBDA (BITMAP C150STREAM COLOR.TABLES)                                 (* gbn 
                                                                           "13-Jan-86 21:37")
    (CENTRONICS.RESET C150STREAM)
    (LET*[(BACKINGSTREAM (\C150BackingStream C150STREAM))
          (MAXX (SUB1 (BITMAPWIDTH BITMAP)))
          (MAXY (SUB1 (BITMAPHEIGHT BITMAP)))
          (LINEBYTES (FOLDHI (BITMAPWIDTH BITMAP)
                            BITSPERBYTE))
          (PrintingTimeInSeconds 1)
          (PrintingTimer (SETUPTIMER PrintingTimeInSeconds NIL (QUOTE SECONDS]
     (C150.SETMARGINS BACKINGSTREAM)
     (C150.SEPARATOR BACKINGSTREAM)
     (bind (BLANKLINES ← 0)
           (FIRSTLINE ← T) for SCANLINE from MAXY to 0 by -4
        do
        (if (\C150.ALLWHITESPACE BITMAP COLOR.TABLES SCANLINE)
            then (add BLANKLINES 1)
                 (BLOCK)
          else
            
            (* * First dump the buffered microlinefeeds)

          (if (AND FIRSTLINE C150.CLIPBUFFER)
              then                                                         (* don't bother 
                                                                           printing these 
                                                                           microlinefeeds, since 
                                                                           they are just the 
                                                                           blanks at the top of 
                                                                           the buffer)
                   (SETQ FIRSTLINE NIL)
            else (for I to BLANKLINES do (\C150.MICROLINEFEED BACKINGSTREAM)))
          (SETQ BLANKLINES 0)
          [for SUBSCAN from 0 to 3
             do
             (if (TIMEREXPIRED? PrintingTimer (QUOTE SECONDS))
                 then (BLOCK)
                      (SETUPTIMER PrintingTimeInSeconds PrintingTimer (QUOTE SECONDS)))
             (for COLOR from 0 to 3
                do                                                         (* loop over (black 
                                                                           magenta yellow cyan))
                   (LET [(COLOR.ARRAY.BASE (fetch (ARRAYP BASE) of (ELT COLOR.TABLES COLOR]
                        (\C150.SENDLINEINFO BACKINGSTREAM COLOR LINEBYTES SUBSCAN)
                        (for XPOSITION from 0 to MAXX by 8
                           do (BOUT BACKINGSTREAM (for BIT from 0 to 7
                                                     sum (LLSH (\GETBASE COLOR.ARRAY.BASE
                                                                      (BITMAPBIT BITMAP
                                                                             (IPLUS XPOSITION BIT)
                                                                             (IDIFFERENCE SCANLINE 
                                                                                    SUBSCAN)))
                                                               (IDIFFERENCE 7 BIT]
          (\C150.MICROLINEFEED BACKINGSTREAM))
        finally (if (NOT C150.CLIPBUFFER)
                    then                                                   (* print out the 
                                                                           remaining 
                                                                           microlinefeeds)
                         (for I from 1 to BLANKLINES do (\C150.MICROLINEFEED BACKINGSTREAM])

(\FILLCIRCLE.C150
  [LAMBDA (C150STREAM CENTERX CENTERY RADIUS TEXTURE)                      (* hdj 
                                                                           " 6-Jun-85 16:17")
    (COND
       ((OR (NOT (NUMBERP RADIUS))
            (ILESSP (SETQ RADIUS (FIXR RADIUS))
                   0))
        (\ILLEGAL.ARG RADIUS))
       (T (GLOBALRESOURCE \BRUSHBBT
                 (PROG (TOP BOTTOM RIGHT LEFT OPERATION DestinationBitMap
                            (DISPLAYDATA (fetch IMAGEDATA of C150STREAM))
                            (X 0)
                            (Y RADIUS)
                            (D (ITIMES 2 (IDIFFERENCE 1 RADIUS)))
                            DESTINATIONBASE RASTERWIDTH CX CY TEXTUREBM GRAYHEIGHT GRAYWIDTH GRAYBASE 
                            NBITS (FCBBT \BRUSHBBT))
                       (SETQ TOP (SUB1 (fetch DDClippingTop of DISPLAYDATA)))
                       (SETQ BOTTOM (fetch DDClippingBottom of DISPLAYDATA))
                       (SETQ LEFT (fetch DDClippingLeft of DISPLAYDATA))
                       (SETQ RIGHT (SUB1 (fetch DDClippingRight of DISPLAYDATA)))
                       (SETQ OPERATION (ffetch DDOPERATION of DISPLAYDATA))
                       (SETQ DestinationBitMap (fetch DDDestination of DISPLAYDATA))
                       (SETQ NBITS (fetch (BITMAP BITMAPBITSPERPIXEL) of DestinationBitMap))
                       [SETQ TEXTUREBM (COND
                                          ((BITMAPP TEXTURE))
                                          [(AND (NEQ NBITS 1)
                                                (BITMAPP (COLORTEXTUREFROMCOLOR#
                                                          (COLORNUMBERP (OR TEXTURE (DSPCOLOR NIL 
                                                                                           C150STREAM
                                                                                           ]
                                          [(AND (NULL TEXTURE)
                                                (BITMAPP (ffetch DDTexture of DISPLAYDATA]
                                          ([OR (FIXP TEXTURE)
                                               (AND (NULL TEXTURE)
                                                    (SETQ TEXTURE (ffetch DDTexture of DISPLAYDATA]
                                                                           (* create bitmap for 
                                                                           the texture. Could 
                                                                           reuse a bitmap but for 
                                                                           now this is good 
                                                                           enough.)
                                           (SETQ TEXTUREBM (BITMAPCREATE 16 4))
                                           (SETQ GRAYBASE (fetch (BITMAP BITMAPBASE) of TEXTUREBM))
                                           (\PUTBASE GRAYBASE 0 (\SFReplicate (LOGAND (LRSH TEXTURE 
                                                                                            12)
                                                                                     15)))
                                           (\PUTBASE GRAYBASE 1 (\SFReplicate (LOGAND (LRSH TEXTURE 8
                                                                                            )
                                                                                     15)))
                                           (\PUTBASE GRAYBASE 2 (\SFReplicate (LOGAND (LRSH TEXTURE 4
                                                                                            )
                                                                                     15)))
                                           (\PUTBASE GRAYBASE 3 (\SFReplicate (LOGAND TEXTURE 15)))
                                           TEXTUREBM)
                                          (T (\ILLEGAL.ARG TEXTURE]
                       (SETQ GRAYBASE (fetch (BITMAP BITMAPBASE) of TEXTUREBM))
                       (SETQ DESTINATIONBASE (fetch BITMAPBASE of DestinationBitMap))
                       (SETQ RASTERWIDTH (fetch BITMAPRASTERWIDTH of DestinationBitMap))
                                                                           (* update as many 
                                                                           fields in the brush 
                                                                           bitblt table as 
                                                                           possible from DS.)
                       (replace PBTFLAGS of FCBBT with 0)
                       (replace PBTDESTBPL of FCBBT with (UNFOLD RASTERWIDTH BITSPERWORD))
                                                                           (* clear gray 
                                                                           information. 
                                                                           PBTSOURCEBPL is used 
                                                                           for gray information 
                                                                           too.)
                       (replace PBTSOURCEBPL of FCBBT with 0)
                       (replace PBTUSEGRAY of FCBBT with T)
                       [replace PBTGRAYWIDTHLESSONE of FCBBT
                          with (SUB1 (SETQ GRAYWIDTH (IMIN (fetch (BITMAP BITMAPWIDTH) of TEXTUREBM)
                                                           16]
                       [replace PBTGRAYHEIGHTLESSONE of FCBBT
                          with (SUB1 (SETQ GRAYHEIGHT (IMIN (fetch (BITMAP BITMAPHEIGHT) of TEXTUREBM
                                                                   )
                                                            16]
                       (replace PBTDISJOINT of FCBBT with T)
                       (\SETPBTFUNCTION FCBBT (QUOTE TEXTURE)
                              OPERATION)
                       (replace PBTHEIGHT of FCBBT with 1)                 (* take into account 
                                                                           the brush thickness.)
                       (SETQ CX CENTERX)
                       (SETQ CY CENTERY)                                   (* change Y TOP and 
                                                                           BOTTOM to be in bitmap 
                                                                           coordinates)
                       (SETQ CY (\SFInvert DestinationBitMap CY))
                       [SETQ BOTTOM (PROG1 (SUB1 (\SFInvert DestinationBitMap TOP))
                                           (SETQ TOP (SUB1 (\SFInvert DestinationBitMap BOTTOM]
                       (COND
                          ((EQ RADIUS 0)                                   (* put a single point 
                                                                           down. Use \LINEBLT to 
                                                                           get proper texture.
                                                                           NIL)
                           (\LINEBLT FCBBT CX CY CX DESTINATIONBASE RASTERWIDTH LEFT RIGHT BOTTOM TOP 
                                  GRAYWIDTH GRAYHEIGHT GRAYBASE NBITS)
                           (RETURN)))
                   LP                                                      (* (UNFOLD x 2) is used 
                                                                           instead of (ITIMES x 2))
                       [COND
                          [(IGREATERP 0 D)
                           (SETQ X (ADD1 X))
                           (COND
                              ((IGREATERP (UNFOLD (IPLUS D Y)
                                                 2)
                                      1)
                               (SETQ D (IPLUS D (UNFOLD (IDIFFERENCE X Y)
                                                       2)
                                              4)))
                              (T (SETQ D (IPLUS D (UNFOLD X 2)
                                                1))                        (* don't draw unless Y 
                                                                           changes.)
                                 (GO LP]
                          ((OR (EQ 0 D)
                               (IGREATERP X D))
                           (SETQ X (ADD1 X))
                           (SETQ D (IPLUS D (UNFOLD (IDIFFERENCE X Y)
                                                   2)
                                          4)))
                          (T (SETQ D (IPLUS (IDIFFERENCE D (UNFOLD Y 2))
                                            3]
                       (COND
                          ((EQ Y 0)                                        (* draw the middle line 
                                                                           differently to avoid 
                                                                           duplication.)
                           (\LINEBLT FCBBT (IDIFFERENCE CX X)
                                  CY
                                  (IPLUS CX X)
                                  DESTINATIONBASE RASTERWIDTH LEFT RIGHT BOTTOM TOP GRAYWIDTH 
                                  GRAYHEIGHT GRAYBASE NBITS))
                          (T (\FILLCIRCLEBLT CX CY X Y)
                             (SETQ Y (SUB1 Y))
                             (GO LP)))
                       (MOVETO CENTERX CENTERY C150STREAM)
                       (RETURN NIL])

(\OUTCHARFN.C150
  [LAMBDA (C150STREAM CHARCODE)                                            (* hdj 
                                                                           "10-Jun-85 15:14")
    (SELCHARQ CHARCODE
         (EOL                                                              (* New Line)
              (NEWLINE.C150 C150STREAM)
              (replace (STREAM CHARPOSITION) of C150STREAM with 0))
         (LF                                                               (* Line feed--move 
                                                                           down, but not over)
             (\DSPXPOSITION.C150 C150STREAM (PROG1 (\DSPXPOSITION.C150 C150STREAM)
                                                   (NEWLINE.C150 C150STREAM))))
         (↑L                                                               (* Form Feed)
             (replace (STREAM CHARPOSITION) of C150STREAM with 0)
             (NEWPAGE.C150 C150STREAM))
         (\BOUT C150STREAM CHARCODE])

(\SEARCHC150FONTFILES
  [LAMBDA (FAMILY SIZE FACE ROTATION)                                      (* hdj 
                                                                           " 5-Jun-85 14:19")
            
            (* * returns a list of the fonts that can be read in for the C150 device.
            Rotation is ignored because it is assumed that all devices support 0 90 
            and 270)

    (DECLARE (GLOBALVARS DISPLAYFONTEXTENSIONS DISPLAYFONTDIRECTORIES))
    (SELECTQ (SYSTEMTYPE)
        (D (for E FILENAMEPATTERN FONTSFOUND THISFONT inside DISPLAYFONTEXTENSIONS
              do (SETQ FILENAMEPATTERN (\FONTFILENAME FAMILY SIZE FACE E))
                 [for DIR inside DISPLAYFONTDIRECTORIES
                    do (for FONTFILE in (DIRECTORY (PACKFILENAME (QUOTE DIRECTORY)
                                                          DIR
                                                          (QUOTE BODY)
                                                          FILENAMEPATTERN))
                          do (OR (MEMBER (SETQ THISFONT (\FONTINFOFROMFILENAME FONTFILE (QUOTE 
                                                                                              DISPLAY
                                                                                               )))
                                        FONTSFOUND)
                                 (SETQ FONTSFOUND (CONS THISFONT FONTSFOUND]
              finally (RETURN FONTSFOUND)))
        (SHOULDNT])

(\STRINGWIDTH.C150
  [LAMBDA (C150STREAM STR RDTBL)                                           (* hdj 
                                                                           " 5-Jun-85 12:56")
                                                                           (* Returns the width of 
                                                                           for the current 
                                                                           font/spacefactor in 
                                                                           STREAM.)
    (PROG (WIDTHSBASE)
          (RETURN (\STRINGWIDTH.GENERIC STR (SETQ WIDTHSBASE (ffetch (\DISPLAYDATA DDWIDTHSCACHE)
                                                                of (ffetch IMAGEDATA of C150STREAM)))
                         RDTBL
                         (\FGETWIDTH WIDTHSBASE (CHARCODE SPACE])
)

(RPAQQ MISSINGC150FONTCOERCIONS (((GACHA)
                                  (MODERN))
                                 ((TIMESROMAN)
                                  (MODERN))
                                 ((HELVETICA)
                                  (MODERN))))

(RPAQQ \C150COLORTABLE NIL)

(RPAQQ \C150.FRAMEBUFFER NIL)

(RPAQQ \C150STREAM NIL)

(RPAQ C150COLORMAP (READARRAY 16 (QUOTE POINTER) 0))
((0 0 0)
(0 0 255)
(0 255 0)
(255 0 0)
(255 255 0)
(255 0 255)
(0 255 255)
(255 255 255)
(0 0 0)
(0 0 255)
(0 255 0)
(255 0 0)
(255 255 0)
(255 0 255)
(0 255 255)
(255 255 255)
NIL
)

(RPAQQ C150FONTCOERCIONS (((CLASSIC 8)
                           (CLASSIC 10))
                          ((MODERN 8)
                           (MODERN 10))
                          ((MODERN 24)
                           (MODERN 18))
                          ((MODERN 18)
                           (CLASSIC 18))
                          ((CLASSIC 24)
                           (CLASSIC 18))
                          ((CLASSIC 12)
                           (CLASSIC 14))))

(RPAQQ C150FONTDIRECTORIES ({ERIS}<LISPCORE>LIBRARY>))

(RPAQQ C150FONTEXTENSIONS (C150FONT))

(RPAQ? C150.CLIPBUFFER T)

(RPAQ? \C150DEFAULTDEVICE (QUOTE CENTRONICS))
(DEFINEQ

(COLORMAP.TO.C150TABLE
  [LAMBDA (COLORMAP)                                                       (* hdj 
                                                                           " 3-Aug-85 21:36")
    (LET*((SIZE (ARRAYSIZE COLORMAP))
          (TABLETABLE (ARRAY 4 (QUOTE POINTER)
                             NIL 0))
          (BLACKTABLE (ARRAY SIZE (QUOTE SMALLP)
                             0 0))
          (CYANTABLE (ARRAY SIZE (QUOTE SMALLP)
                            0 0))
          (MAGENTATABLE (ARRAY SIZE (QUOTE SMALLP)
                               0 0))
          (YELLOWTABLE (ARRAY SIZE (QUOTE SMALLP)
                              0 0)))
     (bind CYAN MAGENTA YELLOW for PIXELVAL from 0 to (SUB1 SIZE)
        do [SETQ CYAN (SETA CYANTABLE PIXELVAL (IDIFFERENCE 1 (IQUOTIENT (fetch (RGB RED)
                                                                            of (COLORMAPENTRY 
                                                                                      COLORMAP 
                                                                                      PIXELVAL))
                                                                     128]
           [SETQ MAGENTA (SETA MAGENTATABLE PIXELVAL (IDIFFERENCE 1 (IQUOTIENT (fetch (RGB GREEN)
                                                                                  of (COLORMAPENTRY
                                                                                      COLORMAP 
                                                                                      PIXELVAL))
                                                                           128]
           [SETQ YELLOW (SETA YELLOWTABLE PIXELVAL (IDIFFERENCE 1 (IQUOTIENT (fetch (RGB BLUE)
                                                                                of (COLORMAPENTRY
                                                                                    COLORMAP PIXELVAL
                                                                                    ))
                                                                         128]
           (if (AND (EQ CYAN 1)
                    (EQ MAGENTA 1)
                    (EQ YELLOW 1))
               then (SETA CYANTABLE PIXELVAL 0)
                    (SETA MAGENTATABLE PIXELVAL 0)
                    (SETA YELLOWTABLE PIXELVAL 0)
                    (SETA BLACKTABLE PIXELVAL 1)))
     (SETA TABLETABLE 0 BLACKTABLE)
     (SETA TABLETABLE 1 MAGENTATABLE)
     (SETA TABLETABLE 2 YELLOWTABLE)
     (SETA TABLETABLE 3 CYANTABLE)
     TABLETABLE])
)
(FILESLOAD COLOR XXGEOM XXFILL)
(IF (NOT (GETD (QUOTE POLYSHADE.BLT)))
    THEN
    (* A fix for KOTO, which is not necessary in <lc>n>)
    (MOVD (QUOTE POLYSHADE.DISPLAY)
          (QUOTE POLYSHADE.BLT)))
(DECLARE: DONTEVAL@LOAD DOCOPY 
(\C150INIT)

(FILESLOAD CENTRONICS)
)
(DECLARE: EVAL@LOAD DONTCOPY 
(FILESLOAD (LOADFROM)
       ADISPLAY LLDISPLAY)
)
(DECLARE: EVAL@COMPILE 
(DEFMACRO \C150BackingStream (C150STREAM)
       (BQUOTE (fetch (STREAM F1)
                      of , C150STREAM)))
)
(PUTPROPS C150STREAM COPYRIGHT ("Xerox Corporation" 1985 1986))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (2416 20778 (C150.SEPARATOR 2426 . 2839) (C150.SETMARGINS 2841 . 4574) (
\C150.ALLWHITESPACE 4576 . 6320) (\C150.BUFFER.DOT 6322 . 6553) (\C150.MICROLINEFEED 6555 . 6835) (
\C150.SENDLINE 6837 . 7856) (\C150.SENDLINEINFO 7858 . 8357) (\C150INIT 8359 . 12525) (
\CREATECHARSET.C150 12527 . 20776)) (20779 135286 (CREATEC150BUFFER 20789 . 21931) (NEWLINE.C150 21933
 . 22878) (NEWPAGE.C150 22880 . 23386) (OPENC150STREAM 23388 . 26698) (C150.RESET 26700 . 27074) (
SEND.TO.C150 27076 . 27516) (STARTPAGE.C150 27518 . 28241) (\BITBLT.C150 28243 . 39228) (\BLTCHAR.C150
 39230 . 46739) (\BLTSHADE.C150 46741 . 54213) (\C150.CRLF 54215 . 54665) (\CHANGECHARSET.C150 54667
 . 58079) (\CHARWIDTH.C150 58081 . 58888) (\CLOSEFN.C150 58890 . 59533) (\CREATEC150FONT 59535 . 60463
) (\READC150FONTFILE 60465 . 61352) (\DRAWCIRCLE.C150 61354 . 70823) (\DRAWCURVE.C150 70825 . 74177) (
\DRAWELLIPSE.C150 74179 . 90084) (\DRAWLINE.C150 90086 . 92331) (\DSPBACKCOLOR.C150 92333 . 93755) (
\DSPCLIPPINGREGION.C150 93757 . 94804) (\DSPCOLOR.C150 94806 . 96147) (\C150.ASSURE.COLOR 96149 . 
98725) (\C150.LOOKUPRGB 98727 . 100214) (\DSPFONT.C150 100216 . 103285) (\DSPLEFTMARGIN.C150 103287 . 
104410) (\DSPLINEFEED.C150 104412 . 105295) (\DSPOPERATION.C150 105297 . 106757) (\DSPPRINTCHAR.C150 
106759 . 109848) (\DSPPRINTCR/LF.C150 109850 . 112967) (\DSPRESET.C150 112969 . 114625) (
\DSPRIGHTMARGIN.C150 114627 . 115995) (\DSPXPOSITION.C150 115997 . 117372) (\DSPYPOSITION.C150 117374
 . 118012) (\DUMPPAGEBUFFER.C150 118014 . 121744) (\FILLCIRCLE.C150 121746 . 131735) (\OUTCHARFN.C150 
131737 . 132803) (\SEARCHC150FONTFILES 132805 . 134363) (\STRINGWIDTH.C150 134365 . 135284)) (136566 
139219 (COLORMAP.TO.C150TABLE 136576 . 139217)))))
STOP