0022627: Change OCCT memory management defaults
[occt.git] / src / CGM / cgmobin.c
1 #include <limits.h>
2 #include "cgmout.h"
3
4 /* File stream name */
5
6 static FILE *cgmob;
7
8 /* declare internal functions */
9 # if (defined __STDC__ && __STDC__) || defined __cplusplus
10 /* use function prototypes, they are requred for ANSI C and C++ compilers */
11 void CGMObin(FILE *stream, Code c, Long *pi, Float *pr, char *str);
12 /* Main Output Routine */
13 static void MOBopcode(Code c, Long len),                         /* Output an Op code */
14             MOBint(Long n, Prec prec, Enum sign),                /* Output an Integer */
15             MOBreal(Double x, Enum real_type, Enum real_or_vdc), /* Output a real number */
16             MOBcolour(struct colour *col, Enum type),            /* Output a colour */
17             MOBvdc(Int n, Long *pi, Float *pr),                  /* Output a number of VDCs */
18             MOBpointlist(Long n, Long *pi, Float *pr, Enum set), /* Output a Points List */
19             MOBclist(register Long num, register Long *col,
20                      Prec mode, Enum type, Prec prec),           /* Output a colour list */
21             MOBbits(Posint value, Prec prec, Long *bit),         /* Output a value to a bit stream */
22             MOBstring(char *s),                                  /* Output a string */
23             MOBout(Posint hex, Prec bytes),                      /* Output values to the output buffer */
24             MOBcharci(Code c, Int *class, Int *id);              /* Convert Op code value to Class and Id */
25 #else
26 void CGMObin();  /* Main Output Routine */
27 static void MOBopcode(),    /* Output an Op code */
28             MOBint(),       /* Output an Integer */
29             MOBreal(),      /* Output a real number */
30             MOBcolour(),    /* Output a colour */
31             MOBvdc(),       /* Output a number of VDCs */
32             MOBpointlist(), /* Output a Points List */
33             MOBclist(),     /* Output a colour list */
34             MOBbits(),      /* Output a value to a bit stream */
35             MOBstring(),    /* Output a string */
36             MOBout(),       /* Output values to the output buffer */
37             MOBcharci();    /* Convert Op code value to Class and Id */
38 #endif
39 /*  Local Parameters */
40
41 #define ENUMERATED   (Prec) 16
42
43 #define PARTITION    (Code) 0xff
44
45 #define UNSIGNED     (Enum) 0
46 #define SIGNED       (Enum) 1
47
48 #define FLOATING     (Enum) 0
49 #define FIXED        (Enum) 1
50
51 #define RUNLENGTH    (Enum) 0
52 #define PACKED       (Enum) 1
53
54 #define BYTE         (Prec) 1
55 #define WORD         (Prec) 2
56 #define LONGINT      (Prec) 4
57
58 /*  Parameter sizes */
59
60 #define ENUMSIZE     ( (Long) 2 )
61 #define INDEXSIZE    ( (Long) curbin.index_prec>>3 )
62 #define COLINDEXSIZE ( (Long) curbin.colind_prec>>3 )
63 #define INTSIZE      ( (Long) curbin.int_prec>>3 )
64 #define REALSIZE     ( (Long) (curbin.real_whole + curbin.real_fraction)>>3 )
65 #define VDCSIZE      ( (Long) (cur.vdc_type == REAL\
66                        ? (curbin.vdc_whole + curbin.vdc_fraction)>>3 \
67                        : curbin.vdcint_prec>>3 ) )
68 #define COLOURSIZE    ( (Long) (cur.color_mode == DIRECT\
69                        ? 3*curbin.col_prec>>3 : curbin.colind_prec>>3 ) )
70 #define STRINGSIZE(x) ( (Long) (256 * strlen(x) / 255 + 1) )
71
72 /*  Basic Common Output functions */
73
74 #define PUTBYTE(x)    MOBout( (Posint) x, (Prec) 1 )
75 #define PUTWORD(x)    MOBout( (Posint) x, (Prec) 2 )
76 #define PUTINT(x)     MOBint( (Long) x, curbin.int_prec, SIGNED )
77 #define PUTREAL(x)    MOBreal ( (Double)x, curbin.real_type, REAL )
78 #define PUTINDEX(x)   MOBint( (Long) x, curbin.index_prec, SIGNED )
79 #define PUTENUM(x)    MOBint( (Long) x, ENUMERATED, SIGNED )
80 #define PUTINTVDC(x)  MOBint( (Long) x, curbin.vdcint_prec, SIGNED )
81 #define PUTREALVDC(x) MOBreal( (Double)x, curbin.vdc_type, VDC )
82
83 /* Local Variables */
84
85 static size_t mobblen = BUFF_LEN,   /* Normal Output Buffer length */
86             mobparmlen,           /* Parameter length in bytes */
87             mobremainder,         /* Bytes left after partition */
88             mobdeflen,            /* MF Defaults replacement length */
89             mobindex = 0;         /* Output buffer pointer */
90 static char mobstdbuff[BUFF_LEN], /* Normal Output buffer */
91            *mobbuff = mobstdbuff, /* Buffer origin */
92            *mobdefbuff;           /* MF Defaults replacement buffer */
93
94 /*static char *func="CGMobin", mess[40];*/
95 static char mess[40];
96
97 /********************************************************* CGMObin *****/
98 void
99 CGMObin(FILE *stream, Code c, Long *pi, Float *pr, char *str)
100 {
101    register Long j, n, num;
102    Code major;
103    Long parmlen = ZERO;
104    static Long defindex, saveparmlen;
105    static Logical first = TRUE, first_pic = TRUE;
106    Int class, id;
107
108    if ( c == (Code) EOF )
109    {
110       MOBout ( (Posint) 0, (Prec) 0); /* flush output buffer */
111       exit(0);
112    }
113
114    major=c>>8;
115    num = *pi++;
116
117    switch(major)
118    {
119       case 0x00: /* Graphics Primitives */
120
121          switch(c)
122          {
123             case NONOP:  /* Ignore Non-Op */
124                break;
125
126             case LINE:      /* Polyline */
127             case DISJTLINE: /* Disjoint Polyline */
128             case MARKER: /* Polymarker */
129                parmlen = 2*num*VDCSIZE;
130                if ( first ) MOBopcode(c, parmlen);
131                else         MOBopcode(PARTITION, parmlen);
132                first = ( parmlen >= ZERO );
133                MOBpointlist(num, pi, pr, NOSET);
134                break;
135
136             case TEXT: /* Text */
137                parmlen = 2*VDCSIZE + ENUMSIZE + STRINGSIZE(str);
138                MOBopcode(c, parmlen);
139                MOBvdc( (Int)2, pi, pr);
140                PUTENUM ( num );
141                MOBstring(str);
142                break;
143
144             case RESTRTEXT: /* Restricted Text */
145                parmlen = 4*VDCSIZE + ENUMSIZE + STRINGSIZE(str);
146                MOBopcode(c, parmlen);
147                MOBvdc( (Int)4, pi, pr);
148                PUTENUM ( num );
149                MOBstring(str);
150                break;
151
152             case APNDTEXT: /* Append Text */
153                parmlen = ENUMSIZE + STRINGSIZE(str);
154                MOBopcode(c, parmlen);
155                PUTENUM ( num );
156                MOBstring(str);
157                break;
158
159             case POLYGON: /* Polygon */
160                parmlen = 2*num*VDCSIZE;
161                if ( first ) MOBopcode(c, parmlen);
162                else         MOBopcode(PARTITION, parmlen);
163                first = ( parmlen >= ZERO );
164                MOBpointlist(num, pi, pr, NOSET);
165                break;
166
167             case POLYGONSET: /* Polygon Set */
168                parmlen = num * ( 2*VDCSIZE + ENUMSIZE );
169                if ( first ) MOBopcode(c, parmlen);
170                else         MOBopcode(PARTITION, parmlen);
171                first = ( parmlen >= ZERO );
172                MOBpointlist(num, pi, pr, SET);
173                break;
174
175             case CELLARRAY: /* Cell Array */
176             {
177                register Long *pt = pi, i, k;
178                Long red, green, blue, nc, ncol;
179                unsigned short run, packed;
180                Long last, lastred, lastgreen, lastblue;
181                static Long nx, ny;
182                static Prec lprec;
183                static Enum runlength;
184
185 /*  Number of colour cells */
186
187                nc = abs( num );
188                ncol = abs(cur.color_mode == DIRECT ? 3*num : num );
189
190                if ( first )
191                {
192
193 /*  set up basic parameter length */
194                   parmlen = 6*VDCSIZE + 3*INTSIZE + ENUMSIZE;
195                   pt += 6;    /* skip 3 points */
196                   nx = *pt++;     /* Number of columns */
197                   ny = *pt++;     /* Number of rows */
198                   j  = *pt++;     /* Local precision */
199
200                   if ( j == ZERO || num > 0 )
201                   {
202
203 /*  Find largest colour value if cell within buffer */
204
205                      for ( i = 0, k = 0; i < ncol; i++, pt++ )
206                      {
207                         if ( *pt > k ) k = *pt;
208                      }
209                      j = 0;
210                      while ( k )
211                      {
212                         k >>= 1; j++;
213                      }
214                   }
215                   lprec = ( j <= 1  ?  1
216                           : j <= 2  ?  2
217                           : j <= 4  ?  4
218                           : j <= 8  ?  8
219                           : j <= 16 ? 16
220                           : j <= 24 ? 24
221                                     : 32 );
222                   pt = pi + 9;
223                }
224
225 /*  Find number of bytes for both coding methods */
226
227                run = 0; packed = 0;
228                for ( j = 0; j < nc; j += nx )
229                {
230
231 /*  Make sure row starts on a word boundary  */
232
233                   if ( packed & 1 ) packed++;
234                   if ( run & 1 ) run++;
235
236 /*  Calculate length of packed list in bytes per row */
237
238                   packed += ( (cur.color_mode == DIRECT ? 3*nx : nx)
239                                * lprec + 7 )>>3;
240
241 /*  Calculate length of run length in bits */
242
243                   k = 0;
244                   if ( cur.color_mode == INDEXED )
245                   {
246                      last = -1;
247                      for ( i = 0; i < nx; i++, pt++ )
248                      {
249                         if ( *pt != last)
250                         {
251                            k += curbin.int_prec + lprec;
252                            last = *pt;
253                         }
254                      }
255                   }
256                   else
257                   {
258                      lastred = -1; lastgreen = -1; lastblue = -1;
259                      for ( i = 0; i < nx; i++ )
260                      {
261                         red = *pt++; green = *pt++; blue = *pt++;
262                         if ( red != lastred || green != lastgreen
263                                        || blue != lastblue )
264                         {
265                            k += curbin.int_prec + 3*lprec;
266                            lastred = red;
267                            lastgreen = green;
268                            lastblue = blue;
269                         }
270                      }
271                   }
272
273 /*  Convert runlength to bytes */
274                   run += (k + 7) >>3;
275                }
276
277                if ( first )
278                {
279
280 /*  Decide which encoding is smallest  */
281
282                   if ( run < packed )
283                   {
284                      runlength = RUNLENGTH;
285                      parmlen += run;
286                   }
287                   else
288                   {
289                      runlength = PACKED;
290                      parmlen += packed;
291                   }
292
293                   if ( num < 0 ) parmlen = - parmlen;
294                   MOBopcode(c, parmlen);
295
296                   MOBvdc ( (Int)6, pi, pr );
297                   PUTINT ( nx );
298                   PUTINT ( ny );
299                   PUTINT ( lprec );
300
301                   pi += 9;
302                   PUTENUM ( runlength );
303                }
304                else
305                {
306                   parmlen = ( runlength = RUNLENGTH ? run : packed );
307                   if ( num < 0 ) parmlen = - parmlen;
308                   MOBopcode(PARTITION, parmlen);
309                }
310
311                first = ( num >= ZERO );
312
313 /*  Output cell array a row at a time */
314
315                for ( j = 0; j < nc; j += nx )
316                {
317                   MOBclist (nx, pi, cur.color_mode, runlength, lprec);
318                   pi += ( cur.color_mode == DIRECT ? 3*nx : nx );
319                }
320                break;
321             }
322
323             case GDP: /* Generalised Drawing Primitive */
324                parmlen = 2*INTSIZE + 2*num*VDCSIZE + STRINGSIZE(str);
325                if ( first ) MOBopcode(c, parmlen);
326                else         MOBopcode(PARTITION, parmlen);
327                first = ( parmlen >= ZERO );
328                PUTINT ( *pi );
329                PUTINT ( num );
330                MOBpointlist(num, pi, pr, NOSET);
331                MOBstring(str);
332                break;
333
334             case RECT: /* Rectangle */
335                parmlen = 4*VDCSIZE;
336                MOBopcode(c, parmlen);
337                MOBvdc( (Int)4, pi, pr);
338                break;
339
340             default:
341                (void) sprintf( mess, "(code: 0x%x)", c);
342                break;
343          }
344          break;
345
346       case 0x30:  /*  Delimiter Elements  */
347
348          switch(c)
349          {
350
351             case BEGMF: /* Begin Metafile */
352                cgmob = stream;
353                curbin = bindef;
354                parmlen = STRINGSIZE(str);
355                MOBopcode(c, parmlen);
356                MOBstring(str);
357                break;
358
359             case ENDMF: /* End Metafile */
360                MOBopcode(c, (Long)0 );
361                break;
362
363             case BEGPIC: /* Begin Picture Descriptor */
364                parmlen = STRINGSIZE(str);
365                MOBopcode(c, parmlen);
366                MOBstring(str);
367                if ( first_pic )
368                {
369                   first_pic = FALSE;
370                   mfbin = curbin;
371                }
372                else
373                   curbin = mfbin;
374                break;
375
376             case BEGPICBODY: /* Begin Picture Body */
377                MOBopcode(c, (Long)0 );
378                break;
379
380             case ENDPIC: /* End  Picture */
381                MOBopcode(c, (Long)0 );
382                break;
383
384             default:
385                (void) sprintf( mess, "(code: 0x%x)", c);
386                break;
387          }
388          break;
389
390
391       case 0x31: /* Metafile Descriptor Elements */
392          switch(c)
393          {
394             case MFVERSION: /* Metafile version */
395                parmlen = INTSIZE;
396                MOBopcode(c, parmlen);
397                PUTINT ( num );
398                break;
399
400             case MFDESC: /* Metafile Description */
401                parmlen = STRINGSIZE(str);
402                MOBopcode(c, parmlen);
403                MOBstring(str);
404                break;
405
406             case VDCTYPE: /* VDC Type */
407                parmlen = ENUMSIZE;
408                MOBopcode(c, parmlen);
409                PUTENUM ( cur.vdc_type );
410                break;
411
412             case INTEGERPREC: /* Integer Precision */
413                parmlen = INTSIZE;
414                MOBopcode(c, parmlen);
415                j = ( cur.int_bits <= 8  ?  8
416                    : cur.int_bits <= 16 ? 16
417                    : cur.int_bits <= 24 ? 24
418                                         :32 );
419                PUTINT ( j );
420                curbin.int_prec = j;
421                break;
422
423             case REALPREC: /* Real Precision */
424                parmlen = ENUMSIZE + 2*INTSIZE;
425                MOBopcode(c, parmlen);
426                PUTENUM ( curbin.real_type );
427                if ( curbin.real_type == FIXED )
428                { /* NB: only 16,16 and 32,32 are permitted */
429                   curbin.real_whole =
430                      (cur.real_bits > 16 || -cur.real_places > 16 ? 32 : 16);
431                   curbin.real_fraction = curbin.real_whole;
432                }
433                PUTINT ( curbin.real_whole );
434                PUTINT ( curbin.real_fraction );
435                break;
436
437             case INDEXPREC: /* Index Precision */
438                parmlen = INTSIZE;
439                MOBopcode(c, parmlen);
440                curbin.index_prec = ( cur.index_bits <=  8 ?  8
441                                    : cur.index_bits <= 16 ? 16
442                                    : cur.index_bits <= 24 ? 24
443                                                           : 32 );
444                PUTINT ( curbin.index_prec );
445                break;
446
447             case COLRPREC: /* Colour Precision */
448                parmlen = INTSIZE;
449                MOBopcode(c, parmlen);
450                curbin.col_prec = ( cur.col_bits <=  8 ?  8
451                                  : cur.col_bits <= 16 ? 16
452                                  : cur.col_bits <= 24 ? 24
453                                                       : 32 );
454                PUTINT ( curbin.col_prec );
455                break;
456
457             case COLRINDEXPREC: /* Colour Index Precision */
458                parmlen = INTSIZE;
459                MOBopcode(c, parmlen);
460                curbin.colind_prec = ( cur.colind_bits <=  8 ?  8
461                                     : cur.colind_bits <= 16 ? 16
462                                     : cur.colind_bits <= 24 ? 24
463                                                             : 32 );
464                PUTINT ( curbin.colind_prec );
465                break;
466
467             case MAXCOLRINDEX: /* Maximum Colour Index */
468                parmlen = COLINDEXSIZE;
469                MOBopcode(c, parmlen);
470                MOBint (cur.max_colind, curbin.colind_prec, UNSIGNED);
471                break;
472
473             case COLRVALUEEXT: /* Colour value extent */
474                parmlen = 6 * curbin.col_prec >>3;
475                MOBopcode(c, parmlen);
476                curbin.min_rgb.red   = cur.min_rgb.red;
477                curbin.min_rgb.green = cur.min_rgb.green;
478                curbin.min_rgb.blue  = cur.min_rgb.blue;
479                MOBcolour ( &curbin.min_rgb, DIRECT );
480                curbin.max_rgb.red   = cur.max_rgb.red;
481                curbin.max_rgb.green = cur.max_rgb.green;
482                curbin.max_rgb.blue  = cur.max_rgb.blue;
483                MOBcolour ( &curbin.max_rgb, DIRECT );
484                break;
485
486             case MFELEMLIST: /* Metafile element List */
487                parmlen = INTSIZE + 2*num*INDEXSIZE;
488                MOBopcode(c, parmlen);
489                PUTINT ( num );
490                for(n = 0; n < num; n++, pi++)
491                {
492                   switch ( (Int)*pi )
493                   {
494                      case 0:
495                      case 1:
496                         class = -1; id = (Int)*pi;
497                         break;
498                      default:
499                         MOBcharci( (Code)*pi, &class, &id);
500                         break;
501                   }
502                   PUTINDEX ( class );
503                   PUTINDEX ( id );
504                }
505                break;
506
507             case BEGMFDEFAULTS: /* Begin Metafile defaults Replacement */
508 /*  Save current index value */
509                defindex = mobindex;
510                saveparmlen = mobparmlen;
511                mobparmlen = 0;
512 /*  Create new buffer  */
513                mobblen = ARRAY_MAX;
514                mobbuff = mobdefbuff = (char *) malloc( (size_t)mobblen );
515                mobindex = 0;
516                break;
517
518             case ENDMFDEFAULTS: /* End Metafile defaults Replacement */
519 /*  reset buffer and index  */
520                mobbuff = mobstdbuff;
521                mobdeflen = mobindex;
522                mobindex = defindex;
523                mobblen = BUFF_LEN;
524                mobparmlen = saveparmlen;
525                MOBopcode(BEGMFDEFAULTS, mobdeflen);
526
527 /* copy defaults buffer to output */
528                for ( n = 0; n < (int)mobdeflen; n++ )
529                      PUTBYTE( mobdefbuff[n] );
530                FREE( mobdefbuff );
531                break;
532
533             case FONTLIST: /* Font List */
534             {
535                register Long *pt = pi;
536
537                for ( j=0, parmlen=0; j < num; j = *pt++ )
538                                    parmlen += STRINGSIZE( &str[j] );
539                MOBopcode(c, parmlen);
540                for ( j=0, pt = pi; j < num; j = *pt++ )
541                                    MOBstring( &str[j] );
542                break;
543             }
544
545             case CHARSETLIST: /* Character set list */
546             {
547                register Long *pt = pi;
548
549                for ( j=0, parmlen=0; j < num; j = *pt++ )
550                {
551                   parmlen += ENUMSIZE + STRINGSIZE(&str[j]);
552                   pt++;
553                }
554                MOBopcode(c, parmlen);
555                for ( j=0, pt = pi; j < num; j = *pt++ )
556                {
557                   PUTENUM ( *pt++ );
558                   MOBstring( &str[j] );
559                }
560                break;
561             }
562
563             case CHARCODING: /* Character coding Announcer */
564                parmlen = ENUMSIZE;
565                MOBopcode(c, parmlen);
566                PUTENUM ( num );
567                break;
568
569             default:
570                (void) sprintf( mess, "(code: 0x%x)", c);
571                break;
572          }
573          break;
574
575       case 0x32: /* Picture Descriptor Elements */
576          switch(c)
577          {
578             case SCALEMODE: /* Scaling Mode */
579                parmlen = ENUMSIZE + REALSIZE;
580                MOBopcode(c, parmlen);
581                PUTENUM ( cur.scale_mode );
582                MOBreal ( (Double)cur.scale_factor, FLOATING, REAL );
583                break;
584
585             case COLRMODE: /* Colour Selection Mode */
586                parmlen = ENUMSIZE;
587                MOBopcode(c, parmlen);
588                PUTENUM ( cur.color_mode );
589                break;
590
591             case LINEWIDTHMODE: /* Line width Specification */
592                parmlen = ENUMSIZE;
593                MOBopcode(c, parmlen);
594                PUTENUM ( cur.linewidth_mode );
595                break;
596
597             case MARKERSIZEMODE: /* Marker size Specification */
598                parmlen = ENUMSIZE;
599                MOBopcode(c, parmlen);
600                PUTENUM ( cur.markersize_mode );
601                break;
602
603             case EDGEWIDTHMODE: /* Edge width Specification */
604                parmlen = ENUMSIZE;
605                MOBopcode(c, parmlen);
606                PUTENUM ( cur.edgewidth_mode );
607                break;
608
609             case VDCEXT: /* VDC Extent */
610                parmlen = 4*VDCSIZE;
611                MOBopcode(c, parmlen);
612                if (cur.vdc_type == REAL)
613                {
614                  PUTREALVDC ( cur.vdc_extent.a.x.real );
615                  PUTREALVDC ( cur.vdc_extent.a.y.real );
616                  PUTREALVDC ( cur.vdc_extent.b.x.real );
617                  PUTREALVDC ( cur.vdc_extent.b.y.real );
618                }
619                else
620                {
621                  PUTINTVDC ( cur.vdc_extent.a.x.intr );
622                  PUTINTVDC ( cur.vdc_extent.a.y.intr );
623                  PUTINTVDC ( cur.vdc_extent.b.x.intr );
624                  PUTINTVDC ( cur.vdc_extent.b.y.intr );
625                }
626                break;
627
628             case BACKCOLR: /* Background Colour */
629                parmlen = 3 * curbin.col_prec >>3;
630                MOBopcode(c, parmlen);
631                MOBcolour( &cur.back, DIRECT );
632                break;
633
634             default:
635                (void) sprintf( mess, "(code: 0x%x)", c);
636          }
637          break;
638
639       case 0x33:  /* Control Elements */
640          switch(c)
641          {
642             case VDCINTEGERPREC: /* VDC Integer Precision */
643                parmlen = INTSIZE;
644                MOBopcode(c, parmlen);
645                curbin.vdcint_prec = ( cur.vdcint_bits <= 8  ?  8
646                                     : cur.int_bits <= 16 ? 16
647                                     : cur.int_bits <= 24 ? 24
648                                                          :32 );
649                PUTINT ( curbin.vdcint_prec );
650                break;
651
652             case VDCREALPREC: /* VDC Real Precision */
653                parmlen = ENUMSIZE + 2*INTSIZE;
654                MOBopcode(c, parmlen);
655                PUTENUM ( curbin.vdc_type );
656                if ( curbin.real_type == FIXED )
657                {  /* NB: only 16,16 or 32,32 permitted */
658                   curbin.vdc_whole =
659                      (cur.vdc_bits > 16 || -cur.vdc_places > 16 ? 32 : 16);
660                   curbin.vdc_fraction = curbin.vdc_whole;
661                }
662                PUTINT ( curbin.vdc_whole );
663                PUTINT ( curbin.vdc_fraction );
664                break;
665
666             case AUXCOLR: /* Auxiliary Colour */
667                parmlen = COLOURSIZE;
668                MOBopcode(c, parmlen);
669                MOBcolour( &cur.aux, cur.color_mode );
670                break;
671
672             case TRANSPARENCY: /* Transparency */
673                parmlen = ENUMSIZE;
674                MOBopcode(c, parmlen);
675                PUTENUM ( cur.transparency );
676                break;
677
678             case CLIPRECT: /* Clip Rectangle */
679                parmlen = 4*VDCSIZE;
680                MOBopcode(c, parmlen);
681                if ( cur.vdc_type == REAL )
682                {
683                  PUTREALVDC ( cur.clip_rect.a.x.real );
684                  PUTREALVDC ( cur.clip_rect.a.y.real );
685                  PUTREALVDC ( cur.clip_rect.b.x.real );
686                  PUTREALVDC ( cur.clip_rect.b.y.real );
687                }
688                else
689                {
690                  PUTINTVDC ( cur.clip_rect.a.x.intr );
691                  PUTINTVDC ( cur.clip_rect.a.y.intr );
692                  PUTINTVDC ( cur.clip_rect.b.x.intr );
693                  PUTINTVDC ( cur.clip_rect.b.y.intr );
694                }
695                break;
696
697             case CLIP: /* Clip Indicator */
698                parmlen = ENUMSIZE;
699                MOBopcode(c, parmlen);
700                PUTENUM ( cur.clip_ind );
701                break;
702
703             default:
704                (void) sprintf( mess, "(code: 0x%x)", c);
705                break;
706          }
707          break;
708
709       case 0x34: /* Circles and Ellipses */
710          switch(c)
711          {
712             case CIRCLE: /* Circle */
713                parmlen = 3*VDCSIZE;
714                MOBopcode(c, parmlen);
715                MOBvdc( (Int)3, pi, pr );
716                break;
717
718             case ARC3PT: /* Circular Arc  3 point */
719                parmlen = 6*VDCSIZE;
720                MOBopcode(c, parmlen);
721                MOBvdc( (Int)6, pi, pr );
722                break;
723
724             case ARC3PTCLOSE: /* Circular Arc  3 point close */
725                parmlen = 6*VDCSIZE + ENUMSIZE;
726                MOBopcode(c, parmlen);
727                MOBvdc( (Int)6, pi, pr );
728                PUTENUM ( *(pi+6) );
729                break;
730
731             case ARCCTR: /* Circle Arc centre */
732                parmlen = 7*VDCSIZE;
733                MOBopcode(c, parmlen);
734                MOBvdc( (Int)7, pi, pr );
735                break;
736
737             case ARCCTRCLOSE: /* Circle Arc centre close */
738                parmlen = 7*VDCSIZE + ENUMSIZE;
739                MOBopcode(c, parmlen);
740                MOBvdc( (Int)7, pi, pr );
741                PUTENUM ( *(pi+7) );
742                break;
743
744             case ELLIPSE: /* Ellipse */
745                parmlen = 6*VDCSIZE;
746                MOBopcode(c, parmlen);
747                MOBvdc( (Int)6, pi, pr );
748                break;
749
750             case ELLIPARC: /* Elliptical Arc */
751                parmlen = 10*VDCSIZE;
752                MOBopcode(c, parmlen);
753                MOBvdc( (Int)10, pi, pr );
754                break;
755
756             case ELLIPARCCLOSE: /* Elliptical Arc close */
757                parmlen = 10*VDCSIZE + ENUMSIZE;
758                MOBopcode(c, parmlen);
759                MOBvdc( (Int)10, pi, pr );
760                PUTENUM ( *(pi+10) );
761                break;
762
763             default:
764                (void) sprintf( mess, "(code: 0x%x)", c);
765                break;
766          }
767          break;
768
769       case 0x35: /* Attributes */
770
771          switch(c)
772          {
773             case LINEINDEX: /* Line Bundle index */
774                parmlen = INDEXSIZE;
775                MOBopcode(c, parmlen);
776                PUTINDEX ( curatt.line_ind );
777                break;
778
779             case LINETYPE: /* Line Type */
780                parmlen = INDEXSIZE;
781                MOBopcode(c, parmlen);
782                PUTINDEX ( curatt.line_type );
783                break;
784
785             case LINEWIDTH: /* Line Width */
786                if(cur.linewidth_mode == SCALED)
787                {
788                  parmlen = REALSIZE;
789                  MOBopcode(c, parmlen);
790                  PUTREAL ( curatt.line_width.real );
791                }
792                else
793                {
794                  parmlen = VDCSIZE;
795                  MOBopcode(c, parmlen);
796                  if ( cur.vdc_type == REAL )
797                       PUTREALVDC ( curatt.line_width.real );
798                  else PUTINTVDC ( curatt.line_width.intr );
799                }
800                break;
801
802             case LINECOLR: /* Line Colour */
803                parmlen = COLOURSIZE;
804                MOBopcode(c, parmlen);
805                MOBcolour( &curatt.line, cur.color_mode);
806                break;
807
808             case MARKERINDEX: /* Marker Bundle index */
809                parmlen = INDEXSIZE;
810                MOBopcode(c, parmlen);
811                PUTINDEX ( curatt.mark_ind );
812                break;
813
814             case MARKERTYPE: /* Marker Type */
815                parmlen = INDEXSIZE;
816                MOBopcode(c, parmlen);
817                PUTINDEX ( curatt.mark_type );
818                break;
819
820             case MARKERSIZE: /* Marker Size */
821                if(cur.markersize_mode == SCALED)
822                {
823                  parmlen = REALSIZE;
824                  MOBopcode(c, parmlen);
825                  PUTREAL ( curatt.mark_size.real );
826                }
827                else
828                {
829                  parmlen = VDCSIZE;
830                  MOBopcode(c, parmlen);
831                  if ( cur.vdc_type == REAL )
832                       PUTREALVDC ( curatt.mark_size.real );
833                  else PUTINTVDC ( curatt.mark_size.intr );
834                }
835                break;
836
837             case MARKERCOLR: /* Marker Colour */
838                parmlen = COLOURSIZE;
839                MOBopcode(c, parmlen);
840                MOBcolour( &curatt.marker, cur.color_mode);
841                break;
842
843             case TEXTINDEX: /* Text Bundle index */
844                parmlen = INDEXSIZE;
845                MOBopcode(c, parmlen);
846                PUTINDEX ( curatt.text_ind );
847                break;
848
849             case TEXTFONTINDEX: /* Text Font Index */
850                parmlen = INDEXSIZE;
851                MOBopcode(c, parmlen);
852                PUTINDEX ( curatt.text_font );
853                break;
854
855             case TEXTPREC: /* Text Precision */
856                parmlen = ENUMSIZE;
857                MOBopcode(c, parmlen);
858                PUTENUM ( curatt.text_prec );
859                break;
860
861             case CHAREXPAN: /* Character Expansion Factor */
862                parmlen = REALSIZE;
863                MOBopcode(c, parmlen);
864                PUTREAL ( curatt.char_exp );
865                break;
866
867             case CHARSPACE: /* Character Spacing */
868                parmlen = REALSIZE;
869                MOBopcode(c, parmlen);
870                PUTREAL ( curatt.char_space );
871                break;
872
873             case TEXTCOLR: /* Text Colour */
874                parmlen = COLOURSIZE;
875                MOBopcode(c, parmlen);
876                MOBcolour( &curatt.text, cur.color_mode);
877                break;
878
879             case CHARHEIGHT: /* Character Height */
880                parmlen = VDCSIZE;
881                MOBopcode(c, parmlen);
882                if ( cur.vdc_type == REAL )
883                     PUTREALVDC ( curatt.char_height.real );
884                else PUTINTVDC ( curatt.char_height.intr );
885                break;
886
887             case CHARORI: /* Character Orientation */
888                parmlen = 4*VDCSIZE;
889                MOBopcode(c, parmlen);
890                if ( cur.vdc_type == REAL )
891                {
892                   PUTREALVDC ( curatt.char_up.x.real );
893                   PUTREALVDC ( curatt.char_up.y.real );
894                   PUTREALVDC ( curatt.char_base.x.real );
895                   PUTREALVDC ( curatt.char_base.y.real );
896                }
897                else
898                {
899                   PUTINTVDC (curatt.char_up.x.intr );
900                   PUTINTVDC (curatt.char_up.y.intr );
901                   PUTINTVDC (curatt.char_base.x.intr );
902                   PUTINTVDC (curatt.char_base.y.intr );
903                }
904                break;
905
906             case TEXTPATH: /* Text Path */
907                parmlen = ENUMSIZE;
908                MOBopcode(c, parmlen);
909                PUTENUM ( curatt.text_path );
910                break;
911
912             case TEXTALIGN:       /*  Text Alignment */
913                parmlen = 2*ENUMSIZE + 2*REALSIZE;
914                MOBopcode(c, parmlen);
915                PUTENUM ( curatt.text_halign );
916                PUTENUM ( curatt.text_valign );
917                PUTREAL ( curatt.text_hcont );
918                PUTREAL ( curatt.text_vcont );
919                break;
920
921             case CHARSETINDEX: /* Character Set Index */
922                parmlen = INDEXSIZE;
923                MOBopcode(c, parmlen);
924                PUTINDEX ( curatt.char_set );
925                break;
926
927             case ALTCHARSETINDEX: /* Alt Character Set Index */
928                parmlen = INDEXSIZE;
929                MOBopcode(c, parmlen);
930                PUTINDEX ( curatt.altchar_set );
931                break;
932
933             default:
934                (void) sprintf( mess, "(code: 0x%x)", c);
935                break;
936          }
937          break;
938
939       case 0x36: /* More Attributes */
940          switch(c)
941          {
942             case FILLINDEX: /* Fill Bundle index */
943                parmlen = INDEXSIZE;
944                MOBopcode(c, parmlen);
945                PUTINDEX ( curatt.fill_ind );
946                break;
947
948             case INTSTYLE: /* Interior Style */
949                parmlen = ENUMSIZE;
950                MOBopcode(c, parmlen);
951                PUTENUM ( curatt.int_style );
952                break;
953
954             case FILLCOLR: /* Fill Colour */
955                parmlen = COLOURSIZE;
956                MOBopcode(c, parmlen);
957                MOBcolour( &curatt.fill, cur.color_mode);
958                break;
959
960             case HATCHINDEX: /* Hatch Index */
961                parmlen = INDEXSIZE;
962                MOBopcode(c, parmlen);
963                PUTINDEX(curatt.hatch_ind );
964                break;
965
966             case PATINDEX: /* Pattern Index */
967                parmlen = INDEXSIZE;
968                MOBopcode(c, parmlen);
969                PUTINDEX(curatt.pat_ind );
970                break;
971
972             case EDGEINDEX: /* Edge Bundle index */
973                parmlen = INDEXSIZE;
974                MOBopcode(c, parmlen);
975                PUTINDEX(curatt.edge_ind );
976                break;
977
978             case EDGETYPE: /* Edge Type */
979                parmlen = INDEXSIZE;
980                MOBopcode(c, parmlen);
981                PUTINDEX(curatt.edge_type );
982                break;
983
984             case EDGEWIDTH: /* Edge Width */
985                if(cur.edgewidth_mode == SCALED)
986                {
987                  parmlen = REALSIZE;
988                  MOBopcode(c, parmlen);
989                  PUTREAL ( curatt.edge_width.real );
990                }
991                else
992                {
993                  parmlen = VDCSIZE;
994                  MOBopcode(c, parmlen);
995                  if ( cur.vdc_type == REAL )
996                       PUTREALVDC ( curatt.edge_width.real );
997                  else PUTINTVDC ( curatt.edge_width.intr );
998                }
999                break;
1000
1001             case EDGECOLR: /* Edge Colour */
1002                parmlen = COLOURSIZE;
1003                MOBopcode(c, parmlen);
1004                MOBcolour( &curatt.edge, cur.color_mode);
1005                break;
1006
1007             case EDGEVIS: /* Edge Visibility */
1008                parmlen = ENUMSIZE;
1009                MOBopcode(c, parmlen);
1010                PUTENUM ( curatt.edge_vis );
1011                break;
1012
1013             case FILLREFPT: /* Fill Reference Point */
1014                parmlen = 2*VDCSIZE;
1015                MOBopcode(c, parmlen);
1016                if ( cur.vdc_type == REAL )
1017                {
1018                   PUTREALVDC ( curatt.fill_ref.x.real );
1019                   PUTREALVDC ( curatt.fill_ref.y.real );
1020                }
1021                else
1022                {
1023                   PUTINTVDC ( curatt.fill_ref.x.intr );
1024                   PUTINTVDC ( curatt.fill_ref.y.intr );
1025                }
1026                break;
1027
1028             case PATTABLE: /* Pattern Table */
1029             {
1030                register Long *pt = pi, patind, i, k;
1031                Long nx, ny;
1032                Prec lprec;
1033
1034                parmlen = INDEXSIZE + 3*INTSIZE;
1035                patind = *pt++;
1036                nx = *pt++;
1037                ny = *pt++;
1038                pt++;   /* ignore previous local precision */
1039
1040 /*  Find local precision */
1041
1042                n = (cur.color_mode == DIRECT ? 3*num : num );
1043                for ( i = 0, k = 0; i < n; i++, pt++ )
1044                {
1045                   if ( *pt > k ) k = *pt;
1046                }
1047                j = 0;
1048                while ( k )
1049                {
1050                   k >>= 1; j++;
1051                }
1052                lprec = ( j <=  1 ?  1
1053                        : j <=  2 ?  2
1054                        : j <=  4 ?  4
1055                        : j <=  8 ?  8
1056                        : j <= 16 ? 16
1057                        : j <= 24 ? 24
1058                                  : 32 );
1059
1060 /* Work out parameter length in bytes  */
1061
1062                parmlen += ( lprec * (cur.color_mode == DIRECT ? 3*num : num )
1063                           + 7 )>>3;
1064
1065                MOBopcode(c, parmlen);
1066
1067                PUTINDEX ( patind );
1068                PUTINT ( nx );
1069                PUTINT ( ny );
1070                PUTINT ( lprec );
1071
1072 /*  Output whole cell array */
1073
1074                MOBclist ( num, pi + 4, cur.color_mode, PACKED, lprec);
1075                break;
1076             }
1077
1078             case PATSIZE: /* Pattern Size */
1079                parmlen = 4*VDCSIZE;
1080                MOBopcode(c, parmlen);
1081                if ( cur.vdc_type == REAL )
1082                {
1083                   PUTREALVDC ( curatt.pat_size.a.x.real );
1084                   PUTREALVDC ( curatt.pat_size.a.y.real );
1085                   PUTREALVDC ( curatt.pat_size.b.x.real );
1086                   PUTREALVDC ( curatt.pat_size.b.y.real );
1087                }
1088                else
1089                {
1090                   PUTINTVDC ( curatt.pat_size.a.x.intr );
1091                   PUTINTVDC ( curatt.pat_size.a.y.intr );
1092                   PUTINTVDC ( curatt.pat_size.b.x.intr );
1093                   PUTINTVDC ( curatt.pat_size.b.y.intr );
1094                }
1095                break;
1096
1097             case COLRTABLE: /* Colour Table */
1098                parmlen = COLINDEXSIZE + ((3*num*curbin.col_prec)>>3);
1099                MOBopcode(c, parmlen);
1100                MOBint(*pi++, curbin.colind_prec, UNSIGNED);
1101                for ( j=0; j < num; j++)
1102                {
1103                      MOBint(*pi++, curbin.col_prec, UNSIGNED);
1104                      MOBint(*pi++, curbin.col_prec, UNSIGNED);
1105                      MOBint(*pi++, curbin.col_prec, UNSIGNED);
1106                }
1107                break;
1108
1109             case ASF: /* Aspect source flags */
1110             {
1111                Long k, l, *pt=pi;
1112                Int type, value;
1113                Logical asflag[ASFS];
1114
1115                for ( j=0; j < ASFS; j++) asflag[j] = FALSE;
1116                for ( j=0; j < num; j++ )
1117                {
1118                   type = *pt++; value = (*pt++) + 1;
1119                   if ( type < ASFS ) asflag[type] = value;
1120                   else
1121                   {
1122                      switch ( type )
1123                      {
1124                         case 506:     /* all edge */
1125                            k = 15; l = 17; break;
1126                         case 507:     /* all fill */
1127                            k = 11; l = 14; break;
1128                         case 508:     /* all text */
1129                            k = 6; l = 10; break;
1130                         case 509:     /* all marker */
1131                            k = 3; l = 5; break;
1132                         case 510:     /* all line */
1133                            k = 0; l = 2; break;
1134                         case 511:     /* all */
1135                            k = 0; l = 17; break;
1136                         default:      /* ignore  */
1137                            k = 1; l = 0; break;
1138                      }
1139                      for ( n = k; n < l; n++ ) asflag[n] = value;
1140                   }
1141                }
1142                for ( j=0; j < ASFS; j++)
1143                   if ( asflag[j] ) parmlen += 2*ENUMSIZE;
1144                MOBopcode(c, parmlen);
1145                for ( j=0; j < ASFS; j++)
1146                   if ( asflag[j] )
1147                   {
1148                      PUTENUM ( j );
1149                      PUTENUM ( curatt.asf[j] );
1150                   }
1151                break;
1152             }
1153
1154             default:
1155                (void) sprintf( mess, "(code: 0x%x)", c);
1156                break;
1157          }
1158          break;
1159
1160       case 0x37: /* Escape And External Elements */
1161          switch(c)
1162          {
1163             case ESCAPE: /* Escape */
1164                parmlen = INTSIZE + STRINGSIZE(str);
1165                MOBopcode(c, parmlen);
1166                PUTINT ( num );
1167                MOBstring(str);
1168                break;
1169
1170             case MESSAGE: /* Message */
1171                parmlen = ENUMSIZE + STRINGSIZE(str);
1172                MOBopcode(c, parmlen);
1173                PUTENUM ( num );
1174                MOBstring(str);
1175                break;
1176
1177             case APPLDATA: /* Application Data */
1178                parmlen = INTSIZE + STRINGSIZE(str);
1179                MOBopcode(c, parmlen);
1180                PUTINT ( num );
1181                MOBstring(str);
1182                break;
1183
1184             default:
1185                (void) sprintf( mess, "(code: 0x%x)", c);
1186                break;
1187          }
1188          break;
1189
1190       default:
1191         (void) sprintf( mess, "(code: 0x%x)", c);
1192         break;
1193    }
1194    return;
1195 }
1196
1197 /******************************************************** MOBopcode ****/
1198
1199 static void
1200 MOBopcode( Code c, Long len )
1201 {
1202    Int class, id;
1203    unsigned Long oneword, plen, remainder;
1204    Logical part;
1205
1206 /* Pad out last element if necessary */
1207    while ( mobparmlen && mobparmlen < 0x8000 ) PUTBYTE( ZERO );
1208
1209    plen = abs(len);
1210    part = (len < 0);
1211
1212 /*  check for parameter length > 32766 */
1213
1214    if ( plen > 0x7ffe )
1215    {
1216       remainder = plen - 0x7ffe;
1217       part = TRUE;
1218       plen = 0x7ffe;
1219    }
1220    else remainder = 0;
1221
1222    if ( c != PARTITION )
1223    {
1224       MOBcharci(c, &class, &id);
1225       oneword = (class<<12) + (id<<5) + ( part || (plen > 0x1e) ? 0x1f : plen );
1226       PUTWORD ( oneword );
1227    }
1228
1229 /* Put out parameter length as integer */
1230
1231    if ( c == PARTITION || plen > 0x1e )
1232    {
1233       oneword = ( part ? plen | 0x8000 : plen );
1234       PUTWORD ( oneword );
1235    }
1236
1237    mobparmlen = plen;
1238    mobremainder = remainder;
1239    if (mobparmlen & 1) mobparmlen++;
1240    return;
1241 }
1242
1243 /******************************************************** MOBcharci ****/
1244 static void
1245 MOBcharci( Code c, Int *class, Int *id )
1246 {
1247 /*  Converts Code c to class and Id  */
1248
1249    Code major = c>>8, minor = c & 0xff;
1250
1251    *class = -1; *id = 0;
1252    switch ( major )
1253    {
1254       case 0x00:  /* Graphics Primitives */
1255          if ( minor >= 0x20 && minor <= 0x2A )
1256          {
1257             *class = 4; *id = minor - 0x20 + 1;
1258          }
1259          else if ( minor == 0 ) *class = ZERO;  /*  Non-Op */
1260          break;
1261
1262       case 0x30:  /* Metafile delimiters */
1263          if ( minor >= 0x20 && minor <= 0x24 )
1264          {
1265             *class = 0; *id = minor - 0x20 + 1;
1266          }
1267          break;
1268
1269       case 0x31:  /* Metafile Descriptor Elements */
1270          if ( minor >= 0x20 && minor <= 0x2b )
1271          {
1272             *class = 1; *id = minor - 0x20 + 1;
1273          }
1274          else if ( minor > 0x2c && minor <= 0x2f )
1275          {
1276             *class = 1; *id = minor - 0x20;
1277          }
1278          break;
1279
1280       case 0x32:  /* Picture Descriptor Elements */
1281          if ( minor >= 0x20 && minor <= 0x26 )
1282          {
1283             *class = 2; *id = minor - 0x20 + 1;
1284          }
1285          break;
1286
1287       case 0x33:  /* Control Elements */
1288          if ( minor >= 0x20 && minor <= 0x25 )
1289          {
1290             *class = 3; *id = minor - 0x20 + 1;
1291          }
1292          break;
1293
1294       case 0x34:  /* More Graphics Primitives */
1295          if ( minor >= 0x20 && minor <= 0x27 )
1296          {
1297             *class = 4; *id = minor - 0x20 + 12;
1298          }
1299          break;
1300
1301       case 0x35:  /* Attributes */
1302          if ( minor >= 0x20 && minor <= 0x27 )
1303          {
1304             *class = 5; *id = minor - 0x20 + 1;
1305          }
1306          else if ( minor >= 0x30 && minor <= 0x3b )
1307          {
1308             *class = 5; *id = minor - 0x30 + 9;
1309          }
1310          break;
1311
1312       case 0x36:  /* More Attributes */
1313          if ( minor >= 0x20 && minor <= 0x2c )
1314          {
1315             *class = 5; *id = minor - 0x20 + 21;
1316          }
1317          else if ( minor >= 0x30 && minor <= 0x31 )
1318          {
1319             *class = 5; *id = minor - 0x30 + 34;
1320          }
1321          break;
1322
1323       case 0x37:  /* External elements */
1324          if ( minor == 0x20 )
1325          {
1326             *class = 6; *id = 1;
1327          }
1328          else if ( minor >= 0x21 && minor <= 0x22 )
1329          {
1330             *class = 7; *id = minor - 0x20;
1331          }
1332          break;
1333
1334       default:
1335          break;
1336    }
1337
1338    if ( *class < 0 )
1339    {
1340       (void) sprintf( mess, "(code: 0x%x)", c);
1341       *class = 0;
1342    }
1343
1344    return;
1345 }
1346
1347 /******************************************************** MOBint *******/
1348 static void
1349 MOBint( Long n, Prec prec, Enum sign )
1350 {
1351 /*
1352    if ( sign == SIGNED && n < 0 )
1353       n = (-n | (Posint) 1L<<(prec-1));
1354 */
1355    MOBout( (Posint) n, prec>>3 );
1356    return;
1357 }
1358
1359 /******************************************************** MOBcolour ****/
1360 static void
1361 MOBcolour( struct colour *col, Enum type )
1362 {
1363
1364    if ( type == DIRECT )
1365    {
1366       MOBint( (Long) col->red, curbin.col_prec, UNSIGNED );
1367       MOBint( (Long) col->green, curbin.col_prec, UNSIGNED );
1368       MOBint( (Long) col->blue, curbin.col_prec, UNSIGNED );
1369    }
1370    else
1371    {
1372       MOBint( (Long) col->index, curbin.colind_prec, UNSIGNED );
1373    }
1374
1375    return;
1376 }
1377
1378 /******************************************************** MOBvdc *******/
1379 static void
1380 MOBvdc( Int n, Long *pi, Float *pr)
1381 {
1382    Int i;
1383    for ( i = 0; i < n; i++)
1384    {
1385       if ( cur.vdc_type == INTEGER )
1386       {
1387          PUTINTVDC ( *pi++ );
1388       }
1389       else
1390       {
1391          PUTREALVDC ( *pr++ );
1392       }
1393    }
1394
1395    return;
1396 }
1397
1398 /******************************************************** MOBpointlist */
1399 static void
1400 MOBpointlist(Long n, Long *pi, Float *pr, Enum set)
1401 {
1402    Int i;
1403    for ( i = 0; i < n; i++)
1404    {
1405       if ( cur.vdc_type == INTEGER )
1406       {
1407          PUTINTVDC ( *pi++ );
1408          PUTINTVDC ( *pi++ );
1409       }
1410       else
1411       {
1412          PUTREALVDC ( *pr++ );
1413          PUTREALVDC ( *pr++ );
1414       }
1415       if ( set ) PUTENUM ( *pi++ );
1416    }
1417
1418    return;
1419 }
1420
1421 /******************************************************** MOBreal ******/
1422 static void
1423 MOBreal(Double x, Enum real_type, Enum real_or_vdc )
1424 {
1425    Posint whole, exponent, fract, neg;
1426    Prec prec;
1427    Double f;
1428    neg = ( x < 0.0 ) << 15;
1429
1430    if ( real_type == FIXED )
1431    {
1432       prec = (real_or_vdc == VDC ? curbin.vdc_whole
1433                                  : curbin.real_whole);
1434       whole = (Posint)( neg ? -((floor(x))) : x );
1435       fract = (Posint)( ( neg ? x + (Double)whole : x - (Double)whole )
1436                             * ( 1L<<(prec-2) ) * 4.0 );
1437
1438       if ( prec == 32 )
1439       {
1440          PUTWORD( whole>>16 | neg );
1441          PUTWORD( whole & (Posint)0xffff );
1442          PUTWORD( fract>>16 );
1443          PUTWORD( fract & (Posint)0xffff );
1444       }
1445       else
1446       {
1447          PUTWORD( whole | neg );
1448          PUTWORD( fract );
1449       }
1450    }
1451    else
1452    {
1453 /*  IEEE Floating point reals */
1454
1455       prec = (real_or_vdc == VDC ? curbin.vdc_whole + curbin.vdc_fraction
1456                                  : curbin.real_whole + curbin.real_fraction);
1457       prec = (prec == 64 ? 12 : 9);
1458       f = ( neg ? -x : x );
1459
1460       if ( f < (Double)(real_or_vdc == VDC ? cur.vdcmin : cur.realmin) )
1461       {
1462          exponent = ZERO;
1463          fract = ZERO;
1464       }
1465       else
1466       {
1467
1468 /*  check if greater than smallest exponent  */
1469
1470          exponent = ( prec == 12 ? 1023 : 127 );
1471
1472          if ( f <= 1.0 / (Double) (prec-1) )
1473          {
1474             exponent = ZERO;
1475          }
1476          else
1477          {
1478             while ( f >= 2.0 )
1479             {
1480                f /= 2.0;
1481                exponent++;
1482             }
1483             while ( f < 1.0 )
1484             {
1485                f *= 2.0;
1486                exponent--;
1487             }
1488          }
1489          fract = (Long) ( (f - 1.0) * (Double)(1L<<(prec == 12 ? 52 : 23)) );
1490       }
1491
1492 #if defined(_LP64)
1493       if ( prec == 12 )
1494       {
1495          PUTWORD( (exponent<<4) | neg | (fract>>48) );
1496          PUTWORD( (fract >> 32) & (Posint)0xffff );
1497          PUTWORD( (fract >> 16) & (Posint)0xffff );
1498          PUTWORD( fract & (Posint)0xffff );
1499       }
1500       else
1501 #endif
1502       {
1503          PUTWORD( (exponent<<7) | neg | (fract>>16) );
1504          PUTWORD( fract & (Posint)0xffff );
1505       }
1506    }
1507    return;
1508 }
1509
1510 /******************************************************** MOBstring ****/
1511 static void
1512 MOBstring( char *s )
1513 {
1514 /*  Output a text string if CMS translate from EBCDIC to ASCII  */
1515
1516    register Int i, len, slen = strlen(s);
1517    register char chr;
1518    len = slen;
1519    do
1520    {
1521       PUTBYTE ( len >= 0xff ? 0xff : len );
1522       len -= 0xff;
1523    } while ( len >= 0 );
1524
1525    for (i = 0; i < slen; i++)
1526    {
1527    chr = *s++;
1528    PUTBYTE ( chr );
1529    }
1530 return;
1531 }
1532
1533 /******************************************************** MOBclist *****/
1534 static void
1535 MOBclist( register Long num, register Long *col,
1536           Prec mode, Enum type, Prec prec )
1537 {
1538 /*  Output a colour list */
1539
1540    register Long j, k, n;
1541    Long bits, bytes = 0;
1542    if ( type == RUNLENGTH )
1543    {
1544       Long run = 1, bit = 0;
1545
1546       if ( mode == DIRECT )
1547       {
1548          Posint red, green, blue, lastred, lastgreen, lastblue;
1549
1550          lastred = (*col++);
1551          lastgreen = (*col++);
1552          lastblue = (*col++);
1553          for ( j = 1; j <= num; j++ )
1554          {
1555             red = (*col++); green = (*col++); blue = (*col++);
1556             if ( j == num ||
1557                  red != lastred || green != lastgreen || blue != lastblue )
1558             {
1559                MOBbits ( run, curbin.int_prec, &bit );
1560                MOBbits ( lastred, prec, &bit );
1561                MOBbits ( lastgreen, prec, &bit );
1562                MOBbits ( lastblue, prec, &bit );
1563                if ( j == num ) break;
1564                lastred = red; lastgreen = green; lastblue = blue;
1565                run = 1;
1566             }
1567             else run++;
1568          }
1569       }
1570       else   /* Indexed runlength */
1571       {
1572          Long lastcol;
1573
1574          lastcol = (*col++);
1575          for ( j = 1; j <= num; j++, col++ )
1576          {
1577             if ( j == num || *col != lastcol )
1578             {
1579                MOBbits ( run, curbin.int_prec, &bit );
1580                MOBbits ( lastcol, prec, &bit );
1581                if ( j == num ) break;
1582                lastcol = *col;
1583                run = 1;
1584             }
1585             else run++;
1586          }
1587       }
1588
1589 /* make sure list ends on a word boundary */
1590
1591       if ( bit ) MOBbits ( (Posint) 0 , (Prec) 16, &bit );
1592
1593    }
1594    else   /* Packed mode */
1595    {
1596       n = ( mode == DIRECT ? 3*num : num );
1597       bytes = ( n*prec + 7 ) >>3;
1598
1599       for ( j = 0, bits = 0, k = 0; j < n; j++)
1600       {
1601          if ( bits ) k <<= prec;
1602          else        k = 0;
1603          k += (*col++);
1604          bits += prec;
1605
1606          while ( bits >= 8 )
1607          {
1608             bits -= 8;
1609             PUTBYTE ( (k>>bits) & 0xff );
1610          }
1611       }
1612       if ( bits > 0 ) PUTBYTE ( k<<(8-bits) );
1613
1614 /* Pad buffer if necessary */
1615       if ( bytes & 1 ) PUTBYTE ( 0 );
1616    }
1617    return;
1618 }
1619
1620 /******************************************************** MOBbits ******/
1621 static void
1622 MOBbits ( Posint value, Prec prec, Long *bit )
1623 {
1624 /*  Output 'value' as 'prec' bits
1625     using 'word' to hold current value
1626     returns number of bits left in 'bits'  */
1627
1628    static Posint oneword = 0;
1629    Posint mask = (Posint)0xffffffff;
1630    *bit += prec;
1631    if ( *bit <= 16 )
1632    {
1633       oneword |= value<<(16 - *bit);
1634    }
1635    else
1636    {
1637       while ( *bit > 16 )
1638       {
1639          *bit -= 16;
1640 /*       k = prec + *bit - 16; */
1641          oneword |= value>>*bit;
1642          value &= mask>>(32 - *bit);
1643          MOBout ( oneword, WORD );
1644          oneword = value<<16;
1645       }
1646       oneword = value<<(16 - *bit);
1647    }
1648    return;
1649 }
1650
1651 /******************************************************** MOBout *******/
1652 static void
1653 MOBout( Posint hex, Prec bytes )
1654 {
1655 /*  Output 'hex' as 'bytes' bytes to output file 'cgmob'
1656     which is either the file or MF defaults buffer */
1657
1658    register Int /*i,*/ b_len;
1659    b_len = bytes;
1660    mobindex = ZERO;
1661    if ( bytes > 0 ) for( ; bytes ; mobindex++ )
1662    {
1663       bytes--;
1664       mobbuff[mobindex] = (char)((hex >> (8*bytes) ) & 0xff);
1665       mobparmlen--;
1666    }
1667    fwrite(mobbuff,b_len,(size_t)1,cgmob);
1668 /*
1669 start:
1670    if ( bytes > 0 ) for( ; bytes ; mobindex++ )
1671    {
1672       if ( mobindex == mobblen )
1673       {
1674          if ( cgmstate != MF_DEFAULTS )
1675          {
1676             fwrite(mobbuff,mobblen,(size_t)1,cgmob);
1677             mobindex=ZERO;
1678          }
1679          else
1680          {
1681             mobblen += BUFF_LEN;
1682             mobbuff = (char *)realloc (mobbuff, (size_t)mobblen);
1683          }
1684       }
1685       if ( mobindex == ZERO )
1686       {
1687          for(i = ZERO; i < mobblen ; i++) mobbuff[i] = '\0';
1688       }
1689       bytes--;
1690       mobbuff[mobindex] = ( hex>>(8*bytes) ) & 0xff;
1691       mobparmlen--;
1692    }
1693    else
1694    {
1695       fwrite(mobbuff,BUFF_LEN,(size_t)1,cgmob);
1696       mobindex = ZERO;
1697    }
1698    fflush(cgmob);
1699    if ( mobremainder && mobparmlen == 0 )
1700    {
1701       if ( mobremainder > 0x7ffe )
1702       {
1703          hex = 0xfffe;
1704          mobremainder -= 0x7ffe;
1705       }
1706       else
1707       {
1708          hex = mobremainder;
1709          mobremainder = 0;
1710       }
1711       mobparmlen = hex & 0x7fff;
1712       bytes = 2;
1713       mobparmlen += 2;
1714       goto start;
1715    }
1716 */
1717    return;
1718 }