Fix #2979578 unable to open second pcmanfm instance in specific case.
[lxde/pcmanfm.git] / src / pcmanfm.c
CommitLineData
b6e3c554
HJYP
1/*
2 * pcmanfm.c
d3451adb 3 *
7b7d923f 4 * Copyright 2009 - 2010 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
d3451adb 5 *
b6e3c554
HJYP
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
d3451adb 10 *
b6e3c554
HJYP
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
d3451adb 15 *
b6e3c554
HJYP
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 */
21
08e70fea 22#ifdef HAVE_CONFIG_H
b6e3c554 23#include <config.h>
08e70fea
HJYP
24#endif
25
b6e3c554
HJYP
26#include <gtk/gtk.h>
27#include <stdio.h>
f8f2bfad
HJYP
28#include <glib/gi18n.h>
29
30#include <stdlib.h>
31#include <string.h>
32/* socket is used to keep single instance */
33#include <sys/types.h>
34#include <sys/socket.h>
35#include <sys/un.h>
36#include <signal.h>
37#include <unistd.h> /* for getcwd */
b6e3c554 38
20c0bc9a 39#include <libfm/fm-gtk.h>
4d55886c 40#include "app-config.h"
b6e3c554 41#include "main-win.h"
8505a8ef 42#include "desktop.h"
71f82759 43#include "volume-manager.h"
c5fccf1d 44#include "pref.h"
df6826e0 45#include "pcmanfm.h"
8505a8ef 46
f8f2bfad
HJYP
47static int sock;
48GIOChannel* io_channel = NULL;
49
50gboolean daemon_mode = FALSE;
51
f8f2bfad 52static char** files_to_open = NULL;
f970e846
HJYP
53static char* profile = NULL;
54static char* config_name = NULL;
f8f2bfad
HJYP
55static gboolean no_desktop = FALSE;
56static gboolean show_desktop = FALSE;
57static gboolean desktop_off = FALSE;
58static gboolean desktop_running = FALSE;
59static gboolean new_tab = FALSE;
60static int show_pref = 0;
61static gboolean desktop_pref = FALSE;
62static char* set_wallpaper = NULL;
63static gboolean find_files = FALSE;
5b890032 64static char* ipc_cwd = NULL;
f8f2bfad
HJYP
65
66static int n_pcmanfm_ref = 0;
67
68static GOptionEntry opt_entries[] =
8505a8ef 69{
f970e846 70 { "new-tab", 't', 0, G_OPTION_ARG_NONE, &new_tab, N_("Open folders in new tabs of the last used window instead of creating new windows"), NULL },
a48f9fc8 71 { "profile", 'p', 0, G_OPTION_ARG_STRING, &profile, N_("Name of configuration profile"), "<profile name>" },
f8f2bfad
HJYP
72 { "desktop", '\0', 0, G_OPTION_ARG_NONE, &show_desktop, N_("Launch desktop manager"), NULL },
73 { "desktop-off", '\0', 0, G_OPTION_ARG_NONE, &desktop_off, N_("Turn off desktop manager if it's running"), NULL },
f8f2bfad 74 { "daemon-mode", 'd', 0, G_OPTION_ARG_NONE, &daemon_mode, N_("Run PCManFM as a daemon"), NULL },
f8f2bfad 75 { "desktop-pref", '\0', 0, G_OPTION_ARG_NONE, &desktop_pref, N_("Open desktop preference dialog"), NULL },
f970e846 76 { "set-wallpaper", 'w', 0, G_OPTION_ARG_FILENAME, &set_wallpaper, N_("Set desktop wallpaper"), N_("<image file>") },
a48f9fc8 77 { "show-pref", '\0', 0, G_OPTION_ARG_INT, &show_pref, N_("Open preference dialog. 'n' is number of the page you want to show (1, 2, 3...)."), "n" },
f8f2bfad 78 { "find-files", 'f', 0, G_OPTION_ARG_NONE, &find_files, N_("Open Find Files utility"), NULL },
f970e846 79 { "no-desktop", '\0', 0, G_OPTION_ARG_NONE, &no_desktop, N_("No function. Just to be compatible with nautilus"), NULL },
f8f2bfad
HJYP
80 {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &files_to_open, NULL, N_("[FILE1, FILE2,...]")},
81 { NULL }
82};
83
84static gboolean single_instance_check();
85static void single_instance_finalize();
86static void get_socket_name(char* buf, int len);
87static gboolean pcmanfm_run();
88static gboolean on_socket_event(GIOChannel* ioc, GIOCondition cond, gpointer data);
b6e3c554
HJYP
89
90int main(int argc, char** argv)
91{
4d55886c 92 FmConfig* config;
f8f2bfad
HJYP
93 GError* err = NULL;
94
95#ifdef ENABLE_NLS
96 bindtextdomain ( GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR );
97 bind_textdomain_codeset ( GETTEXT_PACKAGE, "UTF-8" );
98 textdomain ( GETTEXT_PACKAGE );
99#endif
100
101 /* initialize GTK+ and parse the command line arguments */
102 if(G_UNLIKELY(!gtk_init_with_args(&argc, &argv, "", opt_entries, GETTEXT_PACKAGE, &err)))
103 {
104 g_printf("%s\n", err->message);
c5fccf1d 105 g_error_free(err);
f8f2bfad
HJYP
106 return 1;
107 }
108
109 /* ensure that there is only one instance of pcmanfm.
110 if there is an existing instance, command line arguments
111 will be passed to the existing instance, and exit() will be called here. */
112 single_instance_check();
113
114 /* intercept signals */
115 signal( SIGPIPE, SIG_IGN );
116 /* signal( SIGHUP, gtk_main_quit ); */
117 signal( SIGINT, gtk_main_quit );
118 signal( SIGTERM, gtk_main_quit );
b6e3c554 119
f970e846
HJYP
120 config = fm_app_config_new(); /* this automatically load libfm config file. */
121 /* load pcmanfm-specific config file */
122 if(profile)
123 config_name = g_strconcat("pcmanfm/", profile, ".conf", NULL);
4b3e1fe9 124 fm_app_config_load_from_file(FM_APP_CONFIG(config), config_name);
f970e846 125
4d55886c 126 fm_gtk_init(config);
b6e3c554 127
f8f2bfad
HJYP
128 /* the main part */
129 if(pcmanfm_run())
130 {
71f82759 131 fm_volume_manager_init();
f8f2bfad
HJYP
132 gtk_main();
133 if(desktop_running)
134 fm_desktop_manager_finalize();
f8f2bfad 135 fm_config_save(config, NULL); /* save libfm config */
f970e846 136 fm_app_config_save((FmAppConfig*)config, config_name); /* save pcmanfm config */
71f82759 137 fm_volume_manager_finalize();
f8f2bfad
HJYP
138 }
139 single_instance_finalize();
8505a8ef 140
f8f2bfad
HJYP
141 fm_gtk_finalize();
142 g_object_unref(config);
f8f2bfad
HJYP
143 return 0;
144}
145
7b7d923f 146inline static void buf_append_str(GByteArray* buf, const char* str)
f8f2bfad 147{
7b7d923f
HJYP
148 int len;
149 if(G_LIKELY(str))
150 {
151 len = strlen(str) + 1;
152 g_byte_array_append(buf, (guint8*)&len, sizeof(len));
153 g_byte_array_append(buf, (guint8*)str, len);
154 }
155 else
156 {
157 len = 0;
158 g_byte_array_append(buf, (guint8*)&len, sizeof(len));
159 }
160}
161
162inline static GByteArray* args_to_ipc_buf()
163{
164 int i, len;
165 GByteArray* buf = g_byte_array_sized_new(4096);
5b890032
HJYP
166 /* send our current working dir to existing instance via IPC. */
167 ipc_cwd = g_get_current_dir();
7b7d923f 168 buf_append_str(buf, ipc_cwd);
5b890032 169 g_free(ipc_cwd);
7b7d923f
HJYP
170
171 g_byte_array_append(buf, (guint8*)&new_tab, sizeof(new_tab));
172 g_byte_array_append(buf, (guint8*)&show_desktop, sizeof(show_desktop));
173 g_byte_array_append(buf, (guint8*)&desktop_off, sizeof(desktop_off));
174 g_byte_array_append(buf, (guint8*)&desktop_pref, sizeof(desktop_pref));
175 buf_append_str(buf, set_wallpaper);
176 g_byte_array_append(buf, (guint8*)&show_pref, sizeof(show_pref));
177 g_byte_array_append(buf, (guint8*)&find_files, sizeof(find_files));
178 g_byte_array_append(buf, (guint8*)&no_desktop, sizeof(no_desktop));
179
a1a528d2 180 len = files_to_open ? g_strv_length(files_to_open) : 0;
2b46b521
HJYP
181 g_byte_array_append(buf, (guint8*)&len, sizeof(len));
182 for(i = 0; i < len; ++i)
183 buf_append_str(buf, files_to_open[i]);
7b7d923f 184
f8f2bfad
HJYP
185 return buf;
186}
187
7b7d923f
HJYP
188inline static gboolean buf_read_bool(const char**p)
189{
190 gboolean ret;
191 memcpy(&ret, *p, sizeof(ret));
192 *p += sizeof(ret);
193 return ret;
194}
195
196inline static int buf_read_int(const char**p)
197{
198 int ret;
199 memcpy(&ret, *p, sizeof(ret));
200 *p += sizeof(ret);
201 return ret;
202}
203
204inline static char* buf_read_str(const char**p)
205{
206 char* ret;
207 int len = buf_read_int(p);
208 if(len > 0)
209 {
210 ret = g_malloc(len);
211 memcpy(ret, *p, len);
212 *p += len;
213 }
214 else
215 ret = NULL;
216 return ret;
217}
218
219inline static void ipc_buf_to_args(GByteArray* buf)
f8f2bfad 220{
7b7d923f
HJYP
221 int i, len;
222 char* p = buf->data;
223 char* cwd = buf_read_str(&p);
224 new_tab = buf_read_bool(&p);
225 show_desktop = buf_read_bool(&p);
226 desktop_off = buf_read_bool(&p);
227 desktop_pref = buf_read_bool(&p);
228 g_free(set_wallpaper);
229 set_wallpaper = buf_read_str(&p);
230 show_pref = buf_read_int(&p);
231 find_files = buf_read_bool(&p);
232 no_desktop = buf_read_bool(&p);
233
234 len = buf_read_int(&p);
2b46b521 235 g_debug("len = %d", len);
7b7d923f 236 if(len > 0)
b6e3c554 237 {
7b7d923f
HJYP
238 files_to_open = g_new(char*, len + 1);
239 for(i = 0; i < len; ++i)
f8f2bfad 240 {
7b7d923f 241 char* file = buf_read_str(&p);
ee12f37e
HJYP
242 char* scheme = g_uri_parse_scheme(file);
243 if(scheme) /* a valid URI */
244 {
245 /* FIXME: should we canonicalize URIs? and how about file:///? */
246 files_to_open[i] = file;
247 g_free(scheme);
248 }
249 else /* a file path */
250 {
251 files_to_open[i] = fm_canonicalize_filename(file, cwd);
252 g_free(file);
253 }
f8f2bfad 254 }
7b7d923f 255 files_to_open[i] = NULL;
b6e3c554 256 }
7b7d923f
HJYP
257 else
258 files_to_open = NULL;
259 g_free(cwd);
f8f2bfad 260}
8505a8ef 261
f8f2bfad
HJYP
262gboolean on_socket_event( GIOChannel* ioc, GIOCondition cond, gpointer data )
263{
264 int client, r;
265 socklen_t addr_len = 0;
266 struct sockaddr_un client_addr ={ 0 };
267 static char buf[ 1024 ];
7b7d923f 268 GByteArray* args;
b6e3c554 269
f8f2bfad
HJYP
270 if ( cond & G_IO_IN )
271 {
272 client = accept( g_io_channel_unix_get_fd( ioc ), (struct sockaddr *)&client_addr, &addr_len );
273 if ( client != -1 )
274 {
7b7d923f 275 args = g_byte_array_sized_new(4096);
f8f2bfad 276 while( (r = read( client, buf, sizeof(buf) )) > 0 )
7b7d923f 277 g_byte_array_append( args, (guint8*)buf, r);
f8f2bfad
HJYP
278 shutdown( client, 2 );
279 close( client );
44409230 280 ipc_buf_to_args(args);
7b7d923f 281 g_byte_array_free( args, TRUE );
f8f2bfad
HJYP
282 pcmanfm_run();
283 }
284 }
285 return TRUE;
286}
19fbd668 287
f8f2bfad
HJYP
288void get_socket_name( char* buf, int len )
289{
290 char* dpy = gdk_get_display();
291 g_snprintf( buf, len, "/tmp/.pcmanfm2-socket%s-%s", dpy, g_get_user_name() );
292 g_free( dpy );
293}
8505a8ef 294
f8f2bfad
HJYP
295gboolean single_instance_check()
296{
297 struct sockaddr_un addr;
298 int addr_len;
299 int ret;
300 int reuse;
b6e3c554 301
f8f2bfad
HJYP
302 if((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
303 {
304 ret = 1;
305 goto _exit;
306 }
307
308 /* FIXME: use abstract socket */
309 addr.sun_family = AF_UNIX;
310 get_socket_name(addr.sun_path, sizeof( addr.sun_path ));
311#ifdef SUN_LEN
312 addr_len = SUN_LEN(&addr);
313#else
314 addr_len = strlen( addr.sun_path ) + sizeof( addr.sun_family );
315#endif
316
317 /* try to connect to existing instance */
318 if(connect(sock, (struct sockaddr*)&addr, addr_len) == 0)
319 {
320 /* connected successfully */
7b7d923f
HJYP
321 GByteArray* buf = args_to_ipc_buf();
322 write(sock, buf->data, buf->len);
323 g_byte_array_free(buf, TRUE);
f8f2bfad
HJYP
324
325 shutdown( sock, 2 );
326 close( sock );
327 ret = 0;
328 goto _exit;
329 }
330
331 /* There is no existing server, and we are in the first instance. */
332 unlink( addr.sun_path ); /* delete old socket file if it exists. */
333 reuse = 1;
334 ret = setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse) );
335 if(bind(sock, (struct sockaddr*)&addr, addr_len) == -1)
336 {
337 ret = 1;
338 goto _exit;
339 }
340
341 io_channel = g_io_channel_unix_new(sock);
342 g_io_channel_set_encoding(io_channel, NULL, NULL);
343 g_io_channel_set_buffered(io_channel, FALSE);
344 g_io_add_watch(io_channel, G_IO_IN,
345 (GIOFunc)on_socket_event, NULL);
346 if(listen(sock, 5) == -1)
347 {
348 ret = 1;
349 goto _exit;
350 }
d3451adb 351 return TRUE;
f8f2bfad
HJYP
352
353_exit:
354
355 gdk_notify_startup_complete();
356 exit( ret );
357}
358
359void single_instance_finalize()
360{
361 char lock_file[256];
362 shutdown(sock, 2);
363 g_io_channel_unref(io_channel);
364 close(sock);
365 get_socket_name(lock_file, sizeof( lock_file ));
366 unlink(lock_file);
367}
368
ee12f37e
HJYP
369static FmJobErrorAction on_file_info_job_error(FmFileInfoJob* job, GError* err, FmJobErrorSeverity severity, gpointer user_data)
370{
371 if(err->domain == G_IO_ERROR && err->code == G_IO_ERROR_NOT_MOUNTED)
372 {
373 FmPath* current = fm_file_info_job_get_current(job);
374 if( fm_mount_path(NULL, current, TRUE) )
375 return FM_JOB_RETRY;
376 }
377 return FM_JOB_CONTINUE;
378}
f8f2bfad
HJYP
379
380gboolean pcmanfm_run()
381{
382 gboolean ret = TRUE;
f8f2bfad 383
f8f2bfad
HJYP
384 if(!files_to_open)
385 {
386 /* Launch desktop manager */
387 if(show_desktop)
388 {
389 if(!desktop_running)
390 {
391 fm_desktop_manager_init();
392 desktop_running = TRUE;
393 }
19abb8bf 394 show_desktop = FALSE;
f8f2bfad
HJYP
395 return TRUE;
396 }
397 else if(desktop_off)
398 {
399 if(desktop_running)
400 {
401 desktop_running = FALSE;
402 fm_desktop_manager_finalize();
403 }
19abb8bf 404 desktop_off = FALSE;
f8f2bfad
HJYP
405 return FALSE;
406 }
407 else if(show_pref > 0)
408 {
c5fccf1d
HJYP
409 fm_edit_preference(NULL, show_pref - 1);
410 show_pref = 0;
f8f2bfad
HJYP
411 return TRUE;
412 }
413 else if(desktop_pref)
414 {
c5fccf1d 415 fm_desktop_preference();
19abb8bf 416 desktop_pref = FALSE;
f8f2bfad
HJYP
417 return TRUE;
418 }
419 else if(set_wallpaper)
420 {
f970e846 421 /* g_debug("\'%s\'", set_wallpaper); */
f8f2bfad 422 /* Make sure this is a support image file. */
f970e846 423 if(gdk_pixbuf_get_file_info(set_wallpaper, NULL, NULL))
f8f2bfad 424 {
f970e846
HJYP
425 if(app_config->wallpaper)
426 g_free(app_config->wallpaper);
427 app_config->wallpaper = set_wallpaper;
f8f2bfad 428 set_wallpaper = NULL;
f970e846 429 if(app_config->wallpaper_mode == FM_WP_COLOR)
c5fccf1d 430 app_config->wallpaper_mode = FM_WP_FIT;
4b3e1fe9 431 fm_config_emit_changed(FM_CONFIG(app_config), "wallpaper");
dcecce78 432 fm_app_config_save(app_config, config_name);
f8f2bfad
HJYP
433 }
434 return FALSE;
435 }
436 }
437
438 if(G_UNLIKELY(find_files))
439 {
440 /* FIXME: find files */
441 }
442 else
443 {
df6826e0
HJYP
444 if(files_to_open)
445 {
446 char** filename;
0a053694 447 FmJob* job = fm_file_info_job_new(NULL, 0);
cacf261a 448 FmPath* cwd = NULL;
d951adb8 449 GList* infos;
df6826e0
HJYP
450 for(filename=files_to_open; *filename; ++filename)
451 {
cacf261a
HJYP
452 FmPath* path;
453 if( **filename == '/' || strstr(*filename, ":/") ) /* absolute path or URI */
454 path = fm_path_new(*filename);
0d8dce1a
HJYP
455 else if( strcmp(*filename, "~") == 0 ) /* special case for home dir */
456 {
457 path = fm_path_get_home();
458 fm_main_win_add_win(NULL, path);
459 continue;
460 }
cacf261a
HJYP
461 else /* basename */
462 {
463 if(G_UNLIKELY(!cwd))
464 {
465 /* FIXME: This won't work if those filenames are passed via IPC since the receiving process has different cwd. */
466 char* cwd_str = g_get_current_dir();
467 cwd = fm_path_new(cwd_str);
468 g_free(cwd_str);
469 }
470 path = fm_path_new_relative(cwd, *filename);
471 }
4b3e1fe9 472 fm_file_info_job_add(FM_FILE_INFO_JOB(job), path);
df6826e0
HJYP
473 fm_path_unref(path);
474 }
cacf261a
HJYP
475 if(cwd)
476 fm_path_unref(cwd);
ee12f37e 477 g_signal_connect(job, "error", G_CALLBACK(on_file_info_job_error), NULL);
a48f9fc8 478 fm_job_run_sync_with_mainloop(job);
d951adb8
HJYP
479 infos = fm_list_peek_head_link(FM_FILE_INFO_JOB(job)->file_infos);
480 fm_launch_files_simple(NULL, NULL, infos, pcmanfm_open_folder, NULL);
df6826e0 481 g_object_unref(job);
cacf261a 482 ret = (n_pcmanfm_ref >= 1); /* if there is opened window, return true to run the main loop. */
2b46b521
HJYP
483
484 g_strfreev(files_to_open);
485 files_to_open = NULL;
df6826e0
HJYP
486 }
487 else
f8f2bfad
HJYP
488 {
489 FmPath* path;
5b890032 490 char* cwd = ipc_cwd ? ipc_cwd : g_get_current_dir();
0d8dce1a
HJYP
491 path = fm_path_new(cwd);
492 fm_main_win_add_win(NULL, path);
493 fm_path_unref(path);
494 g_free(cwd);
5b890032 495 ipc_cwd = NULL;
f8f2bfad
HJYP
496 }
497 }
498 return ret;
499}
500
501/* After opening any window/dialog/tool, this should be called. */
502void pcmanfm_ref()
503{
504 ++n_pcmanfm_ref;
505 /* g_debug("ref: %d", n_pcmanfm_ref); */
506}
507
508/* After closing any window/dialog/tool, this should be called.
509 * If the last window is closed and we are not a deamon, pcmanfm will quit.
510 */
511void pcmanfm_unref()
512{
513 --n_pcmanfm_ref;
514 /* g_debug("unref: %d, daemon_mode=%d, desktop_running=%d", n_pcmanfm_ref, daemon_mode, desktop_running); */
515 if( 0 == n_pcmanfm_ref && !daemon_mode && !desktop_running )
516 gtk_main_quit();
b6e3c554 517}
df6826e0
HJYP
518
519gboolean pcmanfm_open_folder(GAppLaunchContext* ctx, GList* folder_infos, gpointer user_data, GError** err)
520{
df6826e0
HJYP
521 GList* l = folder_infos;
522 for(; l; l=l->next)
523 {
524 FmFileInfo* fi = (FmFileInfo*)l->data;
525 fm_main_win_open_in_last_active(fi->path);
526 }
527 return TRUE;
528}
dcecce78
HJYP
529
530void pcmanfm_save_config()
531{
532 fm_config_save(fm_config, NULL);
533 fm_app_config_save(app_config, config_name);
534}
c56a211a
HJYP
535
536void pcmanfm_open_folder_in_terminal(GtkWindow* parent, FmPath* dir)
537{
538 GAppInfo* app;
c56a211a
HJYP
539 char** argv;
540 int argc;
541 if(!fm_config->terminal)
542 {
543 fm_show_error(parent, _("Terminal emulator is not set."));
544 fm_edit_preference(parent, PREF_ADVANCED);
545 return;
546 }
547 if(!g_shell_parse_argv(fm_config->terminal, &argc, &argv, NULL))
548 return;
549 app = g_app_info_create_from_commandline(argv[0], NULL, 0, NULL);
550 g_strfreev(argv);
551 if(app)
552 {
553 GError* err = NULL;
554 GAppLaunchContext* ctx = gdk_app_launch_context_new();
555 char* cwd_str;
556
557 if(fm_path_is_native(dir))
558 cwd_str = fm_path_to_str(dir);
559 else
560 {
561 GFile* gf = fm_path_to_gfile(dir);
562 cwd_str = g_file_get_path(gf);
563 g_object_unref(gf);
564 }
99476ede 565 gdk_app_launch_context_set_screen(GDK_APP_LAUNCH_CONTEXT(ctx), parent ? gtk_widget_get_screen(GTK_WIDGET(parent)) : gdk_screen_get_default());
c56a211a
HJYP
566 gdk_app_launch_context_set_timestamp(GDK_APP_LAUNCH_CONTEXT(ctx), gtk_get_current_event_time());
567 g_chdir(cwd_str); /* FIXME: currently we don't have better way for this. maybe a wrapper script? */
568 g_free(cwd_str);
569 if(!g_app_info_launch(app, NULL, ctx, &err))
570 {
571 fm_show_error(parent, err->message);
572 g_error_free(err);
573 }
574 g_object_unref(ctx);
575 g_object_unref(app);
576 }
577}
7cb06c27
HJYP
578
579/* FIXME: Need to load content of ~/Templates and list available templates in popup menus. */
580void pcmanfm_create_new(GtkWindow* parent, FmPath* cwd, const char* templ)
581{
582 GError* err = NULL;
583 FmPath* dest;
584 char* basename;
585_retry:
586 basename = fm_get_user_input(parent, _("Create New..."), _("Enter a name for the newly created file:"), _("New"));
587 if(!basename)
588 return;
589
590 dest = fm_path_new_child(cwd, basename);
591 g_free(basename);
592
593 if( templ == TEMPL_NAME_FOLDER )
594 {
595 GFile* gf = fm_path_to_gfile(dest);
596 if(!g_file_make_directory(gf, NULL, &err))
597 {
98daf506 598 if(err->domain == G_IO_ERROR && err->code == G_IO_ERROR_EXISTS)
7cb06c27
HJYP
599 {
600 fm_path_unref(dest);
601 g_error_free(err);
602 g_object_unref(gf);
603 err = NULL;
604 goto _retry;
605 }
606 fm_show_error(parent, err->message);
607 g_error_free(err);
608 }
609
610 if(!err) /* select the newly created file */
611 {
612 /*FIXME: this doesn't work since the newly created file will
613 * only be shown after file-created event was fired on its
614 * folder's monitor and after FmFolder handles it in idle
615 * handler. So, we cannot select it since it's not yet in
616 * the folder model now. */
617 /* fm_folder_view_select_file_path(fv, dest); */
618 }
619 g_object_unref(gf);
620 }
621 else if( templ == TEMPL_NAME_BLANK )
622 {
623 GFile* gf = fm_path_to_gfile(dest);
624 GFileOutputStream* f = g_file_create(gf, G_FILE_CREATE_NONE, NULL, &err);
625 if(f)
626 {
627 g_output_stream_close(G_OUTPUT_STREAM(f), NULL, NULL);
628 g_object_unref(f);
629 }
630 else
631 {
98daf506 632 if(err->domain == G_IO_ERROR && err->code == G_IO_ERROR_EXISTS)
7cb06c27
HJYP
633 {
634 fm_path_unref(dest);
635 g_error_free(err);
636 g_object_unref(gf);
637 err = NULL;
638 goto _retry;
639 }
640 fm_show_error(parent, err->message);
641 g_error_free(err);
642 }
643
644 if(!err) /* select the newly created file */
645 {
646 /*FIXME: this doesn't work since the newly created file will
647 * only be shown after file-created event was fired on its
648 * folder's monitor and after FmFolder handles it in idle
649 * handler. So, we cannot select it since it's not yet in
650 * the folder model now. */
651 /* fm_folder_view_select_file_path(fv, dest); */
652 }
653 g_object_unref(gf);
654 }
655 else /* templates in ~/Templates */
656 {
657 FmPath* dir = fm_path_new(g_get_user_special_dir(G_USER_DIRECTORY_TEMPLATES));
658 FmPath* template = fm_path_new_child(dir, templ);
659 fm_copy_file(template, cwd);
660 fm_path_unref(template);
661 }
662 fm_path_unref(dest);
663}