]> icculus.org git repositories - dana/obconf.git/blob - src/theme.c
move install.[ch] to theme.[ch]
[dana/obconf.git] / src / theme.c
1 #include "theme.h"
2 #include "main.h"
3 #include "gettext.h"
4
5 #include <errno.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <fcntl.h>
9 #include <zlib.h>
10 #include <libtar.h>
11
12 static gzFile gzf = NULL;
13
14 #define gtk_msg(type, args...) \
15 {                                                                        \
16     GtkWidget *msgw;                                                     \
17     msgw = gtk_message_dialog_new(GTK_WINDOW(mainwin),                   \
18                                   GTK_DIALOG_DESTROY_WITH_PARENT |       \
19                                   GTK_DIALOG_MODAL,                      \
20                                   type,                                  \
21                                   GTK_BUTTONS_OK,                        \
22                                   args);                                 \
23     gtk_dialog_run(GTK_DIALOG(msgw));                                    \
24     gtk_widget_destroy(msgw);                                            \
25 }
26
27 static int gzopen_frontend(const char *path, int oflags, int mode);
28 static int gzclose_frontend(int nothing);
29 static ssize_t gzread_frontend(int nothing, void *buf, size_t s);
30 static ssize_t gzwrite_frontend(int nothing, const void *buf, size_t s);
31 static gchar *get_theme_dir();
32 static gboolean change_dir(const gchar *dir);
33 static gboolean install_theme_to(gchar *theme, gchar *file, gchar *to);
34
35 tartype_t funcs = {
36     (openfunc_t) gzopen_frontend,
37     (closefunc_t) gzclose_frontend,
38     (readfunc_t) gzread_frontend,
39     (writefunc_t) gzwrite_frontend
40 };
41
42 gboolean theme_install(gchar *path, gchar *theme)
43 {
44     gchar *dest;
45     gchar *curdir;
46
47     if (!(dest = get_theme_dir()))
48         return FALSE;
49
50     curdir = g_get_current_dir();
51     if (!change_dir(dest)) {
52         g_free(curdir);
53         return FALSE;
54     }
55
56     if (install_theme_to(theme, path, dest))
57         gtk_msg(GTK_MESSAGE_INFO, _("%s was installed to %s"), theme, dest);
58
59     g_free(dest);
60
61     change_dir(curdir);
62     g_free(curdir);
63
64     return TRUE;
65 }
66
67 static gchar *get_theme_dir()
68 {
69     gchar *dir;
70     gint r;
71
72     dir = g_build_path(G_DIR_SEPARATOR_S, g_get_home_dir(), ".themes", NULL);
73     r = mkdir(dir, 0777);
74     if (r == -1 && errno != EEXIST) {
75         gtk_msg(GTK_MESSAGE_ERROR,
76                 _("Unable to create directory \"%s\": %s"),
77                 dir, strerror(errno));
78         g_free(dir);
79         dir = NULL;
80     }
81
82     return dir;
83 }
84
85 static gboolean change_dir(const gchar *dir)
86 {
87     if (chdir(dir) == -1) {
88         gtk_msg(GTK_MESSAGE_ERROR, _("Unable to move to directory \"%s\": %s"),
89                 dir, strerror(errno));
90         return FALSE;
91     }
92     return TRUE;
93 }
94
95 static gboolean install_theme_to(gchar *theme, gchar *file, gchar *to)
96 {
97     TAR *t;
98     gchar *glob;
99     gint r;
100
101     if (tar_open(&t, file, &funcs, 0, O_RDONLY, TAR_GNU) == -1) {
102         gtk_msg(GTK_MESSAGE_ERROR,
103                 _("Unable to open the file \"%s\": %s"),
104                 file, strerror(errno));
105         return FALSE;
106     }
107
108     glob = g_strdup_printf("%s/openbox-3/*", theme);
109     r = tar_extract_glob(t, glob, to);
110     g_free(glob);
111
112     tar_close(t);
113
114     if (r != 0)
115         gtk_msg(GTK_MESSAGE_ERROR,
116                 _("Unable to extract the file \"%s\".\nIt does not appear to be a valid Openbox theme archive (in tar.gz format)."),
117                 file, strerror(errno));
118
119     return r == 0;
120 }
121
122 static int gzopen_frontend(const char *path, int oflags, int mode)
123 {
124     int fd;
125
126     if ((fd = open(path, oflags, mode)) < 0) return -1;
127     if (!(gzf = gzdopen(fd, "rb"))) return -1;
128     return 1;
129 }
130
131 static int gzclose_frontend(int nothing)
132 {
133     g_return_val_if_fail(gzf != NULL, 0);
134     return gzclose(gzf);
135 }
136
137 static ssize_t gzread_frontend(int nothing, void *buf, size_t s)
138 {
139     return gzread(gzf, buf, s);
140 }
141
142 static ssize_t gzwrite_frontend(int nothing, const void *buf, size_t s)
143 {
144     return gzwrite(gzf, buf, s);
145 }
146