]> icculus.org git repositories - dana/obconf.git/blob - src/main.c
Add translation (Complete)
[dana/obconf.git] / src / main.c
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
2
3    main.c for ObConf, the configuration tool for Openbox
4    Copyright (c) 2003-2008   Dana Jansens
5    Copyright (c) 2003        Tim Riley
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    See the COPYING file for a copy of the GNU General Public License.
18 */
19
20 #include "main.h"
21 #include "archive.h"
22 #include "theme.h"
23 #include "appearance.h"
24 #include "windows.h"
25 #include "margins.h"
26 #include "mouse.h"
27 #include "desktops.h"
28 #include "dock.h"
29 #include "preview_update.h"
30 #include "gettext.h"
31
32 #include <gdk/gdkx.h>
33 #define SN_API_NOT_YET_FROZEN
34 #include <libsn/sn.h>
35 #undef SN_API_NOT_YET_FROZEN
36 #include <stdlib.h>
37
38 GtkWidget *mainwin = NULL;
39 GtkWidget *tabstrip = NULL;
40
41 GtkBuilder *builder;
42 xmlDocPtr doc;
43 xmlNodePtr root;
44 RrInstance *rrinst;
45 gchar *obc_config_file = NULL;
46 gint obc_tab;
47 ObtPaths *paths;
48 ObtXmlInst *parse_i;
49
50 static gchar *obc_theme_install = NULL;
51 static gchar *obc_theme_archive = NULL;
52
53 void obconf_error(gchar *msg, gboolean modal)
54 {
55     GtkWidget *d;
56
57     d = gtk_message_dialog_new(mainwin ? GTK_WINDOW(mainwin) : NULL,
58                                GTK_DIALOG_DESTROY_WITH_PARENT,
59                                GTK_MESSAGE_ERROR,
60                                GTK_BUTTONS_CLOSE,
61                                "%s", msg);
62     gtk_window_set_title(GTK_WINDOW(d), _("ObConf Error"));
63     if (modal)
64         gtk_dialog_run(GTK_DIALOG(d));
65     else {
66         g_signal_connect_swapped(G_OBJECT(d), "response",
67                                  G_CALLBACK(gtk_widget_destroy),
68                                  G_OBJECT(d));
69         gtk_widget_show(d);
70     }
71 }
72
73 static void print_version()
74 {
75     g_print("ObConf %s\n", PACKAGE_VERSION);
76     g_print(_("Copyright (c)"));
77     g_print(" 2003-2008   Dana Jansens\n");
78     g_print(_("Copyright (c)"));
79     g_print(" 2003        Tim Riley\n");
80     g_print(_("Copyright (c)"));
81     g_print(" 2007        Javeed Shaikh\n\n");
82     g_print("This program comes with ABSOLUTELY NO WARRANTY.\n");
83     g_print("This is free software, and you are welcome to redistribute it\n");
84     g_print("under certain conditions. See the file COPYING for details.\n\n");
85
86     exit(EXIT_SUCCESS);
87 }
88
89 static void print_help()
90 {
91     g_print(_("Syntax: obconf [options] [ARCHIVE.obt]\n"));
92     g_print(_("\nOptions:\n"));
93     g_print(_("  --help                Display this help and exit\n"));
94     g_print(_("  --version             Display the version and exit\n"));
95     g_print(_("  --install ARCHIVE.obt Install the given theme archive and select it\n"));
96     g_print(_("  --archive THEME       Create a theme archive from the given theme directory\n"));
97     g_print(_("  --config-file FILE    Specify the path to the config file to use\n"));
98     g_print(_("  --tab NUMBER          Switch to tab number NUMBER on startup\n"));
99     g_print(_("\nPlease report bugs at %s\n\n"), PACKAGE_BUGREPORT);
100
101     exit(EXIT_SUCCESS);
102 }
103
104 static void parse_args(int argc, char **argv)
105 {
106     int i;
107
108     for (i = 1; i < argc; ++i) {
109         if (!strcmp(argv[i], "--help"))
110             print_help();
111         if (!strcmp(argv[i], "--version"))
112             print_version();
113         else if (!strcmp(argv[i], "--install")) {
114             if (i == argc - 1) /* no args left */
115                 g_printerr(_("--install requires an argument\n"));
116             else
117                 obc_theme_install = argv[++i];
118         }
119         else if (!strcmp(argv[i], "--archive")) {
120             if (i == argc - 1) /* no args left */
121                 g_printerr(_("--archive requires an argument\n"));
122             else
123                 obc_theme_archive = argv[++i];
124         }
125         else if (!strcmp(argv[i], "--config-file")) {
126             if (i == argc - 1) /* no args left */
127                 g_printerr(_("--config-file requires an argument\n"));
128             else
129                 obc_config_file = argv[++i];
130         }
131         else if (!strcmp(argv[i], "--tab")) {
132             if (i == argc - 1) /* no args left */
133                 g_printerr(_("--tab requires an argument\n"));
134             else {
135                 obc_tab = atoi(argv[++i]) - 1;
136                 /* tab number should not be negative */
137                 obc_tab = MAX(obc_tab, 0);
138             }
139         }
140         else
141             obc_theme_install = argv[i];
142     }
143 }
144
145 static gboolean get_all(Window win, Atom prop, Atom type, gint size,
146                         guchar **data, guint *num)
147 {
148     gboolean ret = FALSE;
149     gint res;
150     guchar *xdata = NULL;
151     Atom ret_type;
152     gint ret_size;
153     gulong ret_items, bytes_left;
154
155     res = XGetWindowProperty(gdk_x11_get_default_xdisplay(), win, prop, 0l, G_MAXLONG,
156                              FALSE, type, &ret_type, &ret_size,
157                              &ret_items, &bytes_left, &xdata);
158     if (res == Success) {
159         if (ret_size == size && ret_items > 0) {
160             guint i;
161
162             *data = g_malloc(ret_items * (size / 8));
163             for (i = 0; i < ret_items; ++i)
164                 switch (size) {
165                 case 8:
166                     (*data)[i] = xdata[i];
167                     break;
168                 case 16:
169                     ((guint16*)*data)[i] = ((gushort*)xdata)[i];
170                     break;
171                 case 32:
172                     ((guint32*)*data)[i] = ((gulong*)xdata)[i];
173                     break;
174                 default:
175                     g_assert_not_reached(); /* unhandled size */
176                 }
177             *num = ret_items;
178             ret = TRUE;
179         }
180         XFree(xdata);
181     }
182     return ret;
183 }
184
185 static gboolean prop_get_string_utf8(Window win, Atom prop, gchar **ret)
186 {
187     gchar *raw;
188     gchar *str;
189     guint num;
190
191     if (get_all(win, prop,
192                 gdk_x11_get_xatom_by_name("UTF8_STRING"),
193                 8,(guchar**)&raw, &num))
194     {
195         str = g_strndup(raw, num); /* grab the first string from the list */
196         g_free(raw);
197         if (g_utf8_validate(str, -1, NULL)) {
198             *ret = str;
199             return TRUE;
200         }
201         g_free(str);
202     }
203     return FALSE;
204 }
205
206 int main(int argc, char **argv)
207 {
208     gchar *p;
209     GError *error = NULL;
210     gboolean exit_with_error = FALSE;
211
212     bindtextdomain(PACKAGE_NAME, LOCALEDIR);
213     bind_textdomain_codeset(PACKAGE_NAME, "UTF-8");
214     textdomain(PACKAGE_NAME);
215
216     gtk_init(&argc, &argv);
217     parse_args(argc, argv);
218
219     if (obc_theme_archive) {
220         archive_create(obc_theme_archive);
221         return 0;
222     }
223
224     p = g_build_filename(RESOURCEDIR, "obconf.ui", NULL);
225     builder = gtk_builder_new();
226     gtk_builder_add_from_file(builder, p, &error);
227     g_free(p);
228
229     if (error) {
230         obconf_error(_("Failed to load the obconf.ui interface file. You have probably failed to install ObConf properly."), TRUE);
231         g_printerr("%s\n", error->message);
232         g_error_free(error);
233         exit_with_error = TRUE;
234     }
235
236     paths = obt_paths_new();
237     parse_i = obt_xml_instance_new();
238     rrinst = RrInstanceNew(gdk_x11_get_default_xdisplay(), gdk_x11_get_default_screen());
239
240     if (!obc_config_file) {
241         gchar *p;
242
243         if (prop_get_string_utf8(GDK_ROOT_WINDOW(),
244                                  gdk_x11_get_xatom_by_name("_OB_CONFIG_FILE"),
245                                  &p))
246         {
247             obc_config_file = g_filename_from_utf8(p, -1, NULL, NULL, NULL);
248             g_free(p);
249         }
250     }
251
252     xmlIndentTreeOutput = 1;
253     if (!((obc_config_file &&
254            obt_xml_load_file(parse_i, obc_config_file, "openbox_config")) ||
255           obt_xml_load_config_file(parse_i, "openbox", "rc.xml",
256                                    "openbox_config")))
257     {
258         obconf_error(_("Failed to load an rc.xml. You have probably failed to install Openbox properly."), TRUE);
259         exit_with_error = TRUE;
260     }
261     else {
262         doc = obt_xml_doc(parse_i);
263         root = obt_xml_root(parse_i);
264     }
265
266     /* look for parsing errors */
267     {
268         xmlErrorPtr e = xmlGetLastError();
269         if (e) {
270             char *a = g_strdup_printf
271                 (_("Error while parsing the Openbox configuration file.  Your configuration file is not valid XML.\n\nMessage: %s"),
272                  e->message);
273             obconf_error(a, TRUE);
274             g_free(a);
275             exit_with_error = TRUE;
276         }
277     }
278
279     if (!exit_with_error) {
280         gtk_builder_connect_signals(builder, NULL);
281
282         {
283             gchar *s = g_strdup_printf
284                 ("<span weight=\"bold\" size=\"xx-large\">ObConf %s</span>",
285                  PACKAGE_VERSION);
286             gtk_label_set_markup(GTK_LABEL
287                                  (gtk_builder_get_object(builder, "title_label")),
288                                  s);
289             g_free(s);
290         }
291
292         theme_setup_tab();
293         appearance_setup_tab();
294         windows_setup_tab();
295         moveresize_setup_tab();
296         mouse_setup_tab();
297         desktops_setup_tab();
298         margins_setup_tab();
299         dock_setup_tab();
300
301         mainwin = get_widget("main_window");
302         tabstrip = get_widget("tabstrip");
303
304         if (obc_theme_install)
305             theme_install(obc_theme_install);
306         else
307             theme_load_all();
308
309         /* the main window is not shown here ! it is shown when the theme
310            previews are completed */
311         gtk_main();
312
313         preview_update_set_active_font(NULL);
314         preview_update_set_inactive_font(NULL);
315         preview_update_set_menu_header_font(NULL);
316         preview_update_set_menu_item_font(NULL);
317         preview_update_set_osd_active_font(NULL);
318         preview_update_set_osd_inactive_font(NULL);
319         preview_update_set_title_layout(NULL);
320     }
321
322     RrInstanceFree(rrinst);
323     obt_xml_instance_unref(parse_i);
324     obt_paths_unref(paths);
325
326     xmlFreeDoc(doc);
327     return 0;
328 }
329
330 gboolean on_main_window_delete_event(GtkWidget *w, GdkEvent *e, gpointer d)
331 {
332     gtk_main_quit();
333     return FALSE;
334 }
335
336 void on_close_clicked()
337 {
338     gtk_main_quit();
339 }
340
341 void obconf_show_main()
342 {
343     SnDisplay *sn_d;
344     SnLauncheeContext *sn_cx;
345
346     if (gtk_widget_get_visible(mainwin)) return;
347
348     gtk_widget_show_all(mainwin);
349
350     /* Focus on the tab number specified by --tab. */
351     if (obc_tab)
352         gtk_notebook_set_current_page(GTK_NOTEBOOK(tabstrip), obc_tab);
353
354
355     sn_d = sn_display_new(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()),
356                           NULL, NULL);
357
358     sn_cx = sn_launchee_context_new_from_environment
359         (sn_d, gdk_screen_get_number(gdk_display_get_default_screen
360                                      (gdk_display_get_default())));
361
362     if (sn_cx)
363         sn_launchee_context_setup_window
364             (sn_cx, GDK_WINDOW_XID(gtk_widget_get_window(mainwin)));
365
366     if (sn_cx)
367         sn_launchee_context_complete(sn_cx);
368
369     if (sn_cx)
370         sn_launchee_context_unref(sn_cx);
371     sn_display_unref(sn_d);
372 }