/* $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 */
