0022627: Change OCCT memory management defaults
[occt.git] / src / CGM / cgmochar.c
1 #include "cgmout.h"
2
3 /*  File stream name  */
4
5 extern char cgmroot[];
6 static FILE *cgmoc;
7
8 /*  declare void internal functions  */
9
10 # if (defined __STDC__ && __STDC__) || defined __cplusplus
11 /* use function prototypes, they are requred for ANSI C and C++ compilers */
12 /* Main Output driver */
13 void CGMOchar(FILE *stream, Code c, Long *pi, Float *pr, char *pc);
14  /* Check Attributes */
15 static void MOCchkatt(Code type),
16 /* Conditional output of integer */
17             MOCcint(Code code, Int n, Long *var1, Long *var2),
18 /* Conditional output of Enumerated types */
19             MOCcenum(Code code, int n, Enum *var1, Enum *var2),
20 /* Conditional output of a real */
21             MOCcreal(Code code, Float *var1, Float *var2, Enum  r),
22 /* Conditional output of a colour */
23             MOCccol(Code code, int n, struct colour *var1, struct colour *var2),
24 /* Conditional output of a rectangle */
25             MOCrectc(Code code, struct rect *var1, struct rect *var2),
26 /* Output n VDCs */
27             MOCvdc(int n, Long *pi, Float *pr),
28 /* Output a points list */
29             MOCpoints(Long n, Long *pi, Float *pr, Enum set),
30 /* Output an attribute */
31             MOCattrib(Code code),
32 /* Output a real */
33             MOCreal(Double x, Enum type, Prec *ptlist),
34 /* Output an Integer */
35             MOCinteger(Long intval, Logical present, Logical allowed),
36 /* Output a colour list */
37             MOCcells(register Long n, register Long *pi, Enum mode, Prec prec),
38 /* Output a text string */
39             MOCstring(register char *s),
40 /* Output a direct colour */
41             MOCdircol(Posint r, Posint g, Posint b, Prec prec),
42 /* Check if default colour prec & value are used */
43             MOCcoldef(),
44 /* Output a character to the buffer */
45             MOCout(Code hex);
46 #else
47 void CGMOchar();           /* Main Output driver */
48 static void MOCchkatt(),   /* Check Attributes */
49             MOCcint(),     /* Conditional output of integer */
50             MOCcenum(),    /* Conditional output of Enumerated types */
51             MOCcreal(),    /* Conditional output of a real */
52             MOCccol(),     /* Conditional output of a colour */
53             MOCrectc(),    /* Conditional output of a rectangle */
54             MOCvdc(),      /* Output n VDCs */
55             MOCpoints(),   /* Output a points list */
56             MOCattrib(),   /* Output an attribute */
57             MOCreal(),     /* Output a real */
58             MOCinteger(),  /* Output an Integer */
59             MOCcells(),    /* Output a colour list */
60             MOCstring(),   /* Output a text string */
61             MOCdircol(),   /* Output a direct colour */
62             MOCcoldef(),   /* Check if default colour prec & value are used */
63             MOCout();      /* Output a character to the buffer */
64 #endif
65
66 /*  Local Variables */
67
68 static Long subchars=0;
69 static char charsub[CHARSUBNUM];
70
71 /*static char *func="CGMochar", mess[40];*/
72 static char mess[40];
73
74 /*  Macros to do common comparisons  */
75
76 #define RDIFF(x,y)  ( FABS(x-y) > cur.realmin )
77 #define VDIFF(x,y)  ( FABS(x-y) > cur.vdcmin )
78 #define RADIFF(x)   ( FABS(oldatt.x-curatt.x) > cur.realmin )
79 #define VADIFF(x)   ( FABS(oldatt.x-curatt.x) > cur.vdcmin )
80
81 #define ACINT(x,y)    ( MOCcint(x, (Int)1, &oldatt.y, &curatt.y) )
82 #define ACENUM(x,y)   ( MOCcenum(x, (Int)1, &oldatt.y, &curatt.y) )
83 #define ACREAL(x,y,z) ( MOCcreal(x, &oldatt.y, &curatt.y, z) )
84 #define ACCOL(x,y)    ( MOCccol(x, (Int)1, &oldatt.y, &curatt.y) )
85 #define NEWATTRIB(x)  ( oldatt.x = curatt.x )
86 #define ATTDIFF(x)    ( oldatt.x != curatt.x )
87 #define PUTINT(x)     ( MOCinteger( (Long) x, FALSE, FALSE) )
88 #define PUTREAL(x)  ( MOCreal( (Double)(x), REAL, (Prec *) NULL) )
89 #define PUTVDC(x)   ( MOCreal( (Double)(x), VDC, (Prec *) NULL) )
90
91 /***************************************************** CGMOchar ********/
92
93 void
94 CGMOchar(FILE *stream, Code c, Long *pi, Float *pr, char *pc )
95 {
96
97 /*   Character encoding Output. stream is output channel
98                                 c is MF element code  */
99
100    static Logical first = TRUE, first_pic = TRUE;
101    static Prec loc_prec;
102    static Long pic_num = ZERO;
103    register Long n, j, num;
104    Code major;
105    char pcx[STRING_MAX];
106
107    if ( c == (Code) EOF )
108    {
109    exit(0);
110    }
111
112    cgmoc = stream;
113    major = c>>8;
114    num = *pi++;
115
116    switch (major)
117    {
118       case 0x00:               /* Graphics Primitives  */
119
120          switch (c)
121          {
122             case NONOP:        /* Ignore Non-Op */
123                break;
124
125             case LINE:         /*  Polyline   */
126                if ( first )
127                {
128                   MOCchkatt(LINE);
129                   MOCout(c);
130                }
131                first = ( num >= ZERO );
132                MOCpoints ( num, pi, pr, NOSET);
133                break;
134
135             case DISJTLINE:         /*  Disjoint Polyline  */
136                if ( first )
137                {
138                   MOCchkatt(LINE);
139                   MOCout(c);
140                }
141                first = ( num >= ZERO );
142                MOCpoints ( num, pi, pr, NOSET);
143                break;
144
145             case MARKER:         /*  Polymarker  */
146                if ( first )
147                {
148                   MOCchkatt(MARKER);
149                   MOCout(c);
150                }
151                first = ( num >= ZERO );
152                MOCpoints ( num, pi, pr, NOSET);
153                break;
154
155             case TEXT:         /*  Text   */
156                MOCchkatt(TEXT);
157                MOCout(c);
158                MOCvdc ((Int)2, pi, pr);
159                PUTINT (num);
160                MOCstring (pc);
161                break;
162
163             case RESTRTEXT:         /*  Restricted Text */
164                MOCchkatt(TEXT);
165                MOCout(c);
166                MOCvdc( (Int)4, pi, pr);
167                PUTINT (num);
168                MOCstring (pc);
169                break;
170
171             case APNDTEXT:         /*  Append Text   */
172                MOCchkatt(TEXT);
173                MOCout(c);
174                PUTINT (num);
175                MOCstring (pc);
176                break;
177
178             case POLYGON:         /*  Polygon   */
179                if ( first )
180                {
181                   MOCchkatt(POLYGON);
182                   MOCout(c);
183                }
184                first = ( num >= ZERO );
185                MOCpoints ( num, pi, pr, NOSET);
186                break;
187
188             case POLYGONSET:         /*  Polygon Set  */
189                if ( first )
190                {
191                   MOCchkatt(POLYGON);
192                   MOCout(c);
193                }
194                first = ( num >= ZERO );
195                MOCpoints ( num, pi, pr, SET);
196                break;
197
198             case CELLARRAY:         /*  Cell Array  */
199                if ( first )
200                {
201                   MOCout(c);
202                   MOCvdc( (Int)6, pi, pr);
203                   pi +=6;
204                   PUTINT ( *pi++ );
205                   PUTINT ( *pi++ );
206                   loc_prec = *pi++;
207                   if ( num > 0 )
208                   {
209                      register Long max = ZERO, *ppc = pi;
210
211 /*  if within a buffer then find maximum colour  */
212
213                      n = ( cur.color_mode == INDEXED ? num
214                                                      : 3*num );
215                      for ( j = 0; j < n; j++, ppc++ )
216                                  if ( *ppc > max ) max = *ppc;
217                      for ( loc_prec = 0; max ; max >>= 1, loc_prec++ )
218                      ;
219                   }
220                   PUTINT ( loc_prec);
221                }
222                first = ( num >= ZERO );
223                MOCcells ( num, pi, cur.color_mode, loc_prec);
224                break;
225
226             case GDP:         /*  Generalised Drawing Primitive  */
227                if ( *pi == -1 ) MOCchkatt(LINE);  /* RAL-GKS arc */
228                else             MOCchkatt(POLYGON);
229                MOCout(c);
230                PUTINT ( *pi++ );
231                MOCpoints ( num, pi, pr, ZERO);
232                MOCstring (pc);
233                break;
234
235             case RECT:         /*  Rectangle   */
236                MOCchkatt(POLYGON);
237                MOCout(c);
238                MOCvdc( (Int)4, pi, pr);
239                break;
240
241             default:
242                (void) sprintf(mess,"(code: 0x%x)",c);
243                break;
244          }
245          break;
246
247       case 0x30:  /*  Delimiter Elements  */
248
249          switch (c)
250          {
251
252             case BEGMF:         /*  Begin Metafile   */
253                MOCout (c);
254
255 /*  Character Substitution */
256
257                MOCout ( (Code)0x7e3e);      /* Tilde           0x7e */
258
259                MOCout ( (Code)0x7e40);      /* Null            0x00*/
260
261                MOCout ( (Code)0x7e4a);      /* Line feed       0x0a */
262                MOCout ( (Code)0x7e4d);      /* carriage return 0x0d */
263
264                MOCout (st_term);
265
266 /* now set up substitution list ( without NULL ) */
267                charsub[subchars++] = 0x7e;
268                charsub[subchars++] = 0x0a;
269                charsub[subchars++] = 0x0d;
270
271                curchar = chardef;
272
273 /*  Set old values to current defaults */
274
275                old = cur;
276                oldchar = curchar;
277                oldatt = curatt;
278                strcpy(pcx, pc);
279                if ( strcmp (pcx, "") == 0 )
280                   strcpy(pcx,"Generated with CGM DRIVER");
281                MOCstring (pcx);
282                break;
283
284             case ENDMF:         /*  End Metafile   */
285                MOCout (c);
286                MOCout( (Code)0 );   /* Starts a new record  */
287                break;
288
289             case BEGPIC:          /*  Begin Picture Descriptor   */
290                if ( first_pic )
291                {
292                   MOCcoldef ();
293                   mfchar = curchar;
294                }
295                else
296                   curchar = mfchar; /*  set current character defaults */
297
298                first_pic = FALSE;
299                old = cur;    /*  reset old settings to MF defaults  */
300                oldchar = curchar;
301                oldatt = curatt;
302
303                MOCout( (Code)0 );   /*  Start on new record  */
304                MOCout (c);
305
306                if ( strcmp(pc, "\0") )  MOCstring (pc);
307                else
308                {
309                    sprintf(pcx, "Picture %ld", pic_num++);
310                    MOCstring (pcx);
311                }
312                break;
313
314             case BEGPICBODY:         /*  Begin Picture Body  */
315                MOCout (c);
316                break;
317
318             case ENDPIC:         /*  End  Picture    */
319                MOCout (c);
320                break;
321
322             default:
323                (void) sprintf(mess,"(code 0x%x)",c);
324                break;
325          }
326          break;
327
328
329       case 0x31:  /* Metafile Descriptor Elements  */
330          switch (c)
331          {
332             case MFVERSION:         /*  Metafile version   */
333                MOCout(c);
334                PUTINT (num);
335                break;
336
337             case MFDESC:         /*  Metafile Description  */
338                MOCout(c);
339                
340                   MOCstring ( pc );
341                
342                break;
343
344             case VDCTYPE:         /*  VDC Type   */
345                MOCcenum (c, (Int)1, &old.vdc_type, &cur.vdc_type);
346                break;
347
348             case INTEGERPREC:         /*  Integer Precision  */
349                curchar.int_prec = cur.int_bits;
350                MOCcint (c, (Int)1, &oldchar.int_prec, &curchar.int_prec);
351                break;
352
353             case REALPREC:         /*  Real Precision   */
354                curchar.real.prec = cur.real_bits;
355                curchar.real.min = cur.real_places;
356                curchar.real.defexp = cur.real_defexp;
357                if ( curchar.real.defexp > curchar.real.min )
358                   curchar.real.defexp = curchar.real.min;
359                curchar.real.expald = cur.real_expald;
360
361                MOCcint (c, (Int)4, &oldchar.real.prec, &curchar.real.prec);
362                break;
363
364             case INDEXPREC:         /*  Index Precision   */
365                curchar.index_prec = cur.index_bits;
366                MOCcint(c, (Int)1, &oldchar.index_prec, &curchar.index_prec);
367                break;
368
369             case COLRPREC:         /*  Colour Precision  */
370                curchar.col_prec = cur.col_bits;
371                MOCcint(c, (Int)1, &oldchar.col_prec, &curchar.col_prec);
372                break;
373
374             case COLRINDEXPREC:         /*  Colour Index Precision  */
375                curchar.colind_prec = cur.colind_bits;
376                MOCcint(c, (Int)1, &oldchar.colind_prec, &curchar.colind_prec);
377                break;
378
379             case MAXCOLRINDEX:         /*  Maximum Colour Index  */
380                MOCcint(c, (Int)1, &old.max_colind, &cur.max_colind);
381                break;
382
383             case COLRVALUEEXT:         /*  Colour value extent  */
384                MOCcint(COLRPREC, (Int)1, &curchar.col_prec, &cur.col_bits);
385                curchar.min_rgb = cur.min_rgb;
386                curchar.max_rgb = cur.max_rgb;
387                MOCccol ( c, (Int)2, &oldchar.min_rgb, &curchar.min_rgb);
388                break;
389
390             case MFELEMLIST:         /*  Metafile element List  */
391                MOCout(c);
392                MOCout(st_start);
393                for (j = ZERO; j < num ; j++, pi++ )
394                {
395                   switch ( (Int) *pi )
396                   {
397                      case 0:
398                      case 1:
399                         PUTINT ( *pi );
400                         break;
401
402                      default:
403                         MOCout( (Code) *pi );
404                         if ( *pi == BEGMFDEFAULTS )
405                                     MOCout ( ENDMFDEFAULTS );
406                         break;
407                   }
408                }
409                MOCout(st_term);
410                break;
411
412             case BEGMFDEFAULTS: /* Begin Metafile defaults Replacement*/
413                MOCcoldef ();
414
415             case ENDMFDEFAULTS: /* End Metafile defaults Replacement */
416                MOCout(c);
417                break;
418
419             case FONTLIST:         /*  Font List   */
420                MOCout(c);
421                for (j = ZERO ; j < num ; )
422                {
423                   MOCstring ( &pc[j] );
424                   j = *pi++;
425                }
426                break;
427
428             case CHARSETLIST:         /*  Character set list  */
429                MOCout(c);
430                for ( j = ZERO; j < num ; )
431                {
432                   Int b1, b2;
433                   char c1, chr[2];
434
435                   PUTINT ( *pi++ );
436                   sscanf( &pc[j], "%1d%c%d", &b1, &c1, &b2);
437                   sprintf( chr, "%c", (b1<<4) + b2);
438
439                   MOCstring ( chr );
440                   j = *pi++;
441                }
442                break;
443
444             case CHARCODING:         /*  Character coding Announcer  */
445                MOCout(c);
446                PUTINT (num);
447                break;
448
449             default:
450                (void) sprintf(mess,"(code: 0x%x)",c);
451                break;
452          }
453          break;
454
455       case 0x32:  /* Picture Descriptor Elements  */
456          switch (c)
457          {
458             case SCALEMODE:         /*  Scaling Mode   */
459                if (old.scale_mode != cur.scale_mode ||
460                    RDIFF(old.scale_factor, cur.scale_factor) )
461                {
462                   MOCout(c);
463                   old.scale_mode = cur.scale_mode;
464                   old.scale_factor = cur.scale_factor;
465                   PUTINT ( cur.scale_mode );
466                   PUTREAL ( cur.scale_factor );
467                }
468                break;
469
470             case COLRMODE:         /*  Colour Selection Mode */
471                MOCcenum(c, (Int)1, &old.color_mode, &cur.color_mode);
472                break;
473
474             case LINEWIDTHMODE:    /*  Line width Specification  */
475                MOCcenum(c, (Int)1, &old.linewidth_mode, &cur.linewidth_mode);
476                break;
477
478             case MARKERSIZEMODE:   /*  Marker size Specification  */
479                MOCcenum(c, (Int)1, &old.markersize_mode, &cur.markersize_mode);
480                break;
481
482             case EDGEWIDTHMODE:     /*  Edge width Specification  */
483                MOCcenum(c, (Int)1, &old.edgewidth_mode, &cur.edgewidth_mode);
484                break;
485
486             case VDCEXT:         /*  VDC Extent    */
487                MOCrectc(c, &old.vdc_extent, &cur.vdc_extent);
488                break;
489
490             case BACKCOLR:         /*  Background Colour  */
491                MOCout ( c );
492                MOCdircol ( cur.back.red, cur.back.green, cur.back.blue,
493                            curchar.col_prec);
494                break;
495
496             default:
497                (void) sprintf(mess,"(code: 0x%x)",c);
498          }
499          break;
500
501       case 0x33:  /* Control Elements  */
502          switch(c)
503          {
504             case VDCINTEGERPREC:       /* VDC Integer Precision  */
505                MOCcint(c, (Int)1, &oldchar.vdcint_prec, &curchar.vdcint_prec);
506                break;
507
508             case VDCREALPREC:       /* VDC Real Precision  */
509                curchar.vdc.prec = cur.vdc_bits;
510                curchar.vdc.min  = cur.vdc_places;
511                curchar.vdc.defexp = cur.vdc_defexp;
512                if ( curchar.vdc.defexp > curchar.vdc.min )
513                   curchar.vdc.defexp = curchar.vdc.min;
514                curchar.vdc.expald = cur.vdc_expald;
515                MOCcint(c, (Int)4, &oldchar.vdc.prec, &curchar.vdc.prec);
516                break;
517
518             case AUXCOLR:       /* Auxiliary Colour  */
519                if (cur.color_mode == DIRECT)
520                {
521                   MOCccol(c, (Int)1, &old.aux, &cur.aux);
522                }
523                else
524                {
525                   MOCcint(c, (Int)1, &old.aux.index, &cur.aux.index);
526                }
527                break;
528
529             case TRANSPARENCY:       /* Transparency  */
530                MOCcenum(c, (Int)1, &old.transparency, &cur.transparency);
531                break;
532
533             case CLIPRECT:       /* Clip Rectangle  */
534                MOCrectc(c, &old.clip_rect, &cur.clip_rect);
535                break;
536
537             case CLIP:       /* Clip Indicator  */
538                MOCcenum(c, (Int)1, &old.clip_ind, &cur.clip_ind);
539                break;
540
541             default:
542                (void) sprintf(mess,"(code: 0x%x)",c);
543                break;
544          }
545          break;
546
547       case 0x34:  /* Circles and Ellipses  */
548          switch(c)
549          {
550             case CIRCLE:       /* Circle      */
551                MOCchkatt(POLYGON);
552                MOCout(c);
553                MOCvdc( (Int)3, pi, pr);
554                break;
555
556             case ARC3PT:       /* Circular Arc  3 point */
557                MOCchkatt(LINE);
558                MOCout(c);
559                MOCvdc( (Int)6, pi, pr);
560                break;
561
562             case ARC3PTCLOSE:       /* Circular Arc  3 point close */
563                MOCchkatt(POLYGON);
564                MOCout(c);
565                MOCvdc( (Int)6, pi, pr);
566                PUTINT (*(pi+6));
567                break;
568
569             case ARCCTR:       /* Circle Arc centre */
570                MOCchkatt(LINE);
571                MOCout(c);
572                MOCvdc( (Int)7, pi, pr);
573                break;
574
575             case ARCCTRCLOSE:       /* Circle Arc centre close */
576                MOCchkatt(POLYGON);
577                MOCout(c);
578                MOCvdc( (Int)7, pi, pr);
579                PUTINT (*(pi+7));
580                break;
581
582             case ELLIPSE:       /* Ellipse    */
583                MOCchkatt(POLYGON);
584                MOCout(c);
585                MOCvdc( (Int)6, pi, pr);
586                break;
587
588             case ELLIPARC:       /* Elliptical Arc */
589                MOCchkatt(LINE);
590                MOCout(c);
591                MOCvdc( (Int)10, pi, pr);
592                break;
593
594             case ELLIPARCCLOSE:       /* Elliptical Arc close*/
595                MOCchkatt(POLYGON);
596                MOCout(c);
597                MOCvdc( (Int)10, pi, pr);
598                PUTINT (*(pi+10));
599                break;
600
601             default:
602                (void) sprintf(mess,"(code: 0x%x)",c);
603                break;
604          }
605          break;
606
607       case 0x35:  /* Attributes  */
608
609          switch(c)
610          {
611             case LINEINDEX:       /*  Line Bundle index  */
612                att.line_index = TRUE;
613                break;
614
615             case LINETYPE:       /*  Line Type   */
616                att.line_type = TRUE;
617                break;
618
619             case LINEWIDTH:       /*  Line Width */
620                att.line_width = TRUE;
621                break;
622
623             case LINECOLR:       /*  Line Colour  */
624                att.line_color = TRUE;
625                break;
626
627             case MARKERINDEX:       /*  Marker Bundle index  */
628                att.mark_index = TRUE;
629                break;
630
631             case MARKERTYPE:       /*  Marker Type   */
632                att.mark_type = TRUE;
633                break;
634
635             case MARKERSIZE:       /*  Marker Size */
636                att.mark_size = TRUE;
637                break;
638
639             case MARKERCOLR:       /*  Marker Colour  */
640                att.mark_color = TRUE;
641                break;
642
643             case TEXTINDEX:       /*  Text Bundle index  */
644                att.text_index = TRUE;
645                break;
646
647             case TEXTFONTINDEX:       /*  Text Font Index  */
648                att.text_font = TRUE;
649                break;
650
651             case TEXTPREC:       /*  Text Precision   */
652                att.text_prec = TRUE;
653                break;
654
655             case CHAREXPAN:       /*  Character Expansion Factor  */
656                att.char_expan = TRUE;
657                break;
658
659             case CHARSPACE:       /*  Character Spacing  */
660                att.char_space = TRUE;
661                break;
662
663             case TEXTCOLR:       /*  Text Colour   */
664                att.text_color = TRUE;
665                break;
666
667             case CHARHEIGHT:       /*  Character Height   */
668                att.char_height = TRUE;
669                break;
670
671             case CHARORI:       /*  Character Orientation */
672                att.char_orient = TRUE;
673                break;
674
675             case TEXTPATH:       /*  Text Path */
676                att.text_path = TRUE;
677                break;
678
679             case TEXTALIGN:       /*  Text Alignment */
680                att.text_align = TRUE;
681                break;
682
683             case CHARSETINDEX:      /*  Character Set Index */
684                att.char_set = TRUE;
685                break;
686
687             case ALTCHARSETINDEX:   /*  Alt Character Set Index */
688                att.altchar_set = TRUE;
689                break;
690
691             default:
692                (void) sprintf(mess,"(code: 0x%x)",c);
693                return;
694          }
695          if ( cgmstate == MF_DEFAULTS ) MOCattrib ( c );
696          break;
697
698       case 0x36:  /* More Attributes  */
699          switch(c)
700          {
701             case FILLINDEX:       /*  Fill Bundle index  */
702                att.fill_index = TRUE;
703                break;
704
705             case INTSTYLE:       /*  Interior Style  */
706                att.int_style = TRUE;
707                break;
708
709             case FILLCOLR:       /*  Fill Colour */
710                att.fill_color = TRUE;
711                break;
712
713             case HATCHINDEX:       /*  Hatch Index  */
714                att.hatch_ind = TRUE;
715                break;
716
717             case PATINDEX:       /*  Pattern Index  */
718                att.pat_ind = TRUE;
719                break;
720
721             case EDGEINDEX:       /*  Edge Bundle index  */
722                att.edge_index = TRUE;
723                break;
724
725             case EDGETYPE:       /*  Edge Type  */
726                att.edge_type = TRUE;
727                break;
728
729             case EDGEWIDTH:       /*  Edge Width */
730                att.edge_width = TRUE;
731                break;
732
733             case EDGECOLR:       /*  Edge Colour  */
734                att.edge_color = TRUE;
735                break;
736
737             case EDGEVIS:       /*  Edge Visibility  */
738                att.edge_vis = TRUE;
739                break;
740
741             case FILLREFPT:       /*  Fill Reference Point  */
742                att.fill_ref = TRUE;
743                break;
744
745             case PATSIZE:       /*  Pattern Size  */
746                att.pat_size = TRUE;
747                break;
748
749             case PATTABLE:       /*  Pattern Table  */
750                if ( first )
751                {
752                   register Long max = ZERO;
753                   MOCout(c);
754                   PUTINT ( *pi++ );
755                   PUTINT ( *pi++ );
756                   PUTINT ( *pi++ );
757                   loc_prec = *pi++;
758                   if ( num > 0 )
759                   {
760                      long *ppc=pi;
761 /*  if within a buffer then find maximum colour  */
762
763                      n = ( cur.color_mode == INDEXED ? num
764                                                      : 3*num );
765                      for ( j = 0; j < n; j++, ppc++)
766                         if ( *ppc > max ) max = *ppc;
767                      for ( loc_prec = 0; max ; max >>= 1, loc_prec++ )
768                      ;
769                   }
770                   PUTINT ( loc_prec);
771                }
772                first = ( num >= ZERO );
773                MOCcells ( num, pi, cur.color_mode, loc_prec);
774                return;
775
776             case COLRTABLE:       /*  Colour Table  */
777                if ( first )
778                {
779                   MOCout(c);
780                   PUTINT ( *pi++ );
781                }
782                first = ( num >= ZERO );
783                MOCcells ( num, pi, DIRECT, (Prec) 0);
784                return;
785
786             case ASF:       /*  Aspect source flags  */
787             {
788                short diff = FALSE, type, value, k, l;
789
790 /*  First check if any relevant ASF has changed  */
791
792                for ( n = ZERO; n < ASFS ; n++ )
793                {
794                   if ( curatt.asf[n] != oldatt.asf[n] ) diff++;
795                }
796                if ( diff )
797                {
798
799 /* Output ASFs as they were input - ignoring duplicates */
800
801                   MOCout(c);
802                   for ( n = ZERO; n < num ; n++ )
803                   {
804                      type  = (short) (*pi++);
805                      value = (short) (*pi++);
806                      if ( type < ASFS )
807                      {
808                         if ( value != oldatt.asf[type] )
809                         {
810                            PUTINT ( type );
811                            PUTINT ( value );
812                            oldatt.asf[type] = value;
813                         }
814                      }
815                      else
816                      {
817                         PUTINT ( type );
818                         PUTINT ( value );
819                         switch (type)
820                         {
821                            case 506:   /*  all edge  */
822                               k = 15;
823                               l = 17;
824                               break;
825                            case 507:   /*  all fill  */
826                               k = 11;
827                               l = 14;
828                               break;
829                            case 508:   /*  all text  */
830                               k =  6;
831                               l = 10;
832                               break;
833                            case 509:   /*  all marker */
834                               k =  3;
835                               l =  5;
836                               break;
837                            case 510:   /*  all line */
838                               k =  0;
839                               l =  2;
840                               break;
841                            case 511:   /*  all  */
842                               k =  0;
843                               l = 17;
844                               break;
845                            default:   /*  ignore */
846                               k =  1;
847                               l =  0;
848                               break;
849                         }
850                         for ( ; k <= l; k++) oldatt.asf[k] = value;
851                      }
852                   }
853                }
854                return;
855
856             }
857             default:
858                (void) sprintf(mess,"(code: 0x%x)",c);
859                return;
860          }
861          if ( cgmstate == MF_DEFAULTS ) MOCattrib ( c );
862          break;
863
864       case 0x37:  /* Escape And External Elements  */
865          switch (c)
866          {
867             case ESCAPE:         /*  Escape  */
868                MOCout(c);
869                PUTINT (num);
870                MOCstring (pc);
871                break;
872
873             case MESSAGE:         /*  Message  */
874                MOCout(c);
875                PUTINT (num);
876                MOCstring (pc);
877                break;
878
879             case APPLDATA:         /*  Application Data  */
880                MOCout(c);
881                PUTINT (num);
882                MOCstring (pc);
883                break;
884
885             default:
886                (void) sprintf(mess,"(code: 0x%x)",c);
887                break;
888          }
889          break;
890
891       default:
892         (void) sprintf(mess,"(code: 0x%x)",c);
893         break;
894    }
895
896    return;
897 }
898
899 /****************************************************** MOCchkatt ******/
900 static void
901 MOCchkatt ( Code type )
902 {
903 /*   Check 'type' Attributes and send to Output if changed  */
904
905     Logical bundled, indiv;
906
907     switch (type)
908     {
909         case LINE:
910
911           bundled = (curatt.asf[0] == BUNDLED
912                   || curatt.asf[1] == BUNDLED
913                   || curatt.asf[2] == BUNDLED );
914           indiv = (curatt.asf[0] == INDIVIDUAL
915                 || curatt.asf[1] == INDIVIDUAL
916                 || curatt.asf[2] == INDIVIDUAL );
917
918           if ( bundled && att.line_index)
919           {
920              ACINT(LINEINDEX, line_ind);
921              att.line_index = FALSE;
922           }
923
924           if ( indiv && att.line_type)
925           {
926              ACINT(LINETYPE, line_type);
927              att.line_type = FALSE;
928           }
929
930           if ( indiv && att.line_width )
931           {
932              if (cur.linewidth_mode == SCALED)
933              {
934                 ACREAL(LINEWIDTH, line_width.real, REAL);
935              }
936              else if ( cur.vdc_type == REAL)
937              {
938                 ACREAL(LINEWIDTH, line_width.real, VDC);
939              }
940              else
941              {
942                 ACINT(LINEWIDTH, line_width.intr);
943              }
944              att.line_width = FALSE;
945          }
946
947          if ( indiv && att.line_color )
948          {
949             if (cur.color_mode == DIRECT)
950             {
951                ACCOL (LINECOLR, line );
952             }
953             else
954             {
955                ACINT(LINECOLR, line.index);
956             }
957             att.line_color = FALSE;
958           }
959           break;
960
961         case MARKER:
962
963           bundled = (curatt.asf[3] == BUNDLED
964                   || curatt.asf[4] == BUNDLED
965                   || curatt.asf[5] == BUNDLED );
966           indiv = (curatt.asf[3] == INDIVIDUAL
967                 || curatt.asf[4] == INDIVIDUAL
968                 || curatt.asf[5] == INDIVIDUAL );
969
970           if ( bundled && att.mark_index)
971           {
972              ACINT(MARKERINDEX, mark_ind);
973              att.mark_index = FALSE;
974           }
975
976           if ( indiv && att.mark_type)
977           {
978              ACINT(MARKERTYPE, mark_type);
979              att.mark_type = FALSE;
980           }
981
982           if ( indiv && att.mark_size )
983           {
984              if (cur.markersize_mode == SCALED)
985              {
986                 ACREAL(MARKERSIZE, mark_size.real, REAL );
987              }
988              else if ( cur.vdc_type == REAL)
989              {
990                 ACREAL(MARKERSIZE, mark_size.real, VDC );
991              }
992              else
993              {
994                 ACINT(MARKERSIZE, mark_size.intr );
995              }
996              att.mark_size = FALSE;
997          }
998
999          if ( indiv && att.mark_color )
1000          {
1001             if (cur.color_mode == DIRECT)
1002             {
1003                ACCOL (MARKERCOLR, marker );
1004             }
1005             else
1006             {
1007                ACINT(MARKERCOLR, marker.index );
1008             }
1009             att.mark_color = FALSE;
1010           }
1011           break;
1012
1013         case TEXT:
1014
1015           bundled = (curatt.asf[6] == BUNDLED
1016                   || curatt.asf[7] == BUNDLED
1017                   || curatt.asf[8] == BUNDLED
1018                   || curatt.asf[9] == BUNDLED
1019                   || curatt.asf[10] == BUNDLED );
1020           indiv = (curatt.asf[6] == INDIVIDUAL
1021                 || curatt.asf[7] == INDIVIDUAL
1022                 || curatt.asf[8] == INDIVIDUAL
1023                 || curatt.asf[9] == INDIVIDUAL
1024                 || curatt.asf[10] == INDIVIDUAL );
1025
1026           if ( bundled && att.text_index)
1027           {
1028              ACINT(TEXTINDEX, text_ind);
1029              att.text_index = FALSE;
1030           }
1031
1032           if ( indiv && att.text_font)
1033           {
1034              ACINT(TEXTFONTINDEX, text_font);
1035              att.text_font = FALSE;
1036           }
1037
1038           if ( indiv && att.text_prec)
1039           {
1040              ACENUM(TEXTPREC, text_prec);
1041              att.text_prec = FALSE;
1042           }
1043
1044           if ( indiv && att.char_expan)
1045           {
1046              ACREAL(CHAREXPAN, char_exp, REAL );
1047              att.char_expan = FALSE;
1048           }
1049
1050           if ( indiv && att.char_space)
1051           {
1052              ACREAL(CHARSPACE, char_space, REAL );
1053              att.char_space = FALSE;
1054           }
1055
1056           if ( indiv && att.text_color )
1057           {
1058             if (cur.color_mode == DIRECT)
1059             {
1060                ACCOL (TEXTCOLR, text );
1061             }
1062             else
1063             {
1064                ACINT(TEXTCOLR, text.index );
1065             }
1066             att.text_color = FALSE;
1067           }
1068
1069           if ( att.char_height)
1070           {
1071             if (cur.vdc_type == REAL)
1072             {
1073                ACREAL(CHARHEIGHT, char_height.real, VDC );
1074             }
1075             else
1076             {
1077                ACINT(CHARHEIGHT, char_height.intr );
1078             }
1079             att.char_height = FALSE;
1080           }
1081
1082           if ( att.char_orient)
1083           {
1084             if (cur.vdc_type == REAL)
1085             {
1086                if ( VADIFF(char_up.x.real) || VADIFF(char_up.y.real) ||
1087                     VADIFF(char_base.x.real) || VADIFF(char_base.y.real) )
1088                {
1089                   MOCout(CHARORI);
1090                   NEWATTRIB (char_up.x.real);
1091                   NEWATTRIB (char_up.y.real);
1092                   NEWATTRIB (char_base.x.real);
1093                   NEWATTRIB (char_base.y.real);
1094                   PUTVDC (curatt.char_up.x.real);
1095                   PUTVDC (curatt.char_up.y.real);
1096                   PUTVDC (curatt.char_base.x.real);
1097                   PUTVDC (curatt.char_base.y.real);
1098                }
1099             }
1100             else
1101             {
1102                if ( ATTDIFF(char_up.x.intr)
1103                   || ATTDIFF(char_up.y.intr)
1104                   || ATTDIFF(char_base.x.intr)
1105                   || ATTDIFF(char_base.y.intr) )
1106                {
1107                   MOCout(CHARORI);
1108                   NEWATTRIB (char_up.x.intr);
1109                   NEWATTRIB (char_up.y.intr);
1110                   NEWATTRIB (char_base.x.intr);
1111                   NEWATTRIB (char_base.y.intr);
1112                   PUTINT (curatt.char_up.x.intr);
1113                   PUTINT (curatt.char_up.y.intr);
1114                   PUTINT (curatt.char_base.x.intr);
1115                   PUTINT (curatt.char_base.y.intr);
1116                }
1117             }
1118             att.char_orient = FALSE;
1119           }
1120
1121           if ( att.char_set)
1122           {
1123              ACINT(CHARSETINDEX, char_set );
1124              att.char_set = FALSE;
1125           }
1126
1127           if ( att.altchar_set)
1128           {
1129              ACINT(ALTCHARSETINDEX, altchar_set );
1130              att.altchar_set = FALSE;
1131           }
1132
1133           if ( att.text_path )
1134           {
1135              ACENUM(TEXTPATH, text_path );
1136              att.text_path = FALSE;
1137           }
1138
1139           if ( att.text_align )
1140           {
1141              if ( ATTDIFF(text_halign) ||  ATTDIFF(text_valign) ||
1142                   RADIFF(text_hcont) || RADIFF(text_vcont) )
1143              {
1144                 MOCout(TEXTALIGN);
1145                 NEWATTRIB (text_halign);
1146                 NEWATTRIB (text_valign);
1147                 PUTINT ( curatt.text_halign);
1148                 PUTINT ( curatt.text_valign);
1149                 NEWATTRIB (text_hcont);
1150                 NEWATTRIB (text_vcont);
1151                 PUTREAL( curatt.text_hcont );
1152                 PUTREAL( curatt.text_vcont );
1153              }
1154              att.text_align = FALSE;
1155           }
1156           break;
1157
1158         case POLYGON:  /*  Fill and edge attributes  */
1159
1160           bundled = (curatt.asf[11] == BUNDLED
1161                   || curatt.asf[12] == BUNDLED
1162                   || curatt.asf[13] == BUNDLED
1163                   || curatt.asf[14] == BUNDLED );
1164           indiv = (curatt.asf[11] == INDIVIDUAL
1165                 || curatt.asf[12] == INDIVIDUAL
1166                 || curatt.asf[13] == INDIVIDUAL
1167                 || curatt.asf[14] == INDIVIDUAL );
1168
1169          if ( bundled && att.fill_index)
1170          {
1171             ACINT(FILLINDEX, fill_ind);
1172             att.fill_index = FALSE;
1173          }
1174
1175          if ( indiv && att.int_style)
1176          {
1177             ACENUM(INTSTYLE, int_style);
1178             att.int_style = FALSE;
1179          }
1180
1181          if ( indiv && att.hatch_ind )
1182          {
1183             ACINT(HATCHINDEX, hatch_ind);
1184             att.hatch_ind = FALSE;
1185          }
1186
1187          if ( indiv && att.pat_ind )
1188          {
1189             ACINT(PATINDEX, pat_ind);
1190             att.pat_ind = FALSE;
1191          }
1192
1193          if ( indiv && att.fill_color )
1194          {
1195             if (cur.color_mode == DIRECT)
1196             {
1197               ACCOL (FILLCOLR, fill );
1198             }
1199             else
1200             {
1201               ACINT(FILLCOLR, fill.index );
1202             }
1203             att.fill_color = FALSE;
1204          }
1205
1206          if ( att.pat_size)
1207          {
1208            if (cur.vdc_type == REAL)
1209            {
1210               if ( VADIFF(pat_size.a.x.real) || VADIFF(pat_size.a.y.real) ||
1211                    VADIFF(pat_size.b.x.real) || VADIFF(pat_size.b.y.real) )
1212               {
1213                  MOCout(PATSIZE);
1214                  NEWATTRIB (pat_size.a.x.real);
1215                  NEWATTRIB (pat_size.a.y.real);
1216                  NEWATTRIB (pat_size.b.x.real);
1217                  NEWATTRIB (pat_size.b.y.real);
1218                  PUTVDC (curatt.pat_size.a.x.real);
1219                  PUTVDC (curatt.pat_size.a.y.real);
1220                  PUTVDC (curatt.pat_size.b.x.real);
1221                  PUTVDC (curatt.pat_size.b.y.real);
1222               }
1223            }
1224            else
1225            {
1226               if ( ATTDIFF(pat_size.a.x.intr) ||
1227                    ATTDIFF(pat_size.a.y.intr) ||
1228                    ATTDIFF(pat_size.b.x.intr) ||
1229                    ATTDIFF(pat_size.b.y.intr) )
1230               {
1231                  MOCout(PATSIZE);
1232                  NEWATTRIB (pat_size.a.x.intr);
1233                  NEWATTRIB (pat_size.a.y.intr);
1234                  NEWATTRIB (pat_size.b.x.intr);
1235                  NEWATTRIB (pat_size.b.y.intr);
1236                  PUTINT (curatt.pat_size.a.x.intr);
1237                  PUTINT (curatt.pat_size.a.y.intr);
1238                  PUTINT (curatt.pat_size.b.x.intr);
1239                  PUTINT (curatt.pat_size.b.y.intr);
1240               }
1241            }
1242            att.pat_size = FALSE;
1243          }
1244
1245         /*   Edge characteristics   */
1246
1247          bundled = (curatt.asf[15] == BUNDLED
1248                   || curatt.asf[16] == BUNDLED
1249                   || curatt.asf[17] == BUNDLED );
1250          indiv = (curatt.asf[15] == INDIVIDUAL
1251                 || curatt.asf[16] == INDIVIDUAL
1252                 || curatt.asf[17] == INDIVIDUAL );
1253
1254          if ( bundled && att.edge_index)
1255          {
1256             ACINT(EDGEINDEX, edge_ind);
1257             att.edge_index = FALSE;
1258          }
1259
1260          if ( indiv && att.edge_type)
1261          {
1262             ACINT(EDGETYPE, edge_type);
1263             att.edge_type = FALSE;
1264          }
1265
1266          if ( indiv && att.edge_width )
1267          {
1268             if (cur.edgewidth_mode == SCALED)
1269             {
1270                ACREAL(EDGEWIDTH, edge_width.real, REAL );
1271             }
1272             else if ( cur.vdc_type == REAL)
1273             {
1274                ACREAL(EDGEWIDTH, edge_width.real, VDC );
1275             }
1276             else
1277             {
1278                ACINT(EDGEWIDTH, edge_width.intr );
1279             }
1280             att.edge_width = FALSE;
1281          }
1282
1283          if ( indiv && att.edge_color )
1284          {
1285             if (cur.color_mode == DIRECT)
1286             {
1287               ACCOL (EDGECOLR, edge );
1288             }
1289             else
1290             {
1291               ACINT(EDGECOLR, edge.index );
1292             }
1293             att.edge_color = FALSE;
1294          }
1295
1296          if ( att.edge_vis)
1297          {
1298             ACENUM(EDGEVIS, edge_vis);
1299             att.edge_vis = FALSE;
1300          }
1301
1302          break;
1303
1304      default:
1305         (void) sprintf(mess,"(type: 0x%x)", type);
1306         break;
1307    }
1308
1309    return;
1310 }
1311
1312 /****************************************************** MOCattrib ******/
1313 static void
1314 MOCattrib ( Code code )
1315 {
1316 /*  Outputs attribute code 'code'  */
1317
1318    MOCout( code );
1319
1320    switch ( code )
1321    {
1322       case LINEINDEX:       /*  Line Bundle index  */
1323          PUTINT ( curatt.line_ind );
1324          break;
1325
1326       case LINETYPE:       /*  Line Type   */
1327          PUTINT ( curatt.line_type );
1328          break;
1329
1330       case LINEWIDTH:       /*  Line Width */
1331          if ( cur.linewidth_mode == SCALED )
1332             PUTREAL ( curatt.line_width.real );
1333          else if ( cur.vdc_type == REAL )
1334             PUTVDC ( curatt.line_width.real );
1335          else
1336             PUTINT ( curatt.line_width.intr );
1337          break;
1338
1339       case LINECOLR:       /*  Line Colour  */
1340          if ( cur.color_mode == DIRECT )
1341             MOCdircol ( curatt.line.red, curatt.line.green,
1342                         curatt.line.blue, curchar.col_prec );
1343          else
1344             PUTINT ( curatt.line.index );
1345          break;
1346
1347       case MARKERINDEX:       /*  Marker Bundle index  */
1348          PUTINT ( curatt.mark_ind );
1349          break;
1350
1351       case MARKERTYPE:       /*  Marker Type   */
1352          PUTINT ( curatt.mark_type );
1353          break;
1354
1355       case MARKERSIZE:       /*  Marker Size */
1356          if ( cur.markersize_mode == SCALED )
1357             PUTREAL ( curatt.mark_size.real );
1358          else if ( cur.vdc_type == REAL )
1359             PUTVDC ( curatt.mark_size.real );
1360          else
1361             PUTINT ( curatt.mark_size.intr );
1362          break;
1363
1364       case MARKERCOLR:       /*  Marker Colour  */
1365          if ( cur.color_mode == DIRECT )
1366             MOCdircol ( curatt.marker.red, curatt.marker.green,
1367                         curatt.marker.blue, curchar.col_prec );
1368          else
1369             PUTINT ( curatt.marker.index );
1370          break;
1371
1372       case TEXTINDEX:       /*  Text Bundle index  */
1373          PUTINT ( curatt.text_ind );
1374          break;
1375
1376       case TEXTFONTINDEX:       /*  Text Font Index  */
1377          PUTINT ( curatt.text_font );
1378          break;
1379
1380       case TEXTPREC:       /*  Text Precision   */
1381          PUTINT ( curatt.text_prec );
1382          break;
1383
1384       case CHAREXPAN:       /*  Character Expansion Factor  */
1385          PUTREAL ( curatt.char_exp );
1386          break;
1387
1388       case CHARSPACE:       /*  Character Spacing  */
1389          PUTREAL ( curatt.char_space );
1390          break;
1391
1392       case TEXTCOLR:       /*  Text Colour   */
1393          if ( cur.color_mode == DIRECT )
1394             MOCdircol ( curatt.text.red, curatt.text.green,
1395                         curatt.text.blue, curchar.col_prec );
1396          else
1397             PUTINT ( curatt.text.index );
1398          break;
1399
1400       case CHARHEIGHT:       /*  Character Height   */
1401          if ( cur.vdc_type == REAL )
1402             PUTVDC ( curatt.char_height.real );
1403          else
1404             PUTINT ( curatt.char_height.intr );
1405          break;
1406
1407       case CHARORI:       /*  Character Orientation */
1408          if ( cur.vdc_type == REAL )
1409          {
1410             PUTREAL ( curatt.char_up.x.real );
1411             PUTREAL ( curatt.char_up.y.real );
1412             PUTREAL ( curatt.char_base.x.real );
1413             PUTREAL ( curatt.char_base.y.real );
1414          }
1415          else
1416          {
1417             PUTINT ( curatt.char_up.x.intr );
1418             PUTINT ( curatt.char_up.y.intr );
1419             PUTINT ( curatt.char_base.x.intr );
1420             PUTINT ( curatt.char_base.y.intr );
1421          }
1422          break;
1423
1424       case TEXTPATH:       /*  Text Path */
1425          PUTINT ( curatt.text_path );
1426          break;
1427
1428       case TEXTALIGN:       /*  Text Alignment */
1429          PUTINT ( curatt.text_halign );
1430          PUTINT ( curatt.text_valign );
1431          PUTREAL ( curatt.text_hcont );
1432          PUTREAL ( curatt.text_vcont );
1433          break;
1434
1435       case CHARSETINDEX:      /*  Character Set Index */
1436          PUTINT ( curatt.char_set );
1437          break;
1438
1439       case ALTCHARSETINDEX:   /*  Alt Character Set Index */
1440          PUTINT ( curatt.altchar_set );
1441          break;
1442
1443       case FILLINDEX:       /*  Fill Bundle index  */
1444          PUTINT ( curatt.fill_ind );
1445          break;
1446
1447       case INTSTYLE:       /*  Interior Style  */
1448          PUTINT ( curatt.int_style );
1449          break;
1450
1451       case FILLCOLR:       /*  Fill Colour */
1452          if ( cur.color_mode == DIRECT )
1453             MOCdircol ( curatt.fill.red, curatt.fill.green,
1454                         curatt.fill.blue, curchar.col_prec );
1455          else
1456             PUTINT ( curatt.fill.index );
1457          break;
1458
1459       case HATCHINDEX:       /*  Hatch Index  */
1460          PUTINT ( curatt.hatch_ind );
1461          break;
1462
1463       case PATINDEX:       /*  Pattern Index  */
1464          PUTINT ( curatt.pat_ind );
1465          break;
1466
1467       case EDGEINDEX:       /*  Edge Bundle index  */
1468          PUTINT ( curatt.edge_ind );
1469          break;
1470
1471       case EDGETYPE:       /*  Edge Type  */
1472          PUTINT ( curatt.edge_type );
1473          break;
1474
1475       case EDGEWIDTH:       /*  Edge Width */
1476          if ( cur.edgewidth_mode == SCALED )
1477             PUTREAL ( curatt.edge_width.real );
1478          else if ( cur.vdc_type == REAL )
1479             PUTVDC ( curatt.edge_width.real );
1480          else
1481             PUTINT ( curatt.edge_width.intr );
1482          break;
1483
1484       case EDGECOLR:       /*  Edge Colour  */
1485          if ( cur.color_mode == DIRECT )
1486             MOCdircol ( curatt.edge.red, curatt.edge.green,
1487                         curatt.edge.blue, curchar.col_prec );
1488          else
1489             PUTINT ( curatt.edge.index );
1490          break;
1491
1492       case EDGEVIS:       /*  Edge Visibility  */
1493          PUTINT ( curatt.edge_vis );
1494          break;
1495
1496       case FILLREFPT:       /*  Fill Reference Point  */
1497          if ( cur.vdc_type == REAL )
1498          {
1499             PUTVDC ( curatt.fill_ref.x.real );
1500             PUTVDC ( curatt.fill_ref.y.real );
1501          }
1502          else
1503          {
1504             PUTINT ( curatt.fill_ref.x.intr );
1505             PUTINT ( curatt.fill_ref.y.intr );
1506          }
1507          break;
1508
1509       case PATSIZE:       /*  Pattern Size  */
1510          if ( cur.vdc_type == REAL )
1511          {
1512             PUTVDC ( curatt.pat_size.a.x.real );
1513             PUTVDC ( curatt.pat_size.a.y.real );
1514             PUTVDC ( curatt.pat_size.b.x.real );
1515             PUTVDC ( curatt.pat_size.b.y.real );
1516          }
1517          else
1518          {
1519             PUTINT ( curatt.pat_size.a.x.intr );
1520             PUTINT ( curatt.pat_size.a.y.intr );
1521             PUTINT ( curatt.pat_size.b.x.intr );
1522             PUTINT ( curatt.pat_size.b.y.intr );
1523          }
1524          break;
1525
1526       default:
1527          (void) sprintf(mess,"(type: 0x%x)", code);
1528          break;
1529    }
1530
1531    return;
1532 }
1533
1534 /****************************************************** MOCcint ********/
1535 static void
1536 MOCcint ( Code code, Int n, Long *var1, Long *var2)
1537 {
1538 /*  Conditionally outputs 'code' and 'n' integers starting at *var2
1539     only if at least one is different      */
1540
1541     register Long i;
1542     register Logical diff = FALSE;
1543
1544     for (i = ZERO; i < n; i++)
1545        if (var1[i] != var2[i]) diff = TRUE;
1546     if (diff)
1547     {
1548         MOCout(code);
1549         for (i = ZERO ; i < n ; i++)
1550         {
1551            PUTINT ( *var2 );
1552            *var1++ = *var2++;
1553         }
1554     }
1555     return;
1556 }
1557
1558 /****************************************************** MOCcenum *******/
1559 static void
1560 MOCcenum (Code code, int n, Enum *var1, Enum *var2 )
1561 {
1562 /*  Conditionally outputs 'code' and 'n' short integers starting at *var2
1563     only if at least one is different      */
1564
1565     register Long i;
1566     register Logical diff = FALSE;
1567
1568     for (i = ZERO; i < n; i++)
1569        if (var1[i] != var2[i]) diff = TRUE;
1570     if (diff)
1571     {
1572         MOCout(code);
1573         for (i = ZERO ; i < n ; i++)
1574         {
1575            PUTINT ( *var2 );
1576            *var1++ = *var2++;
1577         }
1578     }
1579     return;
1580 }
1581
1582 /****************************************************** MOCcreal *******/
1583 static void
1584 MOCcreal (Code code, Float *var1, Float *var2, Enum  r)
1585 {
1586 /*  Conditionally outputs 'code' and real *var2 if different from *var1
1587     using precision specified by r      */
1588
1589     if ( FABS(*var1-*var2) > (r == REAL ? cur.realmin : cur.vdcmin) )
1590     {
1591         MOCout(code);
1592         MOCreal ((Double)*var2, r, null);
1593         *var1 = *var2;
1594     }
1595     return;
1596 }
1597
1598 /****************************************************** MOCrectc *******/
1599 static void
1600 MOCrectc( Code code, struct rect *var1, struct rect *var2 )
1601 {
1602 /*  Conditionally outputs 'code' and 4 VDCs indicated by *var2
1603     if different from *var1 using vdc precision   */
1604
1605    if (cur.vdc_type == INTEGER)
1606    {
1607       if ( (*var1).a.x.intr != (*var2).a.x.intr ||
1608            (*var1).a.y.intr != (*var2).a.y.intr ||
1609            (*var1).b.x.intr != (*var2).b.x.intr ||
1610            (*var1).b.y.intr != (*var2).b.y.intr  )
1611       {
1612           MOCout(code);
1613           (*var1).a.x.intr = (*var2).a.x.intr;
1614           PUTINT ( (*var1).a.x.intr );
1615           (*var1).a.y.intr = (*var2).a.y.intr;
1616           PUTINT ( (*var1).a.y.intr );
1617           (*var1).b.x.intr = (*var2).b.x.intr;
1618           PUTINT ( (*var1).b.x.intr );
1619           (*var1).b.y.intr = (*var2).b.y.intr;
1620           PUTINT ( (*var1).b.y.intr );
1621       }
1622    }
1623    else
1624    {
1625       if ( VDIFF( (*var1).a.x.real, (*var2).a.x.real ) ||
1626            VDIFF( (*var1).a.y.real, (*var2).a.y.real ) ||
1627            VDIFF( (*var1).b.x.real, (*var2).b.x.real ) ||
1628            VDIFF( (*var1).b.y.real, (*var2).b.y.real ) )
1629       {
1630           MOCout(code);
1631           (*var1).a.x.real = (*var2).a.x.real;
1632           PUTVDC ( (*var2).a.x.real );
1633           (*var1).a.y.real = (*var2).a.y.real;
1634           PUTVDC ( (*var2).a.y.real );
1635           (*var1).b.x.real = (*var2).b.x.real;
1636           PUTVDC ( (*var2).b.x.real );
1637           (*var1).b.y.real = (*var2).b.y.real;
1638           PUTVDC ( (*var2).b.y.real );
1639       }
1640    }
1641    return;
1642 }
1643
1644 /****************************************************** MOCccol ********/
1645 static void
1646 MOCccol (Code code, int n, struct colour *var1, struct colour *var2)
1647 {
1648 /*  Conditional output 'code' and colour indicated by *var2
1649     if different from colour *var1  */
1650
1651     register int i, j;
1652     register Logical diff = FALSE;
1653
1654     for (i = j = ZERO; i < n; i++, j++ )
1655     {
1656        if ( (var1[j].red != var2[j].red) ||
1657             (var1[j].green != var2[j].green) ||
1658             (var1[j].blue != var2[j].blue) ) diff = TRUE;
1659     }
1660
1661     if (diff)
1662     {
1663        MOCout(code);
1664        for (i = j = ZERO; i < n; i++, j++)
1665        {
1666           var1[j].red = var2[j].red;
1667           var1[j].green = var2[j].green;
1668           var1[j].blue = var2[j].blue;
1669           MOCdircol (var1[j].red, var1[j].green, var1[j].blue,
1670                      curchar.col_prec);
1671        }
1672     }
1673     return;
1674 }
1675
1676 /****************************************************** MOCvdc *********/
1677 static void
1678 MOCvdc (int n, Long *pi, Float *pr )
1679 {
1680 /*  Outputs n VDCs starting at pi/pr  */
1681
1682    register Long j;
1683
1684    if (cur.vdc_type == REAL)
1685       for ( j = ZERO; j < n; j++)
1686          PUTVDC( *pr++ );
1687    else
1688       for ( j = ZERO; j < n; j++)
1689          PUTINT ( *pi++ );
1690
1691    return;
1692 }
1693
1694 /****************************************************** MOCpoints ******/
1695 static void
1696 MOCpoints(Long n, Long *pi, Float *pr, Enum set )
1697 {
1698 /*  Outputs n points starting at pi/pr
1699     'set' indicates if this is a Polygon set */
1700
1701    static Logical first = TRUE;
1702    static Long ix, iy;
1703    static Long exp_x, exp_y;
1704    static Float xx, yy;
1705    register Long i;
1706
1707    if ( first )
1708    {
1709       exp_x = exp_y = curchar.vdc.defexp;
1710       xx = yy = 0.0F;
1711       ix = iy = ZERO;
1712    }
1713    if ( n >= ZERO ) first = TRUE;
1714    else
1715    {
1716       first = FALSE;
1717       n = -n;
1718    }
1719
1720    if (cur.vdc_type == REAL)
1721    {
1722       for ( i=0; i < n; i++ )
1723       {
1724         xx += *pr -= xx;
1725         MOCreal ( (Double)*pr++, VDC, &exp_x);
1726         yy += *pr -= yy;
1727         MOCreal ( (Double)*pr++, VDC, &exp_y);
1728         if (set) PUTINT ( *pi++ );
1729       }
1730    }
1731    else
1732    {
1733       for ( i=0; i < n; i++ )
1734       {
1735         ix += *pi -= ix;
1736         PUTINT ( *pi++ );
1737         iy += *pi -= iy;
1738         PUTINT ( *pi++ );
1739         if ( set)  PUTINT ( *pi++ );
1740       }
1741    }
1742    return;
1743 }
1744
1745 /****************************************************** MOCreal ********/
1746 static void
1747 MOCreal ( Double x, Enum type, Prec *ptlist )
1748 {
1749 /*  Outputs real value 'x', using type 'type'
1750     pointlist indicates if this is part of a pointslist  */
1751
1752    register Long def_exp, mantissa, expnt;
1753    register Double y, realmin, prec;
1754    register Logical present = ZERO, expald;
1755
1756    if ( type == REAL )
1757    {
1758       def_exp = curchar.real.defexp;
1759       realmin = (Double) cur.realmin;
1760       prec = (Double) ( (1L<<curchar.real.prec) - 1);
1761       prec = (Double)( curchar.real.prec > 0 ? (1L<<curchar.real.prec) - 1
1762                                           : 1.0/((1L<<-curchar.real.prec)-1) );
1763       expald = ( curchar.real.expald == ALLOWED );
1764    }
1765    else
1766    {
1767       def_exp = curchar.vdc.defexp;
1768       realmin = (Double) cur.vdcmin;
1769       prec = (Double)( curchar.vdc.prec > 0 ? (1L<<curchar.vdc.prec) - 1
1770                                             : 1.0/((1L<<-curchar.vdc.prec)-1) );
1771       expald = ( curchar.vdc.expald == ALLOWED );
1772    }
1773
1774    if (ptlist != NULL) def_exp = *ptlist;
1775
1776    y = (Double) ( x>0 ? x : -x );
1777    expnt = ZERO;
1778
1779    if ( y < realmin )
1780    {
1781       mantissa = ZERO;
1782    }
1783    else
1784    {
1785       if ( expald ) /* if Exponent allowed */
1786       {
1787          while (y >= prec)
1788          {
1789             y /= (Double) 2.0;
1790             expnt++;
1791          }
1792          while (y < prec)
1793          {
1794             y *= (Double) 2.0;
1795             expnt--;
1796          }
1797          mantissa = (long)y;
1798
1799  /*  Strip off trailing zeros   */
1800
1801          while ( mantissa && !(mantissa & 0x01) )
1802          {
1803             mantissa >>= 1;
1804             expnt++;
1805          }
1806          present = (expnt != def_exp);
1807       }
1808       else
1809       {
1810          while (expnt < def_exp)
1811          {
1812             y /= (Double) 2.0;
1813             expnt++;
1814          }
1815          while (expnt > def_exp)
1816          {
1817             y *= (Double) 2.0;
1818             expnt--;
1819          }
1820          mantissa = (long) y;
1821       }
1822
1823       if ( x < 0.0 )  mantissa = -mantissa;
1824    }
1825
1826    MOCinteger ( (Long) mantissa, present, expald);
1827    if (present) PUTINT ( expnt );
1828
1829    if ( mantissa && (ptlist != NULL) ) *ptlist = expnt;
1830
1831    return;
1832 }
1833
1834 /****************************************************** MOCinteger *****/
1835 static void
1836 MOCinteger (Long intval, Logical present, Logical allowed)
1837 {
1838 /*  Output an integer 'intval', 'present' indicates if exponent present
1839     and 'allowed' if allowed */
1840
1841    register Long ival;
1842    register Long i, j;
1843    Code hex[16];
1844
1845    ival = abs(intval);
1846
1847  /*  Strip of bits in 5 bit chunks  */
1848
1849    for (j = -1; ival > ZERO && j < curchar.int_prec; ival >>= 5)
1850               hex[++j] = 0x60 | (ival & 0x1F);
1851
1852  /* if zero or top bit set or Exponent follows and bit set
1853     then add another byte  */
1854
1855    if ( (j < ZERO) | ( hex[j] & (1L<<(4-present)) ) |
1856       ( allowed && (hex[j] & 0x18) ) )     hex[++j] = 0x60;
1857
1858    if (allowed) hex[j] |= present << 3;   /*  set exponent present bit */
1859    hex[j] |= (intval++ < ZERO) << 4;      /*  set sign on first byte  */
1860    hex[0] &= 0x5F;                        /*  set continuation bit off */
1861
1862  /*  Reverse bits to buffer  */
1863    for (i = j; i >= ZERO; i--)  MOCout( hex [i] );
1864
1865    return;
1866 }
1867
1868 /****************************************************** MOCstring ******/
1869 static void
1870 MOCstring (register char *s)
1871 {
1872 /*  Output a text string 'string'
1873     if CMS translate from EBCDIC to ASCII  */
1874
1875    register short c;
1876
1877    MOCout(st_start);
1878
1879    while ( (c = *s++) != '\0')
1880      MOCout (c);
1881
1882    MOCout(st_term);
1883
1884    return;
1885 }
1886
1887 /****************************************************** MOCcells *******/
1888 static void
1889 MOCcells (register Long n, register Long *pi, Enum mode, Prec prec)
1890 {
1891 /*  Output a Colour list of 'n' cells, starting at pi
1892     using local precision 'prec' (if zero use current precision)
1893     and colour mode 'mode'  */
1894
1895    register Long i, j, k, num;
1896    static Logical first = TRUE;
1897    static Long normal_list, bit_stream, run_length, run_bits, colbytes;
1898    Posint red, green, blue, lastred, lastgreen, lastblue;
1899    Logical more;
1900    Long col, last, run, *pi0 = pi;
1901
1902    more = (n < 0);
1903    num = ( more ? -n : n);
1904
1905    if ( first )
1906    {
1907       Long bytes, cols;
1908
1909 /* if Prec = 0 the use Current precision */
1910       if ( !prec ) prec = ( mode == INDEXED ? curchar.colind_prec
1911                                             : curchar.col_prec );
1912       colbytes = ( mode == INDEXED ? (prec+5)/6
1913                                    : (3*prec+5)/6 );
1914
1915       normal_list = bit_stream = ZERO;
1916       run_bits = run_length = ZERO;
1917
1918 /*  Work out shortest method of coding list  */
1919
1920       if ( mode == INDEXED )
1921       {
1922          cols = 1;
1923          for ( i = ZERO, last = *pi, run = 1 ; i < num; )
1924          {
1925 /*  make sure last value forces an end */
1926
1927             col = ( ++i == num ? -1 : *pi++ );
1928
1929             if (col == last) run++;
1930             else
1931             {
1932
1933 /*  Work out bytes for run count  */
1934
1935                for ( j=run, bytes=1; j > 0x0f; bytes++, j>>=5);
1936                run_length += bytes;
1937                run_bits += bytes;
1938
1939 /*  Work out bytes for normal colour value  */
1940
1941                for ( j=last, bytes=1; j > 0x0f; bytes++, j>>=5);
1942                run_length += bytes;
1943                run_bits += colbytes;
1944                normal_list += run*bytes;
1945
1946                run = 1;
1947                last = col;
1948             }
1949          }
1950       }
1951       else  /*  Direct Colour */
1952       {
1953          cols = 3;
1954          lastred = *pi++; lastgreen = *pi++; lastblue = *pi++;
1955          for ( i = ZERO, run = 1 ; i < num ; )
1956          {
1957             red = *pi++ ; green = *pi++ ; blue = *pi++;
1958
1959             if ( ++i != num && red == lastred && green == lastgreen
1960                                           && blue == lastblue )
1961                run++;
1962             else
1963             {
1964                for ( j=run , bytes=1; j > 0x0f; bytes++, j>>=5);
1965                normal_list += run*colbytes;
1966                run_length += bytes + colbytes;
1967                run_bits += colbytes;
1968
1969                run = 1;
1970                lastred = red; lastgreen = green; lastblue = blue;
1971             }
1972          }
1973       }
1974
1975 /* work out list lengths */
1976       bit_stream = (cols * num * prec + 5) / 6;
1977
1978 /*   Work out best coding method   */
1979      if ( mode == INDEXED && run_bits < run_length ) run_length = run_bits;
1980      else run_bits = 0;
1981
1982      if ( run_length < normal_list && run_length < bit_stream )
1983      {
1984          run_length = TRUE;  normal_list = FALSE; bit_stream = FALSE;
1985          i = ( run_bits ? 0x43 : 0x42 );
1986      }
1987      else if ( bit_stream < normal_list)
1988      {
1989          run_length = FALSE;  normal_list = FALSE; bit_stream = TRUE;
1990          i = 0x41;
1991      }
1992      else
1993      {
1994          run_length = FALSE;  normal_list = TRUE; bit_stream = FALSE;
1995          i = 0x40;
1996      }
1997    }
1998
1999 /*  Reset continuation marker */
2000
2001    if ( first ) MOCout( (Code) i);
2002    first = ( n >= ZERO );
2003    pi = pi0;
2004
2005 /*   Now send points to Metafile  */
2006
2007    if ( run_length )
2008    {
2009      if ( mode == INDEXED )
2010       {
2011          for ( i = ZERO, last = *pi, run = 1 ; i < num ; )
2012          {
2013             pi++;
2014             col = ( ++i == num ? -1 : *pi );
2015
2016             if (col == last)  run++;
2017             else
2018             {
2019              if ( run_bits )
2020                {
2021                   Code byte;
2022
2023 /*  Run length bitstream */
2024                   for ( j = 0, k = prec-6; j < colbytes; j++, k-=6 )
2025                   {
2026                      byte = ( k >= 0 ? (last>>k & 0x3f) | 0x40
2027                                      : (last<<(-k) & 0x3f) | 0x40 );
2028                      MOCout( byte );
2029                   }
2030                }
2031                else  PUTINT ( last );
2032
2033                PUTINT ( run );
2034                run = 1;
2035                last = col;
2036             }
2037          }
2038       }
2039       else  /*  DIRECT Colour (Run length) */
2040       {
2041          lastred = *pi++; lastgreen = *pi++; lastblue = *pi++;
2042          for ( i = ZERO, run = 1 ; i < num ; i++ )
2043          {
2044             last = TRUE;
2045             red = *pi++; green = *pi++; blue = *pi++;
2046             if ( i != num && red == lastred && green == lastgreen
2047                                           && blue == lastblue )
2048             {
2049                last = FALSE;
2050                run++;
2051             }
2052
2053             if ( last )
2054             {
2055                MOCdircol(lastred, lastgreen, lastblue, prec);
2056                PUTINT ( run );
2057                run = 1;
2058                lastred = red; lastgreen = green; lastblue = blue;
2059             }
2060          }
2061       }
2062    }
2063    else if ( normal_list )
2064    {
2065       if ( mode == INDEXED )
2066       {
2067          for ( i = ZERO ; i < num ; i++ )
2068          {
2069              PUTINT ( *pi++ );
2070          }
2071       }
2072       else
2073          for (i = ZERO; i < num ; i++ )
2074          {
2075             red = *pi++; green = *pi++; blue = *pi++;
2076             MOCdircol ( red, green, blue, prec );
2077          }
2078    }
2079    else
2080    {
2081       Code byte;
2082       int bits;
2083
2084       if ( mode == DIRECT ) num *= 3;
2085
2086       for (i = ZERO, bits = 6, byte = 0x40 ; i < num ; i++ )
2087       {
2088          col = *pi++;
2089          for ( j = prec - 1 ; j >= ZERO ; j--)
2090          {
2091             byte |= ((col>>j) & 1) <<--bits;
2092             if ( !bits )
2093             {
2094                MOCout (byte);
2095                bits = 6;
2096                byte = 0x40;
2097             }
2098          }
2099       }
2100       if ( bits < 6 ) MOCout(byte);
2101    }
2102    return;
2103 }
2104
2105 /****************************************************** MOCdircol ******/
2106 static void
2107 MOCdircol ( Posint r, Posint g, Posint b, Prec prec )
2108 {
2109 /*  Output a direct colour (r, g, b) using precision 'prec'  */
2110
2111    register Long i;
2112    register Code c;
2113
2114    if (prec & 0x01)
2115    {
2116       /*   odd number of bits  */
2117
2118       r <<= 1; g <<= 1; b <<= 1;
2119    }
2120    else prec--;
2121
2122 /* if default colour precision convert to 8 bits */
2123    if ( ! cur.colprec_flag )
2124    {
2125       r >>= 2; g >>= 2; b >>= 2;
2126    }
2127    for (i = prec; i > ZERO ; i-- )
2128    {
2129       c = (short) (0x40 | (((r>>i)&1)<<5) | (((g>>i)&1)<<4) | (((b>>i)&1)<<3));
2130       i--;
2131       c = (short) (c    | (((r>>i)&1)<<2) | (((g>>i)&1)<<1) | ((b>>i)&1));
2132       MOCout( c );
2133    }
2134    return;
2135 }
2136
2137 /****************************************************** MOCcoldef ******/
2138 static void
2139 MOCcoldef ()
2140 {
2141 /*  Check if colour precision or Value extent are not set use defaults */
2142
2143    if ( ! cur.colprec_flag && cur.col_bits != curchar.col_prec )
2144    {
2145       curchar.col_prec = cur.col_bits;
2146       MOCout ( COLRPREC );
2147       PUTINT ( curchar.col_prec );
2148    }
2149    if ( ! cur.colval_flag && ( cur.min_rgb.red != curchar.min_rgb.red
2150                           ||  cur.min_rgb.green != curchar.min_rgb.green
2151                           ||  cur.min_rgb.blue != curchar.min_rgb.blue
2152                           ||  cur.max_rgb.red != curchar.max_rgb.red
2153                           ||  cur.max_rgb.green != curchar.max_rgb.green
2154                           ||  cur.max_rgb.blue != curchar.max_rgb.blue ))
2155    {
2156       curchar.min_rgb = cur.min_rgb;
2157       curchar.max_rgb = cur.max_rgb;
2158       MOCout ( COLRVALUEEXT );
2159       MOCdircol ( curchar.min_rgb.red,
2160                   curchar.min_rgb.green,
2161                   curchar.min_rgb.blue,
2162                   curchar.col_prec );
2163       MOCdircol ( curchar.max_rgb.red,
2164                   curchar.max_rgb.green,
2165                   curchar.max_rgb.blue,
2166                   curchar.col_prec );
2167    }
2168    return;
2169 }
2170
2171 /****************************************************** MOCout *********/
2172 static void
2173 MOCout ( Code hex )
2174 {
2175 /*   Add character to buffer and Output if buffer is full */
2176
2177    register Int bits, j;
2178    register unsigned char c;
2179    static size_t index = ZERO;
2180    static unsigned char buffer[BUFF_LEN+1];
2181
2182    bits = ( (hex & 0xff00) > 0 )*8;
2183
2184    for (; bits >= 0 ; bits -= 8)
2185    {
2186       c = (hex>>bits) & 0xff;
2187
2188       if ( c <= 0x20 || c >= 0x7e )
2189          for ( j = 0; j < subchars; j++)
2190          {
2191             if ( c == charsub[j] )
2192             {
2193                hex ^= c<<bits;
2194
2195                c = (c > 0x20 ? c - 0x40 : c + 0x40);
2196                hex |= c<<bits;
2197                c = 0x7e;
2198                bits += 8;
2199                break;
2200             }
2201          }
2202       buffer[index++] = c;
2203
2204       if( ! hex ) for ( ; index < BUFF_LEN; buffer[index++] = '\0');
2205
2206       fwrite (buffer, index, (size_t)1, cgmoc);
2207       fflush (cgmoc);
2208       index = ZERO;
2209    }
2210 /*
2211    register Int bits, j;
2212    register unsigned char c;
2213    static size_t index = ZERO;
2214    static unsigned char buffer[BUFF_LEN+1];
2215
2216    bits = ( (hex & 0xff00) > 0 )*8;
2217
2218    for (; bits >= 0 ; bits -= 8)
2219    {
2220       c = (hex>>bits) & 0xff;
2221
2222       if ( c <= 0x20 || c >= 0x7e )
2223          for ( j = 0; j < subchars; j++)
2224          {
2225             if ( c == charsub[j] )
2226             {
2227                hex ^= c<<bits;
2228
2229                c = (c > 0x20 ? c - 0x40 : c + 0x40);
2230                hex |= c<<bits;
2231                c = 0x7e;
2232                bits += 8;
2233                break;
2234             }
2235          }
2236      buffer[index++] = c;
2237
2238       if( ! hex ) for ( ; index < BUFF_LEN; buffer[index++] = '\0');
2239
2240       if (index == BUFF_LEN)
2241       {
2242          fwrite (buffer, BUFF_LEN, (size_t)1, cgmoc);
2243          fflush (cgmoc);
2244          index = ZERO;
2245       }
2246    }
2247 */
2248    return;
2249 }