1 /*  cssed (c) Iago Rubio 2003, 2005 - A tiny CSS editor.
2  *
3  *  This program is free software; you can redistribute it and/or modify
4  *  it under the terms of the GNU General Public License as published by
5  *  the Free Software Foundation; either version 2 of the License, or
6  *  (at your option) any later version.
7  *
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 Library General Public License for more details.
12  *
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16  */
17 
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21 
22 #include <string.h>
23 #include <gtk/gtk.h>
24 
25 #include "cssedwindow.h"
26 #include "document.h"
27 #include "support.h"
28 #include "utils.h"
29 #include "debug.h"
30 #include "file-type-manager.h"
31 
32 #define g_slist_first(n) g_slist_nth (n,0)
33 
34 // FILE TYPE IMPLEMENTATION
35 CssedFileType*
cssed_file_type_new()36 cssed_file_type_new()
37 {
38 	CssedFileType* type;
39 	type = g_malloc0(sizeof(CssedFileType));
40 	return type;
41 }
42 
43 void
cssed_file_type_free_item(gpointer item,gpointer user_data)44 cssed_file_type_free_item (gpointer item, gpointer user_data)
45 {
46 	g_free(item);
47 }
48 
49 void
cssed_file_type_free(CssedFileType * type)50 cssed_file_type_free(CssedFileType* type)
51 {
52 	if( !type ) return;
53 	g_free(type->label_language);
54 	g_free(type->lable_file);
55 	g_slist_foreach(type->patterns, cssed_file_type_free_item, NULL);
56 	g_slist_free(type->patterns);
57 	g_free(type);
58 }
59 
60 void
cssed_file_type_add_pattern_spec(CssedFileType * type,gchar * spec)61 cssed_file_type_add_pattern_spec(CssedFileType* type, gchar* spec)
62 {
63 	type->patterns = g_slist_append (type->patterns, (gpointer) g_strdup(spec));
64 }
65 
66 //FILE TYPE MANAGER IMPLEMENTATION
67 gboolean
patterns_hash_table_key_equal_func(gconstpointer a,gconstpointer b)68 patterns_hash_table_key_equal_func(gconstpointer a,
69                                    gconstpointer b)
70 {
71 	if( !a && !b ) return TRUE;
72 	if( !a ) return FALSE;
73 	if( !b ) return FALSE;
74 	if( strcmp((gchar*) a, (gchar*) b) == 0 ) return TRUE;
75 	return FALSE;
76 }
77 
78 void
patterns_hash_table_free_entry(gpointer key,gpointer value,gpointer user_data)79 patterns_hash_table_free_entry	   (gpointer key,
80                                     gpointer value,
81                                     gpointer user_data)
82 {
83 	GSList *list;
84 	list = g_slist_first((GSList*) value);
85 	while(list)
86 	{
87 		g_free(list->data);
88 		list = g_slist_next(list);
89 	}
90 	g_slist_free (list);
91 	g_free(key);
92 }
93 
94 CssedFileTypeManager*
cssed_file_type_manager_new()95 cssed_file_type_manager_new()
96 {
97 	CssedFileTypeManager* manager;
98 
99 	manager = g_malloc0(sizeof(CssedFileTypeManager));
100 	memset (manager->filetype, 0, sizeof(gpointer) * CSSED_NUMFILETYPES);
101 	manager->patterns_hash_table = g_hash_table_new (g_str_hash, g_str_equal);
102 
103 	return manager;
104 }
105 
106 void
cssed_file_type_manager_free(CssedFileTypeManager * manager)107 cssed_file_type_manager_free( CssedFileTypeManager *manager )
108 {
109 	gint i;
110 
111 	if(!manager) return;
112 
113 	g_hash_table_foreach(manager->patterns_hash_table, patterns_hash_table_free_entry, NULL);
114 	g_hash_table_destroy(manager->patterns_hash_table);
115 	// now free all file types
116 	for(i=0;i<CSSED_NUMFILETYPES;i++){
117 		if( manager->filetype[i] != NULL )
118 			cssed_file_type_free(manager->filetype[i]);
119 	}
120 	g_free(manager);
121 }
122 
123 gboolean
patterns_hash_table_find_func(gpointer key,gpointer value,gpointer user_data)124 patterns_hash_table_find_func   (gpointer key,
125                                  gpointer value,
126                                  gpointer user_data)
127 {
128 	gchar *filename;
129 	gchar *toupper_pattern;
130 	gchar *pattern;
131 	gboolean match;
132 
133 	filename = (gchar*) user_data;
134 	pattern = (gchar*) key;
135 
136 	if( !filename ) return FALSE;
137 	match = g_pattern_match_simple( pattern, filename);
138 	DBGMSG (__FILE__,__LINE__,"Pattern matching:\n%s with %s (%s)", filename, pattern, match?"MATCH !!":"NO");
139 	if( match ) return TRUE;
140 
141 	// check for uppercase strings, mixed case is not managed
142 	if( g_ascii_isupper(filename[strlen(filename)-1]) ){
143 		toupper_pattern  = g_ascii_strup(pattern, -1);
144 		match = g_pattern_match_simple(toupper_pattern, filename);
145 		DBGMSG (__FILE__,__LINE__,"Pattern matching:\n%s with %s (%s)", filename, (gchar*) toupper_pattern, match?"MATCH !!":"NO");
146 		g_free(toupper_pattern);
147 		if( match ) return TRUE;
148 	}
149 
150 	return FALSE;
151 }
152 
153 GSList*
cssed_file_type_manager_get_ids_from_filename(CssedFileTypeManager * manager,gchar * filename)154 cssed_file_type_manager_get_ids_from_filename (CssedFileTypeManager *manager, gchar *filename)
155 {
156 	GSList *ids; // GList containing all file type ids that matches the file
157 	GHashTable* hash;
158 
159 	hash = manager->patterns_hash_table;
160 	ids = (GSList*) g_hash_table_find (hash, patterns_hash_table_find_func, filename);
161 	return ids;
162 }
163 
164 
165 GSList*
cssed_file_type_manager_get_ids_from_pattern(CssedFileTypeManager * manager,gchar * pattern)166 cssed_file_type_manager_get_ids_from_pattern( CssedFileTypeManager *manager, gchar *pattern )
167 {
168 	GSList *ids; // GList containing all file type ids that mathes the file
169 	GHashTable* hash;
170 
171 	hash = manager->patterns_hash_table;
172 	ids = (GSList*) g_hash_table_lookup (hash, pattern);
173 	return ids;
174 }
175 
176 CssedFileTypeId
cssed_file_type_manager_get_default_id_from_filename(CssedFileTypeManager * manager,gchar * filename)177 cssed_file_type_manager_get_default_id_from_filename( CssedFileTypeManager *manager, gchar *filename )
178 {
179 	gpointer ids; // GSList containing all file type ids that mathes the file
180 	GSList* idlist;
181 
182 	if( !filename ) return CSSED_FILETYPE_UNKNOW;
183 	if( !manager )  return CSSED_FILETYPE_UNKNOW;
184 
185 	// lookup on patterns hash table
186 	ids = cssed_file_type_manager_get_ids_from_filename (manager, filename);
187 	if( !ids ){
188 		return CSSED_FILETYPE_UNKNOW;
189 	}else{
190 		idlist = g_slist_first( ids ); // the order matters, first is default
191 		if( !idlist ) return CSSED_FILETYPE_UNKNOW;
192 		else return *((CssedFileTypeId*) idlist->data);
193 	}
194 }
195 
196 CssedFileType*
cssed_file_type_manager_get_filetype_from_filename(CssedFileTypeManager * manager,gchar * filename)197 cssed_file_type_manager_get_filetype_from_filename( CssedFileTypeManager *manager, gchar *filename )
198 {
199 	gint defaultid;
200 
201 	defaultid = cssed_file_type_manager_get_default_id_from_filename( manager, filename );
202 	if( defaultid == CSSED_FILETYPE_UNKNOW ) defaultid = CSSED_FILETYPE_TEXT;
203 	return manager->filetype[defaultid];
204 }
205 
206 CssedFileType*
cssed_file_type_manager_get_filetype_from_id(CssedFileTypeManager * manager,CssedFileTypeId id)207 cssed_file_type_manager_get_filetype_from_id( CssedFileTypeManager *manager, CssedFileTypeId id )
208 {
209 	if( id <= CSSED_FILETYPE_UNKNOW || id >= CSSED_NUMFILETYPES ) return NULL;
210 	return manager->filetype[id];
211 }
212 
213 void
cssed_file_type_manager_add_pattern(CssedFileTypeManager * manager,gchar * pattern,CssedFileTypeId id)214 cssed_file_type_manager_add_pattern( CssedFileTypeManager *manager, gchar *pattern, CssedFileTypeId id )
215 {
216 	GHashTable *hash;
217 	GSList *val = NULL;
218 	gchar *key;
219 	gint *idptr;
220 
221 	if( !manager ) return; // no NULLs please
222 	if( !pattern ) return; // no NULLs please
223 	hash = manager->patterns_hash_table;
224 	if( !g_hash_table_lookup_extended (hash, pattern, (gpointer) &key, (gpointer) &val) )
225 			key = g_strdup(pattern);
226 	idptr = g_new0(gint,1);
227 	*idptr = id;
228 	val = g_slist_append(val, idptr);
229 	g_hash_table_insert(hash, key, val);
230 }
231 
232 gboolean
cssed_file_type_manager_delete_pattern(CssedFileTypeManager * manager,gchar * pattern)233 cssed_file_type_manager_delete_pattern( CssedFileTypeManager *manager, gchar *pattern )
234 {
235 	GSList *val = NULL;
236 	gchar *key;
237 	GHashTable *hash;
238 
239 	hash = manager->patterns_hash_table;
240 
241 	if( g_hash_table_lookup_extended (hash, pattern, (gpointer) &key, (gpointer) &val) ){
242 		g_hash_table_remove (hash, (gpointer) &key);
243 		patterns_hash_table_free_entry ((gpointer) key,	(gpointer) val,	NULL);
244 		return TRUE;
245 	}else{
246 		return FALSE;
247 	}
248 }
249 
250 gboolean
cssed_file_type_manager_pattern_exists(CssedFileTypeManager * manager,gchar * pattern)251 cssed_file_type_manager_pattern_exists( CssedFileTypeManager *manager, gchar *pattern )
252 {
253 	if( g_hash_table_lookup(manager->patterns_hash_table, pattern) != NULL ) return TRUE;
254 	else return FALSE;
255 }
256 
257 /* *********************************************************************
258   This is to use by callback as a file type menu item.
259   It should be set as menu item's data the filetype.
260   Use the function below to set the data.
261 * ******************************************************************** */
262 void
on_file_type_menu_activate(GtkMenuItem * menuitem,gpointer user_data)263 on_file_type_menu_activate (GtkMenuItem * menuitem, gpointer user_data)
264 {
265 	CssedFileType* filetype;
266 	CssedWindow* window;
267 	CssedDoc* doc;
268 
269 	filetype = g_object_get_data(G_OBJECT(menuitem), "filetype");
270 	if ( filetype ){
271 		window = CSSED_WINDOW(user_data);
272 		doc = document_get_current(window);
273 		document_set_filetype( doc, filetype );
274 	}
275 }
276 
277 void
cssed_file_type_menu_set_default_callback(CssedWindow * window,GtkWidget * filetype_menu,CssedFileType * filetype)278 cssed_file_type_menu_set_default_callback (CssedWindow *window, GtkWidget *filetype_menu, CssedFileType *filetype)
279 {
280 	g_object_set_data(G_OBJECT(filetype_menu), "filetype", filetype);
281 	g_signal_connect ((gpointer) filetype_menu, "activate",
282 			  G_CALLBACK (on_file_type_menu_activate), window);
283 }
284