]> icculus.org git repositories - dana/obconf.git/blob - src/theme.c
typo
[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 static gchar* name_from_file(const gchar *path);
35
36 tartype_t funcs = {
37     (openfunc_t) gzopen_frontend,
38     (closefunc_t) gzclose_frontend,
39     (readfunc_t) gzread_frontend,
40     (writefunc_t) gzwrite_frontend
41 };
42
43 gchar* theme_install(gchar *path)
44 {
45     gchar *dest;
46     gchar *curdir;
47     gchar *name;
48
49     if (!(dest = get_theme_dir()))
50         return NULL;
51
52     curdir = g_get_current_dir();
53     if (!change_dir(dest)) {
54         g_free(curdir);
55         return NULL;
56     }
57
58     if (!(name = name_from_file(path)))
59         return NULL;
60
61     if (install_theme_to(name, path, dest))
62         gtk_msg(GTK_MESSAGE_INFO, _("\"%s\" was installed to %s"), name, dest);
63
64     g_free(dest);
65
66     change_dir(curdir);
67     g_free(curdir);
68
69     return name;
70 }
71
72 static gchar *get_theme_dir()
73 {
74     gchar *dir;
75     gint r;
76
77     dir = g_build_path(G_DIR_SEPARATOR_S, g_get_home_dir(), ".themes", NULL);
78     r = mkdir(dir, 0777);
79     if (r == -1 && errno != EEXIST) {
80         gtk_msg(GTK_MESSAGE_ERROR,
81                 _("Unable to create directory \"%s\": %s"),
82                 dir, strerror(errno));
83         g_free(dir);
84         dir = NULL;
85     }
86
87     return dir;
88 }
89
90 static gchar* name_from_file(const gchar *path)
91 {
92     /* decipher the theme name from the file name */
93     gchar *fname = g_path_get_basename(path);
94     gint len = strlen(fname);
95     gchar *name = NULL;
96
97     if (len > 4 &&
98         (fname[len-4] == '.' && fname[len-3] == 'o' &&
99          fname[len-2] == 'b' && fname[len-1] == 't'))
100     {
101         fname[len-4] = '\0';
102         name = strdup(fname);
103         fname[len-4] = '.';
104     }
105
106     if (name == NULL)
107         gtk_msg(GTK_MESSAGE_ERROR,
108                 _("Unable to determine the theme's name from \"%s\".  File name should be ThemeName.obt."), fname);
109
110     return name;
111 }
112
113 static gboolean change_dir(const gchar *dir)
114 {
115     if (chdir(dir) == -1) {
116         gtk_msg(GTK_MESSAGE_ERROR, _("Unable to move to directory \"%s\": %s"),
117                 dir, strerror(errno));
118         return FALSE;
119     }
120     return TRUE;
121 }
122
123 static gboolean install_theme_to(gchar *theme, gchar *file, gchar *to)
124 {
125     TAR *t;
126     gchar *glob;
127     gint r;
128
129     if (tar_open(&t, file, &funcs, 0, O_RDONLY, TAR_GNU) == -1) {
130         gtk_msg(GTK_MESSAGE_ERROR,
131                 _("Unable to open the file \"%s\": %s"),
132                 file, strerror(errno));
133         return FALSE;
134     }
135
136     glob = g_strdup_printf("%s/openbox-3/*", theme);
137     r = tar_extract_glob(t, glob, to);
138     g_free(glob);
139
140     tar_close(t);
141
142     if (r != 0)
143         gtk_msg(GTK_MESSAGE_ERROR,
144                 _("Unable to extract the file \"%s\".\nIt does not appear to be a valid Openbox theme archive (in tar.gz format)."),
145                 file, strerror(errno));
146
147     return r == 0;
148 }
149
150 static int gzopen_frontend(const char *path, int oflags, int mode)
151 {
152     int fd;
153
154     if ((fd = open(path, oflags, mode)) < 0) return -1;
155     if (!(gzf = gzdopen(fd, "rb"))) return -1;
156     return 1;
157 }
158
159 static int gzclose_frontend(int nothing)
160 {
161     g_return_val_if_fail(gzf != NULL, 0);
162     return gzclose(gzf);
163 }
164
165 static ssize_t gzread_frontend(int nothing, void *buf, size_t s)
166 {
167     return gzread(gzf, buf, s);
168 }
169
170 static ssize_t gzwrite_frontend(int nothing, const void *buf, size_t s)
171 {
172     return gzwrite(gzf, buf, s);
173 }
174