1 /* input.c: interface for input handlers
2
3 Copyright (C) 1999, 2000, 2001 Bernhard Herzog.
4 Copyright (C) 2003 Masatake YAMATO
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public License
8 as published by the Free Software Foundation; either version 2.1 of
9 the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 USA. */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif /* Def: HAVE_CONFIG_H */
24
25 #include "autotrace.h"
26 #include "private.h"
27 #include "input.h"
28 #include "xstd.h"
29 #include "filename.h"
30 #include <string.h>
31 #include <glib.h>
32
33 typedef struct _at_input_format_entry at_input_format_entry;
34 struct _at_input_format_entry {
35 at_bitmap_reader reader;
36 const gchar *descr;
37 GDestroyNotify user_data_destroy_func;
38 };
39
40 static GHashTable *at_input_formats = NULL;
41 static at_input_format_entry *at_input_format_new(const char *descr, at_input_func reader, gpointer user_data, GDestroyNotify user_data_destroy_func);
42 static void at_input_format_free(at_input_format_entry * entry);
43
44 /*
45 * Helper functions
46 */
47 static void input_list_set(gpointer key, gpointer value, gpointer user_data);
48 static void input_list_strlen(gpointer key, gpointer value, gpointer user_data);
49 static void input_list_strcat(gpointer key, gpointer value, gpointer user_data);
50
51 /**
52 * at_input_init:
53 * Initialize at_input input plugin sub system.
54 *
55 * Return value: 1 for success, else for failure
56 **/
at_input_init(void)57 int at_input_init(void)
58 {
59 if (at_input_formats)
60 return 1;
61
62 at_input_formats = g_hash_table_new_full(g_str_hash, (GEqualFunc) g_str_equal, g_free, (GDestroyNotify) at_input_format_free);
63 if (!at_input_formats)
64 return 0;
65 return 1;
66 }
67
at_input_format_new(const gchar * descr,at_input_func reader,gpointer user_data,GDestroyNotify user_data_destroy_func)68 static at_input_format_entry *at_input_format_new(const gchar * descr, at_input_func reader, gpointer user_data, GDestroyNotify user_data_destroy_func)
69 {
70 at_input_format_entry *entry;
71 entry = g_malloc(sizeof(at_input_format_entry));
72 if (entry) {
73 entry->reader.func = reader;
74 entry->reader.data = user_data;
75 entry->descr = g_strdup(descr);
76 entry->user_data_destroy_func = user_data_destroy_func;
77 }
78 return entry;
79 }
80
at_input_format_free(at_input_format_entry * entry)81 static void at_input_format_free(at_input_format_entry * entry)
82 {
83 g_free((gpointer) entry->descr);
84 if (entry->user_data_destroy_func)
85 entry->user_data_destroy_func(entry->reader.data);
86 g_free(entry);
87
88 }
89
at_input_add_handler(const gchar * suffix,const gchar * description,at_input_func reader)90 int at_input_add_handler(const gchar * suffix, const gchar * description, at_input_func reader)
91 {
92 return at_input_add_handler_full(suffix, description, reader, 0, NULL, NULL);
93 }
94
at_input_add_handler_full(const gchar * suffix,const gchar * description,at_input_func reader,gboolean override,gpointer user_data,GDestroyNotify user_data_destroy_func)95 int at_input_add_handler_full(const gchar * suffix, const gchar * description, at_input_func reader, gboolean override, gpointer user_data, GDestroyNotify user_data_destroy_func)
96 {
97 gchar *gsuffix;
98 const gchar *gdescription;
99 at_input_format_entry *old_entry;
100 at_input_format_entry *new_entry;
101
102 g_return_val_if_fail(suffix, 0);
103 g_return_val_if_fail(description, 0);
104 g_return_val_if_fail(reader, 0);
105
106 gsuffix = g_strdup((gchar *) suffix);
107 g_return_val_if_fail(gsuffix, 0);
108 gsuffix = g_ascii_strdown(gsuffix, strlen(gsuffix));
109
110 gdescription = (const gchar *)description;
111
112 old_entry = g_hash_table_lookup(at_input_formats, gsuffix);
113 if (old_entry && !override) {
114 g_free(gsuffix);
115 return 1;
116 }
117
118 new_entry = at_input_format_new(gdescription, reader, user_data, user_data_destroy_func);
119 g_return_val_if_fail(new_entry, 0);
120
121 g_hash_table_replace(at_input_formats, gsuffix, new_entry);
122 return 1;
123 }
124
at_input_get_handler(gchar * filename)125 at_bitmap_reader *at_input_get_handler(gchar * filename)
126 {
127 char *ext = find_suffix(filename);
128 if (ext == NULL)
129 ext = "";
130
131 return at_input_get_handler_by_suffix(ext);
132 }
133
at_input_get_handler_by_suffix(gchar * suffix)134 at_bitmap_reader *at_input_get_handler_by_suffix(gchar * suffix)
135 {
136 at_input_format_entry *format;
137 gchar *gsuffix;
138
139 if (!suffix || suffix[0] == '\0')
140 return NULL;
141
142 gsuffix = g_strdup(suffix);
143 g_return_val_if_fail(gsuffix, NULL);
144 gsuffix = g_ascii_strdown(gsuffix, strlen(gsuffix));
145 format = g_hash_table_lookup(at_input_formats, gsuffix);
146 g_free(gsuffix);
147
148 if (format)
149 return &(format->reader);
150 else
151 return NULL;
152 }
153
at_input_list_new(void)154 const char **at_input_list_new(void)
155 {
156 char **list, **tmp;
157 gint format_count;
158 gint list_count;
159
160 format_count = g_hash_table_size(at_input_formats);
161 list_count = 2 * format_count;
162 list = g_new(gchar *, list_count + 1);
163 list[list_count] = NULL;
164
165 tmp = list;
166 g_hash_table_foreach(at_input_formats, input_list_set, &tmp);
167 return (const char **)list;
168 }
169
at_input_list_free(const char ** list)170 void at_input_list_free(const char **list)
171 {
172 free((char **)list);
173 }
174
at_input_shortlist(void)175 char *at_input_shortlist(void)
176 {
177 gint length = 0, count;
178 char *list, *tmp;
179 g_hash_table_foreach(at_input_formats, input_list_strlen, &length);
180 count = g_hash_table_size(at_input_formats);
181
182 /* 2 for ", " */
183 length += (2 * count);
184 list = g_malloc(length + 1);
185 list[0] = '\0';
186
187 tmp = list;
188 g_hash_table_foreach(at_input_formats, input_list_strcat, &tmp);
189
190 /* remove final ", " */
191 g_return_val_if_fail(list[length - 2] == ',', NULL);
192 list[length - 2] = '\0';
193 return list;
194 }
195
input_list_set(gpointer key,gpointer value,gpointer user_data)196 static void input_list_set(gpointer key, gpointer value, gpointer user_data)
197 {
198 at_input_format_entry *format = value;
199 const char ***list_ptr = user_data;
200 const char **list = *list_ptr;
201 list[0] = key;
202 list[1] = format->descr;
203 *list_ptr = &(list[2]);
204 }
205
input_list_strlen(gpointer key,gpointer value,gpointer user_data)206 static void input_list_strlen(gpointer key, gpointer value, gpointer user_data)
207 {
208 gint *length;
209 g_return_if_fail(key);
210 g_return_if_fail(user_data);
211
212 length = user_data;
213 *length += strlen(key);
214 }
215
input_list_strcat(gpointer key,gpointer value,gpointer user_data)216 static void input_list_strcat(gpointer key, gpointer value, gpointer user_data)
217 {
218 gchar **list_ptr;
219 gchar *list;
220 list_ptr = user_data;
221 list = *list_ptr;
222 strcat(list, key);
223 strcat(list, ", ");
224
225 /* 2 for ", " */
226 *list_ptr = list + strlen(key) + 2;
227 }
228