2 * By Tony Houghton, <h@realh.co.uk>.
12 #include <sys/types.h>
17 #include "xxdgautostart.h"
19 DesktopEntry
*xdesktop_entry_new(const char *pathname
, const char *basename
,
22 DesktopEntry
*xde
= g_new0(DesktopEntry
, 1);
24 if (!desktop_entry_load(xde
, pathname
, basename
, TRUE
, savable
))
26 desktop_entry_delete(xde
);
32 gboolean
xdesktop_entry_get_only_in_rox(DesktopEntry
*xde
)
34 return (xde
->only_show_in
&& xde
->only_show_in
[0] &&
35 !strcmp(xde
->only_show_in
[0], "ROX") &&
36 (!xde
->only_show_in
[1] || !xde
->only_show_in
[1][0]));
39 gboolean
xdesktop_entry_can_set_only_in_rox(DesktopEntry
*xde
)
41 return xdesktop_entry_get_only_in_rox(xde
) ||
42 (desktop_entry_get_show_in_rox(xde
) &&
43 str_v_is_empty(xde
->only_show_in
));
46 static int str_v_len(char const **str_v
)
50 for (n
= 0; str_v
&& str_v
[n
]; ++n
);
54 static void update_kf_from_show_ins(DesktopEntry
*xde
)
56 if (!xde
->only_show_in
)
58 g_key_file_remove_key(xde
->kf
, _DE
, "OnlyShowIn", NULL
);
62 g_key_file_set_string_list(xde
->kf
, _DE
, "OnlyShowIn",
63 (char const **) xde
->only_show_in
,
64 str_v_len((char const **) xde
->only_show_in
));
66 if (!xde
->not_show_in
)
68 g_key_file_remove_key(xde
->kf
, _DE
, "NotShowIn", NULL
);
72 g_key_file_set_string_list(xde
->kf
, _DE
, "NotShowIn",
73 (char const **) xde
->not_show_in
,
74 str_v_len((char const **) xde
->not_show_in
));
78 void xdesktop_entry_set_only_in_rox(DesktopEntry
*xde
, gboolean state
)
80 g_strfreev(xde
->only_show_in
);
81 xde
->only_show_in
= NULL
;
82 g_strfreev(xde
->not_show_in
);
83 xde
->not_show_in
= NULL
;
86 xde
->only_show_in
= g_new0(char *, 2);
87 xde
->only_show_in
[0] = g_strdup("ROX");
89 update_kf_from_show_ins(xde
);
92 static void remove_rox_from_strv(char ***p_str_v
)
94 if (!str_v_is_empty(*p_str_v
))
97 gboolean moving
= FALSE
;
99 for (ps
= *p_str_v
; *ps
; ++ps
)
106 else if (!strcmp(*ps
, "ROX"))
113 if (str_v_is_empty(*p_str_v
))
115 g_strfreev(*p_str_v
);
121 static void add_rox_to_strv(char ***p_str_v
, gboolean force
)
125 if (!str_v_is_empty(*p_str_v
))
127 gboolean contains_rox
= FALSE
;
129 for (ps
= *p_str_v
; *ps
; ++ps
)
131 if (!strcmp(*ps
, "ROX"))
139 int l
= str_v_len((char const **) *p_str_v
);
141 *p_str_v
= g_renew(char *, *p_str_v
, l
+ 2);
142 (*p_str_v
)[l
] = g_strdup("ROX");
143 (*p_str_v
)[l
+ 1] = NULL
;
148 g_strfreev(*p_str_v
);
149 *p_str_v
= g_new0(char *, 2);
150 (*p_str_v
)[0] = g_strdup("ROX");
155 static void show_strv(char **strv)
159 for (ps = strv; ps && *ps; ++ps)
161 g_print("%s ; ", *ps);
167 void xdesktop_entry_set_start_in_rox(DesktopEntry
*xde
, gboolean state
)
171 add_rox_to_strv(&xde
->only_show_in
, FALSE
);
172 remove_rox_from_strv(&xde
->not_show_in
);
176 remove_rox_from_strv(&xde
->only_show_in
);
177 add_rox_to_strv(&xde
->not_show_in
, TRUE
);
179 update_kf_from_show_ins(xde
);
182 void xdesktop_entry_save(DesktopEntry
*xde
)
190 g_free(xde
->pathname
);
191 xde
->pathname
= g_build_filename(g_get_user_config_dir(),
192 xde
->basename
, NULL
);
195 buffer
= g_key_file_to_data(xde
->kf
, &buflen
, &err
);
198 message_dialog(NULL
, GTK_MESSAGE_ERROR
,
199 _("Unable to prepare Desktop Entry for saving to '%s': %s"),
200 xde
->pathname
, err
? err
->message
: _("unknown reason"));
205 if (!g_file_set_contents(xde
->pathname
, buffer
, buflen
, &err
))
207 message_dialog(NULL
, GTK_MESSAGE_ERROR
,
208 _("Unable to save '%s': %s"),
209 xde
->pathname
, err
? err
->message
: _("unknown reason"));
216 inline static char *add_desktop_extension(const char *basename
)
218 return g_strjoin(".", basename
, "desktop", NULL
);
221 /* basename doesn't include .desktop extension */
222 static char *xdg_autostart_pathname(const char *basename
)
224 char *leafname
= add_desktop_extension(basename
);
225 char *pathname
= g_build_filename(g_get_user_config_dir(), "autostart",
232 /* This has side-effect of creating file if it doesn't clash,
233 * so it must be overwritten or deleted */
234 static int filename_clash(const char *basename
)
236 static char *dir
= NULL
;
238 const char * const *dirs
;
239 const char * const *d
;
242 dirs
= g_get_system_config_dirs();
243 for (d
= dirs
; *d
; ++d
)
245 char *leafname
= add_desktop_extension(basename
);
247 pathname
= g_build_filename(*d
, "autostart", leafname
, NULL
);
249 if (g_file_test(pathname
, G_FILE_TEST_EXISTS
))
257 dir
= g_build_filename(g_get_user_config_dir(), "autostart", NULL
);
258 if (g_mkdir_with_parents(dir
, 0755) == -1)
260 message_dialog(NULL
, GTK_MESSAGE_ERROR
,
261 _("Unable to create '%s' directory"), dir
);
264 if (!g_file_test(dir
, G_FILE_TEST_IS_DIR
))
266 pathname
= xdg_autostart_pathname(basename
);
267 result
= open(pathname
, O_WRONLY
| O_EXCL
|O_CREAT
, 0644);
274 static char *add_number_ext(const char *basename
)
276 int l
= strlen(basename
);
280 for (n
= l
- 1; n
>= 0 && isdigit(basename
[n
]); --n
);
281 /* This will also accept a trailing - with no subsequent digits,
283 if (basename
[n
] == '-')
287 number
= atoi(basename
+ n
+ 1) + 1;
291 return g_strdup_printf("%.*s-%d", l
, basename
, number
);
294 void xdesktop_entry_filenames_from_name(DesktopEntry
*de
, const char *leafname
)
297 char *basename
= NULL
;
304 basename
= g_strdup(leafname
);
305 sep
= strrchr(basename
, '.');
306 if (sep
&& sep
[1] && !strcmp(sep
+ 1, "desktop"))
311 basename
= g_filename_from_utf8(de
->name
, -1, NULL
, NULL
, NULL
);
313 if (!basename
|| !basename
[0])
317 basename
= g_strdup(_("rox-session-autostart"));
321 for (n
= 0; basename
[n
]; ++n
)
323 if (isspace(basename
[n
]))
326 basename
[n
] = tolower(basename
[n
]);
329 while ((fd
= filename_clash(basename
)) == -1)
331 char *old
= basename
;
334 basename
= add_number_ext(basename
);
337 g_free(de
->basename
);
338 de
->basename
= add_desktop_extension(basename
);
339 g_free(de
->pathname
);
340 de
->pathname
= xdg_autostart_pathname(basename
);