rearrange. change default drag threshold
[dana/obconf.git] / src / archive.c
1 #include "theme.h"
2 #include "main.h"
3 #include "gettext.h"
4
5 #include <string.h>
6 #include <errno.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <unistd.h>
10
11 #define gtk_msg(type, args...) \
12 {                                                                        \
13     GtkWidget *msgw;                                                     \
14     msgw = gtk_message_dialog_new(GTK_WINDOW(mainwin),                   \
15                                   GTK_DIALOG_DESTROY_WITH_PARENT |       \
16                                   GTK_DIALOG_MODAL,                      \
17                                   type,                                  \
18                                   GTK_BUTTONS_OK,                        \
19                                   args);                                 \
20     gtk_dialog_run(GTK_DIALOG(msgw));                                    \
21     gtk_widget_destroy(msgw);                                            \
22 }
23
24 static gchar *get_theme_dir();
25 static gboolean change_dir(const gchar *dir);
26 static gchar* name_from_file(const gchar *path);
27 static gchar* name_from_dir(const gchar *dir);
28 static gboolean install_theme_to(const gchar *name, const gchar *file,
29                                  const gchar *to);
30 static gboolean create_theme_archive(const gchar *dir, const gchar *name,
31                                      const gchar *to);
32
33 gchar* archive_install(const gchar *path)
34 {
35     gchar *dest;
36     gchar *name;
37
38     if (!(dest = get_theme_dir()))
39         return NULL;
40
41     if (!(name = name_from_file(path)))
42         return NULL;
43
44     if (install_theme_to(name, path, dest)) {
45         gtk_msg(GTK_MESSAGE_INFO, _("\"%s\" was installed to %s"), name, dest);
46     } else {
47         g_free(name);
48         name = NULL;
49     }
50
51     g_free(dest);
52
53     return name;
54 }
55
56 void archive_create(const gchar *path)
57 {
58     gchar *name;
59     gchar *dest;
60
61     if (!(name = name_from_dir(path)))
62         return;
63
64     {
65         gchar *file;
66         file = g_strdup_printf("%s.obt", name);
67         dest = g_build_path(G_DIR_SEPARATOR_S,
68                             g_get_current_dir(), file, NULL);
69         g_free(file);
70     }
71
72     if (create_theme_archive(path, name, dest))
73         gtk_msg(GTK_MESSAGE_INFO, _("\"%s\" was successfully created"),
74                 dest);
75
76     g_free(dest);
77     g_free(name);
78 }
79
80 static gboolean create_theme_archive(const gchar *dir, const gchar *name,
81                                      const gchar *to)
82 {
83     gchar *glob;
84     gchar **argv;
85     gchar *errtxt = NULL;
86     gchar *parentdir;
87     gint exitcode;
88     GError *e = NULL;
89
90     glob = g_strdup_printf("%s/openbox-3/", name);
91
92     parentdir = g_build_path(G_DIR_SEPARATOR_S, dir, "..", NULL);
93
94     argv = g_new(gchar*, 9);
95     argv[0] = g_strdup("tar");
96     argv[1] = g_strdup("-c");
97     argv[2] = g_strdup("-z");
98     argv[3] = g_strdup("-f");
99     argv[4] = g_strdup(to);
100     argv[5] = g_strdup("-C");
101     argv[6] = g_strdup(parentdir);
102     argv[7] = g_strdup(glob);
103     argv[8] = NULL;
104     if (g_spawn_sync(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL,
105                      NULL, &errtxt, &exitcode, &e))
106     {
107         if (exitcode != EXIT_SUCCESS)
108             gtk_msg(GTK_MESSAGE_ERROR,
109                     _("Unable to create the theme archive \"%s\".\nThe following errors were reported:\n%s"),
110                     to, errtxt);
111
112     }
113     else
114         gtk_msg(GTK_MESSAGE_ERROR, _("Unable to run the \"tar\" command: %s"),
115                 e->message);
116
117     g_strfreev(argv);
118     if (e) g_error_free(e);
119     g_free(errtxt);
120     g_free(parentdir);
121     g_free(glob);
122     return exitcode == EXIT_SUCCESS;
123 }
124
125 static gchar *get_theme_dir()
126 {
127     gchar *dir;
128     gint r;
129
130     dir = g_build_path(G_DIR_SEPARATOR_S, g_get_home_dir(), ".themes", NULL);
131     r = mkdir(dir, 0777);
132     if (r == -1 && errno != EEXIST) {
133         gtk_msg(GTK_MESSAGE_ERROR,
134                 _("Unable to create directory \"%s\": %s"),
135                 dir, strerror(errno));
136         g_free(dir);
137         dir = NULL;
138     }
139
140     return dir;
141 }
142
143 static gchar* name_from_dir(const gchar *dir)
144 {
145     gchar *rc;
146     struct stat st;
147     gboolean r;
148
149     rc = g_build_path(G_DIR_SEPARATOR_S, dir, "openbox-3", "themerc", NULL);
150
151     r = (stat(rc, &st) == 0 && S_ISREG(st.st_mode));
152     g_free(rc);
153
154     if (!r) {
155         gtk_msg(GTK_MESSAGE_ERROR,
156                 _("\"%s\" does not appear to be a valid Openbox theme directory"),
157                 dir);
158         return NULL;
159     }
160     return g_path_get_basename(dir);
161 }
162
163 static gchar* name_from_file(const gchar *path)
164 {
165     /* decipher the theme name from the file name */
166     gchar *fname = g_path_get_basename(path);
167     gint len = strlen(fname);
168     gchar *name = NULL;
169
170     if (len > 4 &&
171         (fname[len-4] == '.' && fname[len-3] == 'o' &&
172          fname[len-2] == 'b' && fname[len-1] == 't'))
173     {
174         fname[len-4] = '\0';
175         name = g_strdup(fname);
176         fname[len-4] = '.';
177     }
178
179     if (name == NULL)
180         gtk_msg(GTK_MESSAGE_ERROR,
181                 _("Unable to determine the theme's name from \"%s\".  File name should be ThemeName.obt."), fname);
182
183     return name;
184 }
185
186 static gboolean change_dir(const gchar *dir)
187 {
188     if (chdir(dir) == -1) {
189         gtk_msg(GTK_MESSAGE_ERROR, _("Unable to move to directory \"%s\": %s"),
190                 dir, strerror(errno));
191         return FALSE;
192     }
193     return TRUE;
194 }
195
196 static gboolean install_theme_to(const gchar *name, const gchar *file,
197                                  const gchar *to)
198 {
199     gchar *glob;
200     gchar **argv;
201     gchar *errtxt = NULL;
202     gint exitcode;
203     GError *e = NULL;
204
205     glob = g_strdup_printf("%s/openbox-3/", name);
206
207     argv = g_new(gchar*, 9);
208     argv[0] = g_strdup("tar");
209     argv[1] = g_strdup("-x");
210     argv[2] = g_strdup("-z");
211     argv[3] = g_strdup("-f");
212     argv[4] = g_strdup(file);
213     argv[5] = g_strdup("-C");
214     argv[6] = g_strdup(to);
215     argv[7] = g_strdup(glob);
216     argv[8] = NULL;
217     if (!g_spawn_sync(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL,
218                       NULL, &errtxt, &exitcode, &e))
219         gtk_msg(GTK_MESSAGE_ERROR, _("Unable to run the \"tar\" command: %s"),
220                 e->message);
221     g_strfreev(argv);
222     if (e) g_error_free(e);
223
224     if (exitcode != EXIT_SUCCESS)
225         gtk_msg(GTK_MESSAGE_ERROR,
226                 _("Unable to extract the file \"%s\".\nPlease ensure that \"%s\" is writable and that the file is a valid Openbox theme archive.\nThe following errors were reported:\n%s"),
227                 file, to, errtxt);
228
229     g_free(errtxt);
230     g_free(glob);
231     return exitcode == EXIT_SUCCESS;
232 }