Updated changelog
[ukeyboard.git] / ukbdcreator / compiler.c
blob4731158465f31ed14f7d36346e12847b2df8e7cf
1 /*
2 * Copyright (c) 2008 Jiri Benc <jbenc@upir.cz>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 #include <sys/types.h>
19 #include <sys/wait.h>
20 #include <unistd.h>
21 #include <stdlib.h>
22 #include <gtk/gtk.h>
23 #include <glib/gstdio.h>
24 #include <gconf/gconf.h>
25 #include <gconf/gconf-client.h>
26 #include "../vkb_compiler.h"
27 #include "ukbdcreator.h"
29 static gchar *saved_layout = NULL;
30 static gchar *saved_lang = NULL;
31 static gint saved_current = -1;
32 static gchar *act_layout = NULL;
34 struct priv {
35 char *buf;
36 size_t pos;
37 int fout;
38 gchar *lang;
41 static void error(void *p, int line, char *msg)
43 (void)p;
44 disp_compile_error(line, msg);
47 static int warning(void *p, int line, char *msg)
49 (void)p;
50 disp_compile_error(line, msg);
51 return -1;
54 static int get_line(void *p, void *buf, size_t size)
56 struct priv *priv = p;
57 size_t dpos = 0;
58 char *dbuf = buf;
60 while (priv->buf[priv->pos]) {
61 if (dpos + 1 < size)
62 dbuf[dpos++] = priv->buf[priv->pos];
63 if (priv->buf[priv->pos++] == '\n')
64 break;
66 dbuf[dpos] = '\0';
67 return (priv->buf[priv->pos] || dpos) ? 0 : -1;
70 static int write_buf(void *p, void *buf, size_t size)
72 struct priv *priv = p;
74 if (write(priv->fout, buf, size) != (ssize_t)size) {
75 disp_error("Error writing temporary file");
76 return -1;
78 return 0;
81 static off_t tell_buf(void *p)
83 struct priv *priv = p;
85 return lseek(priv->fout, 0, SEEK_CUR);
88 static void seek_buf(void *p, off_t pos)
90 struct priv *priv = p;
92 lseek(priv->fout, pos, SEEK_SET);
95 static void return_lang(void *p, char *lang)
97 struct priv *priv = p;
99 priv->lang = g_strdup(lang);
102 static struct compiler_ops ops = {
103 .get_line = get_line,
104 .write = write_buf,
105 .tell = tell_buf,
106 .seek = seek_buf,
107 .error = error,
108 .warning = warning,
109 .return_lang = return_lang,
112 gboolean compile_layout(gchar *buf, gchar **fname, gchar **lang)
114 struct priv priv;
115 int res;
117 priv.buf = buf;
118 priv.pos = 0;
119 priv.lang = NULL;
121 *fname = g_build_filename(g_get_tmp_dir(), "ukbdXXXXXX", NULL);
122 priv.fout = g_mkstemp(*fname);
123 if (priv.fout < 0) {
124 g_free(*fname);
125 disp_error("Error creating temporary file");
126 return FALSE;
128 res = compile(&ops, &priv);
129 close(priv.fout);
130 if (res < 0) {
131 g_unlink(*fname);
132 g_free(*fname);
133 g_free(priv.lang);
134 return FALSE;
136 *lang = priv.lang;
137 return TRUE;
140 static gchar *get_lang(GConfClient *conf)
142 return gconf_client_get_string(conf,
143 "/apps/osso/inputmethod/hildon-im-languages/language-0", NULL);
146 static void set_lang(GConfClient *conf, gchar *val)
148 gconf_client_set_string(conf,
149 "/apps/osso/inputmethod/hildon-im-languages/language-0", val, NULL);
152 static gint get_current(GConfClient *conf)
154 return gconf_client_get_int(conf,
155 "/apps/osso/inputmethod/hildon-im-languages/current", NULL);
158 static void set_current(GConfClient *conf, gint val)
160 gconf_client_set_int(conf,
161 "/apps/osso/inputmethod/hildon-im-languages/current", val, NULL);
164 gboolean test_layout(GConfClient *conf, gchar *fname, gchar *lang)
166 gchar *cmd;
167 int res;
169 if (saved_lang)
170 restore_layout(conf, FALSE);
171 if (inside_scratchbox)
172 cmd = g_strdup_printf("fakeroot /usr/libexec/ukeyboard-set -s %s %s", fname, lang);
173 else
174 cmd = g_strdup_printf("sudo /usr/libexec/ukeyboard-set -s %s %s", fname, lang);
175 res = system(cmd);
176 g_free(cmd);
177 if (!WIFEXITED(res)) {
178 disp_error("Cannot execute helper script");
179 return FALSE;
181 res = WEXITSTATUS(res);
182 if (res == 2) {
183 disp_error("Redefining a system language is not possible.\nPlease use diffent language code.");
184 return FALSE;
186 if (res) {
187 disp_error("Activating of the layout failed");
188 return FALSE;
190 saved_lang = g_strdup(lang);
191 saved_layout = get_lang(conf);
192 saved_current = get_current(conf);
193 set_lang(conf, "en_GB");
194 set_lang(conf, lang);
195 set_current(conf, 0);
196 if (act_layout) {
197 g_unlink(act_layout);
198 g_free(act_layout);
200 act_layout = g_strdup(fname);
201 disp_info("Layout activated");
202 return TRUE;
205 gboolean restore_layout(GConfClient *conf, gboolean warn)
207 gchar *cmd;
208 int res;
210 if (!saved_lang) {
211 if (warn)
212 disp_info("No layout to restore");
213 return FALSE;
215 if (inside_scratchbox)
216 cmd = g_strdup_printf("fakeroot /usr/libexec/ukeyboard-set -r %s", saved_lang);
217 else
218 cmd = g_strdup_printf("sudo /usr/libexec/ukeyboard-set -r %s", saved_lang);
219 res = system(cmd);
220 g_free(cmd);
221 if (!WIFEXITED(res)) {
222 disp_error("Cannot execute helper script");
223 return FALSE;
225 res = WEXITSTATUS(res);
226 if (res) {
227 disp_error("Restoring of original layout failed");
228 return FALSE;
230 set_lang(conf, "en_GB");
231 set_lang(conf, saved_layout);
232 set_current(conf, saved_current);
233 g_free(saved_lang);
234 g_free(saved_layout);
235 saved_lang = saved_layout = NULL;
236 saved_current = -1;
237 if (act_layout) {
238 g_unlink(act_layout);
239 g_free(act_layout);
240 act_layout = NULL;
242 if (warn)
243 disp_info("Layout deactivated");
244 return TRUE;