ftp.nice.ch/pub/next/text/tex/apps/texview.3.a9.s.tar.gz#/texview/color.c

This is color.c in view mode; [Download] [Up]

/*  
 *  This is a set of routines for dvips that are used to process color 
 *  commands in the TeX file (passed by \special commands).  This was
 *  orignally written by J. Hafner, E. Blanz and M. Flickner of IBM
 *  Research, Almaden Research Center.  Contact hafner@almaden.ibm.com.
 *  And then it was completely rewritten by Tomas Rokicki to:
 *
 *      - Be easier on the memory allocator (malloc/free)
 *      - Use less memory overall (by a great deal) and be faster
 *      - Work with the -C, -a, and other options
 *      - Be more adaptable to other drivers and previewers.
 *
 *  The motivating idea:  we want to be able to process 5,000 page
 *  documents using lots of colors on each page on a 640K IBM PC
 *  relatively quickly.
 */
#include "structures.h" /* The copyright notice in that file is included too! */
#include <stdio.h>
extern void free(), error() ;
extern void texflush() ;
extern char *strcpy() ;
extern int strlen(), strcmp() ;
extern void *mymalloc() ;
/*
 *   Externals we use.
 */
extern void cmdout() ;
extern integer pagenum ;
extern FILE *dvifile ;
/*
 *   Here we set some limits on some color stuff.
 */
#define COLORHASH (99)
#define MAXCOLORLEN (25)     /* maximum color length for background */
#define TOTALCOLORLEN (800)  /* sum of lengths of pending colors */
/*
 *   This is where we store the color information for a particular page.
 *   If we free all of these, we free all of the allocated color
 *   stuff; we do no allocations (but one) other than when we allocate
 *   these.
 */
static struct colorpage {
   struct colorpage *next ;
   integer boploc ; /* we use the bop loc as a page indicator */
   char *bg ;
   char colordat[2] ;
} *colorhash[COLORHASH] ;
static char cstack[TOTALCOLORLEN], *csp, *cend, *bg ;
/*
 *   For a new dvi file, call this.  Frees all allocated memory.
 */
void initcolor() {
   int i ;
   struct colorpage *p, *q ;

   for (i=0; i<COLORHASH; i++) {
      for (p=colorhash[i]; p; p = q) {
         q = p->next ;
         free(p) ;
      }
      colorhash[i] = 0 ;
   }
   strcpy(cstack, "\nBlack") ;
   csp = cstack + strlen(cstack) ;
   cend = cstack + TOTALCOLORLEN - 3 ; /* for conservativeness */
   bg = 0 ;
}
/*
 * This takes a call from predospecial to set the background color for
 * the current page.  It is saved in stackdepth and backed down the
 * stack during popcolors.
 */
void
background(bkgrnd)
char *bkgrnd ;
{
   if (bkgrnd && *bkgrnd) {
      if (strlen(bkgrnd) > MAXCOLORLEN)
         error(" color name too long; ignored") ;
      else
         strcpy(bg, bkgrnd) ;
   }
}
/*
 * This routine puts a call from \special for color on the colorstack
 * and sets the color in the PostScript.
 */
void
pushcolor(p,outtops)
char *p ;
Boolean outtops ;
{
   if (strlen(p) + csp > cend)
      error("! out of color stack space") ;
   *csp++ = '\n' ;
   strcpy(csp, p) ;
   csp += strlen(p) ;
   if (outtops) {
      texflush() ;
      cmdout(p) ;
      cmdout("CK") ;
   }
}
/*
 * This routine removes a color from the colorstack and resets the color
 * in the PostScript to the previous color.
 */
void
popcolor(outtops)
Boolean outtops ;
{
   char *p = csp - 1 ;

   while (p >= cstack && *p != '\n')
      p-- ;
   if (p == cstack)
      return ;  /* We don't pop the last color as that is global */
   *p = 0 ;
   csp = p ;
   for (p--; p >= cstack && *p != '\n'; p--) ;
   p++ ;
   if ( outtops ) {
      texflush() ;
      cmdout(p) ;
      cmdout("CK") ;
   }
}
/*
 * This routine clears the colorstack, pushes a new color onto the stack
 * (this is now the root or global color).
 */
void
resetcolorstack(p,outtops)
char *p ;
int outtops ;
{
   char *q = csp - 1 ;

   while (q > cstack && *q != '\n')
      q-- ;
   csp = cstack ;
   *csp = 0 ;
   pushcolor(p, outtops) ;
}
/*
 *   This routine is a bit magic.  It looks up the page in the current
 *   hash table.  If the page is already entered in the hash table, then
 *   it restores the color to what that page had, and sets the last
 *   color.  This will occur if this is not the first time that this
 *   page has been encountered.
 *
 *   If, on the other hand, this is a subsequent time that the page has
 *   been encountered, then it will create a new hash entry and copy the
 *   current color information into it.  Since we can only encounter a
 *   new page after having just finished scanning the previous page,
 *   this is safe.
 */
void
bopcolor(outtops)
int outtops ;
{
   integer pageloc = ftell(dvifile) ;
   int h = pageloc % COLORHASH ;
   struct colorpage *p = colorhash[h] ;

   while (p) {
      if (p->boploc == pageloc)
         break ;
      else
         p = p->next ;
   }
   if (p) {
      strcpy(cstack, p->colordat) ;
      csp = cstack + strlen(cstack) ;
      bg = p->bg ;
      if (outtops && strcmp(bg, "White")!=0 && bg[0]) {
         cmdout(bg) ;
         cmdout("BG") ;
      }
   } else {
      p = (struct colorpage *)mymalloc((integer)
                  (strlen(cstack) + sizeof(struct colorpage) + MAXCOLORLEN)) ;
      p->next = colorhash[h] ;
      p->boploc = pageloc ;
      strcpy(p->colordat, cstack) ;
      p->bg = p->colordat + strlen(cstack) + 1 ;
      if (bg)
         strcpy(p->bg, bg) ;
      else
         *(p->bg) = 0 ;
      bg = p->bg ;
      colorhash[h] = p ;
   }
   if (outtops) {
      char *p = csp - 1 ;
      while (p >= cstack && *p != '\n')
         p-- ;
      p++ ;
      if (strcmp(p, "Black")!=0) {
         cmdout(p) ;
         cmdout("CK") ;
      }
   }
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.