text: /* $Id: rawcolor.c,v 1.3 2001/12/26 22:17:04 sybalsky Exp $ (C) Copyright Venue, All Rights Reserved
   */
  
  /************************************************************************/
  /*									*/
  /*	 C O L O R   B I T B L T / G R A P H I C S   S U P P O R T	*/
  /*									*/
  /*									*/
  /*									*/
  /************************************************************************/
  
  /************************************************************************/
  /*									*/
  /*	(C) Copyright 1989-95 Venue. All Rights Reserved.		*/
  /*	Manufactured in the United States of America.			*/
  /*									*/
  /************************************************************************/
  
  #include "version.h"
  
  #include <sys/types.h>
  #include "lispemul.h"
  #include "lspglob.h"
  #include "lispmap.h"
  #include "lsptypes.h"
  #include "cell.h"
  #include "adr68k.h"
  #include "address.h"
  #include "stream.h"
  #include "dspdata.h"
  #include "pilotbbt.h"
  #include "debug.h"
  #include "arith.h"
  #include "bitblt.h"
  #include "lldsp.h"
  
  #include "bbtsubdefs.h"
  
  #define IMIN(x, y) (((x) > (y)) ? (y) : (x))
  #define IMAX(x, y) (((x) > (y)) ? (x) : (y))
  
  /*******************************/
  /* A LISP Big-bitmap structure */
  /*******************************/
  typedef struct {
    LispPTR bigbmwidth;
    LispPTR bigbmheight;
    LispPTR bigbmlist;
  } BIGBM;
  
  #define GetNewFragment(list, frag, type)      \
    frag = (type)Addr68k_from_LADDR(car(list)); \
    list = cdr(list);
  
  LispPTR SLOWBLTCHAR_index;
  #define SLOWBLTCHAR_argnum 2
  #define PUNT_TO_SLOWBLTCHAR                                                                \
    {                                                                                        \
      if (SLOWBLTCHAR_index == 0xffffffff)                                                   \
        SLOWBLTCHAR_index = get_package_atom("\\PUNT.SLOWBLTCHAR", 17, "INTERLISP", 9, NIL); \
      if (SLOWBLTCHAR_index == 0xffffffff) {                                                 \
        error("SLOWBLTCHAR install fail");                                                   \
        return;                                                                              \
      }                                                                                      \
      CurrentStackPTR += (SLOWBLTCHAR_argnum - 1) * DLWORDSPER_CELL;                         \
      ccfuncall(SLOWBLTCHAR_index, SLOWBLTCHAR_argnum, 3);                                   \
      return;                                                                                \
    }
  
  /***********************************************************/
  /*
                  C_slowbltchar
  
                  by Takeshi
                  June 6, 1989
  */
  /***********************************************************/
  
  /* I'll merge this macro with  FGetNum later */
  #define SFGetNum(ptr, place)                    \
    {                                             \
      if (((ptr)&SEGMASK) == S_POSITIVE) {        \
        (place) = ((ptr)&0xffff);                 \
      } else if (((ptr)&SEGMASK) == S_NEGATIVE) { \
        (place) = (int)((ptr) | 0xffff0000);      \
      } else {                                    \
        PUNT_TO_SLOWBLTCHAR;                      \
      }                                           \
    }
  
  /* place:		native pointer
     val:		native value(should be smallp)
     puntcase:	punt descriptions */
  #define FReplaceSmallp(place, val, puntcase)                       \
    {                                                                \
      if ((0 <= (val)) && ((val) <= MAX_SMALL))                      \
        (LispPTR)(place) = (LispPTR)(S_POSITIVE | (val));            \
      else if (MIN_SMALL <= val)                                     \
        (LispPTR)(place) = (LispPTR)(S_NEGATIVE | (0xffff & (val))); \
      else {                                                         \
        puntcase;                                                    \
      }                                                              \
    }
  
  /* charcode should be pos. smallp */
  #define charcode (args[0] & 0xffff)
  #define displaystream args[1]
  #define Char8Code(x) ((u_char)((x)&0xff))
  #define CharSet(x) ((x) >> 8)
  
  #define PSEUDO_BLACK 255
  #define PSEUDO_WHITE 0
  
  LispPTR *SCREENBITMAPS68k; /* Initialized in initsout.c */
  LispPTR *COLORSCREEN68k;   /* Initialized in initsout.c */
  LispPTR COLORSCREEN_index; /* if it's 0xffffffff, not yet initialized */
  
  /************************************************************************/
  /*									*/
  /*			C _ s l o w b l t c h a r			*/
  /*									*/
  /*	 args[0]		charcode 				*/
  /*	 args[1]		displaystream				*/
  /*									*/
  /*									*/
  /************************************************************************/
  
  C_slowbltchar(LispPTR *args)
  {
    Stream *n_dstream;
    DISPLAYDATA *n_dd;
    FONTDESC *n_fontd;
    CHARSETINFO *n_csinfo;
    BITMAP *n_destbitmap;
    int dest_bpp;
    LispPTR csinfo;
    int curx, cury, newx, rmargin, lmargin, xoff, yoff;
    DLword cl_left, cl_right, cl_bottom, cl_top;
    DLword src_w, src_h, src_x, src_y, dst_x, dst_y, w, h;
  
    u_char forecolor, backcolor;
    register int displayflg;
  
    extern LispPTR *TOPWDS68k;
  
    n_dstream = (Stream *)Addr68k_from_LADDR(displaystream);
    n_dd = (DISPLAYDATA *)Addr68k_from_LADDR(n_dstream->IMAGEDATA);
    n_fontd = (FONTDESC *)Addr68k_from_LADDR(n_dd->ddfont);
    n_destbitmap = (BITMAP *)Addr68k_from_LADDR(n_dd->dddestination);
  
    if ((n_fontd->ROTATION & 0xffff) == 0) {
      if ((csinfo = *(((LispPTR *)Addr68k_from_LADDR(n_fontd->FONTCHARSETVECTOR)) +
                      CharSet(charcode))) == NIL)
        PUNT_TO_SLOWBLTCHAR; /* CSINFO is not cached */
  
      n_csinfo = (CHARSETINFO *)Addr68k_from_LADDR(csinfo);
  
      SFGetNum(n_dd->ddxposition, curx);
      SFGetNum(n_dd->ddyposition, cury);
      SFGetNum(n_dd->ddrightmargin, rmargin);
      SFGetNum(n_dd->ddleftmargin, lmargin);
      SFGetNum(n_dd->ddxoffset, xoff);
      SFGetNum(n_dd->ddyoffset, yoff);
      cl_left = n_dd->ddclippingleft;
      cl_right = n_dd->ddclippingright;
      cl_bottom = n_dd->ddclippingbottom;
      cl_top = n_dd->ddclippingtop;
  
      newx = curx + *(DLword *)Addr68k_from_LADDR(n_dd->ddwidthscache + Char8Code(charcode));
  
      if (newx > rmargin) PUNT_TO_SLOWBLTCHAR; /* do \DSPPRINTCR/LF */
  
      /* If we care about TOPW then it's too slow to create Menu etc.
         But,if we don't,it causes some error  **/
      {
        WINDOW *window;
        SCREEN *ColorScreenData;
        if (COLORSCREEN_index == 0xffffffff) { /* Make sure COLOR lives? */
          COLORSCREEN_index = MAKEATOM("\\COLORSCREEN");
          COLORSCREEN68k = GetVALCELL68k(COLORSCREEN_index);
        }
        ColorScreenData = (SCREEN *)Addr68k_from_LADDR(*COLORSCREEN68k);
        window = (WINDOW *)Addr68k_from_LADDR(ColorScreenData->SCTOPW);
        if ((displaystream != ColorScreenData->SCTOPW) && (displaystream != window->DSP) &&
            (displaystream != *TOPWDS68k) && ((fmemb(n_dd->dddestination, *SCREENBITMAPS68k)) != NIL))
          PUNT_TO_SLOWBLTCHAR;
      }
  
      FReplaceSmallp(n_dd->ddxposition, newx, PUNT_TO_SLOWBLTCHAR);
  
      /* make curx abs coord */
      curx += xoff;
      cury += yoff;
  
      {
        register PILOTBBT *pbt;
        register BITMAP *n_destBM, *n_srcBM;
        register BIGBM *n_destBIGBM;
        register int destYOffset;
        register int width, sourceBitOffset;
        extern int ScreenLocked;
        extern int displayheight;
  
        n_srcBM = (BITMAP *)Addr68k_from_LADDR(n_csinfo->CHARSETBITMAP);
        src_h = n_srcBM->bmheight;
        src_w = n_srcBM->bmwidth;
  
        src_x = *((DLword *)Addr68k_from_LADDR(n_dd->ddoffsetscache + Char8Code(charcode)));
        src_y = 0;
        w = *(DLword *)Addr68k_from_LADDR(n_dd->ddcharimagewidths + Char8Code(charcode));
        h = src_h;
  
        (short)dst_x = (short)curx;
        (short)dst_y = (short)cury - (short)n_csinfo->CHARSETDESCENT;
  
        { /* clipping */
          short left, right, bottom, top;
          short stodx, stody;
  
          left = (short)IMAX((short)dst_x, (short)cl_left);
          right = (short)IMIN((short)dst_x + w, (short)cl_right);
          bottom = (short)IMAX((short)dst_y, (short)cl_bottom);
          top = (short)IMIN((short)dst_y + h, (short)cl_top);
          stodx = (short)dst_x - (short)src_x;
          stody = (short)dst_y - (short)src_y;
          left = IMAX((short)src_x, IMAX(left - stodx, 0));
          bottom = IMAX((short)src_y, IMAX(bottom - stody, 0));
          right = IMIN((short)src_w, IMIN((short)(src_x + w), right - stodx));
          top = IMIN((short)src_h, IMIN((short)(src_y + h), top - stody));
          if ((right <= left) || (top <= bottom)) return;
          w = (DLword)(right - left);
          h = (DLword)(top - bottom);
          dst_x = (DLword)(left + stodx);
          dst_y = (DLword)(bottom + stody);
          src_x = (DLword)left;
          src_y = (DLword)bottom;
        }
  
        /* foreground and background color */
  
        if (n_dd->ddcolor == NIL_PTR) {
          forecolor = PSEUDO_BLACK;
          backcolor = PSEUDO_WHITE;
        } else {
          backcolor = 0xff & cdr(n_dd->ddcolor);
          forecolor = 0xff & car(n_dd->ddcolor);
        }
  
        if (GetTypeNumber(n_dd->dddestination) == TYPE_BITMAP) { /* Bitap */
          n_destBM = (BITMAP *)Addr68k_from_LADDR(n_dd->dddestination);
          ScreenLocked = T;
          /*  xposition is shifted 3 Kludge for cursorin
                 in color(8bpp) ** x's meaning  is different from
                bitbltsub's. For now,I use this func with Kludge */
          displayflg = n_new_cursorin(Addr68k_from_LADDR(n_destBM->bmbase), dst_x << 3,
                                      /* Kludge:YCoordination upside down*/
                                      displayheight - cury, w, h);
          if (displayflg) HideCursor;
  
          ColorizeFont8(n_srcBM, src_x, src_y, n_destBM, dst_x, dst_y, w, h, backcolor, forecolor,
                        n_dd->ddsourcetype, n_dd->ddoperation);
  
          if (displayflg) ShowCursor;
          ScreenLocked = NIL;
  
        } else { /* BIGBM */
          ScreenLocked = T;
          n_destBIGBM = (BIGBM *)n_destbitmap;
          ColorizeFont8_BIGBM(n_srcBM, src_x, src_y, n_destBIGBM, dst_x, dst_y, w, h, backcolor,
                              forecolor, n_dd->ddsourcetype, n_dd->ddoperation);
          ScreenLocked = NIL;
        } /* end if( TYPE_BITMAP ) */
      }
    } else {
      /* ROTATE case ,do-PUNT */
      PUNT_TO_SLOWBLTCHAR;
    }
  
  } /* end C_slowbltchar */
  
  /************************************************************************/
  /*									*/
  /*			C o l o r i z e d F o n t 8			*/
  /*									*/
  /*	Expand a 1bpp font to 8bpp colorized font bitmap, using		*/
  /*	col1 and col0 as the colors for 1 bits & 0 bits, respectively.	*/
  /*									*/
  /*	dbm must be the output bitmap (not a bigbm), whose bpp is 8.	*/
  /*									*/
  /************************************************************************/
  
  #define MAXFONTHEIGHT 48
  #define MAXFONTWIDTH 48
  #define BITSPERNIBBLE 4
  #define BITSPERDLWORD 16
  #define BPP 8
  
  u_int ColorizedFont8CACHE[MAXFONTHEIGHT / BITSPERNIBBLE * MAXFONTWIDTH / BITSPERNIBBLE];
  
  void ColorizeFont8(BITMAP *sBM, DLword sXOffset, DLword sYOffset, BITMAP *dBM, DLword dXOffset, DLword dYOffset, DLword width, DLword height, u_char col0, u_char col1,
                LispPTR sourcetype, LispPTR operation)
  {
    register DLword *nbase;
    register u_char *dbase;
    register int i;
  
    sYOffset = sBM->bmheight - (sYOffset + height);
    dYOffset = dBM->bmheight - (dYOffset + height);
  
    nbase = (DLword *)Addr68k_from_LADDR(sBM->bmbase) + (sBM->bmrasterwidth * sYOffset);
    (DLword *)dbase = (DLword *)Addr68k_from_LADDR(dBM->bmbase) + (dBM->bmrasterwidth * dYOffset);
    for (i = 0, dbase += dXOffset; /* 8bpp */
         i < height; i++, nbase += sBM->bmrasterwidth, ((DLword *)dbase) += dBM->bmrasterwidth) {
      lineBlt8(nbase, (int)sXOffset, dbase, (int)width, col0, col1, sourcetype, operation);
    } /* for end */
  
  } /* ColorizeFont8 end */
  
  /************************************************************************/
  /*									*/
  /*		C o l o r i z e d F o n t 8 _ B I G B M			*/
  /*									*/
  /*	Expand a 1bpp font to 8bpp colorized font bitmap, using		*/
  /*	col1 and col0 as the colors for 1 bits & 0 bits, respectively.	*/
  /*									*/
  /*	dbm must be the output BIGBM (not a bitmap), whose bpp is 8.	*/
  /*									*/
  /************************************************************************/
  
  void ColorizeFont8_BIGBM(BITMAP *sBM, DLword sXOffset, DLword sYOffset, BIGBM *dBM, DLword dXOffset, DLword dYOffset, DLword width, DLword height, u_char col0, u_char col1,
                LispPTR sourcetype, LispPTR operation)
  {
    register DLword *nbase;
    register u_char *dbase;
    register int i;
    int dest_bottom, dest_bigbmheight, dest_fragtop, dest_fragbottom, dest_yoffset, dest_h;
  
    LispPTR dest_bmlist;
    BITMAP *dest_frag;
  
    SFGetNum(dBM->bigbmheight, dest_bigbmheight);
  
    sYOffset = sBM->bmheight - (sYOffset + height);
    dYOffset = dest_bigbmheight - (dYOffset + height);
  
    dest_bottom = dYOffset + height;
    dest_bmlist = (LispPTR)dBM->bigbmlist;
    GetNewFragment(dest_bmlist, dest_frag, BITMAP *);
    dest_fragtop = 0;
    dest_fragbottom = dest_frag->bmheight;
  
    /* search fragment of bitmaps including the destination top. */
    while (dest_fragbottom <= dYOffset) {
      GetNewFragment(dest_bmlist, dest_frag, BITMAP *);
      if (dest_frag == (BITMAP *)Addr68k_from_LADDR(NIL_PTR)) return;
      dest_fragtop = dest_fragbottom;
      dest_fragbottom += dest_frag->bmheight;
    } /* end while */
  
    /* y offset form bitmap top. */
    dest_yoffset = dYOffset - dest_fragtop;
  
  loop:
    /* height of lineBlt8 */
    if (dest_fragbottom > dest_bottom) {
      /* this fragment includes dest bottom. */
      dest_h = dest_bottom - (dest_fragtop + dest_yoffset);
    } else {
      /* remaining fragments include dest bottom. */
      dest_h = dest_fragbottom - (dest_fragtop + dest_yoffset);
    } /* end if */
  
    dbase =
        (DLword *)Addr68k_from_LADDR(dest_frag->bmbase) + (dest_frag->bmrasterwidth * dest_yoffset);
    nbase = (DLword *)Addr68k_from_LADDR(sBM->bmbase) + (sBM->bmrasterwidth * sYOffset);
  
    sYOffset += (DLword)dest_h; /* next src yoffset */
  
    for (i = 0, dbase += dXOffset; i < dest_h;
         i++, nbase += sBM->bmrasterwidth, ((DLword *)dbase) += dest_frag->bmrasterwidth) {
      lineBlt8(nbase, (int)sXOffset, dbase, (int)width, col0, col1, sourcetype, operation);
    }
  
    /* remaining height */
    height -= dest_h;
    if (height > 0) {
      GetNewFragment(dest_bmlist, dest_frag, BITMAP *);
      if (dest_frag != (BITMAP *)Addr68k_from_LADDR(NIL_PTR)) {
        dest_fragtop = dest_fragbottom;
        dest_fragbottom = dest_fragtop + dest_frag->bmheight;
        dest_yoffset = 0; /* y offset must be zero. */
        nbase += sBM->bmrasterwidth;
        goto loop;
      } /* end if(dest_frag) */
    }   /* end if(height) */
  
  } /* end ColorizeFont8_BIGBM() */
  
  /************************************************************************/
  /*									*/
  /*			n e w C o l o r i z e F o n t 8			*/
  /*									*/
  /*									*/
  /*									*/
  /************************************************************************/
  
  void newColorizeFont8(PILOTBBT *pbt, u_char backcolor, u_char forecolor, LispPTR srctype, LispPTR ope)
  {
    register DLword *nbase;
    register u_char *dbase;
    register int i;
  
    nbase = (DLword *)Addr68k_from_LADDR((pbt->pbtsourcehi << 16) | (pbt->pbtsourcelo));
    (DLword *)dbase = (DLword *)Addr68k_from_LADDR((pbt->pbtdesthi << 16) | (pbt->pbtdestlo));
    dbase += pbt->pbtdestbit;
    for (i = 0; i < pbt->pbtheight;
         i++, nbase += pbt->pbtsourcebpl / 16, dbase += pbt->pbtdestbpl / 8) {
      lineBlt8(nbase, pbt->pbtsourcebit, dbase, pbt->pbtwidth, backcolor, forecolor, srctype, ope);
    } /* for end */
  }
  
  /************************************************************************/
  /*									*/
  /*			U n c o l o r i z e _ B i t m a p		*/
  /*									*/
  /*	Uncolorize bitmap from 8bpp to 1bpp.				*/
  /*									*/
  /************************************************************************/
  
  void Uncolorize_Bitmap(LispPTR args[])
  {
    BITMAP *s_bitmap, *d_bitmap;
    register DLword *OnOff;
  
    register u_char *s_base;
    register DLword *d_base;
    register int y;
    int s_height, s_width, s_bitsperpixel, s_rasterwidth, d_rasterwidth;
  
    s_bitmap = (BITMAP *)Addr68k_from_LADDR(args[0]);
    d_bitmap = (BITMAP *)Addr68k_from_LADDR(args[1]);
    OnOff = (DLword *)Addr68k_from_LADDR(args[2]);
  
    s_height = s_bitmap->bmheight;
    s_width = s_bitmap->bmwidth;
    s_bitsperpixel = s_bitmap->bmbitperpixel;
  
    if (s_bitsperpixel != 8) return;
  
    s_base = (u_char *)Addr68k_from_LADDR(s_bitmap->bmbase);
    d_base = (DLword *)Addr68k_from_LADDR(d_bitmap->bmbase);
    s_rasterwidth = s_bitmap->bmrasterwidth;
    d_rasterwidth = d_bitmap->bmrasterwidth;
  
    for (y = 0; y < s_height; y++) {
      register int x;
      register DLword word;
      word = 0;
      for (x = 0; x < s_width; x++) {
        if (OnOff[*(s_base + x)]) {
          switch (x & 0xF) {
            case 0: word |= 0x8000; break;
            case 1: word |= 0x4000; break;
            case 2: word |= 0x2000; break;
            case 3: word |= 0x1000; break;
            case 4: word |= 0x800; break;
            case 5: word |= 0x400; break;
            case 6: word |= 0x200; break;
            case 7: word |= 0x100; break;
            case 8: word |= 0x80; break;
            case 9: word |= 0x40; break;
            case 10: word |= 0x20; break;
            case 11: word |= 0x10; break;
            case 12: word |= 0x8; break;
            case 13: word |= 0x4; break;
            case 14: word |= 0x2; break;
            case 15:
              word |= 0x1;
              break;
            defaults:
              break;
          } /* end switch( x ) */
        }   /* end if( ) */
        if ((x & 0xF) == 0xF) {
          *(d_base++) = word;
          word = 0;
        } /* end if( x ) */
      }   /* end for( x ) */
  
      if ((x & 0xF) != 0) *(d_base++) = word;
  
      if (y != (s_height - 1)) { (DLword *)s_base += s_rasterwidth; } /* end if( y ) */
  
    } /* end for( y ) */
  
  } /* end Uncolorize_Bitmap() */
  
  /************************************************************************/
  /*									*/
  /*			C o l o r i z e _ B i t m a p			*/
  /*									*/
  /*	Colorize bitmap from 1bpp to 8bpp.				*/
  /*									*/
  /************************************************************************/
  
  extern DLword INPUT_atom, REPLACE_atom;
  
  LispPTR Colorize_Bitmap(LispPTR args[])
  {
    BITMAP *s_bitmap, *d_bitmap;
    int s_left, s_bottom, d_left, d_bottom, width, height, color0, color1, d_nbits;
    register DLword *s_base;
    register u_char *d_base;
    register int i;
  
    N_GETNUMBER(args[10], d_nbits, bad_arg);
    if (d_nbits != 8) return (NIL); /* do nothing. */
  
    s_bitmap = (BITMAP *)Addr68k_from_LADDR(args[0]);
    N_GETNUMBER(args[1], s_left, bad_arg);
    N_GETNUMBER(args[2], s_bottom, bad_arg);
    d_bitmap = (BITMAP *)Addr68k_from_LADDR(args[3]);
    N_GETNUMBER(args[4], d_left, bad_arg);
    N_GETNUMBER(args[5], d_bottom, bad_arg);
    N_GETNUMBER(args[6], width, bad_arg);
    N_GETNUMBER(args[7], height, bad_arg);
    N_GETNUMBER(args[8], color0, bad_arg);
    N_GETNUMBER(args[9], color1, bad_arg);
  
    s_base = (DLword *)Addr68k_from_LADDR(s_bitmap->bmbase) +
             s_bitmap->bmrasterwidth * (s_bitmap->bmheight - (s_bottom + height));
    (DLword *)d_base = (DLword *)Addr68k_from_LADDR(d_bitmap->bmbase) +
                       d_bitmap->bmrasterwidth * (d_bitmap->bmheight - (d_bottom + height));
  
    for (i = 0, d_base += d_left; i < height;
         i++, s_base += s_bitmap->bmrasterwidth, (DLword *)d_base += d_bitmap->bmrasterwidth) {
      lineBlt8(s_base, s_left, d_base, width, (u_char)color0, (u_char)color1, INPUT_atom,
               REPLACE_atom);
  
    } /* end for(i) */
  
  bad_arg:
    return (NIL);
  
  } /* end Colorize_Bitmap() */
  
  /************************************************************************/
  /*									*/
  /*		    D r a w _ 8 B p p C o l o r L i n e			*/
  /*									*/
  /*	Draw a line in the  8-bpp display bitmap.			*/
  /*									*/
  /************************************************************************/
  
  #define op_replace =
  #define op_erase &=
  #define op_invert ^=
  #define op_paint |=
  
  #define draw8bpplinex(op)                    \
    while ((x0 <= xlimit) && (y0 <= ylimit)) { \
      *(base++)op color;                       \
      ++x0;                                    \
      cdl += dy;                               \
      if (dx <= cdl) {                         \
        cdl -= dx;                             \
        base += yinc;                          \
        ++y0;                                  \
      }                                        \
    }
  
  #define draw8bppliney(op)                    \
    while ((x0 <= xlimit) && (y0 <= ylimit)) { \
      *base op color;                          \
      base += yinc;                            \
      ++y0;                                    \
      cdl += dx;                               \
      if (dy <= cdl) {                         \
        cdl -= dy;                             \
        ++base;                                \
        ++x0;                                  \
      }                                        \
    }
  
  void Draw_8BppColorLine(LispPTR *args)
  {
    extern DLword REPLACE_atom, INVERT_atom, PAINT_atom, ERASE_atom;
    extern int ScreenLocked;
  
    register u_char color;
    register u_char *base;
    register short x0, y0, xlimit, ylimit, dx, dy, cdl, yinc, raster_width;
    int mode, displayflg;
    u_char *n_bmbase;
  
    x0 = (short)(args[0] & 0xffff);
    y0 = (short)(args[1] & 0xffff);
    xlimit = (short)(args[2] & 0xffff);
    ylimit = (short)(args[3] & 0xffff);
    dx = (short)(args[4] & 0xffff);
    dy = (short)(args[5] & 0xffff);
    cdl = (short)(args[6] & 0xffff);
    yinc = (short)(args[7] & 0xffff);
    yinc *= 2; /* for byte addressing */
  
    if (args[8] == PAINT_atom)
      mode = 3;
    else if (args[8] == INVERT_atom)
      mode = 2;
    else if (args[8] == ERASE_atom)
      mode = 1;
    else
      mode = 0; /* REPLACE_atom */
  
    n_bmbase = (u_char *)Addr68k_from_LADDR(args[9]);
    raster_width = (short)(args[10] & 0xffff);
    color = (u_char)(args[11] & 0xff);
  
    if (yinc >= 0) {
      displayflg = n_new_cursorin((DLword *)n_bmbase, (int)(x0 << 3), (int)y0, (int)(xlimit << 3),
                                  (int)ylimit);
    } else {
      displayflg = n_new_cursorin((DLword *)n_bmbase, (int)(x0 << 3), (int)(y0 - ylimit),
                                  (int)(xlimit << 3), (int)ylimit);
    }
  
    base = n_bmbase + y0 * (raster_width << 1) + x0;
    x0 = y0 = 0;
  
    if (displayflg) {
      ScreenLocked = T;
      HideCursor;
    }
  
    if (dx >= dy) { /* .draw8bpplinex */
      switch (mode) {
        case 0: draw8bpplinex(op_replace); break;
        case 1: draw8bpplinex(op_erase); break;
        case 2: draw8bpplinex(op_invert); break;
        case 3: draw8bpplinex(op_paint); break;
      } /* end switch */
  
    } else { /* .draw8bppliney */
      switch (mode) {
        case 0: draw8bppliney(op_replace); break;
        case 1: draw8bppliney(op_erase); break;
        case 2: draw8bppliney(op_invert); break;
        case 3: draw8bppliney(op_paint); break;
      } /* end switch */
  
    } /* end if( dx >= dy ) */
  
    if (displayflg) {
      ShowCursor;
      ScreenLocked = NIL;
    }
  
  } /* end Draw_8BppColorLine */
  