home *** CD-ROM | disk | FTP | other *** search
/ OpenStep 3.3J / os33j.iso / NextLibrary / TeX / tex / src / texview / color.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-27  |  6.8 KB  |  252 lines

  1. /*  
  2.  *  This is a set of routines for dvips that are used to process color 
  3.  *  commands in the TeX file (passed by \special commands).  This was
  4.  *  orignally written by J. Hafner, E. Blanz and M. Flickner of IBM
  5.  *  Research, Almaden Research Center.  Contact hafner@almaden.ibm.com.
  6.  *  And then it was completely rewritten by Tomas Rokicki to:
  7.  *
  8.  *      - Be easier on the memory allocator (malloc/free)
  9.  *      - Use less memory overall (by a great deal) and be faster
  10.  *      - Work with the -C, -a, and other options
  11.  *      - Be more adaptable to other drivers and previewers.
  12.  *
  13.  *  The motivating idea:  we want to be able to process 5,000 page
  14.  *  documents using lots of colors on each page on a 640K IBM PC
  15.  *  relatively quickly.
  16.  */
  17. #include "structures.h" /* The copyright notice in that file is included too! */
  18. #include <stdio.h>
  19. #include <string.h>
  20. /*
  21.  *   Externals we use.
  22.  */
  23. extern void cmdout() ;
  24. extern void free(), error() ;
  25. extern void texflush() ;
  26. extern void *mymalloc() ;
  27. extern integer pagenum ;
  28. extern FILE *dvifile ;
  29. /*
  30.  *   Here we set some limits on some color stuff.
  31.  */
  32. #define COLORHASH (89)
  33. #define MAXCOLORLEN (120)     /* maximum color length for background */
  34. #define TOTALCOLORLEN (3000)  /* sum of lengths of pending colors */
  35. /*
  36.  *   This is where we store the color information for a particular page.
  37.  *   If we free all of these, we free all of the allocated color
  38.  *   stuff; we do no allocations (but one) other than when we allocate
  39.  *   these.
  40.  */
  41. static struct colorpage {
  42.    struct colorpage *next ;
  43.    integer boploc ; /* we use the bop loc as a page indicator */
  44.    char *bg ;
  45.    char colordat[2] ;
  46. } *colorhash[COLORHASH] ;
  47. static char cstack[TOTALCOLORLEN], *csp, *cend, *bg ;
  48. /*
  49.  *   This routine sends a color command out.  If the command is a
  50.  *   single `word' or starts with a double quote, we send it out
  51.  *   exactly as is (except for any double quote.)  If the command
  52.  *   is a word followed by arguments, we send out the arguments and
  53.  *   then the word prefixed by "TeXcolor".
  54.  */
  55. void colorcmdout(s)
  56. char *s ;
  57. {
  58.    char *p ;
  59.    char tempword[100] ;
  60.  
  61.    while (*s <= ' ')
  62.       s++ ;
  63.    if (*s == '"') {
  64.       cmdout(s+1) ;
  65.       return ;
  66.    }
  67.    for (p=s; *p && *p > ' '; p++) ;
  68.    for (; *p && *p <= ' '; p++) ;
  69.    if (*p == 0) {
  70.       cmdout(s) ;
  71.       return ;
  72.    }
  73.    cmdout(p) ;
  74.    strcpy(tempword, "TeXcolor") ;
  75.    for (p=tempword + strlen(tempword); *s && *s > ' '; p++, s++)
  76.       *p = *s ;
  77.    *p = 0 ;
  78.    cmdout(tempword) ;
  79.    return ;
  80. }
  81. /*
  82.  *   For a new dvi file, call this.  Frees all allocated memory.
  83.  */
  84. #define DEFAULTCOLOR "Black"
  85. void initcolor() {
  86.    int i ;
  87.    struct colorpage *p, *q ;
  88.  
  89.    for (i=0; i<COLORHASH; i++) {
  90.       for (p=colorhash[i]; p; p = q) {
  91.          q = p->next ;
  92.          free(p) ;
  93.       }
  94.       colorhash[i] = 0 ;
  95.    }
  96.    strcpy(cstack, "\n") ;
  97.    strcat(cstack, DEFAULTCOLOR) ;
  98.    csp = cstack + strlen(cstack) ;
  99.    cend = cstack + TOTALCOLORLEN - 3 ; /* for conservativeness */
  100.    bg = 0 ;
  101. }
  102. /*
  103.  * This takes a call from predospecial to set the background color for
  104.  * the current page.  It is saved in stackdepth and backed down the
  105.  * stack during popcolors.
  106.  */
  107. void
  108. background(bkgrnd)
  109. char *bkgrnd ;
  110. {
  111.    if (bkgrnd && *bkgrnd) {
  112.       if (strlen(bkgrnd) > MAXCOLORLEN)
  113.          error(" color name too long; ignored") ;
  114.       else
  115.          strcpy(bg, bkgrnd) ;
  116.    }
  117. }
  118. /*
  119.  * This routine puts a call from \special for color on the colorstack
  120.  * and sets the color in the PostScript.
  121.  */
  122. void
  123. pushcolor(p,outtops)
  124. char *p ;
  125. Boolean outtops ;
  126. {
  127.    if (strlen(p) + csp > cend)
  128.       error("! out of color stack space") ;
  129.    *csp++ = '\n' ;
  130.    strcpy(csp, p) ;
  131.    csp += strlen(p) ;
  132.    if (outtops) {
  133.       texflush() ;
  134.       colorcmdout(p) ;
  135.    }
  136. }
  137. /*
  138.  * This routine removes a color from the colorstack and resets the color
  139.  * in the PostScript to the previous color.
  140.  */
  141. void
  142. popcolor(outtops)
  143. Boolean outtops ;
  144. {
  145.    char *p = csp - 1 ;
  146.  
  147.    while (p >= cstack && *p != '\n')
  148.       p-- ;
  149.    if (p == cstack)
  150.       return ;  /* We don't pop the last color as that is global */
  151.    *p = 0 ;
  152.    csp = p ;
  153.    for (p--; p >= cstack && *p != '\n'; p--) ;
  154.    p++ ;
  155.    if ( outtops ) {
  156.       texflush() ;
  157.       colorcmdout(p) ;
  158.    }
  159. }
  160. /*
  161.  * This routine clears the colorstack, pushes a new color onto the stack
  162.  * (this is now the root or global color).
  163.  */
  164. void
  165. resetcolorstack(p,outtops)
  166. char *p ;
  167. int outtops ;
  168. {
  169.    char *q = csp - 1 ;
  170.  
  171.    while (q > cstack && *q != '\n')
  172.       q-- ;
  173.    if (q > cstack && outtops == 0) {
  174. #ifdef FOOBARNOTDEF
  175. #ifdef SHORTINT
  176.      (void)fprintf(stderr, "You've mistakenly made a global color change ") ;
  177.      (void)fprintf(stderr, "to %s within nested colors\n", p) ;
  178.      (void)fprintf(stderr, "on page %ld. Will try to recover.\n", pagenum) ;
  179. #else   /* ~SHORTINT */
  180.      (void)fprintf(stderr, "You've mistakenly made a global color change ") ;
  181.      (void)fprintf(stderr, "to %s within nested colors\n", p) ;
  182.      (void)fprintf(stderr, "on page %d. Will try to recover.\n", pagenum) ;
  183. #endif  /* ~SHORTINT */
  184. #endif
  185.    }
  186.    csp = cstack ;
  187.    *csp = 0 ;
  188.    pushcolor(p, outtops) ;
  189. }
  190. /*
  191.  *   This routine is a bit magic.  It looks up the page in the current
  192.  *   hash table.  If the page is already entered in the hash table, then
  193.  *   it restores the color to what that page had, and sets the last
  194.  *   color.  This will occur if this is not the first time that this
  195.  *   page has been encountered.
  196.  *
  197.  *   If, on the other hand, this is a subsequent time that the page has
  198.  *   been encountered, then it will create a new hash entry and copy the
  199.  *   current color information into it.  Since we can only encounter a
  200.  *   new page after having just finished scanning the previous page,
  201.  *   this is safe.
  202.  */
  203. void
  204. bopcolor(outtops)
  205. int outtops ;
  206. {
  207.    integer pageloc = ftell(dvifile) ;
  208.    int h = pageloc % COLORHASH ;
  209.    struct colorpage *p = colorhash[h] ;
  210.  
  211.    while (p) {
  212.       if (p->boploc == pageloc)
  213.          break ;
  214.       else
  215.          p = p->next ;
  216.    }
  217.    if (p) {
  218.       strcpy(cstack, p->colordat) ;
  219.       csp = cstack + strlen(cstack) ;
  220.       bg = p->bg ;
  221.       if (outtops && strcmp(bg, "White")!=0 && bg[0]) {
  222.          texflush() ;
  223.          cmdout("gsave") ;
  224.          colorcmdout(bg) ;
  225.          cmdout("clippath fill grestore") ;
  226.       }
  227.    } else {
  228.       p = (struct colorpage *)mymalloc((integer)
  229.                   (strlen(cstack) + sizeof(struct colorpage) + MAXCOLORLEN)) ;
  230.       p->next = colorhash[h] ;
  231.       p->boploc = pageloc ;
  232.       strcpy(p->colordat, cstack) ;
  233.       p->bg = p->colordat + strlen(cstack) + 1 ;
  234.       if (bg)
  235.          strcpy(p->bg, bg) ;
  236.       else
  237.          *(p->bg) = 0 ;
  238.       bg = p->bg ;
  239.       colorhash[h] = p ;
  240.    }
  241.    if (outtops) {
  242.       char *p = csp - 1 ;
  243.       while (p >= cstack && *p != '\n')
  244.          p-- ;
  245.       p++ ;
  246.       texflush() ;
  247.       if (strcmp(p, DEFAULTCOLOR)!=0) {
  248.          colorcmdout(p) ;
  249.       }
  250.    }
  251. }
  252.