r61: Changed to use gnome MIME-type guesser format instead of Apache guesser.
[rox-filer.git] / ROX-Filer / src / type.c
blob9d6443f461a3e8ddce17d896ec4911d3a61a4982
1 /* vi: set cindent:
2 * $Id$
4 * ROX-Filer, filer for the ROX desktop project
5 * By Thomas Leonard, <tal197@ecs.soton.ac.uk>.
6 */
8 /* type.c - code for dealing with filetypes */
10 #include <glib.h>
11 #include <sys/stat.h>
12 #include <unistd.h>
13 #include <stdlib.h>
14 #include <errno.h>
15 #include <ctype.h>
17 #include "string.h"
18 #include "filer.h"
19 #include "pixmaps.h"
20 #include "apps.h"
21 #include "gui_support.h"
22 #include "choices.h"
23 #include "type.h"
24 #include "support.h"
25 #include "options.h"
27 /* Static prototypes */
28 static char *import_extensions(char *line);
30 /* Maps extensions to MIME_types (eg 'png'-> MIME_type *) */
31 static GHashTable *extension_hash = NULL;
32 static char *current_type = NULL; /* (used while reading file) */
34 /* Most things on Unix are text files, so this is the default type */
35 static MIME_type text_plain = {"text", "plain"};
37 void type_init()
39 char *path;
41 extension_hash = g_hash_table_new(g_str_hash, g_str_equal);
43 path = choices_find_path_load_shared("guess", "MIME-types");
44 if (path)
46 current_type = NULL;
47 parse_file(path, import_extensions);
51 /* Add one entry to the extension_hash table */
52 static void add_ext(char *type_name, char *ext)
54 MIME_type *new;
55 char *slash;
56 int len;
58 slash = strchr(type_name, '/');
59 g_return_if_fail(slash != NULL); /* XXX: Report nicely */
60 len = slash - type_name;
62 new = g_malloc(sizeof(MIME_type));
63 new->media_type = g_malloc(sizeof(char) * (len + 1));
64 memcpy(new->media_type, type_name, len);
65 new->media_type[len] = '\0';
67 new->subtype = g_strdup(slash + 1);
68 new->image = NULL;
70 printf("Type = '%s', subtype = '%s', ext = '%s'\n",
71 new->media_type, new->subtype, ext);
72 g_hash_table_insert(extension_hash, g_strdup(ext), new);
75 /* Parse one line from the file and add entries to extension_hash */
76 static char *import_extensions(char *line)
79 if (*line == '\0' || *line == '#')
80 return NULL; /* Comment */
82 if (isspace(*line))
84 if (!current_type)
85 return "Missing MIME-type";
86 while (*line && isspace(*line))
87 line++;
89 if (strncmp(line, "ext:", 4) == 0)
91 char *ext;
92 line += 4;
94 for (;;)
96 while (*line && isspace(*line))
97 line++;
98 if (*line == '\0')
99 break;
100 ext = line;
101 while (*line && !isspace(*line))
102 line++;
103 if (*line)
104 *line++ = '\0';
105 add_ext(current_type, ext);
108 /* else ignore */
110 else
112 char *type = line;
113 while (*line && !isspace(*line))
114 line++;
115 if (*line)
116 *line++ = '\0';
117 while (*line && isspace(*line))
118 line++;
119 if (*line)
120 return "Trailing chars after MIME-type";
121 current_type = g_strdup(type);
123 return NULL;
126 char *basetype_name(FileItem *item)
128 if (item->flags & ITEM_FLAG_SYMLINK)
129 return "Sym link";
130 else if (item->flags & ITEM_FLAG_MOUNT_POINT)
131 return "Mount point";
132 else if (item->flags & ITEM_FLAG_APPDIR)
133 return "App dir";
135 switch (item->base_type)
137 case TYPE_FILE:
138 return "File";
139 case TYPE_DIRECTORY:
140 return "Dir";
141 case TYPE_CHAR_DEVICE:
142 return "Char dev";
143 case TYPE_BLOCK_DEVICE:
144 return "Block dev";
145 case TYPE_PIPE:
146 return "Pipe";
147 case TYPE_SOCKET:
148 return "Socket";
151 return "Unknown";
154 /* MIME-type guessing */
156 /* Returns a pointer to the MIME-type string, or NULL if we have
157 * no opinion.
159 MIME_type *type_from_path(char *path)
161 char *dot;
163 dot = strrchr(path, '.');
164 if (dot)
166 MIME_type *type;
167 type = g_hash_table_lookup(extension_hash, dot + 1);
168 if (type)
169 return type;
172 return &text_plain;
175 /* Actions for types */
177 gboolean type_open(char *path, MIME_type *type)
179 char *argv[] = {NULL, path, NULL};
180 char *open;
181 char *type_name;
183 type_name = g_strconcat(type->media_type, "_", type->subtype, NULL);
184 open = choices_find_path_load_shared(type_name, "MIME-types");
185 g_free(type_name);
186 if (!open)
187 return FALSE;
189 argv[0] = g_strconcat(open, "/AppRun", NULL);
191 if (!spawn_full(argv, getenv("HOME"), 0))
192 report_error("ROX-Filer",
193 "Failed to fork() child process");
195 g_free(argv[0]);
197 return TRUE;
200 /* Return the image for this type, loading it if needed.
201 * Places to check are: (eg type="text_plain", base="text")
202 * 1. Choices/MIME-types/<type>/MIME-icons/<type>
203 * 2. Choices/MIME-types/<type>/MIME-icons/<base>
204 * 3. Choices/MIME-types/<base>/MIME-icons/<base> [ TODO ]
205 * 4. $APP_DIR/MIME-icons/<base>
206 * 5. Unknown type icon.
208 MaskedPixmap *type_to_icon(GtkWidget *window, MIME_type *type)
210 char *open, *path;
211 char *type_name;
213 g_return_val_if_fail(type != NULL, default_pixmap + TYPE_UNKNOWN);
215 /* Already got an image? TODO: Is it out-of-date? */
216 if (type->image)
217 return type->image;
219 type_name = g_strconcat(type->media_type, "_", type->subtype, NULL);
221 /* 1 and 2 : Check for icon provided by specific handler */
222 open = choices_find_path_load_shared(type_name, "MIME-types");
223 if (open)
225 /* 1 : Exact type provided */
226 path = g_strconcat(open, "/MIME-icons/", type_name, ".xpm",
227 NULL);
228 type->image = load_pixmap_from(window, path);
229 g_free(path);
231 if (!type->image)
233 /* 2 : Base type provided */
234 path = g_strconcat(open, "/MIME-icons/",
235 type->media_type, ".xpm", NULL);
236 type->image = load_pixmap_from(window, path);
237 g_free(path);
241 g_free(type_name);
243 if (type->image)
244 return type->image;
246 /* 4 : Load a default icon from our own application dir */
248 path = g_strconcat(getenv("APP_DIR"), "/MIME-icons/", type->media_type,
249 ".xpm", NULL);
250 type->image = load_pixmap_from(window, path);
251 g_free(path);
253 if (type->image)
254 return type->image;
256 /* 5 : Use the unknown type icon */
258 type->image = default_pixmap + TYPE_UNKNOWN;
260 return type->image;