1 /***********************************************************************/
2 /* Open Visualization Data Explorer                                    */
3 /* (C) Copyright IBM Corp. 1989,1999                                   */
4 /* ALL RIGHTS RESERVED                                                 */
5 /* This code licensed under the                                        */
6 /*    "IBM PUBLIC LICENSE - Open Visualization Data Explorer"          */
7 /***********************************************************************/
8 
9 #include <dxconfig.h>
10 
11 #include <ctype.h>
12 
13 #if defined(HAVE_STRING_H)
14 #include <string.h>
15 #endif
16 
17 #include <dx/dx.h>
18 #include "autoaxes.h"
19 #include "plot.h"
20 
21 static RGBColor DEFAULTTICSCOLOR = {1.0, 1.0, 0.0};
22 static RGBColor DEFAULTLABELCOLOR = {1.0, 1.0, 1.0};
23 static RGBColor DEFAULTGRIDCOLOR = {0.3, 0.3, 0.3};
24 static RGBColor DEFAULTBACKGROUNDCOLOR = {0.05, 0.05, 0.05};
25 static Error GetAnnotationColors(Object, Object,
26                                  RGBColor, RGBColor, RGBColor, RGBColor,
27                                  int *,
28                                  RGBColor *, RGBColor *, RGBColor *,
29                                  RGBColor *);
30 static Error _dxfCopyMostAttributes(Object, Object);
31 
32 extern Pointer _dxfNewAxesObject(void); /* from libdx/axes.c */
33 extern Error _dxfSetAxesCharacteristic(Pointer, char *, Pointer);  /* from libdx/axes.c*/
34 extern Object _dxfAutoAxes(Pointer); /* from libdx/axes.c*/
35 
36 int
m_AutoAxes(Object * in,Object * out)37 m_AutoAxes(Object *in, Object *out)
38 {
39     Pointer axeshandle=NULL;
40     Object object, labels, corners;
41     Camera camera;
42     int n = -9999, ns[3], adjust = 1, i;
43     char *xlabel = NULL, *ylabel = NULL, *zlabel = NULL, *extra = NULL;
44     char *fontname;
45     Point cursor, box[8], min, max;
46     int frame;
47     float labelscale=1.0, fuzzattfloat;
48     int cursor_specified = 0;
49     int grid, fuzzattint;
50     Class class;
51     RGBColor labelcolor, ticcolor, gridcolor, backgroundcolor;
52     Array xticklocations=NULL, yticklocations=NULL, zticklocations=NULL;
53     int numlist;
54     float *list_ptr;
55 
56 
57     ns[0] = ns[1] = ns[2] = 0;
58 
59 
60     /* the object */
61     if (!in[0]) {
62         /* object must be specified */
63 	DXSetError(ERROR_BAD_PARAMETER, "#10000", "object");
64         return ERROR;
65     }
66     if (DXGetObjectClass(in[0])==CLASS_FIELD && DXEmptyField((Field)in[0])) {
67         out[0] = in[0];
68         return OK;
69     }
70     class = DXGetObjectClass(in[0]);
71     if ((class != CLASS_FIELD)&&(class != CLASS_GROUP)&&
72         (class != CLASS_XFORM)&&(class != CLASS_CLIPPED)) {
73        /* object must be a field or a group */
74        DXSetError(ERROR_BAD_PARAMETER,"#10190", "object");
75        return ERROR;
76     }
77     object = in[0];
78 
79     /* camera */
80     if (!in[1]) {
81         DXSetError(ERROR_BAD_PARAMETER, "#10000", "camera");
82         return ERROR;
83     }
84     class = DXGetObjectClass(in[1]);
85     if (class != CLASS_CAMERA) {
86        /* camera must be a camera */
87        DXSetError(ERROR_BAD_PARAMETER,"#10660", "camera");
88        return ERROR;
89     }
90     camera = (Camera)in[1];
91 
92     /* labels */
93     labels = in[2]? in[2] : DXGetAttribute(object, "axis labels");
94     if (labels) {
95 	if (!DXExtractNthString(labels, 0, &xlabel)) {
96             /* must be a string list */
97 	    DXSetError(ERROR_BAD_PARAMETER, "#10201", "labels");
98             return ERROR;
99         }
100 	DXExtractNthString(labels, 1, &ylabel);
101 	DXExtractNthString(labels, 2, &zlabel);
102 	if (DXExtractNthString(labels, 3, &extra))
103 	    DXWarning("extra axis label(s) ignored");
104     }
105 
106     /* number of tick marks */
107     n = -9999;
108     if (in[3]) {
109 	if (DXExtractParameter(in[3], TYPE_INT, 1, 3, (Pointer)ns)) {
110 	    n = 0;
111 	} else if (DXExtractParameter(in[3], TYPE_INT, 1, 2, (Pointer)ns)) {
112 	    ns[2] = 0;
113 	    n = 0;
114 	} else if (!DXExtractInteger(in[3], &n)) {
115             /* ticks must be an integer or integer list */
116 	    DXSetError(ERROR_BAD_PARAMETER, "#10050", "ticks");
117             return ERROR;
118 	}
119     }
120 
121     /* corners is in[4] */
122     corners = in[4];
123 
124     /* show frame? */
125     frame = 0;
126     if (in[5] && !DXExtractInteger(in[5], &frame)) {
127         /* frame parameter must be either 0 or 1 */
128 	DXSetError(ERROR_BAD_PARAMETER, "#10070", "frame");
129         return ERROR;
130     }
131     if ((frame<0) || (frame>1)) {
132 	DXSetError(ERROR_BAD_PARAMETER, "#10070", "frame");
133         return ERROR;
134     }
135     /* adjust? */
136     adjust = 1;
137     if (in[6] && !DXExtractInteger(in[6], &adjust)) {
138 	DXSetError(ERROR_BAD_PARAMETER, "#10070", "adjust");
139         return ERROR;
140     }
141     if (adjust!=0 && adjust!=1) {
142 	DXSetError(ERROR_BAD_PARAMETER, "#10070", "adjust");
143         return ERROR;
144     }
145 
146     /* cursor? */
147     cursor_specified = 0;
148     if (in[7]) {
149 	if (!DXExtractParameter(in[7], TYPE_FLOAT, 3, 1, (Pointer)&cursor)) {
150 	    /* "cursor must be a three vector" */
151 	    DXSetError(ERROR_BAD_PARAMETER, "#10230","cursor", 3);
152             return ERROR;
153         }
154 	cursor_specified = 1;
155     }
156 
157     if (in[8]) {
158         if (!DXExtractInteger(in[8], &grid))  {
159            /* grid must be 0 or 1 */
160            DXSetError(ERROR_BAD_PARAMETER,"#10070", "grid");
161            return ERROR;
162         }
163         if ((grid < 0)||(grid > 1)) {
164            DXSetError(ERROR_BAD_PARAMETER,"#10070", "grid");
165            return ERROR;
166         }
167     }
168     else {
169         grid=0;
170     }
171 
172     /* in[9] and in[10] are the colors for the annotation objects */
173     if (!(GetAnnotationColors(in[9], in[10],
174                               DEFAULTTICSCOLOR, DEFAULTLABELCOLOR,
175                               DEFAULTGRIDCOLOR, DEFAULTBACKGROUNDCOLOR,
176                               &frame,
177                               &ticcolor, &labelcolor,
178                               &gridcolor, &backgroundcolor)))
179         return ERROR;
180 
181    /* labelscale */
182    if (in[11]) {
183       if (!DXExtractFloat(in[11],&labelscale)) {
184          DXSetError(ERROR_BAD_PARAMETER, "#10090","labelscale");
185          return ERROR;
186       }
187       if (labelscale < 0) {
188          DXSetError(ERROR_BAD_PARAMETER, "#10090","labelscale");
189          return ERROR;
190       }
191    }
192 
193 
194    /* font */
195    if (in[12]) {
196       if (!DXExtractString(in[12],&fontname)) {
197          DXSetError(ERROR_BAD_PARAMETER, "#10200","font");
198          return ERROR;
199       }
200    }
201    else {
202       fontname = "standard";
203    }
204 
205    /* If specified, these should override the corners and the tics params */
206    /* user-forced xtic locations */
207    if (in[13]) {
208      if (!(DXGetObjectClass(in[13])==CLASS_ARRAY)) {
209          DXSetError(ERROR_BAD_PARAMETER,"xlocations must be a scalar list");
210          return ERROR;
211      }
212      xticklocations = (Array) in[13];
213    }
214    /* user-forced ytic locations */
215    if (in[14]) {
216      if (!(DXGetObjectClass(in[14])==CLASS_ARRAY)) {
217          DXSetError(ERROR_BAD_PARAMETER,"ylocations must be a scalar list");
218          return ERROR;
219      }
220      yticklocations = (Array) in[14];
221    }
222    /* user-forced ztic locations */
223    if (in[15]) {
224      if (!(DXGetObjectClass(in[15])==CLASS_ARRAY)) {
225          DXSetError(ERROR_BAD_PARAMETER,"zlocations must be a scalar list");
226          return ERROR;
227      }
228      zticklocations = (Array) in[15];
229    }
230    /* user-forced xtic labels; need to set in[13] */
231    if (in[16]) {
232      if (!(DXGetObjectClass(in[16])==CLASS_ARRAY)) {
233          DXSetError(ERROR_BAD_PARAMETER,"xlabels must be a string list");
234          return ERROR;
235      }
236      if (!DXGetArrayInfo((Array)in[16], &numlist, NULL,NULL,NULL,NULL))
237         return ERROR;
238      if (!in[13]) {
239          /* need to make an array to use. It will go from 0 to n-1 */
240          xticklocations = DXNewArray(TYPE_FLOAT, CATEGORY_REAL, 0);
241          if (!xticklocations) return ERROR;
242          list_ptr = DXAllocate(numlist*sizeof(float));
243          if (!list_ptr) return ERROR;
244          for (i=0; i<numlist; i++)
245              list_ptr[i] = (float)i;
246          if (!DXAddArrayData(xticklocations, 0, numlist, list_ptr))
247              return ERROR;
248          DXFree((Pointer)list_ptr);
249       }
250    }
251 
252    /* user-forced ytic labels; need to set in[14] */
253    if (in[17]) {
254      if (!(DXGetObjectClass(in[17])==CLASS_ARRAY)) {
255          DXSetError(ERROR_BAD_PARAMETER,"ylabels must be a string list");
256          return ERROR;
257      }
258      if (!DXGetArrayInfo((Array)in[17], &numlist, NULL,NULL,NULL,NULL))
259         return ERROR;
260      if (!in[14]) {
261          /* need to make an array to use. It will go from 0 to n-1 */
262          yticklocations = DXNewArray(TYPE_FLOAT, CATEGORY_REAL, 0);
263          if (!yticklocations) return ERROR;
264          list_ptr = DXAllocate(numlist*sizeof(float));
265          if (!list_ptr) return ERROR;
266          for (i=0; i<numlist; i++)
267              list_ptr[i] = (float)i;
268          if (!DXAddArrayData(yticklocations, 0, numlist, list_ptr))
269              return ERROR;
270          DXFree((Pointer)list_ptr);
271       }
272    }
273    /* user-forced ztic labels; need to set in[15] */
274    if (in[18]) {
275      if (!(DXGetObjectClass(in[18])==CLASS_ARRAY)) {
276          DXSetError(ERROR_BAD_PARAMETER,"zlabels must be a string list");
277          return ERROR;
278      }
279      if (!DXGetArrayInfo((Array)in[18], &numlist, NULL,NULL,NULL,NULL))
280         return ERROR;
281      if (!in[15]) {
282          /* need to make an array to use. It will go from 0 to n-1 */
283          zticklocations = DXNewArray(TYPE_FLOAT, CATEGORY_REAL, 0);
284          if (!zticklocations) return ERROR;
285          list_ptr = DXAllocate(numlist*sizeof(float));
286          if (!list_ptr) return ERROR;
287          for (i=0; i<numlist; i++)
288              list_ptr[i] = (float)i;
289          if (!DXAddArrayData(zticklocations, 0, numlist, list_ptr))
290              return ERROR;
291          DXFree((Pointer)list_ptr);
292       }
293    }
294 
295 
296    /*
297     * Copy object prior to sticking fuzz onto it
298     */
299    object = DXCopy(object, COPY_HEADER);
300    if (! object)
301        return ERROR;
302 
303    /* put some fuzz on the object */
304    /* if there's already some fuzz, don't munge that */
305    if (DXGetFloatAttribute(object, "fuzz", &fuzzattfloat))
306      fuzzattfloat = fuzzattfloat + 6;
307    else if (DXGetIntegerAttribute(object,"fuzz", &fuzzattint))
308      fuzzattfloat = fuzzattint + 6;
309    else
310      fuzzattfloat = 6;
311    object = DXSetFloatAttribute(object, "fuzz", fuzzattfloat);
312 
313    axeshandle = _dxfNewAxesObject();
314     if (!axeshandle) return ERROR;
315     _dxfSetAxesCharacteristic(axeshandle, "OBJECT", (Pointer)&object);
316     _dxfSetAxesCharacteristic(axeshandle, "CAMERA", (Pointer)&camera);
317     _dxfSetAxesCharacteristic(axeshandle, "XLABEL", (Pointer)xlabel);
318     _dxfSetAxesCharacteristic(axeshandle, "YLABEL", (Pointer)ylabel);
319     _dxfSetAxesCharacteristic(axeshandle, "FONT", (Pointer)fontname);
320     _dxfSetAxesCharacteristic(axeshandle, "LABELSCALE", (Pointer)&labelscale);
321     _dxfSetAxesCharacteristic(axeshandle, "ZLABEL", (Pointer)zlabel);
322     _dxfSetAxesCharacteristic(axeshandle, "NUMTICS", (Pointer)&n);
323     _dxfSetAxesCharacteristic(axeshandle, "NUMTICSX", (Pointer)&ns[0]);
324     _dxfSetAxesCharacteristic(axeshandle, "NUMTICSY", (Pointer)&ns[1]);
325     _dxfSetAxesCharacteristic(axeshandle, "NUMTICSZ", (Pointer)&ns[2]);
326     _dxfSetAxesCharacteristic(axeshandle, "CORNERS", (Pointer)&corners);
327     _dxfSetAxesCharacteristic(axeshandle, "FRAME", (Pointer)&frame);
328     _dxfSetAxesCharacteristic(axeshandle, "ADJUST", (Pointer)&adjust);
329     if (cursor_specified)
330        _dxfSetAxesCharacteristic(axeshandle, "CURSOR", (Pointer)&cursor);
331     else
332        _dxfSetAxesCharacteristic(axeshandle, "CURSOR", NULL);
333     _dxfSetAxesCharacteristic(axeshandle, "TYPEX", (Pointer)"lin");
334     _dxfSetAxesCharacteristic(axeshandle, "TYPEY", (Pointer)"lin");
335     _dxfSetAxesCharacteristic(axeshandle, "TYPEZ", (Pointer)"lin");
336     _dxfSetAxesCharacteristic(axeshandle, "GRID", (Pointer)&grid);
337     _dxfSetAxesCharacteristic(axeshandle, "LABELCOLOR", (Pointer)&labelcolor);
338     _dxfSetAxesCharacteristic(axeshandle, "TICKCOLOR", (Pointer)&ticcolor);
339     _dxfSetAxesCharacteristic(axeshandle, "AXESCOLOR", (Pointer)&ticcolor);
340     _dxfSetAxesCharacteristic(axeshandle, "GRIDCOLOR", (Pointer)&gridcolor);
341     _dxfSetAxesCharacteristic(axeshandle, "BACKGROUNDCOLOR",
342                               (Pointer)&backgroundcolor);
343     /* &&& */
344     _dxfSetAxesCharacteristic(axeshandle, "XLOCS",
345                               (Pointer)xticklocations);
346     _dxfSetAxesCharacteristic(axeshandle, "YLOCS",
347                               (Pointer)yticklocations);
348     _dxfSetAxesCharacteristic(axeshandle, "ZLOCS",
349                               (Pointer)zticklocations);
350     _dxfSetAxesCharacteristic(axeshandle, "XLABELS",
351                               (Pointer)in[16]);
352     _dxfSetAxesCharacteristic(axeshandle, "YLABELS",
353                               (Pointer)in[17]);
354     _dxfSetAxesCharacteristic(axeshandle, "ZLABELS",
355                               (Pointer)in[18]);
356 
357     if (!DXGetError() == ERROR_NONE) {
358        DXFree((Pointer)axeshandle);
359        return ERROR;
360     }
361 
362     out[0] = (Object)_dxfAutoAxes(axeshandle);
363 
364     if (out[0]) {
365        if (!DXBoundingBox(out[0],box)) {
366           DXFree((Pointer)axeshandle);
367           return ERROR;
368        }
369        min.x = DXD_MAX_FLOAT;
370        min.y = DXD_MAX_FLOAT;
371        min.z = DXD_MAX_FLOAT;
372        max.x = -DXD_MAX_FLOAT;
373        max.y = -DXD_MAX_FLOAT;
374        max.z = -DXD_MAX_FLOAT;
375        for (i=0; i<8; i++) {
376          if (box[i].x < min.x) min.x = box[i].x;
377          if (box[i].y < min.y) min.y = box[i].y;
378          if (box[i].z < min.z) min.z = box[i].z;
379          if (box[i].x > max.x) max.x = box[i].x;
380          if (box[i].y > max.y) max.y = box[i].y;
381          if (box[i].z > max.z) max.z = box[i].z;
382        }
383        /* delta.x = max.x - min.x; */
384        /* delta.y = max.y - min.y; */
385        /* delta.z = max.z - min.z; */
386 
387        DXFree((Pointer)axeshandle);
388 
389        DXSetIntegerAttribute(out[0], "autoaxes", 1);
390        /* copy all the top level attributes. However, we
391           don't want to copy the color multiplier and
392           opacity multiplier attributes, because then they'll
393           be there twice and will get concatenated together. */
394        _dxfCopyMostAttributes(out[0],in[0]);
395 
396 
397 
398        if (!in[13]) DXDelete((Object)xticklocations);
399        if (!in[14]) DXDelete((Object)yticklocations);
400        if (!in[15]) DXDelete((Object)zticklocations);
401        return OK;
402     }
403     else
404        if (!in[13]) DXDelete((Object)xticklocations);
405        if (!in[14]) DXDelete((Object)yticklocations);
406        if (!in[15]) DXDelete((Object)zticklocations);
407        DXFree((Pointer)axeshandle);
408        return ERROR;
409 
410 }
411 
412 
413 
GetAnnotationColors(Object colors,Object which,RGBColor defaultticcolor,RGBColor defaultlabelcolor,RGBColor defaultgridcolor,RGBColor defaultbackgroundcolor,int * frame,RGBColor * ticcolor,RGBColor * labelcolor,RGBColor * gridcolor,RGBColor * backgroundcolor)414 static Error GetAnnotationColors(Object colors, Object which,
415                                      RGBColor defaultticcolor,
416                                      RGBColor defaultlabelcolor,
417                                      RGBColor defaultgridcolor,
418                                      RGBColor defaultbackgroundcolor,
419                                      int *frame,
420                                      RGBColor *ticcolor,
421                                      RGBColor *labelcolor,
422                                      RGBColor *gridcolor,
423                                      RGBColor *backgroundcolor)
424 {
425   RGBColor *colorlist =NULL;
426   int i, numcolors, numcolorobjects;
427   char *colorstring, *newcolorstring;
428 
429 
430   /* in[9] is the colors list */
431   /* first set up the default colors */
432   *ticcolor = defaultticcolor;
433   *labelcolor = defaultlabelcolor;
434   *gridcolor = defaultgridcolor;
435   *backgroundcolor = defaultbackgroundcolor;
436   if (colors) {
437     if (DXExtractNthString(colors,0,&colorstring)) {
438       /* it's a list of strings */
439       /* first figure out how many there are */
440       if (!_dxfHowManyStrings(colors, &numcolors))
441          goto error;
442       /* allocate space for the 3-vectors */
443       colorlist = DXAllocateLocal(numcolors*sizeof(RGBColor));
444       if (!colorlist) goto error;
445       for (i=0; i<numcolors;i++) {
446         DXExtractNthString(colors,i,&colorstring);
447         if (!DXColorNameToRGB(colorstring, &colorlist[i])) {
448           _dxfLowerCase(colorstring, &newcolorstring);
449           if (!strcmp(newcolorstring,"clear")) {
450               DXResetError();
451               colorlist[i]=DXRGB(-1.0, -1.0, -1.0);
452           }
453           else {
454             goto error;
455           }
456           DXFree((Pointer)newcolorstring);
457       }
458     }
459     }
460     else {
461       if (!DXQueryParameter(colors, TYPE_FLOAT, 3, &numcolors)) {
462          DXSetError(ERROR_BAD_PARAMETER, "#10052", "colors");
463          goto error;
464       }
465       /* it's a list of 3-vectors */
466       colorlist = DXAllocateLocal(numcolors*sizeof(RGBColor));
467       if (!colorlist) goto error;
468       if (!DXExtractParameter(colors, TYPE_FLOAT, 3, numcolors,
469                             (Pointer)colorlist)) {
470          DXSetError(ERROR_BAD_PARAMETER,"#10052", "colors");
471          goto error;
472       }
473     }
474   }
475   if (!which) {
476     if (colors) {
477       /* all objects get whatever color was there */
478       if (numcolors != 1) {
479         /* "more than one color specified for colors parameter; this requires
480             a list of objects to color" */
481          DXSetError(ERROR_BAD_PARAMETER, "#11839");
482          goto error;
483       }
484       if (colorlist[0].r != -1 || colorlist[0].g != -1 ||
485           colorlist[0].b != -1) {
486       *ticcolor = colorlist[0];
487       *labelcolor = colorlist[0];
488       *gridcolor = colorlist[0];
489       *backgroundcolor = colorlist[0];
490       }
491       else {
492          /* clear color is appropriate only for background */
493          DXSetError(ERROR_BAD_PARAMETER, "#11811");
494          goto error;
495       }
496     }
497   }
498   else {
499     /* a list of strings was specified */
500     /* figure out how many */
501     if (!_dxfHowManyStrings(which, &numcolorobjects)) {
502       /* annotation must be a string list */
503       DXSetError(ERROR_BAD_PARAMETER,"#10201", "annotation");
504       goto error;
505     }
506     if (numcolors==1) {
507        for (i=0; i< numcolorobjects; i++) {
508          DXExtractNthString(which, i, &colorstring);
509          _dxfLowerCase(colorstring, &newcolorstring);
510          /* XXX lower case */
511          if ((colorlist[0].r==-1 && colorlist[0].g==-1 &&
512                colorlist[0].b==-1) && strcmp(newcolorstring,"background")) {
513             DXSetError(ERROR_BAD_PARAMETER, "#11811");
514             goto error;
515          }
516          if (!strcmp(newcolorstring, "ticks"))
517            *ticcolor = colorlist[0];
518          else if (!strcmp(newcolorstring, "labels"))
519            *labelcolor = colorlist[0];
520          else if (!strcmp(newcolorstring,"grid"))
521            *gridcolor=colorlist[0];
522          else if (!strcmp(newcolorstring,"background")) {
523            if (colorlist[0].r==-1 &&
524                colorlist[0].g==-1 &&
525                colorlist[0].b==-1) *frame = *frame+2;
526            else
527              *backgroundcolor=colorlist[0];
528          }
529          else if (!strcmp(newcolorstring,"all")) {
530            *ticcolor = colorlist[0];
531            *labelcolor = colorlist[0];
532            *gridcolor=colorlist[0];
533            *backgroundcolor=colorlist[0];
534          }
535          else {
536            /* annotation objects must be one of "ticks", "labels",
537               "background" or "grid" */
538            DXSetError(ERROR_BAD_PARAMETER, "#10203", "annotation strings",
539                       "ticks, labels, background, grid");
540            goto error;
541          }
542          DXFree((Pointer)newcolorstring);
543        }
544     }
545     else {
546       if (numcolors != numcolorobjects) {
547         /* number of colors must match number of annotation objects if
548            number of colors is greater than 1 */
549         DXSetError(ERROR_BAD_PARAMETER,"#11813");
550         goto error;
551       }
552        for (i=0; i< numcolorobjects; i++) {
553          DXExtractNthString(which, i, &colorstring);
554          _dxfLowerCase(colorstring, &newcolorstring);
555          if ((colorlist[i].r==-1 && colorlist[i].g==-1 &&
556                colorlist[i].b==-1) && strcmp(newcolorstring,"background")) {
557             /* clear is appropriate only for background */
558             DXSetError(ERROR_BAD_PARAMETER, "#11811");
559             goto error;
560          }
561          /* XXX lower case */
562          if (!strcmp(newcolorstring, "ticks"))
563            *ticcolor = colorlist[i];
564          else if (!strcmp(newcolorstring, "labels"))
565            *labelcolor = colorlist[i];
566          else if (!strcmp(newcolorstring,"grid"))
567            *gridcolor=colorlist[i];
568          else if (!strcmp(newcolorstring,"background")) {
569            if (colorlist[i].r==-1 &&
570                colorlist[i].g==-1 &&
571                colorlist[i].b==-1) *frame = *frame+2;
572            else
573              *backgroundcolor=colorlist[i];
574          }
575          else {
576            /* annotation objects must be one of "ticks", "labels",
577               "background" or "grid" */
578            DXSetError(ERROR_BAD_PARAMETER,"#10203", "annotation strings",
579                       "ticks, labels, background, grid");
580            goto error;
581          }
582          DXFree((Pointer)newcolorstring);
583        }
584     }
585  }
586   DXFree((Pointer)colorlist);
587   return OK;
588 error:
589   DXFree((Pointer)colorlist);
590   return ERROR;
591 }
592 
_dxfLowerCase(char * stringin,char ** stringout)593 Error _dxfLowerCase(char *stringin, char **stringout)
594 {
595    int length, i;
596 
597    length = strlen(stringin);
598    *stringout = DXAllocateLocal((length+1)*sizeof(char));
599    for (i=0; i<length; i++) {
600      (*stringout)[i] = tolower(stringin[i]);
601    }
602    (*stringout)[length]= '\0';
603    return OK;
604 
605 }
606 
_dxfCopyMostAttributes(Object out,Object in)607 static Error _dxfCopyMostAttributes(Object out, Object in)
608 {
609 
610   char *name;
611   int i, count=0;
612   Object attribute;
613 
614   for (i=0; (attribute = DXGetEnumeratedAttribute(in, i, &name)); i++) {
615       if (strcmp(name,"color multiplier")&&strcmp(name,"opacity multiplier")) {
616          DXSetAttribute(out, name, attribute);
617          count++;
618       }
619   }
620   return OK;
621 
622 }
623 
624