1 /*
2  * Copyright (c) Tony Bybell 1999-2012
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  */
9 
10 #include "globals.h"
11 #include <config.h>
12 #include "currenttime.h"
13 #include "print.h"
14 #include "menu.h"
15 #include <errno.h>
16 
17 #ifdef WAVE_GTK_UNIX_PRINT
18 /* #include <gtk/gtkunixprint.h> */
19 #include <gtk/gtkprintunixdialog.h>
20 #endif
21 
22 static char *render_targets[]=
23         {"PDF", "PS", "MIF", "UNIX"};
24 
25 static char *page_size[]=
26         {"Letter (8.5\" x 11\")", "A4 (11.68\" x 8.26\")", "Legal (14\" x 8.5\")", "Letter Prop (6.57\" x 8.5\")", "A4 Prop (8.26\" x 5.84\")"};
27 
28 static char *render_type[]=
29         {"Full", "Minimal"};
30 
31 static gdouble px[]={11.00, 11.68, 14.00, 8.50, 8.26};
32 static gdouble py[]={ 8.50,  8.26,  8.50, 6.57, 5.84};
33 
34 
35 /*
36  * button/menu/entry activations..
37  */
render_clicked(GtkWidget * widget,gpointer which)38 static void render_clicked(GtkWidget *widget, gpointer which)
39 {
40 (void)widget;
41 
42 int i;
43 
44 for(i=0;i<4;i++) GLOBALS->target_mutex_renderopt_c_1[i]=0;
45 
46 i = (int)((intptr_t)which);
47 GLOBALS->target_mutex_renderopt_c_1[i] = 1; /* mark our choice */
48 
49 DEBUG(printf("picked: %s\n", render_targets[i]));
50 }
51 
pagesize_clicked(GtkWidget * widget,gpointer which)52 static void pagesize_clicked(GtkWidget *widget, gpointer which)
53 {
54 (void)widget;
55 
56 int i;
57 
58 for(i=0;i<5;i++) GLOBALS->page_mutex_renderopt_c_1[i]=0;
59 
60 GLOBALS->page_size_type_renderopt_c_1 = (int)((intptr_t)which);
61 GLOBALS->page_mutex_renderopt_c_1[GLOBALS->page_size_type_renderopt_c_1] = 1; /* mark our choice */
62 
63 DEBUG(printf("picked: %s\n", page_size[GLOBALS->page_size_type_renderopt_c_1]));
64 }
65 
rendertype_clicked(GtkWidget * widget,gpointer which)66 static void rendertype_clicked(GtkWidget *widget, gpointer which)
67 {
68 (void)widget;
69 
70 int i;
71 
72 for(i=0;i<3;i++) GLOBALS->render_mutex_renderopt_c_1[i]=0;
73 
74 i = (int)((intptr_t)which);
75 GLOBALS->render_mutex_renderopt_c_1[i] = 1; /* mark our choice */
76 
77 DEBUG(printf("picked: %s\n", render_type[i]));
78 }
79 
80 
81 static void
ps_print_cleanup(GtkWidget * widget,gpointer data)82 ps_print_cleanup(GtkWidget *widget, gpointer data)
83 {
84 (void)widget;
85 (void)data;
86 
87 FILE *wave;
88 
89 if(GLOBALS->filesel_ok)
90         {
91         DEBUG(printf("PS Print Fini: %s\n", *GLOBALS->fileselbox_text));
92 
93         if(!(wave=fopen(*GLOBALS->fileselbox_text,"wb")))
94                 {
95                 fprintf(stderr, "Error opening PS output file '%s' for writing.\n",*GLOBALS->fileselbox_text);
96                 perror("Why");
97                 errno=0;
98                 }
99                 else
100                 {
101                 print_ps_image(wave,px[GLOBALS->page_size_type_renderopt_c_1],py[GLOBALS->page_size_type_renderopt_c_1]);
102                 fclose(wave);
103                 }
104         }
105 }
106 
107 static void
pdf_print_cleanup(GtkWidget * widget,gpointer data)108 pdf_print_cleanup(GtkWidget *widget, gpointer data)
109 {
110 (void)widget;
111 (void)data;
112 
113 FILE *wave;
114 FILE *wave2;
115 
116 if(GLOBALS->filesel_ok)
117         {
118         DEBUG(printf("PDF Print Fini: %s\n", *GLOBALS->fileselbox_text));
119 
120         if(!(wave=fopen(*GLOBALS->fileselbox_text,"wb")))
121                 {
122                 fprintf(stderr, "Error opening PDF output file '%s' for writing.\n",*GLOBALS->fileselbox_text);
123                 perror("Why");
124                 errno=0;
125                 }
126                 else
127                 {
128 		int len = strlen(*GLOBALS->fileselbox_text) ;
129 		char *zname = malloc_2(len + 4);
130 		strcpy(zname, *GLOBALS->fileselbox_text);
131 
132 #ifdef MAC_INTEGRATION
133 		if((len > 4)&&(!strcmp(".pdf", zname+len-4)))
134 			{
135 			zname[len-4] = 0;
136 			len-=4;
137 			}
138 #endif
139 		strcpy(zname+len, ".ps");
140 
141 		if(!(wave2=fopen(zname,"wb")))
142 			{
143 	                fprintf(stderr, "Error opening PS output tempfile '%s' for writing.\n",zname);
144 	                perror("Why");
145 			fclose(wave);
146 			unlink(*GLOBALS->fileselbox_text);
147 	                errno=0;
148 			}
149 			else
150 			{
151 			char *sysname = malloc_2(7 + 1 + len + 3 + 1 + len + 1);
152 			int rc;
153 
154 #ifdef MAC_INTEGRATION
155 			sprintf(sysname, "pstopdf"	/* 7 */
156 #else
157 			sprintf(sysname, "ps2pdf"	/* 6 */
158 #endif
159 					 " "		/* 1 */
160 					 "%s"		/* len + 3 */
161 					 " "		/* 1 */
162 					 "%s"		/* len */
163 					 , zname, *GLOBALS->fileselbox_text);
164 	                print_ps_image(wave2,px[GLOBALS->page_size_type_renderopt_c_1],py[GLOBALS->page_size_type_renderopt_c_1]);
165 	                fclose(wave2);
166 			fclose(wave);
167 			rc = system(sysname);
168 			if(rc)
169 				{
170 				printf("GTKWAVE | ERROR: rc for '%s' = %d\n", sysname, rc);
171 				unlink(*GLOBALS->fileselbox_text);
172 				}
173 			free_2(sysname);
174 			unlink(zname);
175 			}
176 
177 		free_2(zname);
178                 }
179         }
180 }
181 
182 static void
mif_print_cleanup(GtkWidget * widget,gpointer data)183 mif_print_cleanup(GtkWidget *widget, gpointer data)
184 {
185 (void)widget;
186 (void)data;
187 
188 FILE *wave;
189 
190 if(GLOBALS->filesel_ok)
191         {
192         DEBUG(printf("MIF Print Fini: %s\n", *GLOBALS->fileselbox_text));
193 
194         if(!(wave=fopen(*GLOBALS->fileselbox_text,"wb")))
195                 {
196                 fprintf(stderr, "Error opening MIF output file '%s' for writing.\n",*GLOBALS->fileselbox_text);
197                 perror("Why");
198                 errno=0;
199                 }
200                 else
201                 {
202 		print_mif_image(wave,px[GLOBALS->page_size_type_renderopt_c_1],py[GLOBALS->page_size_type_renderopt_c_1]);
203                 fclose(wave);
204                 }
205         }
206 }
207 
208 
209 #ifdef WAVE_GTK_UNIX_PRINT
wave_GtkPrintJobCompleteFunc(GtkPrintJob * print_job,gpointer user_data,GError * error)210 static void wave_GtkPrintJobCompleteFunc(GtkPrintJob *print_job, gpointer user_data, GError *error)
211 {
212 (void)print_job;
213 (void)error;
214 
215 if(user_data)
216 	{
217 	const char *ban = "Sent print job";
218 	char *buf = wave_alloca(strlen(ban) + strlen(user_data) + 32);
219 
220 	sprintf(buf, "%s '%s'", ban, (char *)user_data);
221 	status_text(buf);
222 
223 	unlink(user_data);
224 	}
225 }
226 #endif
227 
228 static void
unix_print_cleanup(GtkWidget * widget,gpointer data)229 unix_print_cleanup(GtkWidget *widget, gpointer data)
230 {
231 (void)widget;
232 (void)data;
233 
234 #ifdef WAVE_GTK_UNIX_PRINT
235 GtkWidget *ropt = gtk_print_unix_dialog_new("GTK Print UNIX Options", GTK_WINDOW(GLOBALS->mainwindow));
236 gint gd_rc;
237 
238 if(GLOBALS->gprs) { gtk_print_unix_dialog_set_settings(GTK_PRINT_UNIX_DIALOG(ropt), GLOBALS->gprs); }
239 if(GLOBALS->gps) { gtk_print_unix_dialog_set_page_setup(GTK_PRINT_UNIX_DIALOG(ropt), GLOBALS->gps); }
240 
241 gtk_print_unix_dialog_set_manual_capabilities(GTK_PRINT_UNIX_DIALOG(ropt),
242 	GTK_PRINT_CAPABILITY_GENERATE_PS |
243 	GTK_PRINT_CAPABILITY_COPIES
244 	);
245 
246 #ifdef MAC_INTEGRATION
247 osx_menu_sensitivity(FALSE);
248 #endif
249 
250 gd_rc = gtk_dialog_run(GTK_DIALOG (ropt));
251 if(gd_rc == GTK_RESPONSE_OK)
252 	{
253 	GtkPrinter *gp = gtk_print_unix_dialog_get_selected_printer(GTK_PRINT_UNIX_DIALOG(ropt));
254 	GtkPrintSettings *gprs = gtk_print_unix_dialog_get_settings(GTK_PRINT_UNIX_DIALOG(ropt));
255 	GtkPageSetup *gps = gtk_print_unix_dialog_get_page_setup(GTK_PRINT_UNIX_DIALOG(ropt));
256 	GtkPrintJob *gpj = gtk_print_job_new(GLOBALS->loaded_file_name, gp, gprs, gps);
257 	gboolean job_stat;
258 	GError *job_error = NULL;
259 	FILE *wave;
260 	char *save_tmpfilename;
261 	int fd_dummy = -1;
262 
263 	if(gtk_printer_accepts_ps(gp))
264 		{
265 		save_tmpfilename = tmpnam_2(NULL, &fd_dummy);
266 
267 	       	if(!(wave=fopen(save_tmpfilename, "r+b")))
268 	               	{
269 	               	fprintf(stderr, "Error opening PS output file '%s' for writing.\n", save_tmpfilename);
270 	               	perror("Why");
271 	               	errno=0;
272 	               	}
273 	               	else
274 	               	{
275 			if(GLOBALS->gp_tfn) free_2(GLOBALS->gp_tfn);
276 			GLOBALS->gp_tfn = strdup_2(save_tmpfilename);
277 
278                 	print_ps_image(wave,px[GLOBALS->page_size_type_renderopt_c_1],py[GLOBALS->page_size_type_renderopt_c_1]);
279 			fflush(wave);
280 			fclose(wave);
281 			job_stat = gtk_print_job_set_source_file(gpj,
282                                                         GLOBALS->gp_tfn,
283                                                         &job_error);
284 			if(job_stat)
285 				{
286 				gtk_print_job_send(gpj, wave_GtkPrintJobCompleteFunc,
287 						GLOBALS->gp_tfn,
288 						NULL);
289 				GLOBALS->gprs = gtk_print_settings_copy(gprs);
290 				GLOBALS->gps = gtk_page_setup_copy(gps);
291 				}
292 				else
293 				{
294 				unlink(GLOBALS->gp_tfn);
295 				}
296 			}
297 
298 #if !defined _MSC_VER && !defined __MINGW32__
299 		free_2(save_tmpfilename);
300 #endif
301 		if(fd_dummy >=0) close(fd_dummy);
302                	}
303 		else
304 		{
305 		status_text("gtk_printer_accepts_ps() == FALSE, cannot print.");
306 		}
307 	}
308 else
309 if(gd_rc == GTK_RESPONSE_APPLY)
310 	{
311 	status_text("Preview not available.");
312 	}
313 
314 gtk_widget_destroy(ropt);
315 
316 #ifdef MAC_INTEGRATION
317 osx_menu_sensitivity(TRUE);
318 #endif
319 
320 #endif
321 }
322 
323 
324 
ok_callback(void)325 static void ok_callback(void)
326 {
327 GLOBALS->ps_fullpage=GLOBALS->render_mutex_renderopt_c_1[0];
328 if(GLOBALS->target_mutex_renderopt_c_1[0])
329 	{
330 	fileselbox("Print To PDF File",&GLOBALS->filesel_print_pdf_renderopt_c_1,GTK_SIGNAL_FUNC(pdf_print_cleanup), GTK_SIGNAL_FUNC(NULL), "*.pdf", 1);
331 	}
332 else
333 if(GLOBALS->target_mutex_renderopt_c_1[1])
334 	{
335 	fileselbox("Print To PS File",&GLOBALS->filesel_print_ps_renderopt_c_1,GTK_SIGNAL_FUNC(ps_print_cleanup), GTK_SIGNAL_FUNC(NULL), "*.ps", 1);
336 	}
337 else
338 if(GLOBALS->target_mutex_renderopt_c_1[2])
339 	{
340 	fileselbox("Print To MIF File",&GLOBALS->filesel_print_mif_renderopt_c_1,GTK_SIGNAL_FUNC(mif_print_cleanup), GTK_SIGNAL_FUNC(NULL), "*.fm", 1);
341 	}
342 else
343 	{
344 	unix_print_cleanup(NULL,NULL);
345 	}
346 }
347 
destroy_callback(GtkWidget * widget,GtkWidget * nothing)348 static void destroy_callback(GtkWidget *widget, GtkWidget *nothing)
349 {
350 (void)widget;
351 (void)nothing;
352 
353   GLOBALS->is_active_renderopt_c_3=0;
354   gtk_widget_destroy(GLOBALS->window_renderopt_c_6);
355   GLOBALS->window_renderopt_c_6 = NULL;
356 }
357 
358 
renderbox(char * title)359 void renderbox(char *title)
360 {
361     GtkWidget *menu, *menuitem, *optionmenu;
362     GSList *group;
363     GtkWidget *vbox, *hbox, *small_hbox;
364     GtkWidget *button1, *button2;
365     int i;
366 
367     /* fix problem where ungrab doesn't occur if button pressed + simultaneous accelerator key occurs */
368     if(GLOBALS->in_button_press_wavewindow_c_1) { gdk_pointer_ungrab(GDK_CURRENT_TIME); }
369 
370     if(GLOBALS->wave_script_args)
371         {
372         char *s1 = NULL;
373         char *s2 = NULL;
374         char *s3 = NULL;
375 
376         while((!s1)&&(GLOBALS->wave_script_args->curr)) s1 = wave_script_args_fgetmalloc_stripspaces(GLOBALS->wave_script_args);
377         while((!s2)&&(GLOBALS->wave_script_args->curr)) s2 = wave_script_args_fgetmalloc_stripspaces(GLOBALS->wave_script_args);
378         while((!s3)&&(GLOBALS->wave_script_args->curr)) s3 = wave_script_args_fgetmalloc_stripspaces(GLOBALS->wave_script_args);
379 
380         if(s1 && s2 && s3)
381                 {
382 		memset(GLOBALS->target_mutex_renderopt_c_1, 0, 2); GLOBALS->target_mutex_renderopt_c_1[0] = 1; /* PS */
383 #ifdef WAVE_GTK_UNIX_PRINT
384 		for(i=0;i<4;i++)
385 #else
386 		for(i=0;i<3;i++)
387 #endif
388 			{
389 			if(!strcmp(s1, render_targets[i]))
390 				{
391 				fprintf(stderr, "GTKWAVE | Print using '%s'\n",  render_targets[i]);
392 				memset(GLOBALS->target_mutex_renderopt_c_1, 0, 4); GLOBALS->target_mutex_renderopt_c_1[i] = 1; break;
393 				}
394 			}
395 
396 		memset(GLOBALS->page_mutex_renderopt_c_1, 0, 5); GLOBALS->page_mutex_renderopt_c_1[0] = 1; /* 8.5 x 11 */
397 		GLOBALS->page_size_type_renderopt_c_1 = 0;
398 		for(i=0;i<5;i++)
399 			{
400 			if(!strcmp(s2, page_size[i]))
401 				{
402 				fprintf(stderr, "GTKWAVE | Print using '%s'\n",  page_size[i]);
403 				memset(GLOBALS->page_mutex_renderopt_c_1, 0, 5); GLOBALS->page_mutex_renderopt_c_1[i] = 1;
404 				GLOBALS->page_size_type_renderopt_c_1 = i;
405 				break;
406 				}
407 			}
408 
409 		memset(GLOBALS->render_mutex_renderopt_c_1, 0, 3); GLOBALS->render_mutex_renderopt_c_1[0] = 1; /* Full */
410 		for(i=0;i<2;i++)
411 			{
412 			if(!strcmp(s3, render_type[i]))
413 				{
414 				fprintf(stderr, "GTKWAVE | Print using '%s'\n",  render_type[i]);
415 				memset(GLOBALS->render_mutex_renderopt_c_1, 0, 3); GLOBALS->render_mutex_renderopt_c_1[i] = 1; break;
416 				}
417 			}
418 
419 		free_2(s1); free_2(s2); free_2(s3);
420 		ok_callback();
421                 }
422                 else
423                 {
424 		fprintf(stderr, "Missing script entries for renderbox, exiting.\n");
425 		exit(255);
426                 }
427 
428         return;
429         }
430 
431 
432 
433     if(GLOBALS->is_active_renderopt_c_3)
434 	{
435 	if(GLOBALS->window_renderopt_c_6)
436 		{
437 		gdk_window_raise(GLOBALS->window_renderopt_c_6->window);
438 		}
439 	return;
440 	}
441 
442     GLOBALS->is_active_renderopt_c_3=1;
443 
444     /* create a new window */
445     GLOBALS->window_renderopt_c_6 = gtk_window_new(GLOBALS->disable_window_manager ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL);
446     install_focus_cb(GLOBALS->window_renderopt_c_6, ((char *)&GLOBALS->window_renderopt_c_6) - ((char *)GLOBALS));
447 
448     gtk_window_set_title(GTK_WINDOW (GLOBALS->window_renderopt_c_6), title);
449     gtk_widget_set_usize( GTK_WIDGET (GLOBALS->window_renderopt_c_6), 420, -1);
450     gtkwave_signal_connect(GTK_OBJECT (GLOBALS->window_renderopt_c_6), "delete_event",(GtkSignalFunc) destroy_callback, NULL);
451     gtk_window_set_policy(GTK_WINDOW(GLOBALS->window_renderopt_c_6), FALSE, FALSE, FALSE);
452 
453     vbox = gtk_vbox_new (FALSE, 0);
454     gtk_container_add (GTK_CONTAINER (GLOBALS->window_renderopt_c_6), vbox);
455     gtk_widget_show (vbox);
456 
457     small_hbox = gtk_hbox_new (TRUE, 0);
458     gtk_widget_show (small_hbox);
459 
460     menu = gtk_menu_new ();
461     group=NULL;
462 
463     for(i=0;i<4;i++)
464 	{
465 	GLOBALS->target_mutex_renderopt_c_1[i]=0;
466 
467 #ifndef WAVE_GTK_UNIX_PRINT
468 	if(i==3)
469 		{
470 		break;
471 		}
472 #endif
473 
474     	menuitem = gtk_radio_menu_item_new_with_label (group, render_targets[i]);
475     	group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
476     	gtk_menu_append (GTK_MENU (menu), menuitem);
477     	gtk_widget_show (menuitem);
478         gtkwave_signal_connect(GTK_OBJECT (menuitem), "activate", GTK_SIGNAL_FUNC(render_clicked), (void *)((intptr_t)i));
479 	}
480 
481 	GLOBALS->target_mutex_renderopt_c_1[0]=1;	/* "ps" */
482 
483 	optionmenu = gtk_option_menu_new ();
484 	gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), menu);
485 	gtk_box_pack_start (GTK_BOX (small_hbox), optionmenu, TRUE, FALSE, 0);
486 	gtk_widget_show (optionmenu);
487 
488     menu = gtk_menu_new ();
489     group=NULL;
490 
491     for(i=0;i<5;i++)
492 	{
493     	menuitem = gtk_radio_menu_item_new_with_label (group, page_size[i]);
494     	group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
495     	gtk_menu_append (GTK_MENU (menu), menuitem);
496     	gtk_widget_show (menuitem);
497         gtkwave_signal_connect(GTK_OBJECT (menuitem), "activate", GTK_SIGNAL_FUNC(pagesize_clicked), (void *)((intptr_t)i));
498 	GLOBALS->page_mutex_renderopt_c_1[i]=0;
499 	}
500 
501 	GLOBALS->page_mutex_renderopt_c_1[0]=1;	/* "letter" */
502 
503 	optionmenu = gtk_option_menu_new ();
504 	gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), menu);
505 	gtk_box_pack_start (GTK_BOX (small_hbox), optionmenu, TRUE, FALSE, 0);
506 	gtk_widget_show (optionmenu);
507 
508 
509 	gtk_box_pack_start (GTK_BOX (vbox), small_hbox, FALSE, FALSE, 0);
510 
511     menu = gtk_menu_new ();
512     group=NULL;
513 
514     for(i=0;i<2;i++)
515 	{
516     	menuitem = gtk_radio_menu_item_new_with_label (group, render_type[i]);
517     	group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
518     	gtk_menu_append (GTK_MENU (menu), menuitem);
519     	gtk_widget_show (menuitem);
520         gtkwave_signal_connect(GTK_OBJECT (menuitem), "activate", GTK_SIGNAL_FUNC(rendertype_clicked), (void *)((intptr_t)i));
521 	GLOBALS->render_mutex_renderopt_c_1[i]=0;
522 	}
523 
524 	GLOBALS->render_mutex_renderopt_c_1[0]=1;	/* "full" */
525 
526 	optionmenu = gtk_option_menu_new ();
527 	gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), menu);
528 	gtk_box_pack_start (GTK_BOX (small_hbox), optionmenu, TRUE, FALSE, 0);
529 	gtk_widget_show (optionmenu);
530 
531 
532     hbox = gtk_hbox_new (TRUE, 0);
533     gtk_widget_show (hbox);
534 
535     gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
536 
537     button1 = gtk_button_new_with_label ("Select Output File");
538     gtk_widget_set_usize(button1, 100, -1);
539     gtkwave_signal_connect(GTK_OBJECT (button1), "clicked", GTK_SIGNAL_FUNC(ok_callback), NULL);
540     gtk_widget_show (button1);
541     gtk_container_add (GTK_CONTAINER (hbox), button1);
542     GTK_WIDGET_SET_FLAGS (button1, GTK_CAN_DEFAULT);
543     gtkwave_signal_connect_object (GTK_OBJECT (button1), "realize", (GtkSignalFunc) gtk_widget_grab_default, GTK_OBJECT (button1));
544 
545     button2 = gtk_button_new_with_label ("Exit");
546     gtk_widget_set_usize(button2, 100, -1);
547     gtkwave_signal_connect(GTK_OBJECT (button2), "clicked", GTK_SIGNAL_FUNC(destroy_callback), NULL);
548     GTK_WIDGET_SET_FLAGS (button2, GTK_CAN_DEFAULT);
549     gtk_widget_show (button2);
550     gtk_container_add (GTK_CONTAINER (hbox), button2);
551 
552     gtk_widget_show(GLOBALS->window_renderopt_c_6);
553 }
554