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"};
41 extension_hash
= g_hash_table_new(g_str_hash
, g_str_equal
);
43 path
= choices_find_path_load_shared("guess", "MIME-types");
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
)
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);
70 g_hash_table_insert(extension_hash
, g_strdup(ext
), new);
73 /* Parse one line from the file and add entries to extension_hash */
74 static char *import_extensions(char *line
)
77 if (*line
== '\0' || *line
== '#')
78 return NULL
; /* Comment */
83 return "Missing MIME-type";
84 while (*line
&& isspace(*line
))
87 if (strncmp(line
, "ext:", 4) == 0)
94 while (*line
&& isspace(*line
))
99 while (*line
&& !isspace(*line
))
103 add_ext(current_type
, ext
);
111 while (*line
&& !isspace(*line
))
115 while (*line
&& isspace(*line
))
118 return "Trailing chars after MIME-type";
119 current_type
= g_strdup(type
);
124 char *basetype_name(FileItem
*item
)
126 if (item
->flags
& ITEM_FLAG_SYMLINK
)
128 else if (item
->flags
& ITEM_FLAG_MOUNT_POINT
)
129 return "Mount point";
130 else if (item
->flags
& ITEM_FLAG_APPDIR
)
133 switch (item
->base_type
)
139 case TYPE_CHAR_DEVICE
:
141 case TYPE_BLOCK_DEVICE
:
152 /* MIME-type guessing */
154 /* Returns a pointer to the MIME-type string, or NULL if we have
157 MIME_type
*type_from_path(char *path
)
161 dot
= strrchr(path
, '.');
165 type
= g_hash_table_lookup(extension_hash
, dot
+ 1);
173 /* Actions for types */
175 gboolean
type_open(char *path
, MIME_type
*type
)
177 char *argv
[] = {NULL
, path
, NULL
};
181 type_name
= g_strconcat(type
->media_type
, "_", type
->subtype
, NULL
);
182 open
= choices_find_path_load_shared(type_name
, "MIME-types");
186 open
= choices_find_path_load_shared(type
->media_type
,
192 argv
[0] = g_strconcat(open
, "/AppRun", NULL
);
194 if (!spawn_full(argv
, getenv("HOME"), 0))
195 report_error("ROX-Filer",
196 "Failed to fork() child process");
203 /* Tries to load image from <handler>/MIME-icons/<icon>.xpm */
204 static MaskedPixmap
*try_icon_path(GtkWidget
*window
, char *handler
, char *icon
)
212 path
= g_strconcat(handler
, "/MIME-icons/", icon
, ".xpm", NULL
);
213 image
= load_pixmap_from(window
, path
);
219 /* Return the image for this type, loading it if needed.
220 * Find handler application, <app>, then:
221 * Places to check are: (eg type="text_plain", base="text")
222 * 1. <app>/MIME-icons/<type>
223 * 2. <app>/MIME-icons/<base>
224 * 3. $APP_DIR/MIME-icons/<base>
225 * 4. Unknown type icon.
227 MaskedPixmap
*type_to_icon(GtkWidget
*window
, MIME_type
*type
)
233 g_return_val_if_fail(type
!= NULL
, default_pixmap
+ TYPE_UNKNOWN
);
235 /* Already got an image? TODO: Is it out-of-date? */
239 type_name
= g_strconcat(type
->media_type
, "_", type
->subtype
, NULL
);
241 open
= choices_find_path_load_shared(type_name
, "MIME-types");
243 open
= choices_find_path_load_shared(type
->media_type
,
245 if (((i
= try_icon_path(window
, open
, type_name
)))
246 || ((i
= try_icon_path(window
, open
, type
->media_type
)))
247 || ((i
= try_icon_path(window
, getenv("APP_DIR"), type
->media_type
))))
250 type
->image
= default_pixmap
+ TYPE_UNKNOWN
;