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