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)
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
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 */
32 #include <sys/param.h>
41 #include "gui_support.h"
47 /* Static prototypes */
48 static char *import_extensions(guchar
*line
);
49 static void import_for_dir(guchar
*path
);
51 /* Maps extensions to MIME_types (eg 'png'-> MIME_type *) */
52 static GHashTable
*extension_hash
= NULL
;
53 static char *current_type
= NULL
; /* (used while reading file) */
55 /* Most things on Unix are text files, so this is the default type */
56 MIME_type text_plain
= {"text", "plain", NULL
};
63 extension_hash
= g_hash_table_new(g_str_hash
, g_str_equal
);
66 parse_file(make_path(getenv("APP_DIR"), "MIME-info")->str
,
69 list
= choices_list_dirs("MIME-info");
70 for (i
= 0; i
< list
->len
; i
++)
71 import_for_dir((gchar
*) g_ptr_array_index(list
, i
));
72 choices_free_list(list
);
75 /* Parse every file in 'dir' */
76 static void import_for_dir(guchar
*path
)
85 while ((item
= readdir(dir
)))
87 if (item
->d_name
[0] == '.')
91 parse_file(make_path(path
, item
->d_name
)->str
,
98 /* Add one entry to the extension_hash table */
99 static void add_ext(char *type_name
, char *ext
)
105 slash
= strchr(type_name
, '/');
106 g_return_if_fail(slash
!= NULL
); /* XXX: Report nicely */
107 len
= slash
- type_name
;
109 new = g_new(MIME_type
, 1);
110 new->media_type
= g_malloc(sizeof(char) * (len
+ 1));
111 memcpy(new->media_type
, type_name
, len
);
112 new->media_type
[len
] = '\0';
114 new->subtype
= g_strdup(slash
+ 1);
117 g_hash_table_insert(extension_hash
, g_strdup(ext
), new);
120 /* Parse one line from the file and add entries to extension_hash */
121 static char *import_extensions(guchar
*line
)
124 if (*line
== '\0' || *line
== '#')
125 return NULL
; /* Comment */
130 return _("Missing MIME-type");
131 while (*line
&& isspace(*line
))
134 if (strncmp(line
, "ext:", 4) == 0)
141 while (*line
&& isspace(*line
))
146 while (*line
&& !isspace(*line
))
150 add_ext(current_type
, ext
);
158 while (*line
&& *line
!= ':' && !isspace(*line
))
162 while (*line
&& isspace(*line
))
165 return _("Trailing chars after MIME-type");
166 current_type
= g_strdup(type
);
171 char *basetype_name(DirItem
*item
)
173 if (item
->flags
& ITEM_FLAG_SYMLINK
)
174 return _("Sym link");
175 else if (item
->flags
& ITEM_FLAG_MOUNT_POINT
)
176 return _("Mount point");
177 else if (item
->flags
& ITEM_FLAG_APPDIR
)
180 switch (item
->base_type
)
186 case TYPE_CHAR_DEVICE
:
187 return _("Char dev");
188 case TYPE_BLOCK_DEVICE
:
189 return _("Block dev");
199 /* MIME-type guessing */
201 /* Returns a pointer to the MIME-type string, or NULL if we have
204 MIME_type
*type_from_path(char *path
)
208 dot
= strrchr(path
, '.');
212 type
= g_hash_table_lookup(extension_hash
, dot
+ 1);
220 /* Actions for types */
222 gboolean
type_open(char *path
, MIME_type
*type
)
224 char *argv
[] = {NULL
, NULL
, NULL
};
227 gboolean retval
= TRUE
;
232 type_name
= g_strconcat(type
->media_type
, "_", type
->subtype
, NULL
);
233 open
= choices_find_path_load(type_name
, "MIME-types");
237 open
= choices_find_path_load(type
->media_type
,
243 if (stat(open
, &info
))
245 report_error(PROJECT
, g_strerror(errno
));
249 if (S_ISDIR(info
.st_mode
))
250 argv
[0] = g_strconcat(open
, "/AppRun", NULL
);
254 if (!spawn_full(argv
, home_dir
))
256 report_error(PROJECT
,
257 _("Failed to fork() child process"));
267 /* Return the image for this type, loading it if needed.
268 * Places to check are: (eg type="text_plain", base="text")
269 * 1. Choices:MIME-icons/<type>
270 * 2. Choices:MIME-icons/<base>
271 * 3. Unknown type icon.
273 * Note: You must pixmap_unref() the image afterwards.
275 MaskedPixmap
*type_to_icon(MIME_type
*type
)
281 g_return_val_if_fail(type
!= NULL
, default_pixmap
[TYPE_UNKNOWN
]);
284 /* Already got an image? */
287 /* Yes - don't recheck too often */
288 if (abs(now
- type
->image_time
) < 2)
290 pixmap_ref(type
->image
);
293 pixmap_unref(type
->image
);
297 type_name
= g_strconcat(type
->media_type
, "_",
298 type
->subtype
, ".xpm", NULL
);
299 path
= choices_find_path_load(type_name
, "MIME-icons");
302 strcpy(type_name
+ strlen(type
->media_type
), ".xpm");
303 path
= choices_find_path_load(type_name
, "MIME-icons");
309 type
->image
= g_fscache_lookup(pixmap_cache
, path
);
313 type
->image
= default_pixmap
[TYPE_UNKNOWN
];
314 pixmap_ref(type
->image
);
317 type
->image_time
= now
;
319 pixmap_ref(type
->image
);
323 GdkAtom
type_to_atom(MIME_type
*type
)
328 g_return_val_if_fail(type
!= NULL
, GDK_NONE
);
330 str
= g_strconcat(type
->media_type
, "/", type
->subtype
, NULL
);
331 retval
= gdk_atom_intern(str
, FALSE
);
337 /* Display a box allowing the user to set the run action for this type */
338 void show_set_run_action(MIME_type
*type
)
340 static GtkWidget
*box
= NULL
;
341 static GtkWidget
*pixmap
= NULL
, *link_path
, *explain_label
;
342 guchar
*type_name
, *path
;
344 static MaskedPixmap
*drop
= NULL
;
350 GtkWidget
*vbox
, *event
, *hbox
, *button
, *frame
;
352 GtkTargetEntry targets
[] = {
353 {"text/uri-list", 0, 0},
356 box
= gtk_window_new(GTK_WINDOW_DIALOG
);
357 gtk_container_set_border_width(GTK_CONTAINER(box
), 4);
359 vbox
= gtk_vbox_new(FALSE
, 0);
360 gtk_container_add(GTK_CONTAINER(box
), vbox
);
362 explain_label
= gtk_label_new("");
363 gtk_box_pack_start(GTK_BOX(vbox
), explain_label
,
366 frame
= gtk_frame_new(NULL
);
367 gtk_frame_set_shadow_type(GTK_FRAME(frame
), GTK_SHADOW_IN
);
368 gtk_box_pack_start(GTK_BOX(vbox
), frame
, TRUE
, TRUE
, 0);
369 event
= gtk_event_box_new();
370 gtk_container_add(GTK_CONTAINER(frame
), event
);
371 gtk_drag_dest_set(event
, GTK_DEST_DEFAULT_ALL
, targets
,
372 sizeof(targets
) / sizeof(*targets
),
373 GDK_ACTION_COPY
| GDK_ACTION_PRIVATE
);
375 tmp
= g_strconcat(getenv("APP_DIR"), "/pixmaps/drop.xpm", NULL
);
376 drop
= g_fscache_lookup(pixmap_cache
, tmp
);
379 link_box
= gtk_vbox_new(FALSE
, 4);
380 gtk_container_add(GTK_CONTAINER(event
), link_box
);
382 pixmap
= gtk_pixmap_new(drop
->pixmap
, drop
->mask
);
383 gtk_box_pack_start(GTK_BOX(link_box
), pixmap
, FALSE
, TRUE
, 4);
384 link_path
= gtk_label_new("<path>");
385 gtk_misc_set_padding(GTK_MISC(link_path
), 4, 0);
386 gtk_box_pack_start(GTK_BOX(link_box
),
387 link_path
, FALSE
, TRUE
, 4);
389 hbox
= gtk_hbox_new(TRUE
, 0);
390 gtk_box_pack_start(GTK_BOX(vbox
), hbox
, FALSE
, TRUE
, 4);
392 button
= gtk_button_new_with_label(_("Save"));
393 gtk_box_pack_start(GTK_BOX(hbox
), button
, TRUE
, TRUE
, 4);
394 button
= gtk_button_new_with_label(_("Cancel"));
395 gtk_signal_connect_object(GTK_OBJECT(button
), "clicked",
396 GTK_SIGNAL_FUNC(gtk_widget_hide
), GTK_OBJECT(box
));
397 gtk_box_pack_start(GTK_BOX(hbox
), button
, TRUE
, TRUE
, 4);
400 if (GTK_WIDGET_VISIBLE(box
))
401 gtk_widget_hide(box
);
403 type_name
= g_strconcat(type
->media_type
, "/", type
->subtype
, NULL
);
404 gtk_window_set_title(GTK_WINDOW(box
), type_name
);
405 tmp
= g_strdup_printf(
406 _("Default run action for files of type '%s':"),
408 gtk_label_set_text(GTK_LABEL(explain_label
), tmp
);
412 type_name
= g_strconcat(type
->media_type
, "_", type
->subtype
, NULL
);
413 path
= choices_find_path_load(type_name
, "MIME-types");
415 path
= choices_find_path_load(type
->media_type
, "MIME-types");
418 if (path
&& stat(path
, &info
) == 0)
420 if (S_ISDIR(info
.st_mode
))
422 tmp
= g_strconcat(path
, "/AppIcon.xpm", NULL
);
423 pic
= g_fscache_lookup(pixmap_cache
, tmp
);
427 pic
= default_pixmap
[TYPE_APPDIR
];
433 pic
= default_pixmap
[TYPE_EXEC_FILE
];
441 gtk_label_set_text(GTK_LABEL(link_path
),
442 _("No run action set"));
446 char buffer
[MAXPATHLEN
+ 1];
449 got
= readlink(path
, buffer
, sizeof(buffer
) - 1);
453 gtk_label_set_text(GTK_LABEL(link_path
), buffer
);
456 gtk_label_set_text(GTK_LABEL(link_path
), path
);
459 gtk_pixmap_set(GTK_PIXMAP(pixmap
), pic
->pixmap
, pic
->mask
);
461 g_fscache_data_unref(pixmap_cache
, pic
);
465 gtk_widget_show_all(box
);