1 /*
2  * Copyright (c) Tony Bybell 1999-2013.
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 <gtk/gtk.h>
13 #include "gtk12compat.h"
14 #include "menu.h"
15 #include "debug.h"
16 #include "wavealloca.h"
17 #include <string.h>
18 #include <stdlib.h>
19 /* #include <fnmatch.h> */
20 #ifdef MAC_INTEGRATION
21 #include <cocoa_misc.h>
22 #endif
23 
24 #if defined __MINGW32__
25 #include <windows.h>
26 #endif
27 
28 #if GTK_CHECK_VERSION(2,4,0)
29 
30 #ifndef MAC_INTEGRATION
ffunc(const GtkFileFilterInfo * filter_info,gpointer data)31 static gboolean ffunc (const GtkFileFilterInfo *filter_info, gpointer data)
32 {
33 (void)data;
34 
35 const char *rms = strrchr(filter_info->filename, '\\');
36 const char *rms2;
37 
38 if(!rms) rms = filter_info->filename; else rms++;
39 
40 rms2 = strrchr(rms, '/');
41 if(!rms2) rms2 = rms; else rms2++;
42 
43 if(!GLOBALS->pFileChooseFilterName || !GLOBALS->pPatternSpec)
44 	{
45 	return(TRUE);
46 	}
47 
48 if(!strchr(GLOBALS->pFileChooseFilterName, '*') && !strchr(GLOBALS->pFileChooseFilterName, '?'))
49 	{
50 	char *fpos = strstr(rms2, GLOBALS->pFileChooseFilterName);
51 	return(fpos != NULL);
52 	}
53 	else
54 	{
55 	return(g_pattern_match_string(GLOBALS->pPatternSpec, rms2));
56 	}
57 }
58 
59 static
filter_edit_cb(GtkWidget * widget,GdkEventKey * ev,gpointer * data)60 void filter_edit_cb (GtkWidget *widget, GdkEventKey *ev, gpointer *data)
61 {
62 (void)ev;
63 
64 const char *t;
65 gchar *folder_filename;
66 
67 if(GLOBALS->pFileChooseFilterName)
68         {
69         free_2((char *)GLOBALS->pFileChooseFilterName);
70         GLOBALS->pFileChooseFilterName = NULL;
71         }
72 
73 t = gtk_entry_get_text (GTK_ENTRY (widget));
74 
75 if (t == NULL || *t == 0)
76 	{
77         GLOBALS->pFileChooseFilterName = NULL;
78 	}
79 	else
80         {
81         GLOBALS->pFileChooseFilterName = malloc_2(strlen(t) + 1);
82         strcpy(GLOBALS->pFileChooseFilterName, t);
83 
84 	if(GLOBALS->pPatternSpec) g_pattern_spec_free(GLOBALS->pPatternSpec);
85 	GLOBALS->pPatternSpec = g_pattern_spec_new(t);
86         }
87 
88 /* now force refresh with new filter */
89 folder_filename = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER(data));
90 if(folder_filename)
91 	{
92 	gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER(data), folder_filename);
93 	g_free(folder_filename);
94 	}
95 }
96 
97 
98 static
press_callback(GtkWidget * widget,gpointer * data)99 void press_callback (GtkWidget *widget, gpointer *data)
100 {
101 GdkEventKey ev;
102 
103 filter_edit_cb (widget, &ev, data);
104 }
105 
106 #endif
107 #endif
108 
109 
enter_callback(GtkWidget * widget,GtkFileSelection * fw)110 static void enter_callback(GtkWidget *widget, GtkFileSelection *fw)
111 {
112 (void)widget;
113 (void)fw;
114 
115 G_CONST_RETURN char *allocbuf;
116 int alloclen;
117 
118 allocbuf=gtk_file_selection_get_filename(GTK_FILE_SELECTION(GLOBALS->fs_file_c_1));
119 if((alloclen=strlen(allocbuf)))
120 	{
121 	GLOBALS->filesel_ok=1;
122 	if(*GLOBALS->fileselbox_text) free_2(*GLOBALS->fileselbox_text);
123 	*GLOBALS->fileselbox_text=(char *)malloc_2(alloclen+1);
124 	strcpy(*GLOBALS->fileselbox_text, allocbuf);
125 	}
126 
127 DEBUG(printf("Filesel OK %s\n",allocbuf));
128 wave_gtk_grab_remove(GLOBALS->fs_file_c_1);
129 gtk_widget_destroy(GLOBALS->fs_file_c_1);
130 gtkwave_main_iteration();
131 GLOBALS->cleanup_file_c_2();
132 }
133 
cancel_callback(GtkWidget * widget,GtkWidget * nothing)134 static void cancel_callback(GtkWidget *widget, GtkWidget *nothing)
135 {
136 (void)widget;
137 (void)nothing;
138 
139 DEBUG(printf("Filesel Entry Cancel\n"));
140 wave_gtk_grab_remove(GLOBALS->fs_file_c_1);
141 gtk_widget_destroy(GLOBALS->fs_file_c_1);
142 gtkwave_main_iteration();
143 if(GLOBALS->bad_cleanup_file_c_1) GLOBALS->bad_cleanup_file_c_1();
144 }
145 
destroy_callback(GtkWidget * widget,GtkWidget * nothing)146 static void destroy_callback(GtkWidget *widget, GtkWidget *nothing)
147 {
148 (void)widget;
149 (void)nothing;
150 
151 DEBUG(printf("Filesel Destroy\n"));
152 gtkwave_main_iteration();
153 if(GLOBALS->bad_cleanup_file_c_1) GLOBALS->bad_cleanup_file_c_1();
154 }
155 
fileselbox_old(char * title,char ** filesel_path,GtkSignalFunc ok_func,GtkSignalFunc notok_func,char * pattn,int is_writemode)156 void fileselbox_old(char *title, char **filesel_path, GtkSignalFunc ok_func, GtkSignalFunc notok_func, char *pattn, int is_writemode)
157 {
158 #if defined __MINGW32__
159 OPENFILENAME ofn;
160 char szFile[260];       /* buffer for file name */
161 char szPath[260];       /* buffer for path name */
162 char lpstrFilter[260];	/* more than enough room for some patterns */
163 BOOL rc;
164 #else
165 (void)pattn;
166 (void)is_writemode;
167 #endif
168 
169 GLOBALS->fileselbox_text=filesel_path;
170 GLOBALS->filesel_ok=0;
171 GLOBALS->cleanup_file_c_2=ok_func;
172 GLOBALS->bad_cleanup_file_c_1=notok_func;
173 
174 #if defined __MINGW32__
175 ZeroMemory(&ofn, sizeof(ofn));
176 ofn.lStructSize = sizeof(ofn);
177 ofn.lpstrFile = szFile;
178 ofn.lpstrFile[0] = '\0';
179 ofn.lpstrFilter = lpstrFilter;
180 ofn.nMaxFile = sizeof(szFile);
181 ofn.lpstrFileTitle = NULL;
182 ofn.nMaxFileTitle = 0;
183 ofn.lpstrInitialDir = NULL;
184 ofn.Flags = is_writemode ? (OFN_CREATEPROMPT | OFN_OVERWRITEPROMPT) : (OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST);
185 
186 if((!pattn)||(!strcmp(pattn, "*")))
187 	{
188 	sprintf(lpstrFilter, "%s%c%s%c", "All", 0, "*.*", 0);
189 	ofn.nFilterIndex = 0;
190 	}
191 	else
192 	{
193 	sprintf(lpstrFilter, "%s%c%s%c%s%c%s%c", pattn, 0, pattn, 0, "All", 0, "*.*", 0); /* cppcheck */
194 	ofn.nFilterIndex = 0;
195 	}
196 
197 if(*filesel_path)
198 	{
199 	char *fsp = *filesel_path;
200 	int ch_idx = 0;
201 	char ch = 0;
202 
203 	while(*fsp)
204 		{
205 		ch = *fsp;
206 		szFile[ch_idx++] = (ch != '/') ? ch : '\\';
207 		fsp++;
208 		}
209 
210 	szFile[ch_idx] = 0;
211 
212 	if((ch == '/') || (ch == '\\'))
213 		{
214 		strcpy(szPath, szFile);
215 		szFile[0] = 0;
216 		ofn.lpstrInitialDir = szPath;
217 		}
218 	}
219 
220 rc = is_writemode ? GetSaveFileName(&ofn) : GetOpenFileName(&ofn);
221 
222 if (rc==TRUE)
223 	{
224 	GLOBALS->filesel_ok=1;
225         if(*GLOBALS->fileselbox_text) free_2(*GLOBALS->fileselbox_text);
226 	if(!is_writemode)
227 		{
228 	        *GLOBALS->fileselbox_text=(char *)strdup_2(szFile);
229 		}
230 		else
231 		{
232 		char *suf_str = NULL;
233 		int suf_add = 0;
234 		int szlen = 0;
235 		int suflen = 0;
236 
237 		if(pattn)
238 			{
239 			suf_str = strstr(pattn, "*.");
240 			if(suf_str) suf_str++;
241 			}
242 
243 		if(suf_str)
244 			{
245 			szlen = strlen(szFile);
246 			suflen = strlen(suf_str);
247 			if(suflen > szlen)
248 				{
249 				suf_add = 1;
250 				}
251 				else
252 				{
253 				if(strcasecmp(szFile + (szlen - suflen), suf_str))
254 					{
255 					suf_add = 1;
256 					}
257 				}
258 			}
259 
260 		if(suf_str && suf_add)
261 			{
262 			*GLOBALS->fileselbox_text=(char *)malloc_2(szlen + suflen + 1);
263 			strcpy(*GLOBALS->fileselbox_text, szFile);
264 			strcpy(*GLOBALS->fileselbox_text + szlen, suf_str);
265 			}
266 			else
267 			{
268 		        *GLOBALS->fileselbox_text=(char *)strdup_2(szFile);
269 			}
270 		}
271 
272 	GLOBALS->cleanup_file_c_2();
273 	}
274 	else
275 	{
276 	if(GLOBALS->bad_cleanup_file_c_1) GLOBALS->bad_cleanup_file_c_1();
277 	}
278 
279 #else
280 
281 GLOBALS->fs_file_c_1=gtk_file_selection_new(title);
282 gtkwave_signal_connect(GTK_OBJECT(GLOBALS->fs_file_c_1), "destroy", (GtkSignalFunc) destroy_callback, NULL);
283 gtkwave_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(GLOBALS->fs_file_c_1)->ok_button), "clicked", (GtkSignalFunc) enter_callback, GTK_OBJECT(GLOBALS->fs_file_c_1));
284 gtkwave_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(GLOBALS->fs_file_c_1)->cancel_button),"clicked", (GtkSignalFunc) cancel_callback, GTK_OBJECT(GLOBALS->fs_file_c_1));
285 gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(GLOBALS->fs_file_c_1));
286 if(*GLOBALS->fileselbox_text) gtk_file_selection_set_filename(GTK_FILE_SELECTION(GLOBALS->fs_file_c_1), *GLOBALS->fileselbox_text);
287 
288 /*
289  * XXX: filter on patterns when this feature eventually works (or for a later version of GTK)!
290  * if((pattn)&&(pattn[0])) gtk_file_selection_complete(GTK_FILE_SELECTION(fs), pattn);
291  */
292 
293 gtk_widget_show(GLOBALS->fs_file_c_1);
294 wave_gtk_grab_add(GLOBALS->fs_file_c_1);
295 
296 #endif
297 }
298 
299 
fileselbox(char * title,char ** filesel_path,GtkSignalFunc ok_func,GtkSignalFunc notok_func,char * pattn,int is_writemode)300 void fileselbox(char *title, char **filesel_path, GtkSignalFunc ok_func, GtkSignalFunc notok_func, char *pattn, int is_writemode)
301 {
302 #ifndef MAC_INTEGRATION
303 #if GTK_CHECK_VERSION(2,4,0)
304 int can_set_filename = 0;
305 GtkWidget *pFileChoose;
306 GtkWidget *pWindowMain;
307 GtkFileFilter *filter;
308 GtkWidget *label;
309 GtkWidget *label_ent;
310 GtkWidget *box;
311 GtkTooltips *tooltips;
312 struct Global *old_globals = GLOBALS;
313 #endif
314 #endif
315 
316 /* fix problem where ungrab doesn't occur if button pressed + simultaneous accelerator key occurs */
317 if(GLOBALS->in_button_press_wavewindow_c_1) { gdk_pointer_ungrab(GDK_CURRENT_TIME); }
318 
319 if(!*filesel_path) /* if no name specified, hijack loaded file name path */
320 	{
321 	if(GLOBALS->loaded_file_name)
322 		{
323 		char *can = realpath_2(GLOBALS->loaded_file_name, NULL); /* prevents filechooser from blocking/asking where to save file */
324 		char *tname = strdup_2(can ? can : GLOBALS->loaded_file_name);
325 		char *delim = strrchr(tname, '/');
326 		if(!delim) delim =  strrchr(tname, '\\');
327 		if(delim)
328 			{
329 			*(delim+1) = 0; /* keep slash for gtk_file_chooser_set_filename vs gtk_file_chooser_set_current_folder test below */
330 			*filesel_path = tname;
331 			}
332 			else
333 			{
334 			free_2(tname);
335 			}
336 
337 		free(can);
338 		}
339 	}
340 
341 
342 if(GLOBALS->wave_script_args)
343 	{
344 	char *s = NULL;
345 
346 	GLOBALS->fileselbox_text=filesel_path;
347 	GLOBALS->filesel_ok=1;
348 
349 	while((!s)&&(GLOBALS->wave_script_args->curr)) s = wave_script_args_fgetmalloc_stripspaces(GLOBALS->wave_script_args);
350 
351 	if(*GLOBALS->fileselbox_text) free_2(*GLOBALS->fileselbox_text);
352 	if(!s)
353 		{
354 		fprintf(stderr, "Null filename passed to fileselbox in script, exiting.\n");
355 		exit(255);
356 		}
357 	*GLOBALS->fileselbox_text = s;
358 	fprintf(stderr, "GTKWAVE | Filename '%s'\n", s);
359 
360 	ok_func();
361 	return;
362 	}
363 
364 #ifdef MAC_INTEGRATION
365 
366 GLOBALS->fileselbox_text=filesel_path;
367 GLOBALS->filesel_ok=0;
368 char *rc = gtk_file_req_bridge(title, *filesel_path, pattn, is_writemode);
369 if(rc)
370 	{
371         GLOBALS->filesel_ok=1;
372 
373         if(*GLOBALS->fileselbox_text) free_2(*GLOBALS->fileselbox_text);
374         *GLOBALS->fileselbox_text=strdup_2(rc);
375 	g_free(rc);
376 	if(ok_func) ok_func();
377 	}
378 	else
379 	{
380 	if(notok_func) notok_func();
381 	}
382 return;
383 
384 #else
385 
386 #if defined __MINGW32__ || !GTK_CHECK_VERSION(2,4,0)
387 
388 fileselbox_old(title, filesel_path, ok_func, notok_func, pattn, is_writemode);
389 return;
390 
391 #else
392 
393 
394 pWindowMain = GLOBALS->mainwindow;
395 GLOBALS->fileselbox_text=filesel_path;
396 GLOBALS->filesel_ok=0;
397 
398 if(*GLOBALS->fileselbox_text && (!g_path_is_absolute(*GLOBALS->fileselbox_text)))
399 	{
400 #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED || defined __CYGWIN__ || defined HAVE_REALPATH
401 	char *can = realpath_2(*GLOBALS->fileselbox_text, NULL);
402 
403 	if(can)
404 		{
405 		if(*GLOBALS->fileselbox_text) free_2(*GLOBALS->fileselbox_text);
406 	        *GLOBALS->fileselbox_text=(char *)malloc_2(strlen(can)+1);
407 	        strcpy(*GLOBALS->fileselbox_text, can);
408 		free(can);
409 		can_set_filename = 1;
410 		}
411 #else
412 #if __GNUC__
413 #warning Absolute file path warnings might be issued by the file chooser dialogue on this system!
414 #endif
415 #endif
416 	}
417 	else
418 	{
419 	if(*GLOBALS->fileselbox_text)
420 		{
421 		can_set_filename = 1;
422 		}
423 	}
424 
425 if(is_writemode)
426 	{
427 	pFileChoose = gtk_file_chooser_dialog_new(
428 		title,
429 	        NULL,
430 	        GTK_FILE_CHOOSER_ACTION_SAVE,
431 	        GTK_STOCK_CANCEL,
432 	        GTK_RESPONSE_CANCEL,
433 	        GTK_STOCK_SAVE,
434 	        GTK_RESPONSE_ACCEPT,
435 	        NULL);
436 
437 #if GTK_CHECK_VERSION(2,8,0)
438 	gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER (pFileChoose), TRUE);
439 #endif
440 	}
441 	else
442 	{
443 	pFileChoose = gtk_file_chooser_dialog_new(
444 		title,
445 	        NULL,
446 	        GTK_FILE_CHOOSER_ACTION_OPEN,
447 	        GTK_STOCK_CANCEL,
448 	        GTK_RESPONSE_CANCEL,
449 	        GTK_STOCK_OPEN,
450 	        GTK_RESPONSE_ACCEPT,
451 	        NULL);
452 	}
453 
454 GLOBALS->pFileChoose = pFileChoose;
455 
456 if((can_set_filename) && (*filesel_path))
457 	{
458 	int flen = strlen(*filesel_path);
459 	if(((*filesel_path)[flen-1]=='/') || ((*filesel_path)[flen-1]=='\\'))
460 		{
461 		gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(pFileChoose), *filesel_path);
462 		}
463 		else
464 		{
465 		gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(pFileChoose), *filesel_path);
466 		}
467 	}
468 
469 
470 label=gtk_label_new("Custom Filter:");
471 label_ent=gtk_entry_new_with_max_length(40);
472 
473 tooltips=gtk_tooltips_new_2();
474 gtk_tooltips_set_delay_2(tooltips,1500);
475 
476 gtk_entry_set_text(GTK_ENTRY(label_ent), GLOBALS->pFileChooseFilterName ? GLOBALS->pFileChooseFilterName : "*");
477 gtk_signal_connect (GTK_OBJECT (label_ent), "changed",GTK_SIGNAL_FUNC (press_callback), pFileChoose);
478 box=gtk_hbox_new(FALSE, 0);
479 gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
480 gtk_widget_show(label);
481 gtk_box_pack_start(GTK_BOX(box), label_ent, FALSE, FALSE, 0);
482 gtk_widget_set_usize(GTK_WIDGET(label_ent), 300, 22);
483 gtk_tooltips_set_tip_2(tooltips, label_ent, "Enter custom pattern match filter here. Note that \"string\" without * or ? achieves a match on \"*string*\".", NULL);
484 gtk_widget_show(label_ent);
485 gtk_widget_show(box);
486 
487 gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(pFileChoose), box);
488 
489 if(pattn)
490 	{
491 	int is_gtkw = suffix_check(pattn, ".gtkw");
492 	int is_sav = suffix_check(pattn, ".sav");
493 
494 	filter = gtk_file_filter_new();
495 	gtk_file_filter_add_pattern(filter, pattn);
496 	gtk_file_filter_set_name(filter, pattn);
497 	gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(pFileChoose), filter);
498 
499 	if(is_gtkw || is_sav)
500 		{
501 		const char *pattn2 = is_sav ? "*.gtkw" : "*.sav";
502 
503 		filter = gtk_file_filter_new();
504 		gtk_file_filter_add_pattern(filter, pattn2);
505 		gtk_file_filter_set_name(filter, pattn2);
506 		gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(pFileChoose), filter);
507 		}
508 	}
509 
510 if((!pattn)  || (strcmp(pattn, "*")))
511 	{
512 	filter = gtk_file_filter_new();
513 	gtk_file_filter_add_pattern(filter, "*");
514 	gtk_file_filter_set_name(filter, "*");
515 	gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(pFileChoose), filter);
516 	}
517 
518 filter = gtk_file_filter_new();
519 gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME, ffunc, NULL, NULL);
520 gtk_file_filter_set_name(filter, "Custom");
521 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(pFileChoose), filter);
522 if(GLOBALS->pFileChooseFilterName)
523 	{
524 	GLOBALS->pPatternSpec = g_pattern_spec_new(GLOBALS->pFileChooseFilterName);
525 	}
526 
527 gtk_dialog_set_default_response(GTK_DIALOG(pFileChoose), GTK_RESPONSE_ACCEPT);
528 
529 gtk_object_set_data(GTK_OBJECT(pFileChoose), "FileChooseWindow", pFileChoose);
530 gtk_container_set_border_width(GTK_CONTAINER(pFileChoose), 10);
531 gtk_window_set_position(GTK_WINDOW(pFileChoose), GTK_WIN_POS_CENTER);
532 gtk_window_set_modal(GTK_WINDOW(pFileChoose), TRUE);
533 gtk_window_set_policy(GTK_WINDOW(pFileChoose), FALSE, FALSE, FALSE);
534 gtk_window_set_resizable(GTK_WINDOW(pFileChoose), TRUE); /* some distros need this */
535 if(pWindowMain)
536 	{
537 	gtk_window_set_transient_for(GTK_WINDOW(pFileChoose), GTK_WINDOW(pWindowMain));
538 	}
539 gtk_widget_show(pFileChoose);
540 wave_gtk_grab_add(pFileChoose);
541 
542 /* check against old_globals is because of DnD context swapping so make response fail */
543 
544 if((gtk_dialog_run(GTK_DIALOG (pFileChoose)) == GTK_RESPONSE_ACCEPT) &&
545 		(GLOBALS == old_globals) && (GLOBALS->fileselbox_text))
546 	{
547 	G_CONST_RETURN char *allocbuf;
548 	int alloclen;
549 
550 	allocbuf = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (pFileChoose));
551 	if((alloclen=strlen(allocbuf)))
552 	        {
553 		int gtkw_test = 0;
554 
555 	        GLOBALS->filesel_ok=1;
556 
557 	        if(*GLOBALS->fileselbox_text) free_2(*GLOBALS->fileselbox_text);
558 	        *GLOBALS->fileselbox_text=(char *)malloc_2(alloclen+1);
559 	        strcpy(*GLOBALS->fileselbox_text, allocbuf);
560 
561 		/* add missing suffix to write files */
562 		if(pattn && is_writemode)
563 			{
564 			char *s = *GLOBALS->fileselbox_text;
565 			char *s2;
566 			char *suffix = wave_alloca(strlen(pattn) + 1);
567 			char *term;
568 			int attempt_suffix = 1;
569 
570 			strcpy(suffix, pattn);
571 			while((*suffix) && (*suffix != '.')) suffix++;
572 			term = *suffix ? suffix+1 : suffix;
573 			while((*term) && (isalnum((int)(unsigned char)*term))) term++;
574 			*term = 0;
575 
576 			gtkw_test = suffix_check(pattn, ".gtkw") || suffix_check(pattn, ".sav");
577 
578 			if(gtkw_test)
579 				{
580 				attempt_suffix = (!suffix_check(s, ".gtkw")) && (!suffix_check(s, ".sav"));
581 				}
582 
583 			if(attempt_suffix)
584 				{
585 	                        if(strlen(s) > strlen(suffix))
586 	                                {
587 	                                if(strcmp(s + strlen(s) - strlen(suffix), suffix))
588 	                                        {
589 	                                        goto fix_suffix;
590 	                                        }
591 	                                }
592 	                                else
593 	                                {
594 fix_suffix: 	                    	s2 = malloc_2(strlen(s) + strlen(suffix) + 1);
595 	                                strcpy(s2, s);
596 	                                strcat(s2, suffix);
597 	                                free_2(s);
598 					*GLOBALS->fileselbox_text = s2;
599 	                                }
600 				}
601 			}
602 
603 		if((gtkw_test) && (*GLOBALS->fileselbox_text))
604 			{
605 			GLOBALS->is_gtkw_save_file = suffix_check(*GLOBALS->fileselbox_text, ".gtkw");
606 			}
607 	        }
608 
609 	DEBUG(printf("Filesel OK %s\n",allocbuf));
610 	wave_gtk_grab_remove(pFileChoose);
611 	gtk_widget_destroy(pFileChoose);
612 	GLOBALS->pFileChoose = NULL; /* keeps DND from firing */
613 
614 	gtkwave_main_iteration();
615 	ok_func();
616 	}
617 	else
618 	{
619 	DEBUG(printf("Filesel Entry Cancel\n"));
620 	wave_gtk_grab_remove(pFileChoose);
621 	gtk_widget_destroy(pFileChoose);
622 	GLOBALS->pFileChoose = NULL; /* keeps DND from firing */
623 
624 	gtkwave_main_iteration();
625 	if(GLOBALS->bad_cleanup_file_c_1) notok_func();
626 	}
627 
628 if(GLOBALS->pPatternSpec)
629 	{
630 	g_pattern_spec_free(GLOBALS->pPatternSpec);
631 	GLOBALS->pPatternSpec = NULL;
632 	}
633 
634 #endif
635 
636 #endif
637 }
638 
639