1 /* libwmf (convert/wmf2gd.c): library for wmf conversion
2    Copyright (C) 2000 - various; see CREDITS, ChangeLog, and sources
3 
4    The libwmf Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Library General Public License as
6    published by the Free Software Foundation; either version 2 of the
7    License, or (at your option) any later version.
8 
9    The libwmf Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Library General Public License for more details.
13 
14    You should have received a copy of the GNU Library General Public
15    License along with the libwmf Library; see the file COPYING.  If not,
16    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17    Boston, MA 02111-1307, USA.  */
18 
19 
20 #ifdef HAVE_CONFIG_H
21 #include "wmfconfig.h"
22 #endif
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include <math.h>
29 
30 #include "wmfdefs.h"
31 
32 #ifdef X_DISPLAY_MISSING
33 
main(int argc,char ** argv)34 int main (int argc,char** argv)
35 {	fprintf (stderr,"%s: no support for X, sorry.\n",argv[0]);
36 	return (1);
37 }
38 
39 #else /* X_DISPLAY_MISSING */ /* i.e., not */
40 
41 #include "libwmf/x.h"
42 
43 #include <X11/Xutil.h>
44 #include <X11/Xatom.h>
45 
46 typedef struct
47 {	int    argc;
48 	char** argv;
49 
50 	char* wmf_filename;
51 
52 	wmf_x_t options;
53 } PlotData;
54 
55 int  wmf2x_draw (PlotData*);
56 
57 void wmf2x_init (PlotData*,int,char**);
58 void wmf2x_help (PlotData*);
59 int  wmf2x_args (PlotData*);
60 
61 int  explicit_wmf_error (char*,wmf_error_t);
62 
wmf2x_draw(PlotData * pdata)63 int wmf2x_draw (PlotData* pdata)
64 {	int status = 0;
65 	int redraw;
66 	int setmask;
67 	int length;
68 
69 	float wmf_width  = 0;
70 	float wmf_height = 0;
71 
72 	float ratio_wmf;
73 	float ratio_bounds;
74 
75 	char key;
76 
77 	unsigned int root_width  = 800; /* Unfortunately, need these before we open the display... */
78 	unsigned int root_height = 600;
79 	unsigned int disp_width  = 0;
80 	unsigned int disp_height = 0;
81 
82 	unsigned long flags;
83 
84 	wmf_error_t err;
85 
86 	wmf_x_t* ddata = 0;
87 
88 	wmfAPI* API = 0;
89 
90 	wmfAPI_Options api_options;
91 
92 	XEvent event;
93 
94 	XWindowAttributes attributes;
95 
96 	KeySym keysym;
97 
98 	static char* icon_name = "wmf2x";
99 
100 	flags = 0;
101 
102 	flags |= WMF_OPT_FUNCTION;
103 	api_options.function = wmf_x_function;
104 
105 	flags |= WMF_OPT_ARGS;
106 	api_options.argc = pdata->argc;
107 	api_options.argv = pdata->argv;
108 #ifndef DEBUG
109 	flags |= WMF_OPT_IGNORE_NONFATAL;
110 #endif
111 	err = wmf_api_create (&API,flags,&api_options);
112 	status = explicit_wmf_error ("wmf_api_create",err);
113 
114 	if (status)
115 	{	if (API) wmf_api_destroy (API);
116 		return (status);
117 	}
118 
119 	ddata = WMF_X_GetData (API);
120 
121 	ddata->flags |= WMF_X_DISPLAY_OPEN;
122 
123 	ddata->display_name = pdata->options.display_name;
124 	ddata->window_name = pdata->wmf_filename;
125 	ddata->icon_name = icon_name;
126 
127 	length = strlen (pdata->wmf_filename);
128 #if defined (HAVE_EXPAT) || defined (HAVE_LIBXML2)
129 	if (length > 4)
130 	{
131 		if ((strcmp (pdata->wmf_filename + length - 4, ".xml") == 0) ||
132 		    (strcmp (pdata->wmf_filename + length - 4, ".XML") == 0))
133 		{	err = wmf_wmfxml_import (API,pdata->wmf_filename);
134 		}
135 		else err = wmf_file_open (API,pdata->wmf_filename);
136 	}
137 	else err = wmf_file_open (API,pdata->wmf_filename);
138 #else
139 	err = wmf_file_open (API,pdata->wmf_filename);
140 #endif
141 	status = explicit_wmf_error ("wmf_file_open",err);
142 
143 	if (status)
144 	{	wmf_api_destroy (API);
145 		return (status);
146 	}
147 
148 	err = wmf_scan (API,0,&(pdata->options.bbox));
149 	status = explicit_wmf_error ("wmf_scan",err);
150 
151 	if (status)
152 	{	wmf_api_destroy (API);
153 		return (status);
154 	}
155 
156 /* Okay, got this far, everything seems cool.
157  */
158 	ddata->bbox = pdata->options.bbox;
159 
160 	wmf_display_size (API,&disp_width,&disp_height,72,72);
161 
162 	wmf_width  = (float) disp_width;
163 	wmf_height = (float) disp_height;
164 
165 	if (pdata->options.x_width > 0)
166 	{	wmf_width  = pdata->options.x_width;
167 	}
168 	if (pdata->options.x_height > 0)
169 	{	wmf_height = pdata->options.x_height;
170 	}
171 
172 	if ((wmf_width <= 0) || (wmf_height <= 0))
173 	{	fputs ("Bad image size - but this error shouldn't occur...\n",stderr);
174 		status = 1;
175 		wmf_api_destroy (API);
176 		return (status);
177 	}
178 
179 	if ((wmf_width  > (float) root_width )
180 	 || (wmf_height > (float) root_height))
181 	{	ratio_wmf = wmf_height / wmf_width;
182 		ratio_bounds = (float) root_height / (float) root_width;
183 
184 		if (ratio_wmf > ratio_bounds)
185 		{	ddata->x_height = root_height;
186 			ddata->x_width  = (unsigned int) ((float) ddata->x_height / ratio_wmf);
187 		}
188 		else
189 		{	ddata->x_width  = root_width;
190 			ddata->x_height = (unsigned int) ((float) ddata->x_width  * ratio_wmf);
191 		}
192 	}
193 	else
194 	{	ddata->x_width  = (unsigned int) ceil ((double) wmf_width );
195 		ddata->x_height = (unsigned int) ceil ((double) wmf_height);
196 	}
197 
198 	redraw = 1;
199 	setmask = 1;
200 	while (status == 0)
201 	{	if (redraw)
202 		{	err = wmf_play (API,0,&(pdata->options.bbox));
203 			status = explicit_wmf_error ("wmf_play",err);
204 			if (status) break;
205 		}
206 		redraw = 0;
207 
208 		if (setmask)
209 		{	XSelectInput (ddata->display,ddata->window,KeyPressMask|StructureNotifyMask);
210 			setmask = 0;
211 		}
212 
213 		XNextEvent (ddata->display,&event);
214 
215 		switch (event.type)
216 		{
217 		case KeyPress:
218 			XLookupString (&(event.xkey),&key,1,&keysym,0);
219 
220 			switch (key)
221 			{
222 			case 'q':
223 			case 'Q':
224 				status = -1;
225 			break;
226 
227 			case 'r':
228 			case 'R':
229 				redraw = 1;
230 			break;
231 
232 			default:
233 			break;
234 			}
235 		break;
236 
237 		case ConfigureNotify: /* This is all a bit clumsy, because I'm being lazy and letting    *
238 			               * the library ipa do most of the work that ought to be done here! */
239 
240 			XGetWindowAttributes (ddata->display,ddata->window,&attributes);
241 
242 			if ((ddata->x_width != (unsigned int)attributes.width) ||
243 		            (ddata->x_height != (unsigned int)attributes.height))
244 			{	ddata->x_width  = attributes.width;
245 				ddata->x_height = attributes.height;
246 
247 				XFreePixmap (ddata->display,ddata->pixmap);
248 
249 				ddata->flags &= ~WMF_X_PIXMAP_CLOSE;
250 
251 				ddata->pixmap = XCreatePixmap (ddata->display,ddata->root,
252 				                               ddata->x_width,ddata->x_height,ddata->depth);
253 
254 				if (ddata->pixmap == None)
255 				{	WMF_ERROR (API,"unable to create pixmap!");
256 					status = 1;
257 					break;
258 				}
259 
260 				ddata->flags |= WMF_X_PIXMAP_CLOSE;
261 
262 				XSetWindowBackgroundPixmap (ddata->display,ddata->window,ddata->pixmap);
263 
264 				redraw = 1;
265 			}
266 		break;
267 
268 		default:
269 		break;
270 		}
271 		if (status == (-1))
272 		{	status = 0;
273 			break;
274 		}
275 	}
276 
277 	wmf_api_destroy (API);
278 
279 	return (status);
280 }
281 
wmf2x_init(PlotData * pdata,int argc,char ** argv)282 void wmf2x_init (PlotData* pdata,int argc,char** argv)
283 {	pdata->argc = argc;
284 	pdata->argv = argv;
285 
286 	pdata->wmf_filename = 0;
287 
288 	pdata->options.display_name = 0;
289 
290 	pdata->options.x_width  = 0;
291 	pdata->options.x_height = 0;
292 
293 	pdata->options.flags = 0;
294 }
295 
wmf2x_help(PlotData * pdata)296 void wmf2x_help (PlotData* pdata)
297 {	(void)pdata;
298 	fputs ("\
299 Usage: wmf2x [OPTION]... <file.wmf>\n\
300 Display metafile image.\n\
301 \n\
302   -display <display>  where <display> is the display name.\n\
303   --width=<w>         where <w> is the width of the image.\n\
304   --height=<h>        where <h> is the height of the image.\n\
305   --version           display version info and exit.\n\
306   --help              display this help and exit.\n\
307   --wmf-help          display wmf-related help and exit.\n\
308 \n\
309 Report bugs to <http://www.wvware.com/>.\n",stdout);
310 }
311 
wmf2x_args(PlotData * pdata)312 int wmf2x_args (PlotData* pdata)
313 {	int status = 0;
314 	int arg = 0;
315 
316 	int    argc = pdata->argc;
317 	char** argv = pdata->argv;
318 
319 	while ((++arg) < argc)
320 	{	if (strcmp (argv[arg],"--help") == 0)
321 		{	wmf2x_help (pdata);
322 			status = argc; /* i.e., not an error but don't continue */
323 			break;
324 		}
325 
326 		if (strcmp (argv[arg],"--wmf-help") == 0)
327 		{	fputs (wmf_help (),stdout);
328 			status = argc; /* i.e., not an error but don't continue */
329 			break;
330 		}
331 
332 		if (strcmp (argv[arg],"--version") == 0)
333 		{	fprintf (stdout,"%s: version %s\n",PACKAGE,VERSION);
334 			status = argc; /* i.e., not an error but don't continue */
335 			break;
336 		}
337 
338 		if (strcmp (argv[arg],"-display") == 0)
339 		{	if ((++arg) < argc)
340 			{	pdata->options.display_name = argv[arg];
341 				continue;
342 			}
343 			fprintf (stderr,"usage: `wmf2x -display <displayname> <file.wmf>'.\n");
344 			fprintf (stderr,"Try `%s --help' for more information.\n",argv[0]);
345 			status = arg;
346 			break;
347 		}
348 
349 		if (strncmp (argv[arg],"--width=",8) == 0)
350 		{	if (sscanf (argv[arg]+8,"%u",&(pdata->options.x_width)) != 1)
351 			{	fputs ("usage: --width=<width>, where <width> is +ve integer.\n",stderr);
352 				status = arg;
353 				break;
354 			}
355 			continue;
356 		}
357 		if (strncmp (argv[arg],"--height=",9) == 0)
358 		{	if (sscanf (argv[arg]+9,"%u",&(pdata->options.x_height)) != 1)
359 			{	fputs ("usage: --height=<height>, where <height> is +ve integer.\n",stderr);
360 				status = arg;
361 				break;
362 			}
363 			continue;
364 		}
365 
366 		if (strncmp (argv[arg],"--wmf-",6) == 0)
367 		{	continue;
368 		}
369 
370 		if (argv[arg][0] != '-')
371 		{	pdata->wmf_filename = argv[arg];
372 			continue;
373 		}
374 
375 		fprintf (stderr,"option `%s' not recognized.\n",argv[arg]);
376 		fprintf (stderr,"Try `%s --help' for more information.\n",argv[0]);
377 		status = arg;
378 		break;
379 	}
380 
381 	if (status == 0)
382 	{	if (pdata->wmf_filename == 0)
383 		{	fprintf (stderr,"No input file specified!\n");
384 			fprintf (stderr,"Try `%s --help' for more information.\n",argv[0]);
385 			status = argc;
386 		}
387 	}
388 
389 	return (status);
390 }
391 
main(int argc,char ** argv)392 int main (int argc,char** argv)
393 {	int status = 0;
394 
395 	PlotData PData;
396 
397 	wmf2x_init (&PData,argc,argv);
398 
399 	status = wmf2x_args (&PData);
400 
401 	if (status) return (status);
402 
403 	status = wmf2x_draw (&PData);
404 
405 	return (status);
406 }
407 
explicit_wmf_error(char * str,wmf_error_t err)408 int explicit_wmf_error (char* str,wmf_error_t err)
409 {	(void)str;
410 	int status = 0;
411 
412 	switch (err)
413 	{
414 	case wmf_E_None:
415 #ifdef DEBUG
416 		fprintf (stderr,"%s returned with wmf_E_None.\n",str);
417 #endif
418 		status = 0;
419 	break;
420 
421 	case wmf_E_InsMem:
422 #ifdef DEBUG
423 		fprintf (stderr,"%s returned with wmf_E_InsMem.\n",str);
424 #endif
425 		status = 1;
426 	break;
427 
428 	case wmf_E_BadFile:
429 #ifdef DEBUG
430 		fprintf (stderr,"%s returned with wmf_E_BadFile.\n",str);
431 #endif
432 		status = 1;
433 	break;
434 
435 	case wmf_E_BadFormat:
436 #ifdef DEBUG
437 		fprintf (stderr,"%s returned with wmf_E_BadFormat.\n",str);
438 #endif
439 		status = 1;
440 	break;
441 
442 	case wmf_E_EOF:
443 #ifdef DEBUG
444 		fprintf (stderr,"%s returned with wmf_E_EOF.\n",str);
445 #endif
446 		status = 1;
447 	break;
448 
449 	case wmf_E_DeviceError:
450 #ifdef DEBUG
451 		fprintf (stderr,"%s returned with wmf_E_DeviceError.\n",str);
452 #endif
453 		status = 1;
454 	break;
455 
456 	case wmf_E_Glitch:
457 #ifdef DEBUG
458 		fprintf (stderr,"%s returned with wmf_E_Glitch.\n",str);
459 #endif
460 		status = 1;
461 	break;
462 
463 	case wmf_E_Assert:
464 #ifdef DEBUG
465 		fprintf (stderr,"%s returned with wmf_E_Assert.\n",str);
466 #endif
467 		status = 1;
468 	break;
469 
470 	default:
471 #ifdef DEBUG
472 		fprintf (stderr,"%s returned unexpected value.\n",str);
473 #endif
474 		status = 1;
475 	break;
476 	}
477 
478 	return (status);
479 }
480 
481 #endif /* X_DISPLAY_MISSING */
482