4 * ROX-Filer, filer for the ROX desktop project
5 * By Thomas Leonard, <tal197@ecs.soton.ac.uk>.
8 /* type.c - code for dealing with filetypes */
21 #include "gui_support.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"};
39 ChoicesList
*paths
, *next
;
41 extension_hash
= g_hash_table_new(g_str_hash
, g_str_equal
);
43 paths
= choices_find_load_all("guess", "MIME-types");
47 parse_file(paths
->path
, import_extensions
);
55 /* Add one entry to the extension_hash table */
56 static void add_ext(char *type_name
, char *ext
)
62 slash
= strchr(type_name
, '/');
63 g_return_if_fail(slash
!= NULL
); /* XXX: Report nicely */
64 len
= slash
- type_name
;
66 new = g_malloc(sizeof(MIME_type
));
67 new->media_type
= g_malloc(sizeof(char) * (len
+ 1));
68 memcpy(new->media_type
, type_name
, len
);
69 new->media_type
[len
] = '\0';
71 new->subtype
= g_strdup(slash
+ 1);
74 g_hash_table_insert(extension_hash
, g_strdup(ext
), new);
77 /* Parse one line from the file and add entries to extension_hash */
78 static char *import_extensions(char *line
)
81 if (*line
== '\0' || *line
== '#')
82 return NULL
; /* Comment */
87 return "Missing MIME-type";
88 while (*line
&& isspace(*line
))
91 if (strncmp(line
, "ext:", 4) == 0)
98 while (*line
&& isspace(*line
))
103 while (*line
&& !isspace(*line
))
107 add_ext(current_type
, ext
);
115 while (*line
&& !isspace(*line
))
119 while (*line
&& isspace(*line
))
122 return "Trailing chars after MIME-type";
123 current_type
= g_strdup(type
);
128 char *basetype_name(FileItem
*item
)
130 if (item
->flags
& ITEM_FLAG_SYMLINK
)
132 else if (item
->flags
& ITEM_FLAG_MOUNT_POINT
)
133 return "Mount point";
134 else if (item
->flags
& ITEM_FLAG_APPDIR
)
137 switch (item
->base_type
)
143 case TYPE_CHAR_DEVICE
:
145 case TYPE_BLOCK_DEVICE
:
156 /* MIME-type guessing */
158 /* Returns a pointer to the MIME-type string, or NULL if we have
161 MIME_type
*type_from_path(char *path
)
165 dot
= strrchr(path
, '.');
169 type
= g_hash_table_lookup(extension_hash
, dot
+ 1);
177 /* Actions for types */
179 gboolean
type_open(char *path
, MIME_type
*type
)
181 char *argv
[] = {NULL
, path
, NULL
};
185 type_name
= g_strconcat(type
->media_type
, "_", type
->subtype
, NULL
);
186 open
= choices_find_path_load_shared(type_name
, "MIME-types");
190 open
= choices_find_path_load_shared(type
->media_type
,
196 argv
[0] = g_strconcat(open
, "/AppRun", NULL
);
198 if (!spawn_full(argv
, getenv("HOME"), 0))
199 report_error("ROX-Filer",
200 "Failed to fork() child process");
207 /* Tries to load image from <handler>/MIME-icons/<icon>.xpm */
208 static MaskedPixmap
*try_icon_path(GtkWidget
*window
, char *handler
, char *icon
)
216 path
= g_strconcat(handler
, "/MIME-icons/", icon
, ".xpm", NULL
);
217 image
= load_pixmap_from(window
, path
);
223 /* Return the image for this type, loading it if needed.
224 * Find handler application, <app>, then:
225 * Places to check are: (eg type="text_plain", base="text")
226 * 1. <app>/MIME-icons/<type>
227 * 2. <app>/MIME-icons/<base>
228 * 3. $APP_DIR/MIME-icons/<base>
229 * 4. Unknown type icon.
231 MaskedPixmap
*type_to_icon(GtkWidget
*window
, MIME_type
*type
)
237 g_return_val_if_fail(type
!= NULL
, default_pixmap
+ TYPE_UNKNOWN
);
239 /* Already got an image? TODO: Is it out-of-date? */
243 type_name
= g_strconcat(type
->media_type
, "_", type
->subtype
, NULL
);
245 open
= choices_find_path_load_shared(type_name
, "MIME-types");
247 open
= choices_find_path_load_shared(type
->media_type
,
249 if (((i
= try_icon_path(window
, open
, type_name
)))
250 || ((i
= try_icon_path(window
, open
, type
->media_type
)))
251 || ((i
= try_icon_path(window
, getenv("APP_DIR"), type
->media_type
))))
254 type
->image
= default_pixmap
+ TYPE_UNKNOWN
;
261 GdkAtom
type_to_atom(MIME_type
*type
)
266 g_return_val_if_fail(type
!= NULL
, GDK_NONE
);
268 str
= g_strconcat(type
->media_type
, "/", type
->subtype
, NULL
);
269 retval
= gdk_atom_intern(str
, FALSE
);