Integration of OCCT 6.5.0 from SVN
[occt.git] / src / CGM / cgmobin.c
CommitLineData
7fd59977 1#include <limits.h>
2#include "cgmout.h"
3
4/* File stream name */
5
6static 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 */
11void CGMObin(FILE *stream, Code c, Long *pi, Float *pr, char *str);
12/* Main Output Routine */
13static 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
26void CGMObin(); /* Main Output Routine */
27static 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
85static 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 */
90static 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];*/
95static char mess[40];
96
97/********************************************************* CGMObin *****/
98void
99CGMObin(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
1199static void
1200MOBopcode( 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 ****/
1244static void
1245MOBcharci( 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 *******/
1348static void
1349MOBint( 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 ****/
1360static void
1361MOBcolour( 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 *******/
1379static void
1380MOBvdc( 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 */
1399static void
1400MOBpointlist(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 ******/
1422static void
1423MOBreal(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 ****/
1511static void
1512MOBstring( 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 }
1530return;
1531}
1532
1533/******************************************************** MOBclist *****/
1534static void
1535MOBclist( 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 ******/
1621static void
1622MOBbits ( 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 *******/
1652static void
1653MOBout( 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/*
1669start:
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}