r229: Made 'Yes' (or the entry) the default focus in action windows.
[rox-filer.git] / ROX-Filer / src / type.c
blobfbc836e588cb281334dc27e3097043cd4ebd0673
1 /*
2 * $Id$
4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 2000, Thomas Leonard, <tal197@ecs.soton.ac.uk>.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
22 /* type.c - code for dealing with filetypes */
24 #include "config.h"
26 #include <glib.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <errno.h>
31 #include <ctype.h>
32 #include <time.h>
34 #include "string.h"
35 #include "main.h"
36 #include "filer.h"
37 #include "pixmaps.h"
38 #include "run.h"
39 #include "gui_support.h"
40 #include "choices.h"
41 #include "type.h"
42 #include "support.h"
43 #include "options.h"
45 /* Static prototypes */
46 static char *import_extensions(guchar *line);
48 /* Maps extensions to MIME_types (eg 'png'-> MIME_type *) */
49 static GHashTable *extension_hash = NULL;
50 static char *current_type = NULL; /* (used while reading file) */
52 /* Most things on Unix are text files, so this is the default type */
53 MIME_type text_plain = {"text", "plain", NULL};
55 void type_init()
57 ChoicesList *paths, *next;
59 extension_hash = g_hash_table_new(g_str_hash, g_str_equal);
61 paths = choices_find_load_all("guess", "MIME-types");
62 while (paths)
64 current_type = NULL;
65 parse_file(paths->path, import_extensions);
66 next = paths->next;
67 g_free(paths->path);
68 g_free(paths);
69 paths = next;
73 /* Add one entry to the extension_hash table */
74 static void add_ext(char *type_name, char *ext)
76 MIME_type *new;
77 char *slash;
78 int len;
80 slash = strchr(type_name, '/');
81 g_return_if_fail(slash != NULL); /* XXX: Report nicely */
82 len = slash - type_name;
84 new = g_new(MIME_type, 1);
85 new->media_type = g_malloc(sizeof(char) * (len + 1));
86 memcpy(new->media_type, type_name, len);
87 new->media_type[len] = '\0';
89 new->subtype = g_strdup(slash + 1);
90 new->image = NULL;
92 g_hash_table_insert(extension_hash, g_strdup(ext), new);
95 /* Parse one line from the file and add entries to extension_hash */
96 static char *import_extensions(guchar *line)
99 if (*line == '\0' || *line == '#')
100 return NULL; /* Comment */
102 if (isspace(*line))
104 if (!current_type)
105 return "Missing MIME-type";
106 while (*line && isspace(*line))
107 line++;
109 if (strncmp(line, "ext:", 4) == 0)
111 char *ext;
112 line += 4;
114 for (;;)
116 while (*line && isspace(*line))
117 line++;
118 if (*line == '\0')
119 break;
120 ext = line;
121 while (*line && !isspace(*line))
122 line++;
123 if (*line)
124 *line++ = '\0';
125 add_ext(current_type, ext);
128 /* else ignore */
130 else
132 char *type = line;
133 while (*line && *line != ':' && !isspace(*line))
134 line++;
135 if (*line)
136 *line++ = '\0';
137 while (*line && isspace(*line))
138 line++;
139 if (*line)
140 return "Trailing chars after MIME-type";
141 current_type = g_strdup(type);
143 return NULL;
146 char *basetype_name(DirItem *item)
148 if (item->flags & ITEM_FLAG_SYMLINK)
149 return "Sym link";
150 else if (item->flags & ITEM_FLAG_MOUNT_POINT)
151 return "Mount point";
152 else if (item->flags & ITEM_FLAG_APPDIR)
153 return "App dir";
155 switch (item->base_type)
157 case TYPE_FILE:
158 return "File";
159 case TYPE_DIRECTORY:
160 return "Dir";
161 case TYPE_CHAR_DEVICE:
162 return "Char dev";
163 case TYPE_BLOCK_DEVICE:
164 return "Block dev";
165 case TYPE_PIPE:
166 return "Pipe";
167 case TYPE_SOCKET:
168 return "Socket";
171 return "Unknown";
174 /* MIME-type guessing */
176 /* Returns a pointer to the MIME-type string, or NULL if we have
177 * no opinion.
179 MIME_type *type_from_path(char *path)
181 char *dot;
183 dot = strrchr(path, '.');
184 if (dot)
186 MIME_type *type;
187 type = g_hash_table_lookup(extension_hash, dot + 1);
188 if (type)
189 return type;
192 return &text_plain;
195 /* Actions for types */
197 gboolean type_open(char *path, MIME_type *type)
199 char *argv[] = {NULL, NULL, NULL};
200 char *open;
201 char *type_name;
202 gboolean retval = TRUE;
203 struct stat info;
205 argv[1] = path;
207 type_name = g_strconcat(type->media_type, "_", type->subtype, NULL);
208 open = choices_find_path_load_shared(type_name, "MIME-types");
209 g_free(type_name);
210 if (!open)
212 open = choices_find_path_load_shared(type->media_type,
213 "MIME-types");
214 if (!open)
215 return FALSE;
218 if (stat(open, &info))
220 report_error("ROX-Filer", g_strerror(errno));
221 return FALSE;
224 if (S_ISDIR(info.st_mode))
225 argv[0] = g_strconcat(open, "/AppRun", NULL);
226 else
227 argv[0] = open;
229 if (!spawn_full(argv, home_dir))
231 report_error("ROX-Filer",
232 "Failed to fork() child process");
233 retval = FALSE;
236 if (argv[0] != open)
237 g_free(argv[0]);
239 return retval;
242 /* Return the image for this type, loading it if needed.
243 * Places to check are: (eg type="text_plain", base="text")
244 * 1. Choices:MIME-icons/<type>
245 * 2. Choices:MIME-icons/<base>
246 * 3. Unknown type icon.
248 * Note: You must pixmap_unref() the image afterwards.
250 MaskedPixmap *type_to_icon(MIME_type *type)
252 char *path;
253 char *type_name;
254 time_t now;
256 g_return_val_if_fail(type != NULL, default_pixmap + TYPE_UNKNOWN);
258 now = time(NULL);
259 /* Already got an image? */
260 if (type->image)
262 /* Yes - don't recheck too often */
263 if (abs(now - type->image_time) < 2)
265 pixmap_ref(type->image);
266 return type->image;
268 pixmap_unref(type->image);
269 type->image = NULL;
272 type_name = g_strconcat(type->media_type, "_",
273 type->subtype, ".xpm", NULL);
274 path = choices_find_path_load_shared(type_name, "MIME-icons");
275 if (!path)
277 strcpy(type_name + strlen(type->media_type), ".xpm");
278 path = choices_find_path_load_shared(type_name, "MIME-icons");
281 g_free(type_name);
283 if (path)
284 type->image = g_fscache_lookup(pixmap_cache, path);
286 if (!type->image)
288 type->image = default_pixmap + TYPE_UNKNOWN;
289 pixmap_ref(type->image);
292 type->image_time = now;
294 pixmap_ref(type->image);
295 return type->image;
298 GdkAtom type_to_atom(MIME_type *type)
300 char *str;
301 GdkAtom retval;
303 g_return_val_if_fail(type != NULL, GDK_NONE);
305 str = g_strconcat(type->media_type, "/", type->subtype, NULL);
306 retval = gdk_atom_intern(str, FALSE);
307 g_free(str);
309 return retval;