1 /* save.c */
2 /* COPYRIGHT (C) 2000 THE VICTORIA UNIVERSITY OF MANCHESTER and John Levon
3 * This program is free software; you can redistribute it and/or modify it
4 * under the terms of the GNU General Public License as published by the Free
5 * Software Foundation; either version 2 of the License, or (at your option)
6 * any later version.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15 * Place - Suite 330, Boston, MA 02111-1307, USA.
16 */
17 /* Saving of fig file */
18 /*
19 * $Log: save.c,v $
20 * Revision 1.6 2001/01/31 15:38:06 movement
21 * pre11 - fix netscape, add metapost support, credit foggy
22 *
23 * Revision 1.6 2001/01/29 20:57:28 moz
24 * Make netscape work again, metapost support.
25 *
26 * Revision 1.5 2000/12/17 00:57:42 moz
27 * examples, filled open splines, highlight_objects
28 *
29 * Revision 1.4 2000/12/08 22:33:34 moz
30 * Clean up possibly unsafe tmp file handling.
31 *
32 * Revision 1.3 2000/12/06 20:56:04 moz
33 * GPL stuff.
34 *
35 * Revision 1.2 2000/09/05 00:54:51 moz
36 * Make system() calls secure.
37 *
38 * Revision 1.1.1.1 2000/08/21 01:05:31 moz
39 *
40 *
41 * Revision 1.1.1.1 2000/07/19 22:45:30 moz
42 * CVS Import
43 *
44 * Revision 1.26 2000/03/12 04:14:20 moz
45 * Save out node ellipse derries.
46 *
47 * Revision 1.25 2000/03/07 21:46:48 moz
48 * Compile fixes.
49 *
50 * Revision 1.24 2000/03/04 17:16:01 moz
51 * Fix for pre7 unfilled breakage.
52 *
53 * Revision 1.23 2000/02/27 15:20:21 moz
54 * shades.fig now works as xfig.
55 *
56 * Revision 1.22 2000/02/27 14:34:29 moz
57 * Fixed most fillcolour problems with tints and shades.
58 *
59 * Revision 1.21 2000/02/22 22:55:37 moz
60 * Merged export.c
61 * Fixed node text positioning bug.
62 *
63 * Revision 1.20 2000/02/18 21:19:05 moz
64 * polyline.pic usage changed.
65 *
66 * Revision 1.19 2000/01/29 21:01:38 moz
67 * Initialise strings.
68 *
69 * Revision 1.18 1999/11/15 02:04:54 moz
70 * Use rounded trig.
71 * Position multi-line rotated text correctly.
72 * Don't create empty text objects.
73 *
74 * Revision 1.17 1999/08/08 20:55:10 moz
75 * From clean up of structs.
76 *
77 * Revision 1.16 1999/06/17 19:09:37 moz
78 * Save out attachment information.
79 *
80 * Revision 1.15 1999/05/24 17:29:24 moz
81 * If an object is in a compound, use compound's depth.
82 *
83 * Revision 1.14 1999/05/22 23:39:27 moz
84 * Pedantic ANSI.
85 *
86 * Revision 1.13 1999/05/22 02:52:16 moz
87 * Escape on next text sections as well.
88 *
89 * Revision 1.12 1999/05/22 02:49:34 moz
90 * Escape out backslashes and the like.
91 *
92 * Revision 1.11 1999/05/19 17:08:16 moz
93 * 1.0 Checkin.
94 *
95 * Revision 1.10 1999/05/04 14:40:27 moz
96 * Switch arc arrows correctly.
97 *
98 * Revision 1.9 1999/04/29 01:34:55 moz
99 * Save the correct x,y value for the text.
100 *
101 * Revision 1.8 1999/04/27 16:56:04 moz
102 * Flip text angle before saving.
103 *
104 * Revision 1.7 1999/04/27 04:11:57 moz
105 * -Wall appeasement
106 *
107 * Revision 1.6 1999/04/24 22:35:09 moz
108 * Save out user-defined colours.
109 *
110 * Revision 1.5 1999/04/23 20:40:27 moz
111 * Append similar text to output.
112 *
113 * Revision 1.4 1999/04/23 20:21:21 moz
114 * 2 is the value for special LaTeX text.
115 *
116 * Revision 1.3 1999/04/21 18:03:51 moz
117 * Fixes for fitting midpoint of arc.
118 *
119 * Revision 1.2 1999/04/12 19:05:47 moz
120 * Various fixes for fig2dev.
121 *
122 * Revision 1.1 1999/03/30 00:05:58 moz
123 * Initial revision
124 *
125 */
126
127 #include <sys/types.h>
128 #include <sys/stat.h>
129 #include <fcntl.h>
130 #include <math.h>
131
132 #include "include/figurine.h"
133 #include "include/extern.h"
134
135 /* see the file Doc/FORMAT3.2 for a description of the file format */
136
137 static FILE *fl=NULL;
138 static Document *doc;
139 static Object *incompoundob=NULL;
140 /* these are used for aligning pic with top right on export */
141 static long minx;
142 static long miny;
143
144 void
linestyle_out(int ls)145 linestyle_out(int ls)
146 {
147 fprintf(fl,"%d ",ls);
148 }
149
150 void
colour_out(int col)151 colour_out(int col)
152 {
153 fprintf(fl,"%d ",col-STARTOFCOLOURS);
154 }
155
156 void
fillcolour_out(Object * ob)157 fillcolour_out(Object *ob)
158 {
159 if (ob->fs>0 && ob->fs<20 && (ob->fillcolour==FILLCWHITE || ob->fillcolour==FILLCBLACK))
160 fprintf(fl,"%d ",ob->colour-STARTOFCOLOURS);
161 else
162 fprintf(fl,"%d ",ob->fillcolour-STARTOFFILLCOLOURS);
163 }
164
165 void
depth_out(ulong depth)166 depth_out(ulong depth)
167 {
168 /* must convert into FIG3.2 0-999 depth and account for compounds */
169 if (incompoundob==NULL)
170 fprintf(fl,"%d ",(int)(max(ULONG_MAX-999,depth)-(ULONG_MAX-999)));
171 else
172 fprintf(fl,"%d ",(int)(max(ULONG_MAX-999,incompoundob->depth)-(ULONG_MAX-999)));
173 }
174
175 void
fillstyle_out(Object * ob)176 fillstyle_out(Object *ob)
177 {
178 if (ob->fs>0 && ob->fs<20)
179 {
180 if (ob->fillcolour==FILLCWHITE)
181 {
182 if (ob->colour==CBLACK)
183 fprintf(fl,"%d ",ob->fs);
184 else
185 fprintf(fl,"%d ",(20-ob->fs)+20);
186 }
187 else
188 fprintf(fl,"%d ",20-ob->fs);
189 }
190 else
191 {
192 if (ob->fs==SOLID)
193 fprintf(fl,"20 ");
194 else if (ob->fs==20)
195 fprintf(fl,"0 ");
196 else if (ob->fs==-1)
197 fprintf(fl,"-1 ");
198 else
199 fprintf(fl,"%d ",ob->fs+20);
200 };
201 }
202
203 void
joinstyle_out(int js)204 joinstyle_out(int js)
205 {
206 switch (js)
207 {
208 case JoinRound:
209 fprintf(fl,"2 ");
210 break;
211
212 case JoinBevel:
213 fprintf(fl,"1 ");
214 break;
215
216 case JoinMiter:
217 fprintf(fl,"0 ");
218 break;
219 };
220 }
221
222 void
capstyle_out(int es)223 capstyle_out(int es)
224 {
225 switch (es)
226 {
227 case CapButt:
228 fprintf(fl,"0 ");
229 break;
230
231 case CapRound:
232 fprintf(fl,"1 ");
233 break;
234
235 case CapProjecting:
236 fprintf(fl,"2 ");
237 break;
238 };
239 }
240
241 void
arrow_out(Arrow * arrow)242 arrow_out(Arrow *arrow)
243 {
244 if (arrow==NULL)
245 return;
246
247 fprintf(fl, "%d %d %f %f %f\n",arrow->type,arrow->filled,(double)arrow->lw,(arrow->w/80.0)*doc->ppi,(arrow->h/80.0)*doc->ppi);
248 }
249
250 void
derry_out(Object * ob)251 derry_out(Object *ob)
252 {
253 List l;
254 Object *dob;
255
256 l = ob->derries;
257 while (l!=NULL)
258 {
259 dob = get_object_by_ticket(doc->o,DERRY(l)->ticket);
260 if (dob!=NULL)
261 fprintf(fl,"###FIGURINE DERRY %p %ld %ld\n",dob,DERRY(l)->point->x+dob->bbox.x1,DERRY(l)->point->y+dob->bbox.y1);
262
263 l = l->next;
264 };
265 }
266
267 void
derry_check(Object * ob)268 derry_check(Object *ob)
269 {
270 List l;
271
272 if (ob->type==SPLINE || ob->type==ARC)
273 l = ob->ob.spline.points;
274 else
275 l = ob->ob.polyline.points;
276
277 while (l!=NULL)
278 {
279 if (POINT(l)->derried)
280 fprintf(fl,"###FIGURINE DERRY_SOURCE %p %ld %ld\n",ob,POINT(l)->x+ob->bbox.x1,POINT(l)->y+ob->bbox.y1);
281
282 l=l->next;
283 };
284
285 }
286
287 void
polyline_out(Object * ob)288 polyline_out(Object *ob)
289 {
290 List l;
291 int c=0;
292
293 fprintf(fl,"2 1 ");
294 linestyle_out((int)ob->ls);
295 fprintf(fl,"%d ",ob->lw);
296 colour_out((int)ob->colour);
297 fillcolour_out(ob);
298 depth_out(ob->depth);
299 fprintf(fl,"-1 -1 ");
300 fprintf(fl,"8.000 ");
301 joinstyle_out(ob->js);
302 capstyle_out(ob->es);
303 fprintf(fl,"0 ");
304 fprintf(fl,"%d ",ob->farrow!=NULL);
305 fprintf(fl,"%d ",ob->barrow!=NULL);
306
307 l = ob->ob.polyline.points;
308
309 while (l!=NULL)
310 {
311 c++;
312 l = l->next;
313 };
314
315 fprintf(fl,"%d\n",c);
316 arrow_out(ob->farrow);
317 arrow_out(ob->barrow);
318
319 l = ob->ob.polyline.points;
320
321 fprintf(fl,"\t");
322 while (l!=NULL)
323 {
324 fprintf(fl," %ld %ld", (POINT(l)->x+ob->bbox.x1)-minx, (POINT(l)->y+ob->bbox.y1)-miny);
325 l = l->next;
326 };
327
328 fprintf(fl,"\n");
329
330 if (ob->derries!=NULL)
331 derry_out(ob);
332
333 derry_check(ob);
334
335 }
336
337 void
spline_out(Object * ob)338 spline_out(Object *ob)
339 {
340 List l;
341 int c=0;
342
343 fprintf(fl,"3 ");
344 if (ob->ob.spline.closed)
345 fprintf(fl,"5 ");
346 else
347 fprintf(fl,"4 ");
348 linestyle_out((int)ob->ls);
349 fprintf(fl,"%d ",ob->lw);
350 colour_out((int)ob->colour);
351 fillcolour_out(ob);
352 depth_out(ob->depth);
353 fprintf(fl,"-1 ");
354 fillstyle_out(ob);
355 fprintf(fl,"8.000 ");
356 capstyle_out(ob->es);
357 fprintf(fl,"%d ",ob->farrow!=NULL);
358 fprintf(fl,"%d ",ob->barrow!=NULL);
359
360 l = ob->ob.polyline.points;
361
362 while (l!=NULL)
363 {
364 c++;
365 l = l->next;
366 };
367
368 fprintf(fl,"%d\n",c);
369 arrow_out(ob->farrow);
370 arrow_out(ob->barrow);
371
372 l = ob->ob.spline.points;
373
374 fprintf(fl,"\t");
375 while (l!=NULL)
376 {
377 fprintf(fl," %ld %ld", (SPOINT(l)->x+ob->bbox.x1)-minx, (SPOINT(l)->y+ob->bbox.y1)-miny);
378 l = l->next;
379 };
380
381 fprintf(fl,"\n");
382
383 l = ob->ob.spline.points;
384 while (l!=NULL)
385 {
386 fprintf(fl," %f", SPOINT(l)->s);
387 l = l->next;
388 };
389
390 fprintf(fl,"\n");
391
392 if (ob->derries!=NULL)
393 derry_out(ob);
394
395 derry_check(ob);
396
397 }
398
399 void
polygon_out(Object * ob)400 polygon_out(Object *ob)
401 {
402 List l;
403 int c=0;
404 int subtype;
405
406 fprintf(fl,"2 ");
407 if (ob->ob.polyline.pic)
408 subtype = 5;
409 else
410 subtype = 3;
411 fprintf(fl,"%d ",subtype);
412 linestyle_out((int)ob->ls);
413 fprintf(fl,"%d ",ob->lw);
414 colour_out((int)ob->colour);
415 fillcolour_out(ob);
416 depth_out(ob->depth);
417 fprintf(fl,"-1 ");
418 fillstyle_out(ob);
419 fprintf(fl,"8.000 ");
420 joinstyle_out(ob->js);
421 capstyle_out(ob->es);
422 fprintf(fl,"0 0 0 ");
423
424 l = ob->ob.polyline.points;
425
426 while (l!=NULL)
427 {
428 c++;
429 l = l->next;
430 };
431
432 if (subtype==5) /* picture */
433 {
434 fprintf(fl,"%d\n",c);
435 fprintf(fl,"0 %s\n",ob->ob.polyline.pic);
436 }
437 else
438 fprintf(fl,"%d\n",c+1);
439
440 l = ob->ob.polyline.points;
441
442 fprintf(fl,"\t");
443 while (l!=NULL)
444 {
445 fprintf(fl," %ld %ld", (POINT(l)->x+ob->bbox.x1)-minx, (POINT(l)->y+ob->bbox.y1)-miny);
446 l = l->next;
447 };
448
449 if (subtype==3)
450 fprintf(fl," %ld %ld", (POINT(ob->ob.polyline.points)->x+ob->bbox.x1)-minx,
451 (POINT(ob->ob.polyline.points)->y+ob->bbox.y1)-miny);
452
453 fprintf(fl,"\n");
454
455 if (ob->derries!=NULL)
456 derry_out(ob);
457
458 derry_check(ob);
459
460 }
461
462 void
roundbox_out(Object * ob)463 roundbox_out(Object *ob)
464 {
465 fprintf(fl,"2 4 ");
466 linestyle_out((int)ob->ls);
467 fprintf(fl,"%d ",ob->lw);
468 colour_out((int)ob->colour);
469 fillcolour_out(ob);
470 depth_out(ob->depth);
471 fprintf(fl,"-1 ");
472 fillstyle_out(ob);
473 fprintf(fl,"8.000 ");
474 joinstyle_out(ob->js);
475 capstyle_out(ob->es);
476 fprintf(fl,"%d ",ob->ob.roundbox.radius);
477 fprintf(fl,"0 0 ");
478
479 fprintf(fl,"5\n");
480 fprintf(fl,"%ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n",
481 ob->bbox.x1-minx, ob->bbox.y1-miny,
482 ob->bbox.x2-minx, ob->bbox.y1-miny,
483 ob->bbox.x2-minx, ob->bbox.y2-miny,
484 ob->bbox.x1-minx, ob->bbox.y2-miny,
485 ob->bbox.x1-minx, ob->bbox.y1-miny);
486 }
487
488 void
ellipse_out(Object * ob)489 ellipse_out(Object *ob)
490 {
491 fprintf(fl,"1 1 ");
492 linestyle_out((int)ob->ls);
493 fprintf(fl,"%d ",ob->lw);
494 colour_out((int)ob->colour);
495 fillcolour_out(ob);
496 depth_out(ob->depth);
497 fprintf(fl,"-1 ");
498 fillstyle_out(ob);
499 fprintf(fl,"8.000 1 0.000 ");
500 fprintf(fl,"%ld %ld %ld %ld ", (ob->ob.ellipse.centre.x+ob->bbox.x1)-minx, (ob->ob.ellipse.centre.y+ob->bbox.y1)-miny,
501 ob->ob.ellipse.xradius, ob->ob.ellipse.yradius);
502 fprintf(fl,"%ld %ld %ld %ld\n",
503 (ob->ob.ellipse.centre.x+ob->bbox.x1+ob->ob.ellipse.xradius)-minx,
504 (ob->ob.ellipse.centre.y+ob->bbox.y1+ob->ob.ellipse.yradius)-miny,
505 (ob->ob.ellipse.centre.x+ob->bbox.x1+ob->ob.ellipse.xradius)-minx,
506 (ob->ob.ellipse.centre.y+ob->bbox.y1+ob->ob.ellipse.yradius)-miny);
507
508 if (ob->derries!=NULL)
509 derry_out(ob);
510
511 }
512
513 void
arcellipse_out(Object * ob)514 arcellipse_out(Object *ob)
515 {
516 double start,mid,end;
517 long mx,my;
518
519 fprintf(fl,"5 ");
520 if (ob->ob.arcellipse.open)
521 fprintf(fl, "1 ");
522 else
523 fprintf(fl, "2 ");
524 linestyle_out((int)ob->ls);
525 fprintf(fl,"%d ",ob->lw);
526 colour_out((int)ob->colour);
527 fillcolour_out(ob);
528 depth_out(ob->depth);
529 fprintf(fl,"-1 ");
530 if (ob->ob.arcellipse.open)
531 fprintf(fl,"-1 ");
532 else
533 fillstyle_out(ob);
534 fprintf(fl,"8.000 ");
535 capstyle_out(ob->es);
536 fprintf(fl,"0 ");
537 fprintf(fl,"%d ",ob->farrow!=NULL);
538 fprintf(fl,"%d ",ob->barrow!=NULL);
539 fprintf(fl,"%f %f ", (double)(ob->ob.arcellipse.centre.x+ob->bbox.x1)-minx,
540 (double)(ob->ob.arcellipse.centre.x+ob->bbox.y1)-miny);
541 start = (ob->ob.arcellipse.start/64.0)*(PI/180.0);
542 end = (ob->ob.arcellipse.end/64.0)*(PI/180.0);
543 mid = ((end-start)/2.0)+start;
544 mx = (ob->bbox.x1 + (ob->bbox.x2-ob->bbox.x1)/2)-minx;
545 my = (ob->bbox.y1 + (ob->bbox.y2-ob->bbox.y1)/2)-miny;
546 /* we do min & max on start/end to ensure the correct direction of sweep in xfig */
547 fprintf(fl,"%ld ", (long)(mx+ob->ob.arcellipse.xradius*cosround(max(start,end))));
548 fprintf(fl,"%ld ", (long)(my-ob->ob.arcellipse.yradius*sinround(max(start,end))));
549 fprintf(fl,"%ld ", (long)(mx+ob->ob.arcellipse.xradius*cosround(mid)));
550 fprintf(fl,"%ld ", (long)(my-ob->ob.arcellipse.yradius*sinround(mid)));
551 fprintf(fl,"%ld ", (long)(mx+ob->ob.arcellipse.xradius*cosround(min(start,end))));
552 fprintf(fl,"%ld\n",(long)(my-ob->ob.arcellipse.yradius*sinround(min(start,end))));
553 /* these are also switched */
554 arrow_out(ob->barrow);
555 arrow_out(ob->farrow);
556
557 if (ob->derries!=NULL)
558 derry_out(ob);
559
560 }
561
562 void
font_out(int num)563 font_out(int num)
564 {
565 if (num<=34)
566 fprintf(fl,"%d ",num);
567 else
568 fprintf(fl,"%d ",num-34);
569 }
570
571 void
text_out(Object * ob)572 text_out(Object *ob)
573 {
574 List l,l2,l3;
575 VFont *vf;
576 unsigned char *c;
577 long x,y,h;
578
579
580 if (ob->ob.text.node)
581 {
582 Object *eob=ob->ob.text.ellipse;
583 fprintf(fl,"1 1 ");
584 linestyle_out((int)eob->ls);
585 fprintf(fl,"%d ",eob->lw);
586 colour_out((int)eob->colour);
587 fillcolour_out(eob);
588 depth_out(eob->depth);
589 fprintf(fl,"-1 ");
590 fillstyle_out(eob);
591 fprintf(fl,"8.000 1 0.000 ");
592 fprintf(fl,"%ld %ld %ld %ld ", (ob->bbox.x1-minx)+(ob->bbox.x2-ob->bbox.x1)/2,
593 (ob->bbox.y1-miny)+(ob->bbox.y2-ob->bbox.y1)/2,
594 (ob->bbox.x2-ob->bbox.x1)/2,(ob->bbox.y2-ob->bbox.y1)/2);
595 fprintf(fl,"%ld %ld %ld %ld\n",
596 ((ob->bbox.x1-minx)+(ob->bbox.x2-ob->bbox.x1)/2)+(ob->bbox.x2-ob->bbox.x1)/2,
597 ((ob->bbox.y1-miny)+(ob->bbox.y2-ob->bbox.y1)/2)+(ob->bbox.y2-ob->bbox.y1)/2,
598 ((ob->bbox.x1-minx)+(ob->bbox.x2-ob->bbox.x1)/2)+(ob->bbox.x2-ob->bbox.x1)/2,
599 ((ob->bbox.y1-miny)+(ob->bbox.y2-ob->bbox.y1)/2)+(ob->bbox.y2-ob->bbox.y1)/2);
600 if (eob->derries)
601 derry_out(eob);
602 };
603
604 l = ob->ob.text.lines;
605
606 while (l!=NULL)
607 {
608 l2 = TEXTLINE(l)->sections;
609
610 while (l2!=NULL)
611 {
612
613 /* check whether the text is empty (can happen still, but shouldn't) */
614 if (streq(TEXTSEC(l2)->text,""))
615 {
616 l2=l2->next;
617 continue;
618 };
619
620 fprintf(fl,"4 0 ");
621 colour_out((int)ob->colour);
622 depth_out(ob->depth);
623 fprintf(fl,"-1 ");
624 font_out(TEXTSEC(l2)->num);
625 fprintf(fl,"%lu ", (ulong)TEXTSEC(l2)->size);
626 fprintf(fl,"%f ", flip_angle_y(ob->ob.text.angle));
627 if (TEXTSEC(l2)->num>34)
628 fprintf(fl,"2 ");
629 else
630 fprintf(fl,"4 ");
631 fprintf(fl,"%lu ",(ulong)TEXTLINE(l)->h);
632 fprintf(fl,"%lu ",(ulong)TEXTSEC(l2)->w);
633 l3 = doc->views;
634 while ((vf = get_font(TEXTSEC(l2)->num,ZPO(TEXTSEC(l2)->size,VIEW(l3))))==NULL && l!=NULL)
635 l3 = l3->next;
636
637 if (vf==NULL)
638 h = TEXTLINE(l)->y+TEXTLINE(l)->h;
639 else
640 h = TEXTLINE(l)->y+P2D(vf->x->max_bounds.ascent, VIEW(l3));
641
642 if (ob->ob.text.angle!=0.0)
643 {
644 double sina, cosa;
645 long cx,cy;
646
647 sina = sinround(ob->ob.text.angle);
648 cosa = cosround(ob->ob.text.angle);
649
650 cx = (ob->ob.text.bbox.x2-ob->ob.text.bbox.x1)/2;
651 cy = (ob->ob.text.bbox.y2-ob->ob.text.bbox.y1)/2;
652
653 x = ob->bbox.x1 + (ob->ob.text.bbox.x1-ob->bbox.x1) + cx
654 + (cosa*(TEXTSEC(l2)->x-cx)) - (sina*(h-cy));
655
656 y = ob->bbox.y1 + (ob->ob.text.bbox.y1-ob->bbox.y1) + cy
657 + (sina*(TEXTSEC(l2)->x-cx)) + (cosa*(h-cy));
658
659 }
660 else
661 {
662 x = (ob->bbox.x1)+TEXTSEC(l2)->x;
663 y = (ob->bbox.y1) + h;
664 };
665
666 if (ob->ob.text.node)
667 fprintf(fl,"%ld %ld ", x+((ob->bbox.x2-ob->bbox.x1)/2)-(ob->ob.text.bbox.x1-ob->bbox.x1)-minx,
668 y+((ob->bbox.y2-ob->bbox.y1)/2)-(ob->ob.text.bbox.y1-ob->bbox.y1)-miny);
669 else
670 fprintf(fl,"%ld %ld ", x-minx, y-miny);
671
672 c = (unsigned char *)TEXTSEC(l2)->text;
673 while (*c!='\0')
674 {
675 if (*c=='\\') /* escape a backslash */
676 fprintf(fl,"%s", "\\\\");
677 else if (*c>127) /* 8-bit ASCII */
678 fprintf(fl,"\\%o", *c);
679 else
680 fprintf(fl,"%c", *c);
681 c++;
682 };
683
684 /* if next section is same font, append to this line */
685 while (l2->next!=NULL && TEXTSEC(l2->next)->num==TEXTSEC(l2)->num && TEXTSEC(l2->next)->size==TEXTSEC(l2)->size)
686 {
687 c = (unsigned char *)TEXTSEC(l2->next)->text;
688 while (*c!='\0')
689 {
690 if (*c=='\\') /* escape a backslash */
691 fprintf(fl,"%s", "\\\\");
692 else if (*c>127) /* 8-bit ASCII */
693 fprintf(fl,"\\%o", *c);
694 else
695 fprintf(fl,"%c", *c);
696 c++;
697 };
698 l2 = l2->next;
699 };
700
701 /* delimiter */
702 fprintf(fl,"\\001\n");
703
704 l2 = l2->next;
705 };
706 l = l->next;
707 };
708 }
709
710 void
compound_out(Object * ob)711 compound_out(Object *ob)
712 {
713 List l;
714
715 fprintf(fl,"6 %ld %ld %ld %ld\n",ob->bbox.x1-minx,ob->bbox.y1-miny,ob->bbox.x2-minx,ob->bbox.y2-miny);
716
717
718 l = ob->ob.compound.obs;
719 incompoundob = ob;
720
721 while (l!=NULL)
722 {
723 switch (OB(l)->type)
724 {
725 case POLYLINE:
726 polyline_out(OB(l));
727 break;
728
729 case SPLINE:
730 case ARC:
731 spline_out(OB(l));
732 break;
733
734 case POLYGON:
735 polygon_out(OB(l));
736 break;
737
738 case ROUNDBOX:
739 roundbox_out(OB(l));
740 break;
741
742 case ELLIPSE:
743 ellipse_out(OB(l));
744 break;
745
746 case ARCELLIPSE:
747 arcellipse_out(OB(l));
748 break;
749
750 case TEXT:
751 text_out(OB(l));
752 break;
753
754 case COMPOUND:
755 compound_out(OB(l));
756 break;
757
758 default:
759 v_error(OB(l)->type);
760 break;
761 };
762 l = l->next;
763 };
764
765 incompoundob=NULL;
766
767 /* delimiter */
768 fprintf(fl,"-6\n");
769
770 }
771
772 void
save(Document * d)773 save(Document *d)
774 {
775 char file[FIGURINE_PATH_MAX]="";
776 strncpy(file,d->pathname,FIGURINE_PATH_MAX/2);
777 strncat(file,d->filename,FIGURINE_PATH_MAX/2);
778
779 save_name(d,file);
780 }
781
782 void
save_name(Document * d,char * file)783 save_name(Document *d,char *file)
784 {
785 List l;
786 char s[FIGURINE_PATH_MAX]="";
787
788
789 fl = fopen(file,"w");
790
791 if (fl==NULL)
792 {
793 strcpy(s,"File ");
794 strncat(s,file,FIGURINE_PATH_MAX-40);
795 strcat(s," could not be opened for writing.");
796 stk_open_info(s);
797 return;
798 };
799
800 doc = d;
801
802 /* don't shift on save */
803 minx=0;
804 miny=0;
805
806 fprintf(fl,"#FIG 3.2\n");
807 if (doc->landscape)
808 fprintf(fl,"Landscape\n");
809 else
810 fprintf(fl,"Portrait\n");
811 if (doc->centred)
812 fprintf(fl,"Center\n");
813 else
814 fprintf(fl,"Flush Left\n");
815 fprintf(fl,"Inches\n");
816 /* *sigh* two spaces to handle fig2dev 3.2.3 bug */
817 fprintf(fl,"%s \n",doc->canvas_name);
818 fprintf(fl,"100.00\n");
819 if (doc->mpage)
820 fprintf(fl,"Multiple\n");
821 else
822 fprintf(fl,"Single\n");
823 fprintf(fl,"%d\n",doc->transcolour);
824 fprintf(fl,"%ld 2\n",(long)doc->ppi);
825
826 /* output user-defined colours */
827 l = doc->cols;
828 while (l!=NULL)
829 {
830 fprintf(fl,"0 %ld %s\n",UCOLOUR(l)->tag,UCOLOUR(l)->name);
831 l=l->next;
832 };
833
834 l = doc->lo;
835
836 while (l!=NULL)
837 {
838 switch (l->type)
839 {
840 case POLYLINE:
841 polyline_out(OB(l));
842 break;
843
844 case SPLINE:
845 case ARC:
846 spline_out(OB(l));
847 break;
848
849 case POLYGON:
850 polygon_out(OB(l));
851 break;
852
853 case ROUNDBOX:
854 roundbox_out(OB(l));
855 break;
856
857 case ELLIPSE:
858 ellipse_out(OB(l));
859 break;
860
861 case ARCELLIPSE:
862 arcellipse_out(OB(l));
863 break;
864
865 case TEXT:
866 text_out(OB(l));
867 break;
868
869 case COMPOUND:
870 compound_out(OB(l));
871 break;
872
873 default:
874 v_error((int)l->type);
875 break;
876 };
877 l = l->next;
878 };
879
880
881 fclose(fl);
882 }
883
get_tmpfile(char ** name)884 static FILE *get_tmpfile(char **name)
885 {
886 int fd;
887
888 do {
889 *name = tempnam(NULL, "foo");
890 fd = open(*name, O_CREAT | O_EXCL | O_TRUNC | O_RDWR, 0600);
891 } while (fd == -1);
892
893 return fdopen(fd, "w");
894 }
895
896 int fig2dev_version(void);
897
898 /* we need to do this to work round command format breakage in 3.2.3 */
fig2dev_version()899 int fig2dev_version()
900 {
901 char *tfile;
902 char *tfile2;
903 char s[FIGURINE_PATH_MAX]="";
904 char t[FIGURINE_PATH_MAX]="";
905 FILE *fl;
906 FILE *fl2;
907 int ret;
908
909 fl = get_tmpfile(&tfile);
910
911 if (fl==NULL)
912 {
913 strcpy(s,"Temporary file ");
914 strncat(s,tfile,FIGURINE_PATH_MAX-40);
915 strcat(s," could not be opened for writing.");
916 stk_open_info(s);
917 free(tfile);
918 return 322;
919 };
920
921 fl2 = get_tmpfile(&tfile2);
922
923 if (fl2==NULL)
924 {
925 strcpy(s,"Temporary file ");
926 strncat(s,tfile2,FIGURINE_PATH_MAX-40);
927 strcat(s," could not be opened for writing.");
928 stk_open_info(s);
929 fclose(fl);
930 free(tfile);
931 free(tfile2);
932 return 322;
933 };
934
935 fclose(fl2);
936
937 /* simple test file */
938 fprintf(fl,"#FIG 3.2\nLandscape\nFlush Left\nInches\nLetter \n100.00\nSingle\n-2\n1200 2\n");
939 fprintf(fl,"4 0 -1 0 0 0 12 0.0000 4 180 945 8100 5775 Living Room\001\n");
940 fclose(fl);
941
942 strcpy(t,"sh -c \"fig2dev -Leps ");
943 strcat(t,tfile);
944 strcat(t," ");
945 strcat(t,tfile2);
946 strcat(t," >/dev/null 2>/dev/null\" ");
947
948 /* this should fail on < 3.2.3 */
949 ret = system(t);
950 remove(tfile);
951 remove(tfile2);
952
953 free(tfile);
954 free(tfile2);
955
956 if (ret)
957 return 322;
958 else
959 return 323;
960 }
961
962 char *
export_name(Document * d,char * filename,ExportType format)963 export_name(Document *d,char *filename, ExportType format)
964 {
965 List l;
966 FILE *fl2;
967 int fig2dev=322;
968 char *file;
969 char *tfile;
970 char s[FIGURINE_PATH_MAX]="";
971 char t[FIGURINE_PATH_MAX]="";
972 char cmd[FIGURINE_PATH_MAX]="";
973
974 if (!filename)
975 {
976 fl2 = get_tmpfile(&file);
977 if (fl2==NULL)
978 {
979 strcpy(s,"Temporary file ");
980 strncat(s,tfile,FIGURINE_PATH_MAX-40);
981 strcat(s," could not be opened for writing.");
982 stk_open_info(s);
983 free(file);
984 return NULL;
985 };
986 fclose(fl2);
987 }
988 else
989 file = filename;
990
991 /* temp fig files */
992 fl = get_tmpfile(&tfile);
993
994 if (fl==NULL)
995 {
996 strcpy(s,"Temporary file ");
997 strncat(s,tfile,FIGURINE_PATH_MAX-40);
998 strcat(s," could not be opened for writing.");
999 stk_open_info(s);
1000 free(tfile);
1001 return file;
1002 };
1003
1004 if (system("sh -c \"fig2dev -V\" >/dev/null 2>&1 ")!=0)
1005 {
1006 strcpy(s,"fig2dev is not available on your path.");
1007 strcat(s," Cannot export file.");
1008 stk_open_info(s);
1009 free(tfile);
1010 return file;
1011 };
1012
1013 /* determine fig2dev version */
1014 fig2dev = fig2dev_version();
1015
1016 doc = d;
1017
1018 fprintf(fl,"#FIG 3.2\n");
1019 if (doc->landscape)
1020 fprintf(fl,"Landscape\n");
1021 else
1022 fprintf(fl,"Portrait\n");
1023 fprintf(fl,"Flush Left\n");
1024 fprintf(fl,"Inches\n");
1025 /* two spaces for fig2dev 3.2.3 bug */
1026 fprintf(fl,"%s \n",doc->canvas_name);
1027 fprintf(fl,"100.00\n");
1028 fprintf(fl,"Single\n");
1029 fprintf(fl,"%d\n",doc->transcolour);
1030 fprintf(fl,"%ld 2\n",(long)doc->ppi);
1031
1032 /* calculate amount to subtract to move whole pic to topleft */
1033 if (doc->o!=NULL)
1034 {
1035 minx = doc->o->bbox.x1;
1036 miny = doc->o->bbox.y1;
1037 /* if PS, we seem to need to move 2 inches to right */
1038 if (format==EXPORT_PS)
1039 minx-=doc->ppi*2;
1040 };
1041
1042 /* export user-defined colours */
1043 l = doc->cols;
1044 while (l!=NULL)
1045 {
1046 fprintf(fl,"0 %ld %s\n",UCOLOUR(l)->tag,UCOLOUR(l)->name);
1047 l=l->next;
1048 };
1049
1050 l = doc->lo;
1051
1052 while (l!=NULL)
1053 {
1054 switch (l->type)
1055 {
1056 case POLYLINE:
1057 polyline_out(OB(l));
1058 break;
1059
1060 case SPLINE:
1061 case ARC:
1062 spline_out(OB(l));
1063 break;
1064
1065 case POLYGON:
1066 polygon_out(OB(l));
1067 break;
1068
1069 case ROUNDBOX:
1070 roundbox_out(OB(l));
1071 break;
1072
1073 case ELLIPSE:
1074 ellipse_out(OB(l));
1075 break;
1076
1077 case ARCELLIPSE:
1078 arcellipse_out(OB(l));
1079 break;
1080
1081 case TEXT:
1082 text_out(OB(l));
1083 break;
1084
1085 case COMPOUND:
1086 compound_out(OB(l));
1087 break;
1088
1089 default:
1090 v_error((int)l->type);
1091 break;
1092 };
1093 l = l->next;
1094 };
1095
1096 fclose(fl);
1097
1098 /* run fig2dev on tfile */
1099
1100 strcpy(cmd,"fig2dev ");
1101
1102 switch (format)
1103 {
1104 case EXPORT_LATEX_BOX:
1105 strcat(cmd,"-Lbox ");
1106 break;
1107
1108 case EXPORT_LATEX_PICTURE:
1109 strcat(cmd,"-Llatex ");
1110 break;
1111
1112 case EXPORT_EPIC:
1113 strcat(cmd,"-Lepic ");
1114 break;
1115
1116 case EXPORT_EEPIC:
1117 strcat(cmd,"-Leepic ");
1118 break;
1119
1120 case EXPORT_EEPICEMU:
1121 strcat(cmd,"-Leepicemu ");
1122 break;
1123
1124 case EXPORT_PICTEX:
1125 strcat(cmd,"-Lpictex ");
1126 break;
1127
1128 case EXPORT_IBMGL:
1129 strcat(cmd,"-Libmgl ");
1130 if (!doc->landscape)
1131 strcat(cmd,"-P ");
1132 break;
1133
1134 case EXPORT_EPS:
1135 if (fig2dev>322)
1136 strcat(cmd,"-Leps -e ");
1137 else
1138 strcat(cmd,"-Lps -e ");
1139 sprintf(s,"-z %s ",doc->canvas_name);
1140 strcat(cmd,s);
1141 if (doc->landscape)
1142 strcat(cmd,"-l xxx ");
1143 else
1144 strcat(cmd,"-p xxx ");
1145 sprintf(s,"-n '%s' ", strip_dirname(file));
1146 strcat(cmd,s);
1147 break;
1148
1149 case EXPORT_PS:
1150 strcat(cmd,"-Lps ");
1151 if (doc->centred)
1152 strcat(cmd,"-c ");
1153 if (doc->landscape)
1154 strcat(cmd,"-l xxx ");
1155 else
1156 strcat(cmd,"-p xxx ");
1157 /* in 3.2.2 and below this is how we show ps instead of eps */
1158 if (fig2dev <= 322)
1159 strcat(cmd,"-P ");
1160 sprintf(s,"-z %s ",doc->canvas_name);
1161 strcat(cmd,s);
1162 sprintf(s,"-n '%s' ", strip_dirname(file));
1163 strcat(cmd,s);
1164 break;
1165
1166 case EXPORT_PSLATEX:
1167 strcat(cmd,"-Lpstex ");
1168 if (doc->centred)
1169 strcat(cmd,"-c ");
1170 if (doc->landscape)
1171 strcat(cmd,"-l xxx ");
1172 else
1173 strcat(cmd,"-p xxx ");
1174 sprintf(s,"-z %s ",doc->canvas_name);
1175 strcat(cmd,s);
1176 sprintf(s,"-n '%s' ", strip_dirname(file));
1177 strcat(cmd,s);
1178
1179 /* latex file now */
1180 strcpy(s,"fig2dev -Lpstex_t -p '");
1181 strcat(s,strip_dirname(file));
1182 strcat(s,"' '");
1183 strcat(s,tfile);
1184 strcat(s,"' '");
1185 strcat(s,file);
1186 strcat(s,"_t'");
1187 if (system(s)!=0)
1188 {
1189 strcpy(t,"fig2dev command ");
1190 strcat(t, s);
1191 strcat(t," failed. Cannot export file.");
1192 stk_open_info(t);
1193 remove(tfile);
1194 return file;
1195 };
1196 break;
1197
1198 case EXPORT_TEXTYL:
1199 strcat(cmd,"-Ltextyl ");
1200 break;
1201
1202 case EXPORT_TPIC:
1203 strcat(cmd,"-Ltpic ");
1204 break;
1205
1206 case EXPORT_PIC:
1207 strcat(cmd,"-Lpic ");
1208 break;
1209
1210 case EXPORT_METAFONT:
1211 strcat(cmd,"-Lmf ");
1212 break;
1213
1214 case EXPORT_METAPOST:
1215 strcat(cmd,"-Lmp ");
1216 break;
1217
1218 case EXPORT_MULTIMETAPOST:
1219 strcat(cmd,"-Lmmp ");
1220 break;
1221
1222 case EXPORT_AUTOCAD:
1223 strcat(cmd,"-Lacad ");
1224 break;
1225
1226 case EXPORT_PCX:
1227 strcat(cmd,"-Lpcx ");
1228 break;
1229
1230 case EXPORT_PNG:
1231 strcat(cmd,"-Lpng ");
1232 break;
1233
1234 case EXPORT_GIF:
1235 strcat(cmd,"-Lgif ");
1236 break;
1237
1238 case EXPORT_JPEG:
1239 strcat(cmd,"-Ljpeg ");
1240 break;
1241
1242 case EXPORT_TIFF:
1243 strcat(cmd,"-Ltiff ");
1244 break;
1245
1246 case EXPORT_PPM:
1247 strcat(cmd,"-Lppm ");
1248 break;
1249
1250 case EXPORT_XBM:
1251 strcat(cmd,"-Lxbm ");
1252 break;
1253
1254 case EXPORT_XPM:
1255 strcat(cmd,"-Lxpm ");
1256 break;
1257 };
1258
1259 sprintf(s,"-m %f ",doc->magnify/100.0);
1260 strcat(cmd,s);
1261 strcat(cmd,"'");
1262 strcat(cmd,tfile);
1263 strcat(cmd,"' '");
1264 strcat(cmd,file);
1265 strcat(cmd,"'");
1266
1267 /* cmdline has been constructed, so run it */
1268 if (system(cmd)!=0)
1269 {
1270 strcpy(s,"fig2dev command ");
1271 strcat(s, cmd);
1272 strcat(s," failed. Cannot export file.");
1273 stk_open_info(s);
1274 };
1275
1276 /* get rid of tfile */
1277 remove(tfile);
1278 free(tfile);
1279
1280 return(file);
1281 }
1282