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