home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / pstoedit.zip / source.zip / pstoedit.2.50 / cd1.2x / cd.c < prev    next >
C/C++ Source or Header  |  1996-11-22  |  65KB  |  2,317 lines

  1.  
  2. /* cd.c main file for cgmdraw module.
  3.  
  4.         Written by G. Edward Johnson <mailto:lorax@nist.gov>
  5.         Date: April 1996
  6.         Copyright: cd software produced by NIST, an agency of the 
  7.     U.S. government, is by statute not subject to copyright
  8.     in the United States. Recipients of this software assume all 
  9.     responsibilities associated with its operation, modification
  10.     and maintenance.
  11.  
  12.         Portions of this package are from the gd package written by
  13.     Thomas Boutell and are copyright 1994, 1995, Quest Protein 
  14.     Database Center, Cold Spring Harbor Labs.  They are marked in the
  15.     source code.
  16.  
  17. */
  18.  
  19.  
  20. #include <malloc.h>
  21. #include <stdio.h>
  22. #include <math.h>
  23. #include <string.h>
  24. #include <stdlib.h>
  25. #include "defines.h"
  26. #include "cd.h"
  27.  
  28. static    const unsigned char * fontnames [] = {
  29.     (unsigned char *) "Times",
  30.     (unsigned char *) "Times Bold",
  31.     (unsigned char *) "Times Italic",
  32.     (unsigned char *) "Times Bold Italic",
  33.     (unsigned char *) "Helvetica",
  34.     (unsigned char *) "Helvetica Bold",
  35.     (unsigned char *) "Helvetica Italic",
  36.     (unsigned char *) "Helvetica Bold Italic",
  37.     (unsigned char *) "Courier",
  38.     (unsigned char *) "Courier Bold",
  39.     (unsigned char *) "Courier Italic",
  40.     (unsigned char *) "Courier Bold Italic",
  41.     (unsigned char *) "Symbol",
  42.     0 
  43. };
  44.  
  45. static const int numberOfFonts = (sizeof(fontnames) / sizeof(unsigned char *) ) - 1;
  46.  
  47. cdImagePtr cdImageCreate(int sx, int sy)
  48. {
  49.     cdImagePtr im;
  50. /*    fprintf(stderr,"number of Fonts %d\n",numberOfFonts); */
  51.     im = (cdImage *) calloc(SIZEOF(cdImage), 1);
  52.     if (!im) return 0; /* memory allocation failed */
  53.     /* elemlist is set to some number, when it is full, make it bigger */
  54.     im->elemlist = (unsigned char *) calloc(CDSTARTLISTSIZE, SIZEOF(unsigned char ) );
  55.     if (!im->elemlist) return 0; /* memory allocation failed */
  56.     im->sx = sx;
  57.     im->sy = sy;
  58.     im->colorsTotal = 0;
  59.     /* you can have multiple pictures in a file,  keep track of
  60.      * which one you are on */
  61.     im->picnum = 10;
  62.     /* set line_width, line_height, line_color to the defaults */
  63.     /*gej: I should change these when I figure out what the defaults are */
  64.     im->ltype = CDLTYPE;
  65.     im->lwidth = CDLWIDTH;
  66.     im->lcolor = CDLCOLOR;
  67.     /* interior_style, fill_color, hatch_index */
  68.     im->shapestyle = CDSHAPESTYLE;
  69.     im->shapecolor = CDSHAPECOLOR;
  70.     im->shapehatch = CDSHAPEHATCH;
  71.     /* edge_type, edge_width, edge_color, edge_visibility */
  72.     im->edgetype = CDEDGETYPE;
  73.     im->edgecolor = CDEDGECOLOR;
  74.     im->edgewidth = CDEDGEWIDTH;
  75.     im->edgevis = CDEDGEVIS;
  76.     /* text_color, text_height, text_font */
  77.     im->textcolor = CDTEXTCOLOR;
  78.     im->textheight = CDTEXTHEIGHT;
  79.     im->textfont = CDTEXTFONT;
  80.     im->textpath = CDTEXTPATH;
  81.     /* the next three are used for maintaining the element list
  82.      * don't change these ever */
  83.     im->bytestoend = CDSTARTLISTSIZE;
  84.     im->listlen = CDSTARTLISTSIZE;
  85.     im->curelemlist = im->elemlist;
  86.  
  87.     cdCgmHeader(im);
  88.     return im;
  89.        
  90. }
  91.  
  92. static int cdAppNull(unsigned char *es, int x) {
  93. /* put x  nulls in the string.
  94.  * return value is number of octets added (1) */
  95.     int y;
  96.  
  97.     for(y=0; y<x; y++) {
  98.         *es = '\0';
  99.         es++;
  100.     }
  101.     return x;
  102.  
  103. }
  104.  
  105. static int cdAppByte(unsigned char *es, short int addme) {
  106. /* Append an octet to the end of es 
  107.  * Return value is number of octets added
  108.  * for internal cd functions only, do not call
  109.  */
  110.     *es = addme & 0377;
  111.     return 1;
  112. }
  113.  
  114. static int cdAppShort(unsigned char *es, short int addme) {
  115. /* Append a short to the end of es 
  116.  * return value is number of octets added
  117.  * For internal cd functions only, do not call!
  118.  */
  119.     short int temp;
  120.  
  121.     temp = addme >> 8;
  122.     *es = (unsigned char) temp & 0377;
  123.     es++;
  124.     *es = (unsigned char) addme & 0377;
  125.     return 2;
  126. }
  127.  
  128. /* static int cdAppWord(unsigned char *es, int addme){ */
  129. /* Append an word to es 
  130.  * Return value is number of octets added
  131.  * For internal cd functions only, do not call!
  132.  */
  133. /*
  134.     int temp;
  135.     temp = addme >> 24;
  136.     *es = (unsigned char) temp & 0377;
  137.     es++;
  138.     temp = addme >> 16;
  139.     *es = (unsigned char) temp & 0377;
  140.     es++;
  141.     temp = addme >> 8;
  142.     *es = (unsigned char) temp & 0377;
  143.     es++;
  144.     *es = (unsigned char) addme & 0377;
  145.     es++;
  146.     return 4;
  147. }
  148. */
  149.  
  150. static int cdcomhead(unsigned char *es, int elemclass, int id, int len) {
  151. /* sets the command header in the first two bytes of string es 
  152.  * element class is in bits 15-12
  153.  * element id is in bits 11-5
  154.  * parameter list length is in bits 4-0
  155.  */
  156.     int temp;
  157.  
  158.     if (!es) return 0; /* the string must be allocated first */
  159.  
  160.     /* set the element class */
  161.     *es = (unsigned char) elemclass << 4;
  162.     /* set the element id */
  163.     temp = 0177 & id ;
  164.     temp = temp >> 3;
  165.     *es = *es | temp;
  166.     es++;
  167.     id = id << 5;
  168.     *es = (unsigned char) id;
  169.     *es = *es | (unsigned char) ( 037 & len );
  170.  
  171.     return 1;
  172. }
  173.  
  174. static int cdcomheadlong(unsigned char *es, int elemclass, int id, int len) {
  175. /* sets the command header for the long form.
  176.  * first 16 bits:
  177.  *  element class is in bits 15-12
  178.  *  element id is in bits 11-5
  179.  *  parameter list length is in bits 4-0 = 31
  180.  * second 16 bits:
  181.  *  bit 15 = 0  (for last partition)
  182.  *  bit 14-0 param list len
  183.  */
  184.  
  185.     /* I'm lazy, call cdcomhead to set the first two bytes */
  186.     if (!cdcomhead(es, elemclass, id, 31)) return 0;
  187.     es += 2;
  188.  
  189.     /* now set the second two bytes */
  190.     cdAppShort(es, (short int) len);
  191.     *es = *es & 0177; /* make bit 15 = 0 */
  192.     es += 2;
  193.  
  194.     return 1;
  195. }
  196.  
  197. static int cdAddElem(cdImagePtr im, unsigned char *es, int octet_count)
  198. /* adds a string, which is a CGM element to the elemlist.
  199.  * This function is called by other functions in this library and
  200.  * should NOT be called by users of the library
  201.  * For internal cd functions only, do not call!
  202.  */
  203. {
  204.     unsigned char *newlist; /* in case memory allocation fails */
  205.     int x; /* counter */
  206.  
  207.     while ((octet_count + 1) >= im->bytestoend) {
  208.     /* not enough space, must grow elemlist */
  209.         im->listlen = im->listlen + CDGROWLISTSIZE;
  210.         newlist = (unsigned char *) realloc(im->elemlist, SIZEOF(unsigned char ) * im->listlen);
  211.         if (newlist) {
  212.         /* successfully allocated memory */
  213.             im->elemlist = newlist;
  214.             im->bytestoend = im->bytestoend + CDGROWLISTSIZE;
  215.             im->curelemlist = im->elemlist + (im->listlen - im->bytestoend);
  216.         }
  217.         else {
  218.         /* memory allocation failed, save yurself */
  219.             im->listlen = im->listlen - CDGROWLISTSIZE;
  220.             return 0;
  221.         }
  222.     }
  223.  
  224.     /* ok, if we get to here, there is enough space, so add it. */
  225.     for (x=0; x < octet_count; x++) {
  226.         *im->curelemlist = (unsigned char) *es;
  227.         im->curelemlist++;
  228.         es++;
  229.     }
  230.     im->bytestoend = im->bytestoend - octet_count;
  231.     return 1;
  232.  
  233. }
  234.  
  235. int cdCgmHeader(cdImagePtr im) {
  236. /* add the cgm header to the imagepointer's  element list
  237.  * do it all in a string than call cdAddElem on it
  238.  * For internal cd functions only, do not call!
  239.  */
  240.     unsigned char *headerp;
  241.     unsigned char *head;
  242.     unsigned char *buf, *buf2;
  243.     int octet_count=0;
  244.     int blen; /* length of buf */
  245.     int curly;
  246.  
  247.     headerp = (unsigned char *) calloc(1024, SIZEOF(unsigned char ));
  248.         if (!headerp) return 0; /* memory allocation failed */
  249.     head=headerp;
  250.  
  251.     /*** Attribute: BegMF; Elem Class 0; Elem ID 1 */
  252.     buf = (unsigned char *) "cd: CgmDraw Library";
  253.     blen = strlen( (char *) buf);
  254.     cdcomhead(head, 0, 1, blen+1);
  255.     head += 2;
  256.     head += cdAppByte(head, (short int) blen); 
  257.     buf2 = buf;
  258.     while (*buf2) {
  259.         *head++ = *buf2++;
  260.     }
  261.     octet_count += (blen + 3);
  262.     curly = 4 - (octet_count % 4);
  263.     if (curly % 4) {
  264.         octet_count += curly;
  265.         head += cdAppNull(head, curly);
  266.     }
  267.  
  268.     /*** Attribute: MFVersion; Elem Class 1; Elem ID 1 */
  269.     cdcomhead(head, 1, 1, 2);
  270.     head += 2;
  271.     head += cdAppShort(head, (short int) 1);
  272.     octet_count += 4;
  273.  
  274.     /*** Attribute: MFDesc; Elem Class 1; Elem ID 2 */
  275.     buf = (unsigned char *) "'ProfileId: Model-Profile''ProfileEd:1''ColourClass:colour''Source:Nist CGMDraw 1.2''Date: 1996-06-28'";
  276.     blen = strlen( (char *) buf);
  277.     cdcomheadlong(head, 1, 2, blen+1);
  278.     head += 4;
  279.     head += cdAppByte(head, (short int) blen); 
  280.     buf2 = buf;
  281.     while (*buf2) {
  282.         *head++ = *buf2++;
  283.     }
  284.     octet_count += (blen + 5);
  285.     curly = 4 - (octet_count % 4);
  286.     if (curly % 4) {
  287.         octet_count += curly;
  288.         head += cdAppNull(head, curly);
  289.     }
  290.  
  291.     /*** Attribute: ColrPrec; Elem Class 1; Elem ID 7 */
  292.     cdcomhead(head, 1, 7, 2);
  293.     head += 2;
  294.     head += cdAppShort(head, (short int) 8);
  295.     octet_count += 4;
  296.  
  297.     /*** Attribute: ColrIndexPrec; Elem Class 1; Elem ID 8 */
  298.     cdcomhead(head, 1, 8, 2);
  299.     head += 2;
  300.     head += cdAppShort(head, (short int) 8);
  301.     octet_count += 4;
  302.  
  303.     /*** Attribute: MaxColrIndex; Elem Class 1; Elem ID 9 */
  304.     cdcomhead(head, 1, 9, 1);
  305.     head += 2;
  306.     head += cdAppByte(head, (short int) 255);
  307.     octet_count += 4; head++;
  308.  
  309.     /*** Attribute: MFElemList; Elem Class 1; Elem ID 11 */
  310.     /* shorthand here.  1 means 1 element specified, (-1,1)
  311.      * means drawing-plus-control set */
  312.     cdcomhead(head, 1, 11, 6);
  313.     head += 2;
  314.     head += cdAppShort(head, (short int) 1);
  315.     head += cdAppShort(head, (short int) -1);
  316.     head += cdAppShort(head, (short int) 1);
  317.     octet_count += 8;
  318.  
  319.     /*** Attribute: FontList; Elem Class 1; Elem ID 13 */
  320.     /* get string length of all font names together */
  321.     {
  322.     int len = 0;
  323.     const unsigned char * * font = fontnames;
  324.     while (*font) {
  325. /*        fprintf(stderr,"length of '%s' %d\n",*font,strlen((char *) *font)); */
  326.         len += strlen((char *) *font) + 1; /* add one for end */
  327.         font++;
  328.     }
  329. /*    fprintf(stderr,"length of all fontnames %d\n",len); */
  330.     cdcomheadlong(head, 1, 13, len);
  331.     }
  332.     head +=4;
  333.  
  334.     {
  335.     const unsigned char * * font = fontnames;
  336.     while (*font) {
  337.         buf = (unsigned char *) *font;
  338.         blen = strlen( (char *) buf);
  339. /*         fprintf(stderr,"length of %s %d\n",buf,blen); */
  340.         head += cdAppByte(head, (short int) blen);
  341.         buf2 = buf;
  342.         while (*buf2) {
  343.             *head++ = *buf2++;
  344.         }
  345.         octet_count += blen + 1;
  346.         font++;
  347.     }
  348.     }
  349.  
  350.     octet_count += 4 ;
  351.  
  352.     curly = 4 - (octet_count % 4);
  353.     if (curly % 4) {
  354.         octet_count += curly;
  355.         head += cdAppNull(head, curly);
  356.     }
  357.  
  358.  
  359.     if (cdAddElem(im, headerp, octet_count)) {
  360.         free(headerp);
  361.         headerp = 0;
  362.     }
  363.     else {
  364.         free(headerp);
  365.         return 0;
  366.     }
  367.  
  368.     if (cdCgmPic(im, 0)) {
  369.         return 1;
  370.     }
  371.     else {
  372.         return 0;
  373.     }
  374. }
  375.  
  376.  
  377. int cdCgmPic(cdImagePtr im, int sticky) {
  378. /* Start the picture.  if the sticky bit is set, set and use the defaults
  379.  * of the previous picture.  Otherwise, reset all defaults.
  380.  * Gej:  Right now, will only work if the sticky bit is not set (is 0)
  381.  */
  382.  
  383.     int absolute = 1;
  384.  /* if absolute is true, then "Line/Edge Width Specification Mode" is set to absolute */
  385.     unsigned char *headerp;
  386.     unsigned char *head;
  387.     unsigned char *buf, *buf2;
  388.     char *tb;
  389.     int octet_count=0;
  390.     int blen; /* length of buf */
  391.  
  392.     /* increment the picture number */
  393.     im->picnum++;
  394.     tb = (char *) calloc(4*4, SIZEOF(char) );
  395.     headerp = (unsigned char *) calloc(1024, SIZEOF(unsigned char ));
  396.         if (!headerp) return 0; /* memory allocation failed */
  397.     head=headerp;
  398.  
  399.  
  400.     /*** Attribute: BegPic; Elem Class 0; Elem ID 3 */
  401.     sprintf(tb, "picture %d", im->picnum);
  402.     buf = (unsigned char*) tb;
  403.     /* buf = (unsigned char *) "picture 1"; */
  404.     blen = strlen( (char *) buf);
  405.     cdcomhead(head, 0, 3, blen+1);
  406.     head += 2;
  407.     head += cdAppByte(head, (short int) blen); 
  408.     buf2 = buf;
  409.     while (*buf2) {
  410.         *head++ = *buf2++;
  411.     }
  412.  
  413.     free(tb);
  414.  
  415.     octet_count += (blen + 3);
  416.     if (!(blen % 2)) {
  417.         octet_count++;
  418.         head += cdAppNull(head, 1);
  419.     }
  420.     if (octet_count % 4) {
  421.         octet_count +=2;
  422.         head += cdAppNull(head, 2);
  423.     }
  424.  
  425.     if (absolute) {
  426.         /*** Attribute: Line Width Spec Mode; Elem Class 2; Elem ID 3 */
  427.         cdcomhead(head, 2, 3, 2);
  428.         head += 2;
  429.         head += cdAppShort(head, (short int) 0);
  430.         octet_count += 4;
  431.  
  432.         /*** Attribute: Edge Width Spec Mode; Elem Class 2; Elem ID 5 */
  433.         cdcomhead(head, 2, 5, 2);
  434.         head += 2;
  435.         head += cdAppShort(head, (short int) 0);
  436.         octet_count += 4;
  437.     }
  438.  
  439.     /*** Attribute: ColrMode; Elem Class 2; Elem ID 2 */
  440.     cdcomhead(head, 2, 2, 2);
  441.     head += 2;
  442.     head += cdAppShort(head, (short int) 0);
  443.     octet_count += 4;
  444.  
  445.     /*** Attribute: VDCExt; Elem Class 2; Elem ID 6 */
  446.     cdcomhead(head, 2, 6, 8);
  447.     head += 2;
  448.     head += cdAppShort(head, (short int) 0);
  449.     head += cdAppShort(head, (short int) 0);
  450.     head += cdAppShort(head, (short int) im->sx);
  451.     head += cdAppShort(head, (short int) im->sy);
  452.     octet_count += 10;
  453.  
  454.     /*** Attribute: ColrPrec; Elem Class 0; Elem ID 4 */
  455.     cdcomhead(head, 0, 4, 0);
  456.     head += 2;
  457.     octet_count += 2;
  458.  
  459.     if (sticky) {
  460.     /* gej: were screwed. This isn't implemented yet */
  461.         free(headerp);
  462.         return 0;
  463.     }
  464.     else {
  465.     /* reset all the defaults */
  466.         /* set line_width, line_height, line_color to the defaults */
  467.         im->ltype = CDLTYPE;
  468.         im->lwidth = CDLWIDTH;
  469.         im->lcolor = CDLCOLOR;
  470.         /* interior_style, fill_color, hatch_index */
  471.         im->shapestyle = CDSHAPESTYLE;
  472.         im->shapecolor = CDSHAPECOLOR;
  473.         im->shapehatch = CDSHAPEHATCH;
  474.         /* edge_type, edge_width, edge_color, edge_visibility */
  475.         im->edgetype = CDEDGETYPE;
  476.         im->edgecolor = CDEDGECOLOR;
  477.         im->edgewidth = CDEDGEWIDTH;
  478.         im->edgevis = CDEDGEVIS;
  479.         /* text_color, text_height, text_font */
  480.         im->textcolor = CDTEXTCOLOR;
  481.         im->textheight = CDTEXTHEIGHT;
  482.         im->textfont = CDTEXTFONT;
  483.         im->textpath = CDTEXTPATH;
  484.         /* Nuke the color table if there is one */
  485.         cdImageColorClear(im);
  486.     }
  487.  
  488.  
  489.     if (cdAddElem(im, headerp, octet_count)) {
  490.         free(headerp);
  491.         return 1;
  492.     }
  493.     else {
  494.         free(headerp);
  495.         return 0;
  496.     }
  497.  
  498.  
  499. int cdCgmNewPic(cdImagePtr im, int sticky)
  500. /* The CGM standard allows multiple images in a single file.  This function
  501.  * will close the current picture, then open a new one.
  502.  * if sticky is 0 then all attributes will be reset to the defaults
  503.  * if sticky is 1 then all attributes will be inherited from the prevous
  504.  * picture.  This is currently not implemented, be sure to set sticky to
  505.  * 0.
  506.  */
  507. {
  508.     unsigned char *es, *esp;
  509.     int octet_count=0;
  510.  
  511.     esp = (unsigned char *) calloc(1024, SIZEOF(unsigned char ));
  512.         if (!esp) return 0; /* memory allocation failed */
  513.     es=esp;
  514.  
  515.     /* Attribute: End Picture; Elem Class 0; Elem ID 5; Length 0  */
  516.     cdcomhead(es, 0, 5, 0);
  517.     octet_count += 2;
  518.  
  519.  
  520.     if (cdAddElem(im, esp, octet_count)) {
  521.         free(esp);
  522.     }
  523.     else {
  524.         free(esp);
  525.         return 0;
  526.     }
  527.  
  528.     /* now start the new picture */
  529.     return(cdCgmPic(im, sticky));
  530.  
  531.  
  532. }
  533.  
  534. int cdImageCgm(cdImagePtr im, FILE *out)
  535. /* Gej: Write the image to  file *out, which must be open already
  536.  * does not close the file */
  537. {
  538.     int x; /* counter */
  539.     int used; /* number of bytes used in the list */
  540.     unsigned char *efile, *efilep; /* end of file information */
  541.      efile = (unsigned char *) calloc(4*4,SIZEOF(unsigned char ));
  542.         if (!efile) return 0; /* memory allocation failed */
  543.         efilep=efile;
  544.     /* Attribute: End Picture; Elem Class 0; Elem ID 5 */
  545.     *efilep = '\0';
  546.     efilep++;
  547.     *efilep = '\240'; /* set Elem ID */
  548.     efilep++;
  549.     /* Attribute: End Metafile; Elem Class 0; Elem ID 2 */
  550.     *efilep = '\0';
  551.     efilep++;
  552.     *efilep = '\100'; /* set Elem ID */
  553.  
  554.  
  555.         if (cdAddElem(im, efile, 4)) {
  556.                 free(efile);
  557.         efile = 0;
  558.         efilep = 0;
  559.         }
  560.         else {
  561.                 free(efile);
  562.                 return 0;
  563.         }
  564.  
  565.     /* now output the string, one byte at a time */
  566.     used = im->listlen - im->bytestoend;
  567.     for (x=0;x < used; x++) {
  568.         putc((unsigned char) im->elemlist[x], out);
  569.     }
  570.  
  571.     return 1;
  572.  
  573. }
  574.  
  575.  
  576. int cdSetLineType(cdImagePtr im, int lntype) {
  577. /* Attribute: Line Type; Elem Class 5; Elem ID 2
  578.  * Set the line type.  Possible values are:
  579.  * 1=solid, 2=dash, 3=dot, 4=dash-dot, 5=dash-dot-dot
  580.  * Even though new ones can be defined, I am limiting lntype to these values
  581.  * If you really need more, you can make the proper changes.
  582.  */
  583.     unsigned char *es, *esp;
  584.     int octet_count;
  585.  
  586.     /* First check and see if the user doesn't want any changes,
  587.      * if so, just return success */
  588.     if (lntype == -1)
  589.         return 1;
  590.  
  591.     /* Check and see if the value it is being set to is the current
  592.      * value, if so, don't make any changes, just return 1 */
  593.     if (lntype == im->ltype)
  594.         return 1;
  595.  
  596.     /* Make sure that lntype is between 1 and 5 */
  597.     if ((lntype < 1) || (lntype > 5))
  598.         return 0;
  599.  
  600.     /* allocate sufficent space.  should be 32 bits * 4 to be safe */
  601.     es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
  602.     if (!es) return 0; /* memory allocation failed */
  603.     esp=es;
  604.  
  605.     if (!cdcomhead(es, 5, 2, 2)) return 0;
  606.     es += 2;
  607.     /* set Param_List_Len to 2 (signed int at index precision) */
  608.  
  609.     /* add in the value of lntype */
  610.     es += cdAppShort(es, (short int) lntype);
  611.  
  612.     octet_count = 4; /* we just know this */
  613.  
  614.     /* add it to the buffer */
  615.     if (cdAddElem(im, esp, octet_count)) {
  616.         im->ltype = (short int) lntype;
  617.         free(esp);
  618.         return 1;
  619.     }
  620.     else {
  621.         free(esp);
  622.         return 0;
  623.     }
  624.  
  625. }
  626.  
  627. int cdSetLineWidth(cdImagePtr im, int lnwidth) {
  628. /* Attribute: Line Width; Elem Class 5; Elem ID 3
  629.  * sets the line width.  with an image of height X with line width 1
  630.  * the displayed width will be 1/X%.  as an example, if you image is
  631.  * x=5, y=10, and you set line width = 1, and draw a vertical line, the
  632.  * resulting line will  cover 20% of horizontal area.
  633.  */
  634.     unsigned char *es, *esp;
  635.     int octet_count;
  636.  
  637.     /* First check and see if the user doesn't want any changes,
  638.      * if so, just return success */
  639.     if (lnwidth == -1)
  640.         return 1;
  641.  
  642.     /* Check and see if the value it is being set to is the current
  643.      * value, if so, don't make any changes, just return 1 */
  644.     if (lnwidth == im->lwidth)
  645.         return 1;
  646.  
  647.     /* allocate sufficent space.  should be 32 bits * 4 to be safe */
  648.     es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
  649.     if (!es) return 0; /* memory allocation failed */
  650.     esp=es;
  651.  
  652.  
  653.     octet_count = 2;
  654.     if (!cdcomhead(es, 5, 3, 4)) return 0;
  655.     es += 2;
  656.     /*gej: line width is 32 bit floating point number, 16 bits before the
  657.      * decimal, 16 bits after.   */
  658.  
  659.     es += cdAppShort(es, (short int) lnwidth);
  660.  
  661.     /* the next two (after decimal point) will always be zero */
  662.     es += cdAppNull(es, 2);
  663.  
  664.     octet_count += 4;
  665.     
  666.     
  667.     /* add it to the buffer */
  668.     if (cdAddElem(im, esp, octet_count)) {
  669.         im->lwidth = lnwidth;
  670.         free(esp);
  671.         return 1;
  672.     }
  673.     else {
  674.         free(esp);
  675.         return 0;
  676.     }
  677.  
  678.  
  679. }
  680.  
  681. int cdSetLineColor(cdImagePtr im, int lncolor) {
  682. /* Attribute: Line Colour; Elem Class 5; Elem ID 4
  683.  * Sets the line color.  lncolor should be an index into the color
  684.  * table that you have previously allocated.
  685.  */
  686.     unsigned char *es, *esp;
  687.     int octet_count;
  688.     /* First check and see if the user doesn't want any changes,
  689.      * if so, just return success */
  690.     if (lncolor == -1)
  691.         return 1;
  692.  
  693.     /* Check and see if the value it is being set to is the current
  694.      * value, if so, don't make any changes, just return 1 */
  695.     if (lncolor == im->lcolor)
  696.         return 1;
  697.  
  698.     /* Make sure the color they want to use has been allocated. 
  699.      * also, that color must be non-negative */
  700.     if ((lncolor >= im->colorsTotal ) || (lncolor < 0))
  701.         return 0;  /* you must allocate a color before you use it */
  702.  
  703.     /* allocate sufficent space.  should be 32 bits * 4 to be safe */
  704.     es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
  705.     if (!es) return 0; /* memory allocation failed */
  706.     esp=es;
  707.  
  708.  
  709.     if (!cdcomhead(es, 5, 4, 1)) return 0;
  710.     es += 2;
  711.  
  712.     *es =  0377 & lncolor; /* mask off last 8 bits and put in es */
  713.     es++;
  714.  
  715.     es += cdAppNull(es, 1);
  716.  
  717.     octet_count = 4; /* we just know this; 2 octets of header,
  718.                       * 1 octet of data, 1 octet of null data */
  719.  
  720.         /* add it to the buffer */
  721.         if (cdAddElem(im, esp, octet_count)) {
  722.         im->lcolor = (short int) lncolor;
  723.                 free(esp);
  724.                 return 1;
  725.         }
  726.         else {
  727.                 free(esp);
  728.                 return 0;
  729.         }
  730.  
  731.  
  732. }
  733.  
  734. int cdSetFillStyle(cdImagePtr im, int instyle) {
  735. /* set the style of the interior of filled area elements.
  736.  * Attribute: Interior Style; Elem Class 5; Elem ID 22
  737.  * These attributes stay in effect until changed, so you don't have to output
  738.  * them every time.
  739.  *     Interior Style: (integers 0-6, corresponding to: hollow, solid,
  740.  *                      [not pattern], hatch, empty, [not geometric pattern],
  741.  *                      interpolated.)
  742.  * attribute is 16 bit signed int
  743.  */
  744.     unsigned char *es, *esp;
  745.     int octet_count;
  746.  
  747.     /* First check and see if the user doesn't want any changes,
  748.      * if so, just return success */
  749.     if (instyle == -1)
  750.         return 1;
  751.  
  752.     /* Check and see if the value it is being set to is the current
  753.      * value, if so, don't make any changes, just return 1 */
  754.     if (instyle == im->shapestyle)
  755.         return 1;
  756.  
  757.     /* Make sure that lnhatch is between 0 and 6, but not
  758.      * 2, 5, or 6 */
  759.     if ((instyle < 0) || (instyle > 4) || (instyle == 2))
  760.         return 0;
  761.  
  762.     /* allocate sufficent space.  should be 32 bits * 4 to be safe */
  763.     es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
  764.     if (!es) return 0; /* memory allocation failed */
  765.     esp=es;
  766.  
  767.     /* set the header to Class 5, ID 22, Length 2 */
  768.     if (!cdcomhead(es, 5, 22, 2)) return 0;
  769.     es += 2;
  770.  
  771.     /* add in the value of inhatch */
  772.     es += cdAppShort(es, (short int) instyle);
  773.  
  774.     octet_count = 4; /* we just know this */
  775.  
  776.     /* add it to the buffer */
  777.     if (cdAddElem(im, esp, octet_count)) {
  778.         im->shapestyle = (short int) instyle;
  779.         free(esp);
  780.         return 1;
  781.     }
  782.     else {
  783.         free(esp);
  784.         return 0;
  785.     }
  786.  
  787.  
  788. }
  789.  
  790. int cdSetFillColor(cdImagePtr im, int incolor) {
  791. /* set the color of the interior of filled area elements
  792.  * Attribute: Fill Colour; Elem Class 5; Elem ID 23
  793.  * These attributes stay in effect until changed, so you don't have to output
  794.  * them every time.
  795.  *     Fill Colour: (index into the color table)
  796.  */
  797.     unsigned char *es, *esp;
  798.     int octet_count;
  799.     /* First check and see if the user doesn't want any changes,
  800.      * if so, just return success */
  801.     if (incolor == -1)
  802.         return 1;
  803.  
  804.     /* Check and see if the value it is being set to is the current
  805.      * value, if so, don't make any changes, just return 1 */
  806.     if (incolor == im->shapecolor)
  807.         return 1;
  808.  
  809.     /* Make sure the color they want to use has been allocated. 
  810.      * also, that color must be non-negative */
  811.     if ((incolor >= im->colorsTotal ) || (incolor < 0))
  812.         return 0;  /* you must allocate a color before you use it */
  813.  
  814.     /* allocate sufficent space.  should be 32 bits * 4 to be safe */
  815.     es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
  816.     if (!es) return 0; /* memory allocation failed */
  817.     esp=es;
  818.  
  819.     if (!cdcomhead(es, 5, 23, 1)) return 0;
  820.     es += 2;
  821.  
  822.     *es =  0377 & incolor; /* mask off last 8 bits and put in es */
  823.     es++;
  824.     es += cdAppNull(es, 1);
  825.  
  826.     octet_count = 4; /* we just know this; 2 octets of header,
  827.                       * 1 octet of data, 1 octet of null data */
  828.  
  829.         /* add it to the buffer */
  830.         if (cdAddElem(im, esp, octet_count)) {
  831.         im->shapecolor = (short int) incolor;
  832.                 free(esp);
  833.                 return 1;
  834.         }
  835.         else {
  836.                 free(esp);
  837.                 return 0;
  838.         }
  839.  
  840.  
  841.  
  842. }
  843.  
  844. int cdSetFillHatch(cdImagePtr im, int inhatch) {
  845. /* Set the hatch pattern for the interior of filled-area elements
  846.  * the fill style must be set to hatch for this to have an effect.
  847.  * Attribute: Hatch Index; Elem Class 5; Elem ID 24
  848.  * These attributes stay in effect until changed, so you don't have to output
  849.  * them every time.
  850.  *     Hatch Index: (integers 1-6, corresponding to: horizontal lines,
  851.  *                   vertical lines, pos. slope parallel lines,
  852.  *                   neg. slope parallel lines, horizontal/vertical
  853.  *                   crosshatch, positive/negative slope crosshatch)
  854.  */
  855.  
  856.     unsigned char *es, *esp;
  857.     int octet_count, temp;
  858.  
  859.  
  860.     /* First check and see if the user doesn't want any changes,
  861.      * if so, just return success */
  862.     if (inhatch == -1)
  863.         return 1;
  864.  
  865.     /* Check and see if the value it is being set to is the current
  866.      * value, if so, don't make any changes, just return 1 */
  867.     if (inhatch == im->shapehatch)
  868.         return 1;
  869.  
  870.     /* Make sure that lnhatch is between 1 and 6 */
  871.     if ((inhatch < 1) || (inhatch > 6))
  872.         return 0;
  873.  
  874.     /* allocate sufficent space.  should be 32 bits * 4 to be safe */
  875.     es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
  876.     if (!es) return 0; /* memory allocation failed */
  877.     esp=es;
  878.  
  879.     /* set the command header to class 5, id 24, length 2 */
  880.     if (!cdcomhead (es, 5, 24, 2)) return 0;
  881.     es += 2;
  882.  
  883.     /* add in the value of inhatch */
  884.     temp = inhatch >> 8;
  885.     *es = *es | (temp & 0377);
  886.     es++;
  887.     *es = *es | (inhatch & 0377);
  888.     es++;
  889.  
  890.     octet_count = 4; /* we just know this */
  891.  
  892.     /* add it to the buffer */
  893.     if (cdAddElem(im, esp, octet_count)) {
  894.         im->shapehatch = (short int) inhatch;
  895.         free(esp);
  896.         return 1;
  897.     }
  898.     else {
  899.         free(esp);
  900.         return 0;
  901.     }
  902.  
  903. }
  904.  
  905. int cdSetEdgeType(cdImagePtr im, int edtype) {
  906. /* set the type of the edge of filled-area elements.
  907.  * Attribute: Edge Type; Elem Class 5; Elem ID 27
  908.  * These attributes stay in effect until changed, so you don't have to output
  909.  * them every time.
  910.  *     Edge Type (integers 1-5, corresponding to: solid, dash, dot,
  911.  *                dash-dot, dash-dot-dot. These are the same as those used
  912.  *                for line type.)
  913.  * In Part 3 of the standard (Binary Encoding) on page 47 it says that
  914.  * edge type is integer.  This is incorrect.  Edge type is Index, just
  915.  * like line type.
  916.  * Even though new ones can be defined, I am limiting lntype to these values
  917.  * If you really need more, you can make the proper changes.
  918.  */
  919.     unsigned char *es, *esp;
  920.     int octet_count;
  921.  
  922.     /* First check and see if the user doesn't want any changes,
  923.      * if so, just return success */
  924.     if (edtype == -1)
  925.         return 1;
  926.  
  927.     /* Check and see if the value it is being set to is the current
  928.      * value, if so, don't make any changes, just return 1 */
  929.     if (edtype == im->edgetype)
  930.         return 1;
  931.  
  932.     /* Make sure that lntype is between 1 and 5 */
  933.     if ((edtype < 1) || (edtype > 5))
  934.         return 0;
  935.  
  936.     /* allocate sufficent space.  should be 32 bits * 4 to be safe */
  937.     es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
  938.     if (!es) return 0; /* memory allocation failed */
  939.     esp=es;
  940.  
  941.     if(!cdcomhead(es, 5, 27, 2)) return 0;
  942.     es += 2;
  943.  
  944.     /* add in the value of edtype */
  945.     es += cdAppShort(es, (short int) edtype);
  946.  
  947.     octet_count = 4; /* we just know this */
  948.  
  949.     /* add it to the buffer */
  950.     if (cdAddElem(im, esp, octet_count)) {
  951.         im->edgetype = (short int) edtype;
  952.         free(esp);
  953.         return 1;
  954.     }
  955.     else {
  956.         free(esp);
  957.         return 0;
  958.     }
  959.  
  960.  
  961. }
  962.  
  963. int cdSetEdgeWidth(cdImagePtr im, int edwidth) {
  964. /* Set the width of the edge of filled-area elements.
  965.  * Attribute: Edge Width; Elem Class 5; Elem ID 28
  966.  * These attributes stay in effect until changed, so you don't have to output
  967.  * them every time.
  968.  *     Edge Width (should be the same as line width)
  969.  */
  970.     unsigned char *es, *esp;
  971.     int octet_count, temp;
  972.  
  973.     /* First check and see if the user doesn't want any changes,
  974.      * if so, just return success */
  975.     if (edwidth == -1)
  976.         return 1;
  977.  
  978.     /* Check and see if the value it is being set to is the current
  979.      * value, if so, don't make any changes, just return 1 */
  980.     if (edwidth == im->edgewidth)
  981.         return 1;
  982.  
  983.     /* allocate sufficent space.  should be 32 bits * 4 to be safe */
  984.     es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
  985.     if (!es) return 0; /* memory allocation failed */
  986.     esp=es;
  987.  
  988.     octet_count = 2;
  989.     if (!cdcomhead(es, 5, 28, 4)) return 0;
  990.     es += 2;
  991.  
  992.     /*gej: edge width is 32 bit floating point number, 16 bits before the
  993.      * decimal, 16 bits after.   */
  994.     es++; octet_count++;
  995.     temp = edwidth >> 8;
  996.     *es = *es | (temp & 0377);
  997.     es++; octet_count++;
  998.     *es = *es | (edwidth & 0377);
  999.     /* the next two (after decimal point) will always be zero */
  1000.     es += cdAppNull(es, 2);
  1001.     octet_count+=2;
  1002.     
  1003.     
  1004.     /* add it to the buffer */
  1005.     if (cdAddElem(im, esp, octet_count)) {
  1006.         im->edgewidth = edwidth;
  1007.         free(esp);
  1008.         return 1;
  1009.     }
  1010.     else {
  1011.         free(esp);
  1012.         return 0;
  1013.     }
  1014.  
  1015.  
  1016.  
  1017. }
  1018.  
  1019. int cdSetEdgeColor(cdImagePtr im, int edcolor) {
  1020. /* Set the color of the edge of filled-area elements.
  1021.  * Attribute: Edge Color; Elem Class 5; Elem ID 29
  1022.  * These attributes stay in effect until changed, so you don't have to output
  1023.  * them every time.
  1024.  *     Edge Colour (index into the color table)
  1025.  */
  1026.     unsigned char *es, *esp;
  1027.     int octet_count;
  1028.     /* First check and see if the user doesn't want any changes,
  1029.      * if so, just return success */
  1030.     if (edcolor == -1)
  1031.         return 1;
  1032.  
  1033.     /* Check and see if the value it is being set to is the current
  1034.      * value, if so, don't make any changes, just return 1 */
  1035.     if (edcolor == im->edgecolor)
  1036.         return 1;
  1037.  
  1038.     /* Make sure the color they want to use has been allocated. 
  1039.      * also, that color must be non-negative */
  1040.     if ((edcolor >= im->colorsTotal ) || (edcolor < 0))
  1041.         return 0;  /* you must allocate a color before you use it */
  1042.  
  1043.     /* allocate sufficent space.  should be 32 bits * 4 to be safe */
  1044.     es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
  1045.     if (!es) return 0; /* memory allocation failed */
  1046.     esp=es;
  1047.     if (!cdcomhead(es, 5, 29, 1)) return 0;
  1048.     es += 2;
  1049.  
  1050.     *es =  0377 & edcolor; /* mask off last 8 bits and put in es */
  1051.     es++;
  1052.     es += cdAppNull(es, 1);
  1053.  
  1054.     octet_count = 4; /* we just know this; 2 octets of header,
  1055.                       * 1 octet of data, 1 octet of null data */
  1056.  
  1057.         /* add it to the buffer */
  1058.         if (cdAddElem(im, esp, octet_count)) {
  1059.         im->edgecolor = (short int) edcolor;
  1060.                 free(esp);
  1061.                 return 1;
  1062.         }
  1063.         else {
  1064.                 free(esp);
  1065.                 return 0;
  1066.         }
  1067.  
  1068.  
  1069.  
  1070. }
  1071.  
  1072. int cdSetEdgeVis(cdImagePtr im, int edvis) {
  1073. /* Set the visibility of the edge of filled-area elements.
  1074.  * Attribute: Edge Visibility; Elem Class 5; Elem ID 30
  1075.  * These attributes stay in effect until changed, so you don't have to output
  1076.  * them every time.
  1077.  *     Edge Visibility (integer 0 or 1, corresponding to: Off, On)
  1078.  * Attribute is 16 bit signed int.
  1079.  */
  1080.     unsigned char *es, *esp;
  1081.     int octet_count, temp;
  1082.  
  1083.     /* First check and see if the user doesn't want any changes,
  1084.      * if so, just return success */
  1085.     if (edvis == -1)
  1086.         return 1;
  1087.  
  1088.     /* Check and see if the value it is being set to is the current
  1089.      * value, if so, don't make any changes, just return 1 */
  1090.     if (edvis == im->edgevis)
  1091.         return 1;
  1092.  
  1093.     /* allocate sufficent space.  should be 32 bits * 4 to be safe */
  1094.     es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
  1095.     if (!es) return 0; /* memory allocation failed */
  1096.     esp=es;
  1097.  
  1098.     if (!cdcomhead(es, 5, 30, 2)) return 0;
  1099.     es +=2; octet_count = 2;
  1100.     temp = edvis >> 8;
  1101.     *es = *es | (temp & 0377);
  1102.     es++;
  1103.     *es = *es | (edvis & 0377);
  1104.     es++;
  1105.     octet_count += 2;
  1106.     
  1107.     
  1108.     /* add it to the buffer */
  1109.     if (cdAddElem(im, esp, octet_count)) {
  1110.         im->edgevis = (short int) edvis;
  1111.         free(esp);
  1112.         return 1;
  1113.     }
  1114.     else {
  1115.         free(esp);
  1116.         return 0;
  1117.     }
  1118.  
  1119.  
  1120. }
  1121.  
  1122. int cdSetTextFont(cdImagePtr im, int font) {
  1123. /* Attribute: Text Font Index; Elem Class 5; Elem ID 10
  1124.  * font is an index into the font table.  it can have one of the following
  1125.  * values:
  1126.  *  1 Times
  1127.  *  2 Times Bold
  1128.  *  3 Times Italic
  1129.  *  4 Times Bold Italic
  1130.  *  5 Helvetica
  1131.  *  6 Helvetica Bold
  1132.  *  7 Helvetica Italic
  1133.  *  8 Helvetica Bold Italic
  1134.  *  9 Courier
  1135.  * 10 Courier Bold
  1136.  * 11 Courier Italic
  1137.  * 12 Courier Bold Italic
  1138.  * 13 Symbol
  1139.  */
  1140.     unsigned char *es, *esp;
  1141.     int octet_count;
  1142.  
  1143.     /* First check and see if the user doesn't want any changes,
  1144.      * if so, just return success */
  1145.     if (font == -1)
  1146.         return 1;
  1147.  
  1148.     /* Check and see if the value it is being set to is the current
  1149.      * value, if so, don't make any changes, just return 1 */
  1150.     if (font == im->textfont)
  1151.         return 1;
  1152.  
  1153.     /* Make sure that font is between 1 and numberOfFonts */
  1154.     if ((font < 1) || (font > numberOfFonts))
  1155.         return 0;
  1156.  
  1157.     /* allocate sufficent space.  should be 32 bits * 4 to be safe */
  1158.     es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
  1159.     if (!es) return 0; /* memory allocation failed */
  1160.     esp=es;
  1161.  
  1162.     if(!cdcomhead(es, 5, 10, 2)) return 0;
  1163.     es += 2;
  1164.  
  1165.     es += cdAppShort(es, (short int) font);
  1166.  
  1167.     octet_count = 4; /* we just know this */
  1168.  
  1169.     /* add it to the buffer */
  1170.     if (cdAddElem(im, esp, octet_count)) {
  1171.         im->textfont = (short int) font;
  1172.         free(esp);
  1173.         return 1;
  1174.     }
  1175.     else {
  1176.         free(esp);
  1177.         return 0;
  1178.     }
  1179.  
  1180. }
  1181.  
  1182. int cdSetTextColor(cdImagePtr im, int color) {
  1183. /* Attribute: Text Colour ; Elem Class 5; Elem ID 14
  1184.  * set the forground color of text
  1185.  */
  1186.     unsigned char *es, *esp;
  1187.     int octet_count;
  1188.     /* First check and see if the user doesn't want any changes,
  1189.      * if so, just return success */
  1190.     if (color == -1)
  1191.         return 1;
  1192.  
  1193.     /* Check and see if the value it is being set to is the current
  1194.      * value, if so, don't make any changes, just return 1 */
  1195.     if (color == im->textcolor)
  1196.         return 1;
  1197.  
  1198.     /* Make sure the color they want to use has been allocated. 
  1199.      * also, that color must be non-negative */
  1200.     if ((color >= im->colorsTotal ) || (color < 0))
  1201.         return 0;  /* you must allocate a color before you use it */
  1202.  
  1203.     /* allocate sufficent space.  should be 32 bits * 4 to be safe */
  1204.     es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
  1205.     if (!es) return 0; /* memory allocation failed */
  1206.     esp=es;
  1207.  
  1208.     if(!cdcomhead(es, 5, 14, 1)) return 0;
  1209.     es += 2; 
  1210.  
  1211.     *es =  0377 & color; /* mask off last 8 bits and put in es */
  1212.     es++;
  1213.  
  1214.     octet_count = 4; /* we just know this; 2 octets of header,
  1215.                       * 1 octet of data, 1 octet of null data */
  1216.  
  1217.         /* add it to the buffer */
  1218.         if (cdAddElem(im, esp, octet_count)) {
  1219.         im->textcolor = (short int) color;
  1220.                 free(esp);
  1221.                 return 1;
  1222.         }
  1223.         else {
  1224.                 free(esp);
  1225.                 return 0;
  1226.         }
  1227.  
  1228. }
  1229.  
  1230. int cdSetTextHeight(cdImagePtr im, int height) {
  1231. /* Attribute: Character Height; Elem Class 5; Elem ID 15
  1232.  * the height is in the same units as line width
  1233.  */
  1234.     unsigned char *es, *esp;
  1235.     int octet_count;
  1236.     /* First check and see if the user doesn't want any changes,
  1237.      * if so, just return success */
  1238.     if (height == -1)
  1239.         return 1;
  1240.  
  1241.     /* Check and see if the value it is being set to is the current
  1242.      * value, if so, don't make any changes, just return 1 */
  1243.     if (height == im->textheight)
  1244.         return 1;
  1245.  
  1246.     /* allocate sufficent space.  should be 32 bits * 4 to be safe */
  1247.     es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
  1248.     if (!es) return 0; /* memory allocation failed */
  1249.     esp=es;
  1250.  
  1251.     if(!cdcomhead(es, 5, 15, 2)) return 0;
  1252.     octet_count = 2; es += 2;
  1253.  
  1254.     es += cdAppShort(es, height);
  1255.     octet_count += 2;
  1256.  
  1257.         /* add it to the buffer */
  1258.         if (cdAddElem(im, esp, octet_count)) {
  1259.         im->textheight = height;
  1260.                 free(esp);
  1261.                 return 1;
  1262.         }
  1263.         else {
  1264.                 free(esp);
  1265.                 return 0;
  1266.         }
  1267.  
  1268. }
  1269.  
  1270. int cdSetTextPath(cdImagePtr im, int tpath) {
  1271. /* Attribute: Text Path; Elem Class 5; Elem ID 17
  1272.  * Is one of:
  1273.  *   0 right -- Means the direction of the character base vector
  1274.  *   1 left  -- means 180 degrees from the character base vector
  1275.  *   2 up    -- means the direction of the character up vector
  1276.  *   3 down  -- means 180 degrees from the character up vector
  1277.  */
  1278.     unsigned char *es, *esp;
  1279.     int octet_count;
  1280.  
  1281.     /* First check and see if the user doesn't want any changes,
  1282.      * if so, just return success */
  1283.     if (tpath == -1)
  1284.         return 1;
  1285.  
  1286.     /* Check and see if the value it is being set to is the current
  1287.      * value, if so, don't make any changes, just return 1 */
  1288.     if (tpath == im->textpath)
  1289.         return 1;
  1290.  
  1291.     /* allocate sufficent space.  should be 32 bits * 4 to be safe */
  1292.     es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
  1293.     if (!es) return 0; /* memory allocation failed */
  1294.     esp=es;
  1295.     octet_count = 0;
  1296.  
  1297.     if (!cdcomhead(es, 5, 17, 2)) return 0;
  1298.     es +=2; octet_count = 2;
  1299.  
  1300.     es += cdAppShort(es, (short int) tpath);
  1301.     octet_count += 2;
  1302.  
  1303.         /* add it to the buffer */
  1304.         if (cdAddElem(im, esp, octet_count)) {
  1305.         im->textpath = (short int) tpath;
  1306.                 free(esp);
  1307.                 return 1;
  1308.         }
  1309.         else {
  1310.                 free(esp);
  1311.                 return 0;
  1312.         }
  1313.  
  1314. }
  1315.  
  1316. int cdSetTextOrient(cdImagePtr im, int xup, int yup, int xbase, int ybase) {
  1317. /* Attribute: Character Orientation; Elem Class 5; Elem ID 16
  1318.  * (xbase,ybase) is the run and the rise of the line that the text is
  1319.  * written along.  For regular text at an angle, set xup = -ybase
  1320.  * and yup = xbase.  Setting it to something different will result in
  1321.  * skewed text (which may be what you want.) Text written from bottom to
  1322.  * top at a 90 degree angle would have the following parameters  
  1323.  * xup=-1, yup=0, xbase=0, ybase=1
  1324.  *
  1325.  * This function adds the Orientation to the metafile every time.
  1326.  * It does not follow the normal -1 for no change, although if you
  1327.  * put in the same numbers it won't re-add it to the meta file.
  1328.  */
  1329.     unsigned char *es, *esp;
  1330.     int octet_count;
  1331.  
  1332.  
  1333.     /* allocate sufficent space.  should be 32 bits * 4 to be safe */
  1334.     es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
  1335.     if (!es) return 0; /* memory allocation failed */
  1336.     esp=es;
  1337.     octet_count = 0;
  1338.  
  1339.     if (!cdcomhead(es, 5, 16, 8)) return 0;
  1340.     es +=2; octet_count += 2;
  1341.  
  1342.     /* In the metafile it is a 16 bit signed integer */
  1343.     /* add xup */
  1344.     es += cdAppShort(es, (short int) xup);
  1345.     octet_count += 2;
  1346.     /* add the rest */
  1347.     es += cdAppShort(es, (short int) yup);
  1348.     octet_count += 2;
  1349.     es += cdAppShort(es, (short int) xbase);
  1350.     octet_count += 2;
  1351.     es += cdAppShort(es, (short int) ybase);
  1352.     octet_count += 2;
  1353.  
  1354.         /* add it to the buffer */
  1355.         if (cdAddElem(im, esp, octet_count)) {
  1356.                 free(esp);
  1357.                 return 1;
  1358.         }
  1359.         else {
  1360.                 free(esp);
  1361.                 return 0;
  1362.         }
  1363.  
  1364. }
  1365.  
  1366. int cdSetLineAttrib(cdImagePtr im, int lntype, int lnwidth, int lncolor) {
  1367. /* Spits out the attributes of lines.  These attributes stay in effect
  1368.  * until changed, so you don't have to output them every time.
  1369.  */
  1370.  
  1371.     if (!cdSetLineType(im, lntype)) return 0;
  1372.     if (!cdSetLineWidth(im, lnwidth)) return 0;
  1373.     if (!cdSetLineColor(im, lncolor)) return 0;
  1374.  
  1375.     return 1;
  1376.  
  1377. }
  1378.  
  1379. int cdSetShapeFillAttrib(cdImagePtr im, int instyle, int incolor, int inhatch) {
  1380. /* Spits out the attributes for the interior of filled-area elements.
  1381.  * These attributes stay in effect until changed, so you don't have to output
  1382.  * them every time.
  1383.  * Set the following attributes:
  1384.  *     Interior Style: (integers 0-6, corresponding to: hollow, solid, 
  1385.  *                      [not pattern], hatch, empty, [not geometric pattern], 
  1386.  *                      interpolated.)
  1387.  *     Fill Colour: (index into the color table)
  1388.  *     Hatch Index: (integers 1-6, corresponding to: horizontal lines, 
  1389.  *                   vertical lines, pos. slope parallel lines, 
  1390.  *                   neg. slope parallel lines, horizontal/vertical
  1391.  *                   crosshatch, positive/negative slope crosshatch)
  1392.  */
  1393.     if (!cdSetFillStyle(im, instyle)) return 0;
  1394.     if (!cdSetFillColor(im, incolor)) return 0;
  1395.     if (!cdSetFillHatch(im, inhatch)) return 0;
  1396.  
  1397.     return 1;
  1398. }
  1399.  
  1400. int cdSetShapeEdgeAttrib(cdImagePtr im, int edtype, int edwidth, int edcolor, int edvis) {
  1401. /* Spits out the attributes for the edges of filled-area elements.  It may
  1402.  * seem logical that these would be the same as the corresponding line 
  1403.  * attributes, but this is not the case.
  1404.  * These attributes stay in effect until changed, so you don't have to output
  1405.  * them every time.
  1406.  * Set the following attributes:
  1407.  *     Edge Type (integers 1-5, corresponding to: solid, dash, dot,
  1408.  *                dash-dot, dash-dot-dot. These are the same as those used
  1409.  *                for line type.)
  1410.  *     Edge Width (should be the same as line width)
  1411.  *     Edge Colour (index into the color table)
  1412.  *     Edge Visibility (integer 0 or 1, corresponding to: Off, On)
  1413.  */
  1414.     if (!cdSetEdgeType(im, edtype)) return 0;
  1415.     if (!cdSetEdgeWidth(im, edwidth)) return 0;
  1416.     if (!cdSetEdgeColor(im, edcolor)) return 0;
  1417.     if (!cdSetEdgeVis(im, edvis)) return 0;
  1418.  
  1419.     return 1;
  1420. }
  1421.  
  1422. int cdSetTextAttrib(cdImagePtr im, int font, int color, int height) {
  1423. /* Set the attributes of text.  the font is an integer pointer into the
  1424.  * font list where:
  1425.  *  1 Times
  1426.  *  2 Times Bold
  1427.  *  3 Times Italic
  1428.  *  4 Times Bold Italic
  1429.  *  5 Helvetica
  1430.  *  6 Helvetica Bold
  1431.  *  7 Helvetica Italic
  1432.  *  8 Helvetica Bold Italic
  1433.  *  9 Courier
  1434.  * 10 Courier Bold
  1435.  * 11 Courier Italic
  1436.  * 12 Courier Bold Italic
  1437.  * 13 Symbol
  1438.  * color is an index into the colortable which is the color of the text
  1439.  * size is the approximate size you want the text written in.
  1440.  */
  1441.  
  1442.     if(!cdSetTextFont(im, font))   return 0;
  1443.     if(!cdSetTextColor(im, color)) return 0;
  1444.     if(!cdSetTextHeight(im, height)) return 0;
  1445.  
  1446.     return 1;
  1447. }
  1448.  
  1449.  
  1450. int cdImageDestroy(cdImagePtr im)
  1451. /* gej: should work, unless I make changes to cdImage Struct */
  1452. {
  1453.     if (im->elemlist) {
  1454.         free(im->elemlist);
  1455.     }
  1456.     free(im);
  1457.  
  1458.     return 1;
  1459. }
  1460.  
  1461. int cdImageColorClosest(cdImagePtr im, int r, int g, int b)
  1462. /* From gd library, see README file for copyright information */
  1463. /* gej: should work unchanged */
  1464. /* gej: 5/96, changed the colors to use short int */
  1465. {
  1466.     short int i;
  1467.     long rd, gd, bd;
  1468.     int ct = (-1);
  1469.     long mindist = 0;
  1470.     for (i=0; (i<(im->colorsTotal)); i++) {
  1471.         long dist;
  1472.         if (im->open[i]) {
  1473.             continue;
  1474.         }
  1475.         rd = (im->red[i] - r);    
  1476.         gd = (im->green[i] - g);
  1477.         bd = (im->blue[i] - b);
  1478.         dist = rd * rd + gd * gd + bd * bd;
  1479.         if ((i == 0) || (dist < mindist)) {
  1480.             mindist = dist;    
  1481.             ct = i;
  1482.         }
  1483.     }
  1484.     return ct;
  1485. }
  1486.  
  1487. int cdImageColorClear(cdImagePtr im) {
  1488. /* mark all entries in the color table as open */
  1489.     short int i;
  1490.     for (i=0; (i<(cdMaxColors)); i++) {
  1491.         im->open[i] = 1;
  1492.     }
  1493.     return 1;
  1494. }
  1495.  
  1496. int cdImageColorExact(cdImagePtr im, int r, int g, int b)
  1497. /* From gd library, see README file for copyright information */
  1498. /* gej: should work unchanged */
  1499. /* gej: 5/96, changed colors to work with short ints */
  1500. {
  1501.     short int i;
  1502.     for (i=0; (i<(im->colorsTotal)); i++) {
  1503.         if (im->open[i]) {
  1504.             continue;
  1505.         }
  1506.         if ((im->red[i] == r) && 
  1507.             (im->green[i] == g) &&
  1508.             (im->blue[i] == b)) {
  1509.             return i;
  1510.         }
  1511.     }
  1512.     return -1;
  1513. }
  1514.  
  1515. static int cdImageAddColor(cdImagePtr im, int ct, int r, int g, int b)
  1516. /* adds a color to the cgm file.  Does not allocate it in the
  1517.  * cdImagePtr object.  Use cdImageColorAllocate, not this one.
  1518.  */
  1519. {
  1520.     unsigned char *cts, *ctsp; /* GEJ: color table attribute */
  1521.     int octet_count; /* GEJ: octet count */
  1522.     /*
  1523.      * Attribute: Colour Table; Elem Class 5; Elem ID 34
  1524.      * two parameters P1: Starting colour table index (1 octet, UI)
  1525.      * P2: list of direct colour values 3-tuples (3 one-octet values)
  1526.      */
  1527.      /* allocate sufficent space.  should be 32 bits * 4 to be safe */
  1528.         cts = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
  1529.         if (!cts) return -1; /* memory allocation failed */
  1530.         ctsp=cts;
  1531.     *ctsp = *ctsp | b6 | b4; /* set elem class to 5 */
  1532.     *ctsp = *ctsp | b2; /* set elem id to 34 */
  1533.     ctsp++;
  1534.     *ctsp = *ctsp | b6;
  1535.     *ctsp = *ctsp | b2; /* set param list len to 4 */
  1536.     ctsp++;
  1537.     octet_count = 2; /* so far */
  1538.     /* now fill in the index number */
  1539.     *ctsp =  (unsigned char) 0377 & ct; /* mask off last 8 bits and put in ctsp*/
  1540.     ctsp++;octet_count++;
  1541.     /* now fill in the RGB values */
  1542.     *ctsp =  (unsigned char) 0377 & r; /* mask off last 8 bits and put in ctsp*/
  1543.     ctsp++;octet_count++;
  1544.     *ctsp =  (unsigned char) 0377 & g; /* mask off last 8 bits and put in ctsp*/
  1545.     ctsp++;octet_count++;
  1546.     *ctsp =  (unsigned char) 0377 & b; /* mask off last 8 bits and put in ctsp*/
  1547.     ctsp++;octet_count++;
  1548.         /* add it to the buffer */
  1549.         if (cdAddElem(im, cts, octet_count)) {
  1550.                 free(cts);
  1551.                 return 1;
  1552.         }
  1553.         else {
  1554.                 free(cts);
  1555.                 return -1;
  1556.         }
  1557.     
  1558.     
  1559. }
  1560.  
  1561. int cdImageColorAllocate(cdImagePtr im, int r, int g, int b)
  1562. /* From gd library, see README file for copyright information
  1563.  * gej: modified to allocate the color in the CGM buffer as well
  1564.  * as the color table */
  1565. /* gej: 5/96, modified to use short ints for colors */
  1566. {
  1567.     short int i;
  1568.     short int ct = (-1);
  1569.     for (i=0; (i<(im->colorsTotal)); i++) {
  1570.         if (im->open[i]) {
  1571.             ct = i;
  1572.             break;
  1573.         }
  1574.     }    
  1575.     if (ct == (-1)) {
  1576.         ct = im->colorsTotal;
  1577.         if (ct == cdMaxColors) {
  1578.             return -1;
  1579.         }
  1580.         im->colorsTotal++;
  1581.     }
  1582.     im->red[ct] = (short int) r;
  1583.     im->green[ct] = (short int) g;
  1584.     im->blue[ct] = (short int) b;
  1585.     im->open[ct] = (short int) 0;
  1586.     /* GEJ: Now we have successfully alocated it in the color table
  1587.      * so let's put it in the CGM as well. 
  1588.      */
  1589.     if (!cdImageAddColor(im, ct, r, g, b) ) {
  1590.         return -1;
  1591.     }
  1592.     else {
  1593.         return ct;
  1594.     }
  1595.  
  1596. }
  1597.  
  1598. int cdImageColor16(cdImagePtr im) {
  1599. /* allocate the 16 basic colors in the windows pallete */
  1600.     if( -1 == cdImageColorAllocate(im, 255, 255, 255)) return 0;
  1601.     if( -1 == cdImageColorAllocate(im, 0, 0, 0)) return 0;
  1602.     if( -1 == cdImageColorAllocate(im, 128, 0, 0)) return 0;
  1603.     if( -1 == cdImageColorAllocate(im, 0, 128, 0)) return 0;
  1604.     if( -1 == cdImageColorAllocate(im, 128, 128, 0)) return 0;
  1605.     if( -1 == cdImageColorAllocate(im, 0, 0, 128)) return 0;
  1606.     if( -1 == cdImageColorAllocate(im, 128, 0, 128)) return 0;
  1607.     if( -1 == cdImageColorAllocate(im, 0, 128, 128)) return 0;
  1608.     if( -1 == cdImageColorAllocate(im, 128, 128, 128)) return 0;
  1609.     if( -1 == cdImageColorAllocate(im, 192, 192, 192)) return 0;
  1610.     if( -1 == cdImageColorAllocate(im, 255, 0, 0)) return 0;
  1611.     if( -1 == cdImageColorAllocate(im, 0, 255, 0)) return 0;
  1612.     if( -1 == cdImageColorAllocate(im, 255, 255, 0)) return 0;
  1613.     if( -1 == cdImageColorAllocate(im, 0, 0, 255)) return 0;
  1614.     if( -1 == cdImageColorAllocate(im, 255, 0, 255)) return 0;
  1615.     if( -1 == cdImageColorAllocate(im, 0, 255, 255)) return 0;
  1616.  
  1617.     return 1;
  1618.  
  1619. }
  1620.  
  1621. int cdImageColorDeallocate(cdImagePtr im, int color)
  1622. /* From gd library, see README file for copyright information */
  1623. /* gej: should work unchanged */
  1624. {
  1625.     /* Mark it open. */
  1626.     /*im->open[color] = 1;*/
  1627.     /* gej: really can't work, we are not allowing redefinition
  1628.      * of color table entries */
  1629.     return 0;
  1630. }
  1631.  
  1632. int cdLine(cdImagePtr im, int x1, int y1, int x2, int y2)
  1633. /* Graphic Primitive: Polyline; Elem Class 4; Elem ID 1
  1634.  * Actually generate the line, if you are writing a program to use this
  1635.  * library, use this function, not cdImageLine or cdImageDashedLine,
  1636.  * those are just in for compatiblilty with gd 
  1637.  *
  1638.  * This function will draw a line using the current line type, width, and color
  1639.  */
  1640. {
  1641.  
  1642.     unsigned char *es, *esp;
  1643.     int octet_count;
  1644.     short int sweet;
  1645.     short int sour;
  1646.  
  1647.     /* check to make sure the line is withing the scope of the picture
  1648.      * ie. the values you give for drawing the line are within
  1649.      * the values you created the picture with */
  1650.     if (!(cdImageBoundsSafe(im, x1,y1)) || !(cdImageBoundsSafe(im, x2,y2)))
  1651.         return 0;
  1652.  
  1653.     /* allocate sufficent space.  should be 32 bits * 4 to be safe */
  1654.     es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
  1655.     if (!es) return 0; /* memory allocation failed */
  1656.     esp=es;
  1657.  
  1658.     if (!cdcomhead(es, 4, 1, 8)) return 0;
  1659.     es += 2;
  1660.     octet_count = 2;
  1661.  
  1662.     /* now we are ready for the parameter data */
  1663.     sweet = (short int) x1;
  1664.     sour = sweet >> 8;
  1665.     *es = *es | (sour & 0377);
  1666.     es++; octet_count++;
  1667.     *es = (unsigned char) sweet;
  1668.     es++; octet_count++;
  1669.     sweet = (short int) y1;
  1670.     sour = sweet >> 8;
  1671.     *es = *es | (sour & 0377);
  1672.     es++; octet_count++;
  1673.     *es = (unsigned char) sweet;
  1674.     es++; octet_count++;
  1675.     sweet = (short int) x2;
  1676.     sour = sweet >> 8;
  1677.     *es = *es | (sour & 0377);
  1678.     es++; octet_count++;
  1679.     *es = (unsigned char) sweet;
  1680.     es++; octet_count++;
  1681.     sweet = (short int) y2;
  1682.     sour = sweet >> 8;
  1683.     *es = *es | (sour & 0377);
  1684.     es++; octet_count++;
  1685.     *es = (unsigned char) sweet;
  1686.     octet_count++;
  1687.  
  1688.         /* add it to the buffer */
  1689.         if (cdAddElem(im, esp, octet_count)) {
  1690.                 free(esp);
  1691.                 return 1;
  1692.         }
  1693.         else {
  1694.                 free(esp);
  1695.                 return 0;
  1696.         }
  1697.  
  1698.  
  1699.  
  1700. }
  1701.  
  1702. int cdRectangle(cdImagePtr im, int x1, int y1, int x2, int y2) {
  1703. /* Graphic Primitive: rectangle; Elem Class 4; Elem ID 11
  1704.  * Actually generate the rectangle, if you are writing a program to use this
  1705.  * library, use this function, not cdImageRectangle,
  1706.  * those are just in for compatiblilty with gd 
  1707.  *
  1708.  * This function will draw a Rectangle using the current 
  1709.  * edge type, width, color, and visibility, and the current
  1710.  * fill style, color, and hatch
  1711.  */
  1712.     unsigned char *es, *esp;
  1713.     int octet_count;
  1714.     short int sweet;
  1715.     short int sour;
  1716.  
  1717.     /* check to make sure the line is withing the scope of the picture
  1718.      * ie. the values you give for drawing the line are within
  1719.      * the values you created the picture with */
  1720.     if (!(cdImageBoundsSafe(im, x1,y1)) || !(cdImageBoundsSafe(im, x2,y2)))
  1721.         return 0;
  1722.  
  1723.     /* allocate sufficent space.  should be 32 bits * 4 to be safe */
  1724.     es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
  1725.     if (!es) return 0; /* memory allocation failed */
  1726.     esp=es;
  1727.  
  1728.     /* their are four 16 bit signed integers as attributes */
  1729.     if (!cdcomhead(es, 4, 11, 8)) return 0;
  1730.     es +=2; octet_count = 2;
  1731.  
  1732.     /* now we are ready for the parameter data */
  1733.     sweet = (short int) x1;
  1734.     sour = sweet >> 8;
  1735.     *es = *es | (sour & 0377);
  1736.     es++; octet_count++;
  1737.     *es = (unsigned char) sweet;
  1738.     es++; octet_count++;
  1739.     sweet = (short int) y1;
  1740.     sour = sweet >> 8;
  1741.     *es = *es | (sour & 0377);
  1742.     es++; octet_count++;
  1743.     *es = (unsigned char) sweet;
  1744.     es++; octet_count++;
  1745.     sweet = (short int) x2;
  1746.     sour = sweet >> 8;
  1747.     *es = *es | (sour & 0377);
  1748.     es++; octet_count++;
  1749.     *es = (unsigned char) sweet;
  1750.     es++; octet_count++;
  1751.     sweet = (short int) y2;
  1752.     sour = sweet >> 8;
  1753.     *es = *es | (sour & 0377);
  1754.     es++; octet_count++;
  1755.     *es = (unsigned char) sweet;
  1756.     octet_count++;
  1757.  
  1758.         /* add it to the buffer */
  1759.         if (cdAddElem(im, esp, octet_count)) {
  1760.                 free(esp);
  1761.                 return 1;
  1762.         }
  1763.         else {
  1764.                 free(esp);
  1765.                 return 0;
  1766.         }
  1767.  
  1768.  
  1769.  
  1770. }
  1771.  
  1772. int cdCircle(cdImagePtr im, int cx, int cy, int r) {
  1773. /* Graphic Primitive: circle; Elem Class 4; Elem ID 12
  1774.  * cx,cy is the center of the circle, r is the radius
  1775.  *
  1776.  * This function will draw a Circle using the current 
  1777.  * edge type, width, color, and visibility, and the current
  1778.  * fill style, color, and hatch
  1779.  */
  1780.     unsigned char *es, *esp;
  1781.     int octet_count;
  1782.     short int sweet;
  1783.     short int sour;
  1784.  
  1785.     /* check to make sure the circle is withing the scope of the picture
  1786.      * ie. the values you give for drawing the circle are within
  1787.      * the values you created the picture with */
  1788.     if (!(cdImageBoundsSafe(im, cx,cy)))
  1789.         return 0;
  1790.  
  1791.     /* allocate sufficent space.  should be 32 bits * 4 to be safe */
  1792.     es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
  1793.     if (!es) return 0; /* memory allocation failed */
  1794.     esp=es;
  1795.  
  1796.     /* their are three 16 bit signed integers as attributes */
  1797.     if (!cdcomhead(es, 4, 12, 6)) return 0;
  1798.     es +=2; octet_count = 2;
  1799.  
  1800.     /* now we are ready for the parameter data */
  1801.     sweet = (short int) cx;
  1802.     sour = sweet >> 8;
  1803.     *es = *es | (sour & 0377);
  1804.     es++; octet_count++;
  1805.     *es = (unsigned char) sweet;
  1806.     es++; octet_count++;
  1807.     sweet = (short int) cy;
  1808.     sour = sweet >> 8;
  1809.     *es = *es | (sour & 0377);
  1810.     es++; octet_count++;
  1811.     *es = (unsigned char) sweet;
  1812.     es++; octet_count++;
  1813.     sweet = (short int) r;
  1814.     sour = sweet >> 8;
  1815.     *es = *es | (sour & 0377);
  1816.     es++; octet_count++;
  1817.     *es = (unsigned char) sweet;
  1818.     octet_count++;
  1819.  
  1820.  
  1821.         /* add it to the buffer */
  1822.         if (cdAddElem(im, esp, octet_count)) {
  1823.                 free(esp);
  1824.                 return 1;
  1825.         }
  1826.         else {
  1827.                 free(esp);
  1828.                 return 0;
  1829.         }
  1830.  
  1831.  
  1832.  
  1833. }
  1834.  
  1835. int cdArc3Pt(cdImagePtr im, int sx,int sy, int ix,int iy, int ex,int ey) {
  1836. /* Graphic Primitive: Cicular Arc 3 Point; Elem Class 4; Elem ID 13
  1837.  *
  1838.  * This function will draw a Circular Arc using the current 
  1839.  * Line type, width, and color, 
  1840.  */
  1841.     unsigned char *es, *esp;
  1842.     int octet_count;
  1843.     short int sweet;
  1844.     short int sour;
  1845.  
  1846.     /* check to make sure the line is withing the scope of the picture
  1847.      * ie. the values you give for drawing the line are within
  1848.      * the values you created the picture with */
  1849.     if (!(cdImageBoundsSafe(im, sx,sy)) || !(cdImageBoundsSafe(im, ix,iy)) || !(cdImageBoundsSafe(im, ex, ey)))
  1850.         return 0;
  1851.  
  1852.     /* allocate sufficent space.  should be 32 bits * 4 to be safe */
  1853.     es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
  1854.     if (!es) return 0; /* memory allocation failed */
  1855.     esp=es;
  1856.  
  1857.     /* their are six 16 bit signed integers as attributes */
  1858.     if (!cdcomhead(es, 4, 13, 12)) return 0;
  1859.     es +=2; octet_count = 2;
  1860.  
  1861.     /* now we are ready for the parameter data */
  1862.     sweet = (short int) sx;
  1863.     sour = sweet >> 8;
  1864.     *es = *es | (sour & 0377);
  1865.     es++; octet_count++;
  1866.     *es = (unsigned char) sweet;
  1867.     es++; octet_count++;
  1868.     sweet = (short int) sy;
  1869.     sour = sweet >> 8;
  1870.     *es = *es | (sour & 0377);
  1871.     es++; octet_count++;
  1872.     *es = (unsigned char) sweet;
  1873.     es++; octet_count++;
  1874.     sweet = (short int) ix;
  1875.     sour = sweet >> 8;
  1876.     *es = *es | (sour & 0377);
  1877.     es++; octet_count++;
  1878.     *es = (unsigned char) sweet;
  1879.     es++; octet_count++;
  1880.     sweet = (short int) iy;
  1881.     sour = sweet >> 8;
  1882.     *es = *es | (sour & 0377);
  1883.     es++; octet_count++;
  1884.     *es = (unsigned char) sweet;
  1885.     es++; octet_count++;
  1886.     sweet = (short int) ex;
  1887.     sour = sweet >> 8;
  1888.     *es = *es | (sour & 0377);
  1889.     es++; octet_count++;
  1890.     *es = (unsigned char) sweet;
  1891.     es++; octet_count++;
  1892.     sweet = (short int) ey;
  1893.     sour = sweet >> 8;
  1894.     *es = *es | (sour & 0377);
  1895.     es++; octet_count++;
  1896.     *es = (unsigned char) sweet;
  1897.     octet_count++;
  1898.  
  1899.  
  1900.         /* add it to the buffer */
  1901.         if (cdAddElem(im, esp, octet_count)) {
  1902.                 free(esp);
  1903.                 return 1;
  1904.         }
  1905.         else {
  1906.                 free(esp);
  1907.                 return 0;
  1908.         }
  1909.  
  1910.  
  1911. }
  1912.  
  1913. int cdArc3PtClose(cdImagePtr im, int sx,int sy, int ix,int iy, int ex,int ey, int cl) {
  1914. /* Graphic Primitive: Cicular Arc 3 Point Close; Elem Class 4; Elem ID 14
  1915.  *
  1916.  * This function will draw a Circle using the current 
  1917.  * edge type, width, color, and visibility, and the current
  1918.  * fill style, color, and hatch
  1919.  *
  1920.  * cd is the closure type.  It can be either 0 for pie closure or
  1921.  * 1 for chord closure.
  1922.  */
  1923.     unsigned char *es, *esp;
  1924.     int octet_count;
  1925.  
  1926.     /* check to make sure the line is withing the scope of the picture
  1927.      * ie. the values you give for drawing the line are within
  1928.      * the values you created the picture with */
  1929.     if (!(cdImageBoundsSafe(im, sx,sy)) || !(cdImageBoundsSafe(im, ix,iy)) || !(cdImageBoundsSafe(im, ex, ey)))
  1930.         return 0;
  1931.  
  1932.     /* make sure that they close the arc either with pie (0) or chord (1) */
  1933.     if ((cl != 0) && (cl != 1))
  1934.         return 0;
  1935.  
  1936.     /* allocate sufficent space.  should be 32 bits * 6 to be safe */
  1937.     es = (unsigned char *) calloc(4*6, SIZEOF(unsigned char ) );
  1938.     if (!es) return 0; /* memory allocation failed */
  1939.     esp=es;
  1940.  
  1941.     /* their are seven 16 bit signed integers as attributes */
  1942.     if (!cdcomhead(es, 4, 14, 14)) return 0;
  1943.     es +=2; octet_count = 2;
  1944.  
  1945.     /* now we are ready for the parameter data */
  1946.     octet_count += cdAppShort(es, (short int) sx);
  1947.     es +=2;
  1948.     octet_count += cdAppShort(es, (short int) sy);
  1949.     es +=2;
  1950.     octet_count += cdAppShort(es, (short int) ix);
  1951.     es +=2;
  1952.     octet_count += cdAppShort(es, (short int) iy);
  1953.     es +=2;
  1954.     octet_count += cdAppShort(es, (short int) ex);
  1955.     es +=2;
  1956.     octet_count += cdAppShort(es, (short int) ey);
  1957.     es +=2;
  1958.     octet_count += cdAppShort(es, (short int) cl);
  1959.     es +=2;
  1960.  
  1961.         /* add it to the buffer */
  1962.         if (cdAddElem(im, esp, octet_count)) {
  1963.                 free(esp);
  1964.                 return 1;
  1965.         }
  1966.         else {
  1967.                 free(esp);
  1968.                 return 0;
  1969.         }
  1970.  
  1971.  
  1972. }
  1973.  
  1974. int cdEllipse(cdImagePtr im, int cx,int cy, int d1x,int d1y, int d2x,int d2y ) {
  1975. /* Graphic Primitive: Ellipse; Elem Class 4; Elem ID 17
  1976.  *
  1977.  * This function will draw an Ellipse using the current 
  1978.  * edge type, width, color, and visibility, and the current
  1979.  * fill style, color, and hatch
  1980.  */
  1981.     unsigned char *es, *esp;
  1982.     int octet_count;
  1983.  
  1984.     /* check to make sure the line is withing the scope of the picture
  1985.      * ie. the values you give for drawing the line are within
  1986.      * the values you created the picture with */
  1987.     if (!(cdImageBoundsSafe(im, cx,cy)) || !(cdImageBoundsSafe(im, d1x,d1y)) || !(cdImageBoundsSafe(im, d2x, d2y)))
  1988.         return 0;
  1989.  
  1990.     /* allocate sufficent space.  should be 32 bits * 4 to be safe */
  1991.     es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) );
  1992.     if (!es) return 0; /* memory allocation failed */
  1993.     esp=es;
  1994.  
  1995.     /* their are six 16 bit signed integers as attributes */
  1996.     if (!cdcomhead(es, 4, 17, 12)) return 0;
  1997.     es +=2; octet_count = 2;
  1998.  
  1999.     /* now we are ready for the parameter data */
  2000.     octet_count += cdAppShort(es, (short int) cx);
  2001.     es +=2;
  2002.     octet_count += cdAppShort(es, (short int) cy);
  2003.     es +=2;
  2004.     octet_count += cdAppShort(es, (short int) d1x);
  2005.     es +=2;
  2006.     octet_count += cdAppShort(es, (short int) d1y);
  2007.     es +=2;
  2008.     octet_count += cdAppShort(es, (short int) d2x);
  2009.     es +=2;
  2010.     octet_count += cdAppShort(es, (short int) d2y);
  2011.     es +=2;
  2012.  
  2013.         /* add it to the buffer */
  2014.         if (cdAddElem(im, esp, octet_count)) {
  2015.                 free(esp);
  2016.                 return 1;
  2017.         }
  2018.         else {
  2019.                 free(esp);
  2020.                 return 0;
  2021.         }
  2022.  
  2023.  
  2024. }
  2025.  
  2026. int cdPolygon(cdImagePtr im, cdPointPtr p, int n) {
  2027. /* Graphic Primitive: Polygon; Elem Class 4; Elem ID 7
  2028.  *
  2029.  * cdPointPtr is defined in cd.h, basically, it is two arrays of integers
  2030.  * p[m].x and p[m].y  containing the x and y values respectively.  n
  2031.  * is the number of points in this array (not the index of the last point,
  2032.  * which is n-1).  n must be at least 3 (otherwise
  2033.  * you really don't have much of a polygon, it is closer to a line.)
  2034.  *
  2035.  * This function will draw a Polygon using the current 
  2036.  * edge type, width, color, and visibility, and the current
  2037.  * fill style, color, and hatch
  2038.  */
  2039.     unsigned char *es, *esp;
  2040.     int octet_count;
  2041.     int x; /* counter */
  2042. /*     fprintf(stderr,"cdPolygon %d\n",n); */
  2043.  
  2044.     if (n < 3) return 0; /* it is either a point or a line */
  2045.  
  2046.     if (n < 8) {
  2047.     /* It fits in the short form of the command, lets us
  2048.      * add it right now, shall we? */
  2049.         /* allocate sufficent space. Should be 32 bits*10 to be safe */
  2050.         es = (unsigned char *) calloc(4*10,SIZEOF(unsigned char ));
  2051.         if (!es) return 0; /* memory allocation failed */
  2052.         esp=es;
  2053.  
  2054.  
  2055.         /* their are n*2 16 bit signed integers as attributes */
  2056.         if (!cdcomhead(es, 4, 7, (n*4))) return 0;
  2057.         es +=2; octet_count = 2;
  2058.  
  2059.     }
  2060.     else if (n < 8191) {
  2061.     /* there are more than 7 points in it, that sucks */
  2062.     /* gej, so basically, for this one, I set the header
  2063.      * to cdcomhead(es, 4, 7, 31) then write a function for the long
  2064.      * form that takes the first 15 bits of n and tags a 0 in front
  2065.      * of it and puts it in es, than I do the for loop all over again
  2066.      * that doesn't seem too hard.  But I will leave that for another
  2067.      * day.
  2068.  
  2069.      * keep in mind that if CDGROWLISTSIZE is smaller than n*4
  2070.      * (at most 32769) then things could fail in a most unsavory fashion.
  2071.      */
  2072.         /* allocate sufficent space.  32 bits*(n+1) to be safe */
  2073.         es = (unsigned char *) calloc(4*(n+1), SIZEOF(unsigned char ));
  2074.         if (!es) return 0; /* memory allocation failed */
  2075.         esp=es;
  2076.  
  2077.         if (!cdcomheadlong(es, 4, 7, (n*4))) return 0;
  2078.         es +=4; octet_count = 4;
  2079.     }
  2080.     else {
  2081.     /* there are more than 8191 points in it, I am not going to implement
  2082.      * that, if you want it that bad, do it yourself. */
  2083.         return 0;
  2084.     }
  2085.     
  2086.  
  2087.     for (x=0; x<n; x++) {
  2088.         /* now we are ready for the parameter data */
  2089.         es += cdAppShort(es, (short int) p->x);
  2090.         es += cdAppShort(es, (short int) p->y);
  2091.         octet_count += 4;
  2092.         p++;
  2093.     }
  2094.  
  2095.         /* add it to the buffer */
  2096.         if (cdAddElem(im, esp, octet_count)) {
  2097.                    free(esp);
  2098.                    return 1;
  2099.         }
  2100.         else {
  2101.                    free(esp);
  2102.                    return 0;
  2103.         }
  2104. }
  2105.  
  2106. int cdPolyLine(cdImagePtr im, cdPointPtr p, int n) {
  2107. /* Graphic Primitive: Polyline; Elem Class 4; Elem ID 1
  2108.  *
  2109.  * cdPointPtr is defined in cd.h, basically, it is two arrays of integers
  2110.  * p[m].x and p[m].y  containing the x and y values respectively.  n
  2111.  * is the number of points in this array (not the index of the last point,
  2112.  * which is n-1).  if n is 2, it is a regular line, like cdline
  2113.  *
  2114.  * This function will draw a Polyline using the current 
  2115.  * line type, width, color, and visibility, 
  2116.  */
  2117.     unsigned char *es, *esp;
  2118.     int octet_count;
  2119.     int x; /* counter */
  2120.  
  2121.     if (n < 2) return 0; /* it is a point */
  2122.  
  2123.     if (n < 8) {
  2124.     /* It fits in the short form of the command, lets us
  2125.      * add it right now, shall we? */
  2126.         /* allocate sufficent space. Should be 32 bits*10 to be safe */
  2127.         es = (unsigned char *) calloc(4*10,SIZEOF(unsigned char ));
  2128.         if (!es) return 0; /* memory allocation failed */
  2129.         esp=es;
  2130.  
  2131.  
  2132.         /* their are n*2 16 bit signed integers as attributes */
  2133.         if (!cdcomhead(es, 4, 1, (n*4))) return 0;
  2134.         es +=2; octet_count = 2;
  2135.  
  2136.     }
  2137.     else if (n < 8191) {
  2138.     /* there are more than 7 points in it, that sucks */
  2139.     /* gej, so basically, for this one, I set the header
  2140.      * using the long version cdcomheadlong(es, 4, 1, n*4)
  2141.  
  2142.      * keep in mind that if CDGROWLISTSIZE is smaller than n*4
  2143.      * (at most 32769) then the list may have to grow several times
  2144.      */
  2145.         /* allocate sufficent space.  32 bits*(n+1) to be safe */
  2146.         es = (unsigned char *) calloc(4*(n+1), SIZEOF(unsigned char ));
  2147.         if (!es) return 0; /* memory allocation failed */
  2148.         esp=es;
  2149.  
  2150.         if (!cdcomheadlong(es, 4, 1, (n*4))) return 0;
  2151.         es +=4; octet_count = 4;
  2152.     }
  2153.     else {
  2154.     /* there are more than 8191 points in it, I am not going to implement
  2155.      * that, if you want it that bad, do it yourself. */
  2156.         return 0;
  2157.     }
  2158.     
  2159.  
  2160.     for (x=0; x<n; x++) {
  2161.         /* now we are ready for the parameter data */
  2162.         es += cdAppShort(es, (short int) p->x);
  2163.         es += cdAppShort(es, (short int) p->y);
  2164.         octet_count += 4;
  2165.         p++;
  2166.     }
  2167.  
  2168.         /* add it to the buffer */
  2169.         if (cdAddElem(im, esp, octet_count)) {
  2170.                    free(esp);
  2171.                    return 1;
  2172.         }
  2173.         else {
  2174.                    free(esp);
  2175.                    return 0;
  2176.         }
  2177. }
  2178.  
  2179. int cdText(cdImagePtr im, int x, int y, const char *ts) {
  2180. /* Graphic Primitive: Text; Elem Class 4; Elem ID 4
  2181.  * add text to the picture.  Start it at the point (x,y)
  2182.  * this should be the lower left corner of where the text is
  2183.  * the parameters are point, enumerated(set to 1), string
  2184.  *
  2185.  * String encoding in CGM is a little strange.  After you have the other
  2186.  * parameter info, the first octet for the string is either 0..254 which
  2187.  * is the number of octets of string data, or 255 which signifies a long
  2188.  * string.  if it is 255 then the next 16 bits indicate the length of the
  2189.  * string.  the first bit (bit15) is 0 if this is the last part of the
  2190.  * string and 1 if another part follows it.  the next 15 bits  are in the
  2191.  * range 0..32767 and are the number of octets of string info following.
  2192.  * so the length stored in the command header is the whole enchelada.
  2193.  */
  2194.     int tslen, curly;
  2195.     unsigned char *es, *esp;
  2196.     int octet_count;
  2197.  
  2198.     /* check to make sure the Text is within the scope of the picture
  2199.      * actually, I am only checking the start of it
  2200.      */
  2201.     if (!(cdImageBoundsSafe(im, x, y)))
  2202.         return 0;
  2203.  
  2204.     /* allocate sufficent space.  should be tslen+ 32 bits * 4 to be safe */
  2205.     tslen = strlen(ts);
  2206.  
  2207.     /* if there are more than 32700 characters fail 
  2208.      * gej: this could go as high as 32767 I think, but lets 
  2209.      * cut it off at 32700 */
  2210.     if ((tslen > 32700) || (tslen < 0))return 0;
  2211.  
  2212.     es = (unsigned char *) calloc( ((4*4)+tslen), SIZEOF(unsigned char ) );
  2213.     if (!es) return 0; /* memory allocation failed */
  2214.     esp=es;
  2215.  
  2216.     if (!cdcomheadlong(es, 4, 4, 9+tslen)) return 0;
  2217.     es +=4; octet_count = 4;
  2218.  
  2219.     /* add the x position, the y position, then 1, which signifies
  2220.      * that this is all the text, there is none appended after it */
  2221.     es += cdAppShort(es, (short int) x);
  2222.     es += cdAppShort(es, (short int) y);
  2223.     es += cdAppShort(es, (short int) 1);
  2224.     octet_count += 6;
  2225.  
  2226.     /* now take care of the string information, for strings 254 bytes
  2227.      * or less, I could use a short one, but why bother, use the long
  2228.      * form for everything */
  2229.     es += cdAppByte(es, (short int) 255);
  2230.     es += cdAppShort(es, (short int) tslen);
  2231.     octet_count += 3;
  2232.     /* gej: I should set bit 15 to 0 because it is the final part of a 
  2233.      * string but I am not going to since I already checked that it was
  2234.      * a 16 number that was non-negative */
  2235.  
  2236.     while(*ts) {
  2237.         *es++ = (unsigned char) *ts++;
  2238.     }
  2239.     octet_count +=tslen;
  2240.     /* now if the octet_count is not divisible by 4 add null padding */
  2241.     curly = 4 - (octet_count % 4);
  2242.     if (curly % 4) {
  2243.         octet_count += curly;
  2244.         es += cdAppNull(es, curly);
  2245.     }
  2246.  
  2247.         /* add it to the buffer */
  2248.         if (cdAddElem(im, esp, octet_count)) {
  2249.                    free(esp);
  2250.                    return 1;
  2251.         }
  2252.         else {
  2253.                    free(esp);
  2254.                    return 0;
  2255.         }
  2256.  
  2257. }
  2258.  
  2259. int cdImageLine(cdImagePtr im, int x1, int y1, int x2, int y2, int color)
  2260. /* gej: this should be so much easier to do as a cgm 
  2261.  * This is in for compatibility with gd, if you don't need that, use
  2262.  * cdLine instead */
  2263. {
  2264.     int ltstate;
  2265.  
  2266.  
  2267.     /* save the linetype state */
  2268.     ltstate = im->ltype;
  2269.     /* set the attributes of the line */
  2270.     if (!cdSetLineAttrib(im, 1, -1, color)) return 0;
  2271.     if (!cdLine(im, x1, y1, x2, y2)) return 0;/* draw the line */
  2272.     /* restore the state If it fails, don't return an error, because
  2273.      * the line was still drawn */
  2274.     cdSetLineType(im, ltstate);
  2275.  
  2276.     return 1;
  2277. }
  2278.  
  2279. int cdImageDashedLine(cdImagePtr im, int x1, int y1, int x2, int y2, int color)
  2280. /* gej: this should be so much easier to do as a cgm 
  2281.  * in order to really get a dashed line you must call cdSetLineType first
  2282.  * This is in for compatibility with gd, if you don't need that, use
  2283.  * cdLine instead */
  2284. {
  2285.     /* set the attributes of the line */
  2286.     if (!cdSetLineAttrib(im, -1, -1, color)) return 0;
  2287.     /* generate the line */
  2288.     if (!cdLine(im, x1, y1, x2, y2)) return 0;
  2289.  
  2290.     /* everthing is A-OK */
  2291.     return 1;
  2292. }
  2293.  
  2294. int cdImageBoundsSafe(cdImagePtr im, int x, int y)
  2295. /* From gd library, see README file for copyright information */
  2296. /* gej: this should work unchanged */
  2297. {
  2298.     return (!(((y < 0) || (y >= im->sy)) ||
  2299.         ((x < 0) || (x >= im->sx))));
  2300. }
  2301.  
  2302.  
  2303. int cdImageRectangle(cdImagePtr im, int x1, int y1, int x2, int y2, int color)
  2304. /* Graphic Primitive: rectangle; Elem Class 4; Elem ID 11
  2305.  */
  2306.  
  2307. /* gej: but I think I will use the cgm rectangle */
  2308. {
  2309.     if(!cdImageLine(im, x1, y1, x2, y1, color)) return 0;
  2310.     if(!cdImageLine(im, x1, y2, x2, y2, color)) return 0;    
  2311.     if(!cdImageLine(im, x1, y1, x1, y2, color)) return 0;
  2312.     if(!cdImageLine(im, x2, y1, x2, y2, color)) return 0;
  2313.  
  2314.     return 1;
  2315. }
  2316.