1 /* Hey EMACS -*- linux-c -*- */
2 /* $Id: filesel.c 2730 2007-12-16 15:54:33Z roms $ */
3 
4 /*  TiEmu - Tiemu Is an EMUlator
5  *
6  *  Copyright (c) 2000-2001, Thomas Corvazier, Romain Lievin
7  *  Copyright (c) 2001-2003, Romain Lievin
8  *  Copyright (c) 2003, Julien Blache
9  *  Copyright (c) 2004, Romain Li�vin
10  *  Copyright (c) 2005-2007, Romain Li�vin, Kevin Kofler
11  *
12  *  Carbon file dialog code lifted from Systool (LGPL):
13  *  Copyright (c) 2006 Asger Ottar Alstrup, Nicolas Cannasse, Edwin van Rijkom
14  *
15  *  This program is free software; you can redistribute it and/or modify
16  *  it under the terms of the GNU General Public License as published by
17  *  the Free Software Foundation; either version 2 of the License, or
18  *  (at your option) any later version.
19  *  This program is distributed in the hope that it will be useful,
20  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  *  GNU General Public License for more details. *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, write to the Free Software
25  *  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
26  */
27 
28 /*
29 	Some informations about these file selectors: starting at tifiles2-v0.0.6, we
30 	use the 'glib filename encoding' scheme for charset encoding of filenames:
31 	- UTF-8 charset on Windows,
32 	- locale charset on Linux (usually UTF-8 but this is not always true).
33 
34 	GTK+ always uses UTF-8 for widgets (label, file selectors, ...) thus some conversions
35 	may be needed.
36 */
37 
38 #ifdef HAVE_CONFIG_H
39 #  include <config.h>
40 #endif				/*  */
41 
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <gtk/gtk.h>
45 #include <string.h>
46 
47 #ifdef __WIN32__
48 #include <windows.h>
49 #include <wchar.h>
50 #if defined(__GNUC__) && ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)))
51 	typedef OPENFILENAME OPENFILENAME_MAYALIAS __attribute__((may_alias));
52 #else
53 	typedef OPENFILENAME OPENFILENAME_MAYALIAS;
54 #endif
55 #endif
56 
57 #ifdef HAVE_CARBON_CARBON_H
58 #include <Carbon/Carbon.h>
59 #endif
60 
61 #if WITH_KDE
62 #include "kde.h"
63 #endif
64 
65 #include "intl.h"
66 #include "filesel.h"
67 #include "refresh.h"
68 #include "struct.h"
69 
70 /* In case some header happens to define this... */
71 #undef HAVE_CARBON_CARBON_H
72 
73 #ifdef HAVE_CARBON_CARBON_H
74 /* Helpers */
75 #define PATH_SIZE 2048
76 
GetFSRefFromAEDesc(FSRef * fsRef,AEDesc * theItem)77 static OSStatus GetFSRefFromAEDesc( FSRef *fsRef, AEDesc* theItem ) {
78         OSStatus err = noErr;
79         AEDesc coerceDesc= { 0, NULL };
80         if ( theItem->descriptorType != typeFSRef )     {
81                 err = AECoerceDesc( theItem, typeFSRef, &coerceDesc );
82                 if ( err == noErr )
83                 theItem = &coerceDesc;
84         }
85         if ( err == noErr )
86         err = AEGetDescData( theItem, fsRef, sizeof(*fsRef) );
87         AEDisposeDesc( &coerceDesc );
88 
89         if ( err != noErr )     {
90                 FSSpec fsSpec;
91                 AEDesc coerceDesc2 = {0, NULL};
92                 if ( theItem->descriptorType != typeFSS ) {
93                         err = AECoerceDesc( theItem, typeFSS, &coerceDesc2 );
94                         theItem = &coerceDesc2;
95                 }
96                 if ( err == noErr )
97                 err = AEGetDescData( theItem, &fsSpec, sizeof(fsSpec) );
98                 AEDisposeDesc( &coerceDesc2 );
99                 if ( err == noErr )
100                 err = FSpMakeFSRef( &fsSpec, fsRef );
101         }
102         return(err);
103 }
104 
filterProc(AEDesc * theItem,void * info,void * callBackUD,NavFilterModes filterMode)105 static Boolean filterProc(AEDesc * theItem, void * info, void * callBackUD, NavFilterModes filterMode) {
106         const gchar **filters = (const gchar **) callBackUD;
107         if (!filters)
108                 return 1;
109 
110         NavFileOrFolderInfo *i = (NavFileOrFolderInfo*) info;
111         if (i->isFolder)
112                 return 1;
113 
114         if (theItem->descriptorType==typeFSRef) {
115                 FSRef f;
116                 UInt8 path[PATH_SIZE];
117 
118                 GetFSRefFromAEDesc(&f,theItem);
119                 if (FSRefMakePath (&f,path,PATH_SIZE)==noErr) {
120                         char *ext = NULL;
121                         char *next = (char*) path;
122                         while(next) {
123                                 next = strchr(next,'.');
124                                 if (next)
125                                         ext = ++next;
126                         }
127                         if(ext) {
128                                 while(*filters) {
129                                         const gchar *filter=*(filters++);
130                                         if (*(filter++)=='*' && *filter=='.') {
131                                                 next = ext;
132                                                 while (*(++filter)) {
133                                                         if (!*next) break;
134                                                         if (*filter=='?') {
135                                                                 next++;
136                                                         } else if (*filter!=*(next++)) break;
137                                                 }
138                                                 if (!*filter && !*next)
139                                                         return 1;
140                                         }
141                                 }
142                         }
143                 }
144                 return 0;
145         }
146         return 1;
147 }
148 #endif
149 
150 /* Single file selectors */
151 
152 static gchar *fname = NULL;
153 static gint action = 0;
154 
155 // GTK >= 2.4
create_fsel_2(gchar * dirname,gchar * filename,gchar * ext,gboolean save)156 static const gchar* create_fsel_2(gchar *dirname, gchar *filename, gchar *ext, gboolean save)
157 {
158 	GtkWidget *dialog;
159 	GtkFileFilter *filter;
160 	gchar *path, *tmp;
161 	gchar **sarray;
162 	gint i;
163 	gchar *sfilename, *sext;
164 
165 	// gtk_file_chooser_set_current_name and gtk_file_filter_add_pattern ALWAYS want UTF-8.
166 	sfilename = filename ? g_filename_to_utf8(filename,-1,NULL,NULL,NULL) : NULL;
167 	sext = ext ? g_filename_to_utf8(ext,-1,NULL,NULL,NULL) : NULL;
168 
169 	// create box
170 	dialog = gtk_file_chooser_dialog_new (
171 					  save ? "Save File" : "Open File",
172 				      NULL,
173 					  save ? GTK_FILE_CHOOSER_ACTION_SAVE : GTK_FILE_CHOOSER_ACTION_OPEN,
174 				      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
175 				      GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
176 				      NULL);
177 
178 	// set default folder
179 	tmp = g_strconcat(dirname, G_DIR_SEPARATOR_S, NULL);	// add trailing '/' otherwise get_dirname is confused
180 	path = g_path_get_dirname(tmp);
181 	g_free(tmp);
182 
183 	gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path);
184 	g_free(path);
185 
186 	// set default name
187 	if(filename)
188 		gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), sfilename);
189 
190 	// set wildcards
191 	filter = gtk_file_filter_new();
192 	sarray = g_strsplit(sext, ";", -1);
193 	for(i = 0; sarray[i] != NULL; i++)
194 		gtk_file_filter_add_pattern (filter, sarray[i]);
195 	g_strfreev(sarray);
196 	gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter);
197 
198 	// get result
199 	g_free(fname);
200 	if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
201 		fname = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
202 	else
203 		fname = NULL;
204 	gtk_widget_destroy (dialog);
205 
206 	g_free(sfilename);
207 	g_free(sext);
208 
209 	return fname;
210 }
211 
212 // WIN32
create_fsel_3(gchar * dirname,gchar * filename,gchar * ext,gboolean save)213 static const gchar* create_fsel_3(gchar *dirname, gchar *filename, gchar *ext, gboolean save)
214 {
215 #if defined(__WIN32__)
216 	OPENFILENAME_MAYALIAS o;
217 	char lpstrFile[2048] = "\0";
218 	char lpstrFilter[512];
219 	char *p;
220 	gchar **sarray;
221 	int i, n;
222 	int have_widechar = G_WIN32_HAVE_WIDECHAR_API();
223 	void *sdirname;
224 
225 	// clear structure
226 	memset (&o, 0, sizeof(OPENFILENAME));
227 
228 	// set default filename
229 	if(filename)
230 	{
231 		void *temp;
232 		if (have_widechar)
233 		{
234 			temp = g_utf8_to_utf16(filename,-1,NULL,NULL,NULL);
235 			if(!temp) return NULL;
236 			wcsncpy((wchar_t *)lpstrFile, temp, sizeof(lpstrFile)>>1);
237 		}
238 		else
239 		{
240 			temp = g_locale_from_utf8(filename,-1,NULL,NULL,NULL);
241 			if(!temp) return NULL;
242 			strncpy(lpstrFile, temp, sizeof(lpstrFile));
243 		}
244 		g_free(temp);
245 	}
246 
247 	// format filter
248 	sarray = g_strsplit(ext, "|", -1);
249 	for(n = 0; sarray[n] != NULL; n++);
250 
251 	for(i = 0, p = lpstrFilter; i < n; i++)
252 	{
253 		void *temp;
254 		if (have_widechar)
255 		{
256 			temp = g_utf8_to_utf16(sarray[i],-1,NULL,NULL,NULL);
257 			wcscpy((wchar_t *)p,temp);
258 			p += (wcslen(temp)<<1);
259 			*p++ = '\0';
260 			*p++ = '\0';
261 			wcscpy((wchar_t *)p,temp);
262 			p += (wcslen(temp)<<1);
263 			*p++ = '\0';
264 			*p++ = '\0';
265 		}
266 		else
267 		{
268 			temp = g_locale_from_utf8(sarray[i],-1,NULL,NULL,NULL);
269 			strcpy(p,temp);
270 			p += strlen(temp);
271 			*p++ = '\0';
272 			strcpy(p,temp);
273 			p += strlen(temp);
274 			*p++ = '\0';
275 		}
276 		g_free(temp);
277 	}
278 	*p++ = '\0';
279 	if (have_widechar)
280 		*p++ = '\0';
281 	g_strfreev(sarray);
282 
283 	// set structure
284 	o.lStructSize = sizeof (o);
285 	o.lpstrFilter = lpstrFilter;	//"All\0*.*\0Text\0*.TXT\0";
286 	o.lpstrFile = lpstrFile;
287 	if (have_widechar)
288 	{
289 		o.nMaxFile = sizeof(lpstrFile) >> 1;
290 		sdirname = g_utf8_to_utf16(dirname,-1,NULL,NULL,NULL);
291 	}
292 	else
293 	{
294 		o.nMaxFile = sizeof(lpstrFile);
295 		sdirname = g_locale_from_utf8(dirname,-1,NULL,NULL,NULL);
296 	}
297 	o.lpstrInitialDir = sdirname;
298 	o.Flags = 0x02000000 | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY |
299 				 OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_LONGNAMES | OFN_NONETWORKBUTTON;
300 
301 	// open/close
302 	if(save)
303 	{
304 		if(!(have_widechar ? GetSaveFileNameW((OPENFILENAMEW *)&o) : GetSaveFileName((OPENFILENAME *)&o)))
305 		{
306 			g_free(sdirname);
307 			return fname = NULL;
308 		}
309 	}
310 	else
311 	{
312 		if(!(have_widechar ? GetOpenFileNameW((OPENFILENAMEW *)&o) : GetOpenFileName((OPENFILENAME *)&o)))
313 		{
314 			g_free(sdirname);
315 			return fname = NULL;
316 		}
317 	}
318 
319 	g_free(sdirname);
320 
321 	if (have_widechar)
322 		fname = g_utf16_to_utf8((wchar_t *)lpstrFile,-1,NULL,NULL,NULL);
323 	else
324 		fname = g_locale_to_utf8(lpstrFile,-1,NULL,NULL,NULL);
325 	return fname;
326 #elif defined(HAVE_CARBON_CARBON_H)
327         NavDialogRef ref;
328         NavDialogCreationOptions opt;
329         OSStatus ret;
330         gchar **sarray=NULL;
331 
332         fname = NULL;
333         NavGetDefaultDialogCreationOptions(&opt);
334         opt.clientName = CFSTR("TiEmu");
335         opt.modality = kWindowModalityAppModal;
336         opt.optionFlags = kNavDefaultNavDlogOptions | kNavAllFilesInPopup;
337 
338         if (save) {
339                 ret = NavCreatePutFileDialog(&opt,0,kNavGenericSignature,NULL,NULL,&ref);
340         } else {
341                 sarray = g_strsplit(ext, ";", -1);
342                 ret = NavCreateChooseFileDialog(&opt,NULL,NULL,NULL,filterProc,sarray,&ref);
343         }
344         if (ret == noErr) {
345                 if (NavDialogRun(ref) == noErr) {
346                         if (NavDialogGetUserAction(ref) == save?kNavUserActionSaveAs:kNavUserActionChoose) {
347                                 NavReplyRecord reply;
348                                 if (NavDialogGetReply(ref,&reply)  == kNavNormalState) {
349                                         FSRef fsref;
350                                         AEGetNthPtr(&reply.selection,1,typeFSRef,0,0,&fsref,sizeof(FSRef),0);
351                                         fname = g_malloc(PATH_SIZE);
352                                         memset(fname,0,PATH_SIZE);
353                                         if (FSRefMakePath (&fsref,(UInt8*)fname,PATH_SIZE-(save?1:0))==noErr) {
354                                                 if (save) {
355                                                         strcat(fname,"/");
356                                                         CFStringGetCString(reply.saveFileName,fname+strlen(fname),PATH_SIZE-strlen(fname),kCFStringEncodingUTF8);
357                                                 }
358                                         } else {
359                                                 g_free(fname);
360                                                 fname = NULL;
361                                         }
362                                         NavDisposeReply(&reply);
363                                 }
364                         }
365                 }
366                 NavDialogDispose(ref);
367         }
368         if (!save) g_strfreev(sarray);
369         return fname;
370 #endif
371 
372 	return NULL;
373 }
374 
375 // KDE
create_fsel_4(gchar * dirname,gchar * filename,gchar * ext,gboolean save)376 static const gchar* create_fsel_4(gchar *dirname, gchar *filename, gchar *ext, gboolean save)
377 {
378 #if WITH_KDE
379 	gchar *p;
380 	gchar *extspaces = g_strdup(ext);
381 
382 	p = extspaces;
383 	while ((p = strchr(p, ';'))) *p = ' ';
384 
385 	if(save)
386 	{
387 		if (filename)
388 			dirname = g_strconcat(dirname, "/", filename, NULL);
389 		fname = sp_kde_get_write_filename(dirname, extspaces, _("Save file"));
390 	}
391 	else
392 		fname = sp_kde_get_open_filename(dirname, extspaces, _("Open file"));
393 
394 	g_free(extspaces);
395 	return fname;
396 #endif
397 
398 	return NULL;
399 }
400 
401 // Front-end
create_fsel(gchar * dirname,gchar * filename,gchar * ext,gboolean save)402 const gchar *create_fsel(gchar *dirname, gchar *filename, gchar *ext, gboolean save)
403 {
404 #if !defined(__WIN32__) && !defined(HAVE_CARBON_CARBON_H)
405 	if(options.fs_type == 2)
406 	{
407 #if WITH_KDE
408 		const char *p = getenv("KDE_FULL_SESSION");
409 		if (p && *p) // KDE is running
410 			options.fs_type = 3;
411 		else
412 #endif
413 			options.fs_type = 1;
414 	}
415 #endif
416 #if !WITH_KDE
417 	if(options.fs_type == 3)
418 		options.fs_type = 1;
419 #endif
420 	//printf("%i: <%s> <%s> <%s> %i\n", options.fs_type, dirname, filename, ext, save);
421 
422 	switch(options.fs_type)
423 	{
424 	case 0:
425 	case 1:	return create_fsel_2(dirname, filename, ext, save);
426 	case 2: return create_fsel_3(dirname, filename, ext, save);
427 	case 3: return create_fsel_4(dirname, filename, ext, save);
428 	default: return NULL;
429 	}
430 
431 	return NULL;
432 }
433 
434 /* Multiple files selectors */
435 
436 static gchar** filenames = NULL;
437 static gint actions = 0;
438 
439 // GTK >= 2.4
create_fsels_2(gchar * dirname,gchar * filename,gchar * ext)440 static gchar** create_fsels_2(gchar *dirname, gchar *filename, gchar *ext)
441 {
442 	GtkWidget *dialog;
443 	GtkFileFilter *filter;
444 	gchar *path, *tmp;
445 	gchar **sarray;
446 	gint i;
447 	gchar *sfilename, *sext;
448 
449 	// gtk_file_chooser_set_current_name and gtk_file_filter_add_pattern ALWAYS want UTF-8.
450 	sfilename = filename ? g_filename_to_utf8(filename,-1,NULL,NULL,NULL) : NULL;
451 	sext = ext ? g_filename_to_utf8(ext,-1,NULL,NULL,NULL) : NULL;
452 
453 	// create box
454 	dialog = gtk_file_chooser_dialog_new ("Open File",
455 				      NULL,
456 					  GTK_FILE_CHOOSER_ACTION_OPEN,
457 				      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
458 				      GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
459 				      NULL);
460 
461 	// set default folder
462 	tmp = g_strconcat(dirname, G_DIR_SEPARATOR_S, NULL);	// add trailing '/' otherwise get_dirname is confused
463 	path = g_path_get_dirname(tmp);
464 	g_free(tmp);
465 
466 	gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path);
467 	g_free(path);
468 
469 	// set multiple selection
470 	gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE);
471 
472 	// set default name
473 	if(filename)
474 		gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), sfilename);
475 
476 	// set wildcards
477 	filter = gtk_file_filter_new();
478 	sarray = g_strsplit(sext, ";", -1);
479 	for(i = 0; sarray[i] != NULL; i++)
480 		gtk_file_filter_add_pattern (filter, sarray[i]);
481 	g_strfreev(sarray);
482 	gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter);
483 
484 	// get result
485 	if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
486 	{
487 		GSList *list, *p;
488 		gchar **q;
489 
490 		// convert list into string array
491 		list=gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER (dialog));
492 
493 		filenames = (gchar **)g_malloc0((g_slist_length(list)+1) *
494 						sizeof(gchar *));
495 		for(p = list, q = filenames; p; p = g_slist_next(p), q++)
496 			*q = p->data;
497 		*q = NULL;
498 
499 		g_slist_free(list);
500 	}
501 	else
502 		filenames = NULL;
503 	gtk_widget_destroy (dialog);
504 
505 	g_free(sfilename);
506 	g_free(sext);
507 
508 	return filenames;
509 }
510 
511 // WIN32
create_fsels_3(gchar * dirname,gchar * filename,gchar * ext)512 static gchar** create_fsels_3(gchar *dirname, gchar *filename, gchar *ext)
513 {
514 #if defined(__WIN32__)
515 	OPENFILENAME_MAYALIAS o;
516 	char lpstrFile[2048] = "\0";
517 	char lpstrFilter[512];
518 	char *p;
519 	gchar **sarray;
520 	int i, n;
521 	int have_widechar = G_WIN32_HAVE_WIDECHAR_API();
522 	void *sdirname;
523 	gchar *temp1;
524 
525 	// clear structure
526 	memset (&o, 0, sizeof(OPENFILENAME));
527 
528 	// set default filename
529 	if(filename)
530 	{
531 		void *temp;
532 		if (have_widechar)
533 		{
534 			temp = g_utf8_to_utf16(filename,-1,NULL,NULL,NULL);
535 			if(!temp) return NULL;
536 			wcsncpy((wchar_t *)lpstrFile, temp, sizeof(lpstrFile)>>1);
537 		}
538 		else
539 		{
540 			temp = g_locale_from_utf8(filename,-1,NULL,NULL,NULL);
541 			if(!temp) return NULL;
542 			strncpy(lpstrFile, temp, sizeof(lpstrFile));
543 		}
544 		g_free(temp);
545 	}
546 
547 	// format filter
548 	sarray = g_strsplit(ext, "|", -1);
549 	for(n = 0; sarray[n] != NULL; n++);
550 
551 	for(i = 0, p = lpstrFilter; i < n; i++)
552 	{
553 		void *temp;
554 		if (have_widechar)
555 		{
556 			temp = g_utf8_to_utf16(sarray[i],-1,NULL,NULL,NULL);
557 			wcscpy((wchar_t *)p,temp);
558 			p += (wcslen(temp)<<1);
559 			*p++ = '\0';
560 			*p++ = '\0';
561 			wcscpy((wchar_t *)p,temp);
562 			p += (wcslen(temp)<<1);
563 			*p++ = '\0';
564 			*p++ = '\0';
565 		}
566 		else
567 		{
568 			temp = g_locale_from_utf8(sarray[i],-1,NULL,NULL,NULL);
569 			strcpy(p,temp);
570 			p += strlen(temp);
571 			*p++ = '\0';
572 			strcpy(p,temp);
573 			p += strlen(temp);
574 			*p++ = '\0';
575 		}
576 		g_free(temp);
577 	}
578 	*p++ = '\0';
579 	if (have_widechar)
580 		*p++ = '\0';
581 	g_strfreev(sarray);
582 
583 	// set structure
584 	o.lStructSize = sizeof (o);
585 	o.lpstrFilter = lpstrFilter;	//"All\0*.*\0Text\0*.TXT\0";
586 	o.lpstrFile = lpstrFile;		//"C:\msvc\tilp\0foo.txt\0bar.txt"
587 	if (have_widechar)
588 	{
589 		o.nMaxFile = sizeof(lpstrFile) >> 1;
590 		sdirname = g_utf8_to_utf16(dirname,-1,NULL,NULL,NULL);
591 	}
592 	else
593 	{
594 		o.nMaxFile = sizeof(lpstrFile);
595 		sdirname = g_locale_from_utf8(dirname,-1,NULL,NULL,NULL);
596 	}
597 	o.lpstrInitialDir = sdirname;
598 	o.Flags = 0x02000000 | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY |
599 				 OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_LONGNAMES | OFN_NONETWORKBUTTON |
600 				 OFN_ALLOWMULTISELECT;
601 
602 	// open selector
603 	if(!(have_widechar ? GetOpenFileNameW((OPENFILENAMEW *)&o) : GetOpenFileName((OPENFILENAME *)&o)))
604 	{
605 		g_free(sdirname);
606 		return NULL;
607 	}
608 	filenames = NULL;
609 
610 	// converts resulting string
611 	if (have_widechar)
612 		temp1 = g_utf16_to_utf8((wchar_t *)lpstrFile,-1,NULL,NULL,NULL);
613 	else
614 		temp1 = g_locale_to_utf8(lpstrFile,-1,NULL,NULL,NULL);
615 	for(p = lpstrFile, i=0; *p;
616 	    p += have_widechar?((wcslen((wchar_t *)p)+1)<<1):(strlen(p)+1), i++)
617 	{
618 		if(i)	// skip directory
619 		{
620 			gchar *temp;
621 			filenames = g_realloc(filenames, (i+1) * sizeof(gchar *));
622 			if (have_widechar)
623 				temp = g_utf16_to_utf8((wchar_t *)p,-1,NULL,NULL,NULL);
624 			else
625 				temp = g_locale_to_utf8(p,-1,NULL,NULL,NULL);
626 			filenames[i-1] = g_strconcat(temp1, G_DIR_SEPARATOR_S, temp, NULL);
627 			g_free(temp);
628 		}
629 	}
630 	g_free(temp1);
631 
632 	// one file selected ?
633 	if(i == 1)
634 	{
635 		filenames = g_malloc(2 * sizeof(gchar *));
636 		if (have_widechar)
637 			filenames[0] = g_utf16_to_utf8((wchar_t *)lpstrFile,-1,NULL,NULL,NULL);
638 		else
639 			filenames[0] = g_locale_to_utf8(lpstrFile,-1,NULL,NULL,NULL);
640 		filenames[1] = NULL;
641 	}
642 	else
643 		filenames[i-1] = NULL;
644 
645 	g_free(sdirname);
646 
647 	return filenames;
648 #elif defined(HAVE_CARBON_CARBON_H)
649         NavDialogRef ref;
650         NavDialogCreationOptions opt;
651         gchar **sarray;
652 
653         filenames = NULL;
654         NavGetDefaultDialogCreationOptions(&opt);
655         opt.clientName = CFSTR("TiEmu");
656         opt.modality = kWindowModalityAppModal;
657         opt.optionFlags = kNavDefaultNavDlogOptions | kNavAllFilesInPopup;
658 
659         sarray = g_strsplit(ext, ";", -1);
660         if (NavCreateGetFileDialog(&opt,NULL,NULL,NULL,filterProc,sarray,&ref) == noErr) {
661 
662                 if (NavDialogRun(ref) == noErr) {
663                         if (NavDialogGetUserAction(ref)==kNavUserActionOpen) {
664                                 NavReplyRecord reply;
665                                 if (NavDialogGetReply(ref,&reply) == kNavNormalState) {
666                                         long count;
667                                         AECountItems(&reply.selection, &count);
668                                         if (count) {
669                                                 filenames = (gchar **) g_malloc0((count+1)*sizeof(gchar*));
670                                                 while(count>0) {
671                                                         FSRef fsref;
672                                                         AEGetNthPtr(&reply.selection,count--,typeFSRef,0,0,&fsref,sizeof(FSRef),0);
673                                                         filenames[count] = g_malloc(PATH_SIZE);
674                                                         memset(filenames[count],0,PATH_SIZE);
675                                                         if (FSRefMakePath (&fsref,(UInt8*)filenames[count],PATH_SIZE)!=noErr) {
676                                                                g_strfreev(filenames);
677                                                                filenames = NULL;
678                                                         }
679                                                 }
680                                         }
681                                         NavDisposeReply(&reply);
682                                 }
683                         }
684                 }
685                 NavDialogDispose(ref);
686         }
687         g_strfreev(sarray);
688         return filenames;
689 #endif
690 
691 	return NULL;
692 }
693 
create_fsels_4(gchar * dirname,gchar * filename,gchar * ext)694 static gchar** create_fsels_4(gchar *dirname, gchar *filename, gchar *ext)
695 {
696 #if WITH_KDE
697 	gchar *p;
698 	gchar *extspaces = g_strdup(ext);
699 	p = extspaces;
700 	while ((p = strchr(p, ';'))) *p = ' ';
701 	filenames = sp_kde_get_open_filenames(dirname, extspaces, _("Open file"));
702 	g_free(extspaces);
703 	return filenames;
704 #endif
705 
706 	return NULL;
707 }
708 
709 // Front-end
create_fsels(gchar * dirname,gchar * filename,gchar * ext)710 gchar** create_fsels(gchar *dirname, gchar *filename, gchar *ext)
711 {
712 #if !defined(__WIN32__) && !defined(HAVE_CARBON_CARBON_H)
713 	if(options.fs_type == 2)
714 	{
715 #if WITH_KDE
716 		const char *p = getenv("KDE_FULL_SESSION");
717 		if (p && *p) // KDE is running
718 			options.fs_type = 3;
719 		else
720 #endif
721 			options.fs_type = 1;
722 	}
723 #endif
724 #if !WITH_KDE
725 	if(options.fs_type == 3)
726 		options.fs_type = 1;
727 #endif
728 	//printf("%i: <%s> <%s> <%s>\n", options.fs_type, dirname, filename, ext);
729 
730 	switch(options.fs_type)
731 	{
732 	case 0:
733 	case 1:	return create_fsels_2(dirname, filename, ext);
734 	case 2: return create_fsels_3(dirname, filename, ext);
735 	case 3: return create_fsels_4(dirname, filename, ext);
736 	default: return NULL;
737 	}
738 
739 	return NULL;
740 }
741 
742 
743