]> Pileus Git - ~andy/gtk/blob - gtk/queryimmodules.c
queryimmodules: Disable deprecaion warnings for deprecated header
[~andy/gtk] / gtk / queryimmodules.c
1 /* GTK+
2  * querymodules.c:
3  *
4  * Copyright (C) 2000-2010 Red Hat Software
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #include "config.h"
23
24 #include <glib.h>
25 #include <glib/gprintf.h>
26 #include <gmodule.h>
27
28 #include <errno.h>
29 #include <string.h>
30 #ifdef HAVE_UNISTD_H
31 #include <unistd.h>
32 #endif
33
34 #ifdef USE_LA_MODULES
35 #define SOEXT ".la"
36 #else
37 #define SOEXT ("." G_MODULE_SUFFIX)
38 #endif
39
40 #include "gtk/gtkimmodule.h"
41 #include "gtk/gtkversion.h"
42
43 #undef GDK_DEPRECATED
44 #undef GDK_DEPRECATED_FOR
45 #define GDK_DEPRECATED
46 #define GDK_DEPRECATED_FOR(f)
47 #undef GTK_DISABLE_DEPRECATED
48
49 #include "gtk/deprecated/gtkrc.h"
50
51 static void
52 escape_string (GString *contents, const char *str)
53 {
54   while (TRUE)
55     {
56       char c = *str++;
57
58       switch (c)
59         {
60         case '\0':
61           goto done;
62         case '\n':
63           g_string_append (contents, "\\n");
64           break;
65         case '\"':
66           g_string_append (contents, "\\\"");
67           break;
68 #ifdef G_OS_WIN32
69                 /* Replace backslashes in path with forward slashes, so that
70                  * it reads in without problems.
71                  */
72         case '\\':
73           g_string_append (contents, "/");
74           break;
75 #endif
76         default:
77           g_string_append_c (contents, c);
78         }
79     }
80
81  done:;
82 }
83
84 static void
85 print_escaped (GString *contents, const char *str)
86 {
87   g_string_append_c (contents, '"');
88   escape_string (contents, str);
89   g_string_append_c (contents, '"');
90   g_string_append_c (contents, ' ');
91 }
92
93 static gboolean
94 query_module (const char *dir, const char *name, GString *contents)
95 {
96   void          (*list)   (const GtkIMContextInfo ***contexts,
97                            guint                    *n_contexts);
98
99   gpointer list_ptr;
100   gpointer init_ptr;
101   gpointer exit_ptr;
102   gpointer create_ptr;
103
104   GModule *module;
105   gchar *path;
106   gboolean error = FALSE;
107
108   if (g_path_is_absolute (name))
109     path = g_strdup (name);
110   else
111     path = g_build_filename (dir, name, NULL);
112
113   module = g_module_open (path, 0);
114
115   if (!module)
116     {
117       g_fprintf (stderr, "Cannot load module %s: %s\n", path, g_module_error());
118       error = TRUE;
119     }
120
121   if (module &&
122       g_module_symbol (module, "im_module_list", &list_ptr) &&
123       g_module_symbol (module, "im_module_init", &init_ptr) &&
124       g_module_symbol (module, "im_module_exit", &exit_ptr) &&
125       g_module_symbol (module, "im_module_create", &create_ptr))
126     {
127       const GtkIMContextInfo **contexts;
128       guint n_contexts;
129       int i;
130
131       list = list_ptr;
132
133       print_escaped (contents, path);
134       g_string_append_c (contents, '\n');
135
136       (*list) (&contexts, &n_contexts);
137
138       for (i = 0; i < n_contexts; i++)
139         {
140           print_escaped (contents, contexts[i]->context_id);
141           print_escaped (contents, contexts[i]->context_name);
142           print_escaped (contents, contexts[i]->domain);
143           print_escaped (contents, contexts[i]->domain_dirname);
144           print_escaped (contents, contexts[i]->default_locales);
145           g_string_append_c (contents, '\n');
146         }
147       g_string_append_c (contents, '\n');
148     }
149   else
150     {
151       g_fprintf (stderr, "%s does not export GTK+ IM module API: %s\n", path,
152                  g_module_error ());
153       error = TRUE;
154     }
155
156   g_free (path);
157   if (module)
158     g_module_close (module);
159
160   return error;
161 }
162
163 int main (int argc, char **argv)
164 {
165   char *cwd;
166   int i;
167   char *path;
168   gboolean error = FALSE;
169   gchar *cache_file = NULL;
170   gint first_file = 1;
171   GString *contents;
172
173   if (argc > 1 && strcmp (argv[1], "--update-cache") == 0)
174     {
175       cache_file = gtk_rc_get_im_module_file ();
176       first_file = 2;
177     }
178
179   contents = g_string_new ("");
180   g_string_append_printf (contents,
181                           "# GTK+ Input Method Modules file\n"
182                           "# Automatically generated file, do not edit\n"
183                           "# Created by %s from gtk+-%d.%d.%d\n"
184                           "#\n",
185                           argv[0],
186                           GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
187
188   if (argc == first_file)  /* No file arguments given */
189     {
190       char **dirs;
191       int i;
192       GHashTable *dirs_done;
193
194       path = gtk_rc_get_im_module_path ();
195
196       g_string_append_printf (contents, "# ModulesPath = %s\n#\n", path);
197
198       dirs = pango_split_file_list (path);
199       dirs_done = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
200
201       for (i = 0; dirs[i]; i++)
202         if (!g_hash_table_lookup (dirs_done, dirs[i]))
203           {
204             GDir *dir = g_dir_open (dirs[i], 0, NULL);
205             if (dir)
206               {
207                 const char *dent;
208
209                 while ((dent = g_dir_read_name (dir)))
210                   {
211                     if (g_str_has_suffix (dent, SOEXT))
212                       error |= query_module (dirs[i], dent, contents);
213                   }
214
215                 g_dir_close (dir);
216               }
217
218             g_hash_table_insert (dirs_done, dirs[i], GUINT_TO_POINTER (TRUE));
219           }
220
221       g_hash_table_destroy (dirs_done);
222     }
223   else
224     {
225       cwd = g_get_current_dir ();
226
227       for (i = first_file; i < argc; i++)
228         error |= query_module (cwd, argv[i], contents);
229
230       g_free (cwd);
231     }
232
233   if (!error)
234     {
235       if (cache_file)
236         {
237           GError *err;
238
239           err = NULL;
240           if (!g_file_set_contents (cache_file, contents->str, -1, &err))
241             {
242                 g_fprintf (stderr, "%s\n", err->message);
243                 error = 1;
244             }
245         }
246       else
247         g_print ("%s\n", contents->str);
248     }
249
250   return error ? 1 : 0;
251 }