Improve single instance handling.
[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
180 if(files_to_open)
f8f2bfad 181 {
7b7d923f
HJYP
182 len = g_strv_length(files_to_open);
183 g_byte_array_append(buf, (guint8*)&len, sizeof(len));
184 for(i = 0; i < len; ++i)
185 buf_append_str(buf, files_to_open[i]);
f8f2bfad 186 }
7b7d923f 187
f8f2bfad
HJYP
188 return buf;
189}
190
7b7d923f
HJYP
191inline static gboolean buf_read_bool(const char**p)
192{
193 gboolean ret;
194 memcpy(&ret, *p, sizeof(ret));
195 *p += sizeof(ret);
196 return ret;
197}
198
199inline static int buf_read_int(const char**p)
200{
201 int ret;
202 memcpy(&ret, *p, sizeof(ret));
203 *p += sizeof(ret);
204 return ret;
205}
206
207inline static char* buf_read_str(const char**p)
208{
209 char* ret;
210 int len = buf_read_int(p);
211 if(len > 0)
212 {
213 ret = g_malloc(len);
214 memcpy(ret, *p, len);
215 *p += len;
216 }
217 else
218 ret = NULL;
219 return ret;
220}
221
222inline static void ipc_buf_to_args(GByteArray* buf)
f8f2bfad 223{
7b7d923f
HJYP
224 int i, len;
225 char* p = buf->data;
226 char* cwd = buf_read_str(&p);
227 new_tab = buf_read_bool(&p);
228 show_desktop = buf_read_bool(&p);
229 desktop_off = buf_read_bool(&p);
230 desktop_pref = buf_read_bool(&p);
231 g_free(set_wallpaper);
232 set_wallpaper = buf_read_str(&p);
233 show_pref = buf_read_int(&p);
234 find_files = buf_read_bool(&p);
235 no_desktop = buf_read_bool(&p);
236
237 len = buf_read_int(&p);
238 if(len > 0)
b6e3c554 239 {
7b7d923f
HJYP
240 files_to_open = g_new(char*, len + 1);
241 for(i = 0; i < len; ++i)
f8f2bfad 242 {
7b7d923f
HJYP
243 char* file = buf_read_str(&p);
244 files_to_open[i] = fm_canonicalize_filename(file, cwd);
245 g_free(file);
f8f2bfad 246 }
7b7d923f 247 files_to_open[i] = NULL;
b6e3c554 248 }
7b7d923f
HJYP
249 else
250 files_to_open = NULL;
251 g_free(cwd);
f8f2bfad 252}
8505a8ef 253
f8f2bfad
HJYP
254gboolean on_socket_event( GIOChannel* ioc, GIOCondition cond, gpointer data )
255{
256 int client, r;
257 socklen_t addr_len = 0;
258 struct sockaddr_un client_addr ={ 0 };
259 static char buf[ 1024 ];
7b7d923f 260 GByteArray* args;
b6e3c554 261
f8f2bfad
HJYP
262 if ( cond & G_IO_IN )
263 {
264 client = accept( g_io_channel_unix_get_fd( ioc ), (struct sockaddr *)&client_addr, &addr_len );
265 if ( client != -1 )
266 {
7b7d923f 267 args = g_byte_array_sized_new(4096);
f8f2bfad 268 while( (r = read( client, buf, sizeof(buf) )) > 0 )
7b7d923f 269 g_byte_array_append( args, (guint8*)buf, r);
f8f2bfad
HJYP
270 shutdown( client, 2 );
271 close( client );
44409230 272 ipc_buf_to_args(args);
7b7d923f 273 g_byte_array_free( args, TRUE );
f8f2bfad
HJYP
274 pcmanfm_run();
275 }
276 }
277 return TRUE;
278}
19fbd668 279
f8f2bfad
HJYP
280void get_socket_name( char* buf, int len )
281{
282 char* dpy = gdk_get_display();
283 g_snprintf( buf, len, "/tmp/.pcmanfm2-socket%s-%s", dpy, g_get_user_name() );
284 g_free( dpy );
285}
8505a8ef 286
f8f2bfad
HJYP
287gboolean single_instance_check()
288{
289 struct sockaddr_un addr;
290 int addr_len;
291 int ret;
292 int reuse;
b6e3c554 293
f8f2bfad
HJYP
294 if((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
295 {
296 ret = 1;
297 goto _exit;
298 }
299
300 /* FIXME: use abstract socket */
301 addr.sun_family = AF_UNIX;
302 get_socket_name(addr.sun_path, sizeof( addr.sun_path ));
303#ifdef SUN_LEN
304 addr_len = SUN_LEN(&addr);
305#else
306 addr_len = strlen( addr.sun_path ) + sizeof( addr.sun_family );
307#endif
308
309 /* try to connect to existing instance */
310 if(connect(sock, (struct sockaddr*)&addr, addr_len) == 0)
311 {
312 /* connected successfully */
7b7d923f
HJYP
313 GByteArray* buf = args_to_ipc_buf();
314 write(sock, buf->data, buf->len);
315 g_byte_array_free(buf, TRUE);
f8f2bfad
HJYP
316
317 shutdown( sock, 2 );
318 close( sock );
319 ret = 0;
320 goto _exit;
321 }
322
323 /* There is no existing server, and we are in the first instance. */
324 unlink( addr.sun_path ); /* delete old socket file if it exists. */
325 reuse = 1;
326 ret = setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse) );
327 if(bind(sock, (struct sockaddr*)&addr, addr_len) == -1)
328 {
329 ret = 1;
330 goto _exit;
331 }
332
333 io_channel = g_io_channel_unix_new(sock);
334 g_io_channel_set_encoding(io_channel, NULL, NULL);
335 g_io_channel_set_buffered(io_channel, FALSE);
336 g_io_add_watch(io_channel, G_IO_IN,
337 (GIOFunc)on_socket_event, NULL);
338 if(listen(sock, 5) == -1)
339 {
340 ret = 1;
341 goto _exit;
342 }
d3451adb 343 return TRUE;
f8f2bfad
HJYP
344
345_exit:
346
347 gdk_notify_startup_complete();
348 exit( ret );
349}
350
351void single_instance_finalize()
352{
353 char lock_file[256];
354 shutdown(sock, 2);
355 g_io_channel_unref(io_channel);
356 close(sock);
357 get_socket_name(lock_file, sizeof( lock_file ));
358 unlink(lock_file);
359}
360
361
362gboolean pcmanfm_run()
363{
364 gboolean ret = TRUE;
f8f2bfad 365
f8f2bfad
HJYP
366 if(!files_to_open)
367 {
368 /* Launch desktop manager */
369 if(show_desktop)
370 {
371 if(!desktop_running)
372 {
373 fm_desktop_manager_init();
374 desktop_running = TRUE;
375 }
19abb8bf 376 show_desktop = FALSE;
f8f2bfad
HJYP
377 return TRUE;
378 }
379 else if(desktop_off)
380 {
381 if(desktop_running)
382 {
383 desktop_running = FALSE;
384 fm_desktop_manager_finalize();
385 }
19abb8bf 386 desktop_off = FALSE;
f8f2bfad
HJYP
387 return FALSE;
388 }
389 else if(show_pref > 0)
390 {
c5fccf1d
HJYP
391 fm_edit_preference(NULL, show_pref - 1);
392 show_pref = 0;
f8f2bfad
HJYP
393 return TRUE;
394 }
395 else if(desktop_pref)
396 {
c5fccf1d 397 fm_desktop_preference();
19abb8bf 398 desktop_pref = FALSE;
f8f2bfad
HJYP
399 return TRUE;
400 }
401 else if(set_wallpaper)
402 {
f970e846 403 /* g_debug("\'%s\'", set_wallpaper); */
f8f2bfad 404 /* Make sure this is a support image file. */
f970e846 405 if(gdk_pixbuf_get_file_info(set_wallpaper, NULL, NULL))
f8f2bfad 406 {
f970e846
HJYP
407 if(app_config->wallpaper)
408 g_free(app_config->wallpaper);
409 app_config->wallpaper = set_wallpaper;
f8f2bfad 410 set_wallpaper = NULL;
f970e846 411 if(app_config->wallpaper_mode == FM_WP_COLOR)
c5fccf1d 412 app_config->wallpaper_mode = FM_WP_FIT;
4b3e1fe9 413 fm_config_emit_changed(FM_CONFIG(app_config), "wallpaper");
dcecce78 414 fm_app_config_save(app_config, config_name);
f8f2bfad
HJYP
415 }
416 return FALSE;
417 }
418 }
419
420 if(G_UNLIKELY(find_files))
421 {
422 /* FIXME: find files */
423 }
424 else
425 {
df6826e0
HJYP
426 if(files_to_open)
427 {
428 char** filename;
0a053694 429 FmJob* job = fm_file_info_job_new(NULL, 0);
cacf261a 430 FmPath* cwd = NULL;
d951adb8 431 GList* infos;
df6826e0
HJYP
432 for(filename=files_to_open; *filename; ++filename)
433 {
cacf261a
HJYP
434 FmPath* path;
435 if( **filename == '/' || strstr(*filename, ":/") ) /* absolute path or URI */
436 path = fm_path_new(*filename);
0d8dce1a
HJYP
437 else if( strcmp(*filename, "~") == 0 ) /* special case for home dir */
438 {
439 path = fm_path_get_home();
440 fm_main_win_add_win(NULL, path);
441 continue;
442 }
cacf261a
HJYP
443 else /* basename */
444 {
445 if(G_UNLIKELY(!cwd))
446 {
447 /* FIXME: This won't work if those filenames are passed via IPC since the receiving process has different cwd. */
448 char* cwd_str = g_get_current_dir();
449 cwd = fm_path_new(cwd_str);
450 g_free(cwd_str);
451 }
452 path = fm_path_new_relative(cwd, *filename);
453 }
4b3e1fe9 454 fm_file_info_job_add(FM_FILE_INFO_JOB(job), path);
df6826e0
HJYP
455 fm_path_unref(path);
456 }
cacf261a
HJYP
457 if(cwd)
458 fm_path_unref(cwd);
a48f9fc8 459 fm_job_run_sync_with_mainloop(job);
d951adb8
HJYP
460 infos = fm_list_peek_head_link(FM_FILE_INFO_JOB(job)->file_infos);
461 fm_launch_files_simple(NULL, NULL, infos, pcmanfm_open_folder, NULL);
df6826e0 462 g_object_unref(job);
cacf261a 463 ret = (n_pcmanfm_ref >= 1); /* if there is opened window, return true to run the main loop. */
df6826e0
HJYP
464 }
465 else
f8f2bfad
HJYP
466 {
467 FmPath* path;
5b890032 468 char* cwd = ipc_cwd ? ipc_cwd : g_get_current_dir();
0d8dce1a
HJYP
469 path = fm_path_new(cwd);
470 fm_main_win_add_win(NULL, path);
471 fm_path_unref(path);
472 g_free(cwd);
5b890032 473 ipc_cwd = NULL;
f8f2bfad
HJYP
474 }
475 }
476 return ret;
477}
478
479/* After opening any window/dialog/tool, this should be called. */
480void pcmanfm_ref()
481{
482 ++n_pcmanfm_ref;
483 /* g_debug("ref: %d", n_pcmanfm_ref); */
484}
485
486/* After closing any window/dialog/tool, this should be called.
487 * If the last window is closed and we are not a deamon, pcmanfm will quit.
488 */
489void pcmanfm_unref()
490{
491 --n_pcmanfm_ref;
492 /* g_debug("unref: %d, daemon_mode=%d, desktop_running=%d", n_pcmanfm_ref, daemon_mode, desktop_running); */
493 if( 0 == n_pcmanfm_ref && !daemon_mode && !desktop_running )
494 gtk_main_quit();
b6e3c554 495}
df6826e0
HJYP
496
497gboolean pcmanfm_open_folder(GAppLaunchContext* ctx, GList* folder_infos, gpointer user_data, GError** err)
498{
df6826e0
HJYP
499 GList* l = folder_infos;
500 for(; l; l=l->next)
501 {
502 FmFileInfo* fi = (FmFileInfo*)l->data;
503 fm_main_win_open_in_last_active(fi->path);
504 }
505 return TRUE;
506}
dcecce78
HJYP
507
508void pcmanfm_save_config()
509{
510 fm_config_save(fm_config, NULL);
511 fm_app_config_save(app_config, config_name);
512}
c56a211a
HJYP
513
514void pcmanfm_open_folder_in_terminal(GtkWindow* parent, FmPath* dir)
515{
516 GAppInfo* app;
c56a211a
HJYP
517 char** argv;
518 int argc;
519 if(!fm_config->terminal)
520 {
521 fm_show_error(parent, _("Terminal emulator is not set."));
522 fm_edit_preference(parent, PREF_ADVANCED);
523 return;
524 }
525 if(!g_shell_parse_argv(fm_config->terminal, &argc, &argv, NULL))
526 return;
527 app = g_app_info_create_from_commandline(argv[0], NULL, 0, NULL);
528 g_strfreev(argv);
529 if(app)
530 {
531 GError* err = NULL;
532 GAppLaunchContext* ctx = gdk_app_launch_context_new();
533 char* cwd_str;
534
535 if(fm_path_is_native(dir))
536 cwd_str = fm_path_to_str(dir);
537 else
538 {
539 GFile* gf = fm_path_to_gfile(dir);
540 cwd_str = g_file_get_path(gf);
541 g_object_unref(gf);
542 }
99476ede 543 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
544 gdk_app_launch_context_set_timestamp(GDK_APP_LAUNCH_CONTEXT(ctx), gtk_get_current_event_time());
545 g_chdir(cwd_str); /* FIXME: currently we don't have better way for this. maybe a wrapper script? */
546 g_free(cwd_str);
547 if(!g_app_info_launch(app, NULL, ctx, &err))
548 {
549 fm_show_error(parent, err->message);
550 g_error_free(err);
551 }
552 g_object_unref(ctx);
553 g_object_unref(app);
554 }
555}
7cb06c27
HJYP
556
557/* FIXME: Need to load content of ~/Templates and list available templates in popup menus. */
558void pcmanfm_create_new(GtkWindow* parent, FmPath* cwd, const char* templ)
559{
560 GError* err = NULL;
561 FmPath* dest;
562 char* basename;
563_retry:
564 basename = fm_get_user_input(parent, _("Create New..."), _("Enter a name for the newly created file:"), _("New"));
565 if(!basename)
566 return;
567
568 dest = fm_path_new_child(cwd, basename);
569 g_free(basename);
570
571 if( templ == TEMPL_NAME_FOLDER )
572 {
573 GFile* gf = fm_path_to_gfile(dest);
574 if(!g_file_make_directory(gf, NULL, &err))
575 {
98daf506 576 if(err->domain == G_IO_ERROR && err->code == G_IO_ERROR_EXISTS)
7cb06c27
HJYP
577 {
578 fm_path_unref(dest);
579 g_error_free(err);
580 g_object_unref(gf);
581 err = NULL;
582 goto _retry;
583 }
584 fm_show_error(parent, err->message);
585 g_error_free(err);
586 }
587
588 if(!err) /* select the newly created file */
589 {
590 /*FIXME: this doesn't work since the newly created file will
591 * only be shown after file-created event was fired on its
592 * folder's monitor and after FmFolder handles it in idle
593 * handler. So, we cannot select it since it's not yet in
594 * the folder model now. */
595 /* fm_folder_view_select_file_path(fv, dest); */
596 }
597 g_object_unref(gf);
598 }
599 else if( templ == TEMPL_NAME_BLANK )
600 {
601 GFile* gf = fm_path_to_gfile(dest);
602 GFileOutputStream* f = g_file_create(gf, G_FILE_CREATE_NONE, NULL, &err);
603 if(f)
604 {
605 g_output_stream_close(G_OUTPUT_STREAM(f), NULL, NULL);
606 g_object_unref(f);
607 }
608 else
609 {
98daf506 610 if(err->domain == G_IO_ERROR && err->code == G_IO_ERROR_EXISTS)
7cb06c27
HJYP
611 {
612 fm_path_unref(dest);
613 g_error_free(err);
614 g_object_unref(gf);
615 err = NULL;
616 goto _retry;
617 }
618 fm_show_error(parent, err->message);
619 g_error_free(err);
620 }
621
622 if(!err) /* select the newly created file */
623 {
624 /*FIXME: this doesn't work since the newly created file will
625 * only be shown after file-created event was fired on its
626 * folder's monitor and after FmFolder handles it in idle
627 * handler. So, we cannot select it since it's not yet in
628 * the folder model now. */
629 /* fm_folder_view_select_file_path(fv, dest); */
630 }
631 g_object_unref(gf);
632 }
633 else /* templates in ~/Templates */
634 {
635 FmPath* dir = fm_path_new(g_get_user_special_dir(G_USER_DIRECTORY_TEMPLATES));
636 FmPath* template = fm_path_new_child(dir, templ);
637 fm_copy_file(template, cwd);
638 fm_path_unref(template);
639 }
640 fm_path_unref(dest);
641}