forked from AuroraMiddleware/gtk
auto-ize.
Wed Jul 16 16:50:31 2003 Owen Taylor <otaylor@redhat.com> * configure.ac Makefile.am: auto-ize. * xdgmime/: Add freedesktop.org MIME spec implementatin by Jonathan Blandford. * gtkfilesystem.[ch]: Add gtk_file_info_render_icon() gtk_file_info_set/get_icon_type to do icon handling based on MIME type. Add a simple icon caching system. * gtkfilesystemgnomevfs.c: Implement ensure_types() so that extending the set of types for a loaded directory works. Set the MIME type to get the default icon handling. * gtkfilesystemunix.c: Look up the MIME type using xdgmime. * gtkfilechooserimpldefault.c: Display icons in the list.
This commit is contained in:
parent
bc8567d488
commit
7e54248bc3
@ -25,10 +25,12 @@
|
||||
#include "gtkfilechooser.h"
|
||||
#include "gtkfilesystemmodel.h"
|
||||
|
||||
#include <gtk/gtkcellrendererpixbuf.h>
|
||||
#include <gtk/gtkcellrenderertext.h>
|
||||
#include <gtk/gtkentry.h>
|
||||
#include <gtk/gtkhbox.h>
|
||||
#include <gtk/gtkhpaned.h>
|
||||
#include <gtk/gtkicontheme.h>
|
||||
#include <gtk/gtklabel.h>
|
||||
#include <gtk/gtkscrolledwindow.h>
|
||||
#include <gtk/gtktreeview.h>
|
||||
@ -119,6 +121,11 @@ static void tree_name_data_func (GtkTreeViewColumn *tree_column,
|
||||
GtkTreeModel *tree_model,
|
||||
GtkTreeIter *iter,
|
||||
gpointer data);
|
||||
static void list_icon_data_func (GtkTreeViewColumn *tree_column,
|
||||
GtkCellRenderer *cell,
|
||||
GtkTreeModel *tree_model,
|
||||
GtkTreeIter *iter,
|
||||
gpointer data);
|
||||
static void list_name_data_func (GtkTreeViewColumn *tree_column,
|
||||
GtkCellRenderer *cell,
|
||||
GtkTreeModel *tree_model,
|
||||
@ -130,7 +137,7 @@ static void list_size_data_func (GtkTreeViewColumn *tree_column,
|
||||
GtkTreeIter *iter,
|
||||
gpointer data);
|
||||
|
||||
GObjectClass *parent_class;
|
||||
static GObjectClass *parent_class;
|
||||
|
||||
GType
|
||||
_gtk_file_chooser_impl_default_get_type (void)
|
||||
@ -174,6 +181,8 @@ gtk_file_chooser_impl_default_class_init (GtkFileChooserImplDefaultClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
|
||||
|
||||
parent_class = g_type_class_peek_parent (class);
|
||||
|
||||
gobject_class->finalize = gtk_file_chooser_impl_default_finalize;
|
||||
gobject_class->constructor = gtk_file_chooser_impl_default_constructor;
|
||||
gobject_class->set_property = gtk_file_chooser_impl_default_set_property;
|
||||
@ -350,11 +359,19 @@ gtk_file_chooser_impl_default_constructor (GType type,
|
||||
|
||||
column = gtk_tree_view_column_new ();
|
||||
gtk_tree_view_column_set_title (column, "File name");
|
||||
|
||||
renderer = gtk_cell_renderer_pixbuf_new ();
|
||||
gtk_tree_view_column_pack_start (column, renderer, TRUE);
|
||||
gtk_tree_view_column_set_cell_data_func (column, renderer,
|
||||
list_icon_data_func, impl, NULL);
|
||||
gtk_tree_view_column_set_sort_column_id (column, 0);
|
||||
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
gtk_tree_view_column_pack_start (column, renderer, TRUE);
|
||||
gtk_tree_view_column_set_cell_data_func (column, renderer,
|
||||
list_name_data_func, impl, NULL);
|
||||
gtk_tree_view_column_set_sort_column_id (column, 0);
|
||||
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (impl->list), column);
|
||||
|
||||
column = gtk_tree_view_column_new ();
|
||||
@ -822,6 +839,7 @@ tree_selection_changed (GtkTreeSelection *selection,
|
||||
|
||||
impl->list_model = _gtk_file_system_model_new (impl->file_system,
|
||||
file_path, 0,
|
||||
GTK_FILE_INFO_ICON |
|
||||
GTK_FILE_INFO_DISPLAY_NAME |
|
||||
GTK_FILE_INFO_SIZE);
|
||||
_gtk_file_system_model_set_show_folders (impl->list_model, FALSE);
|
||||
@ -915,7 +933,7 @@ entry_activate (GtkEntry *entry,
|
||||
}
|
||||
}
|
||||
|
||||
const GtkFileInfo *
|
||||
static const GtkFileInfo *
|
||||
get_list_file_info (GtkFileChooserImplDefault *impl,
|
||||
GtkTreeIter *iter)
|
||||
{
|
||||
@ -946,6 +964,30 @@ tree_name_data_func (GtkTreeViewColumn *tree_column,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
list_icon_data_func (GtkTreeViewColumn *tree_column,
|
||||
GtkCellRenderer *cell,
|
||||
GtkTreeModel *tree_model,
|
||||
GtkTreeIter *iter,
|
||||
gpointer data)
|
||||
{
|
||||
GtkFileChooserImplDefault *impl = data;
|
||||
const GtkFileInfo *info = get_list_file_info (impl, iter);
|
||||
|
||||
if (info)
|
||||
{
|
||||
GtkWidget *widget = GTK_TREE_VIEW_COLUMN (tree_column)->tree_view;
|
||||
GdkPixbuf *pixbuf = gtk_file_info_render_icon (info, widget, 36);
|
||||
|
||||
g_object_set (cell,
|
||||
"pixbuf", pixbuf,
|
||||
NULL);
|
||||
|
||||
if (pixbuf)
|
||||
g_object_unref (pixbuf);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
list_name_data_func (GtkTreeViewColumn *tree_column,
|
||||
GtkCellRenderer *cell,
|
||||
|
@ -50,7 +50,7 @@ static void gtk_file_chooser_dialog_get_property (GObject *obj
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
GObjectClass *parent_class;
|
||||
static GObjectClass *parent_class;
|
||||
|
||||
GType
|
||||
gtk_file_chooser_dialog_get_type (void)
|
||||
|
@ -67,8 +67,8 @@ static void gtk_file_chooser_entry_do_insert_text (GtkEditable *editabl
|
||||
static void clear_completion_callback (GtkFileChooserEntry *chooser_entry,
|
||||
GParamSpec *pspec);
|
||||
|
||||
GObjectClass *parent_class;
|
||||
GtkEditableClass *parent_editable_iface;
|
||||
static GObjectClass *parent_class;
|
||||
static GtkEditableClass *parent_editable_iface;
|
||||
|
||||
GType
|
||||
_gtk_file_chooser_entry_get_type (void)
|
||||
|
@ -48,7 +48,7 @@ static void gtk_file_chooser_widget_get_property (GObject *obj
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
GObjectClass *parent_class;
|
||||
static GObjectClass *parent_class;
|
||||
|
||||
GType
|
||||
gtk_file_chooser_widget_get_type (void)
|
||||
@ -130,7 +130,7 @@ gtk_file_chooser_widget_constructor (GType type,
|
||||
gtk_widget_push_composite_child ();
|
||||
|
||||
if (!priv->file_system)
|
||||
priv->file_system = _gtk_file_system_unix_new ();
|
||||
priv->file_system = gtk_file_system_unix_new ();
|
||||
|
||||
priv->impl = _gtk_file_chooser_impl_default_new (priv->file_system);
|
||||
gtk_box_pack_start (GTK_BOX (object), priv->impl, TRUE, TRUE, 0);
|
||||
|
@ -18,6 +18,8 @@
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <gtk/gtkicontheme.h>
|
||||
|
||||
#include "gtkfilesystem.h"
|
||||
|
||||
#include <string.h>
|
||||
@ -29,7 +31,7 @@ struct _GtkFileInfo
|
||||
gchar *display_name;
|
||||
gchar *display_key;
|
||||
gchar *mime_type;
|
||||
GdkPixbuf *icon;
|
||||
GtkFileIconType icon_type : 4;
|
||||
guint is_folder : 1;
|
||||
guint is_hidden : 1;
|
||||
};
|
||||
@ -84,8 +86,6 @@ gtk_file_info_copy (GtkFileInfo *info)
|
||||
new_info->display_name = g_strdup (new_info->display_name);
|
||||
if (new_info->mime_type)
|
||||
new_info->mime_type = g_strdup (new_info->mime_type);
|
||||
if (new_info->icon)
|
||||
g_object_ref (new_info->icon);
|
||||
|
||||
return new_info;
|
||||
}
|
||||
@ -99,8 +99,6 @@ gtk_file_info_free (GtkFileInfo *info)
|
||||
g_free (info->display_name);
|
||||
if (info->mime_type)
|
||||
g_free (info->mime_type);
|
||||
if (info->icon)
|
||||
g_object_unref (info->icon);
|
||||
}
|
||||
|
||||
G_CONST_RETURN gchar *
|
||||
@ -134,7 +132,6 @@ gtk_file_info_get_display_key (const GtkFileInfo *info)
|
||||
((GtkFileInfo *)info)->display_key = g_utf8_collate_key (info->display_name, -1);
|
||||
}
|
||||
|
||||
|
||||
return info->display_key;
|
||||
}
|
||||
|
||||
@ -244,31 +241,166 @@ gtk_file_info_set_size (GtkFileInfo *info,
|
||||
info->size = size;
|
||||
}
|
||||
|
||||
GdkPixbuf *
|
||||
gtk_file_info_get_icon (const GtkFileInfo *info)
|
||||
{
|
||||
g_return_val_if_fail (info != NULL, NULL);
|
||||
|
||||
return info->icon;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_file_info_set_icon (GtkFileInfo *info,
|
||||
GdkPixbuf *icon)
|
||||
gtk_file_info_set_icon_type (GtkFileInfo *info,
|
||||
GtkFileIconType icon_type)
|
||||
{
|
||||
g_return_if_fail (info != NULL);
|
||||
g_return_if_fail (icon == NULL || GDK_IS_PIXBUF (icon));
|
||||
|
||||
if (icon != info->icon)
|
||||
info->icon_type = icon_type;
|
||||
}
|
||||
|
||||
GtkFileIconType
|
||||
gtk_file_info_get_icon_type (const GtkFileInfo *info)
|
||||
{
|
||||
g_return_val_if_fail (info != NULL, GTK_FILE_ICON_REGULAR);
|
||||
|
||||
return info->icon_type;
|
||||
}
|
||||
|
||||
typedef struct _IconCacheElement IconCacheElement;
|
||||
|
||||
struct _IconCacheElement
|
||||
{
|
||||
gint size;
|
||||
GdkPixbuf *pixbuf;
|
||||
};
|
||||
|
||||
static void
|
||||
icon_cache_element_free (IconCacheElement *element)
|
||||
{
|
||||
if (element->pixbuf)
|
||||
g_object_unref (element->pixbuf);
|
||||
g_free (element);
|
||||
}
|
||||
|
||||
static void
|
||||
icon_theme_changed (GtkIconTheme *icon_theme)
|
||||
{
|
||||
GHashTable *cache;
|
||||
|
||||
/* Difference from the initial creation is that we don't
|
||||
* reconnect the signal
|
||||
*/
|
||||
cache = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
(GDestroyNotify)g_free,
|
||||
(GDestroyNotify)icon_cache_element_free);
|
||||
g_object_set_data_full (G_OBJECT (icon_theme), "gtk-file-icon-cache",
|
||||
cache, (GDestroyNotify)g_hash_table_destroy);
|
||||
}
|
||||
|
||||
static GdkPixbuf *
|
||||
get_cached_icon (GtkWidget *widget,
|
||||
const gchar *name,
|
||||
gint pixel_size)
|
||||
{
|
||||
GtkIconTheme *icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
|
||||
GHashTable *cache = g_object_get_data (G_OBJECT (icon_theme), "gtk-file-icon-cache");
|
||||
IconCacheElement *element;
|
||||
|
||||
if (!cache)
|
||||
{
|
||||
if (info->icon)
|
||||
g_object_unref (info->icon);
|
||||
cache = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
(GDestroyNotify)g_free,
|
||||
(GDestroyNotify)icon_cache_element_free);
|
||||
|
||||
info->icon = icon;
|
||||
|
||||
if (info->icon)
|
||||
g_object_ref (info->icon);
|
||||
g_object_set_data_full (G_OBJECT (icon_theme), "gtk-file-icon-cache",
|
||||
cache, (GDestroyNotify)g_hash_table_destroy);
|
||||
g_signal_connect (icon_theme, "changed",
|
||||
G_CALLBACK (icon_theme_changed), NULL);
|
||||
}
|
||||
|
||||
element = g_hash_table_lookup (cache, name);
|
||||
if (!element)
|
||||
{
|
||||
element = g_new0 (IconCacheElement, 1);
|
||||
g_hash_table_insert (cache, g_strdup (name), element);
|
||||
}
|
||||
|
||||
if (element->size != pixel_size)
|
||||
{
|
||||
if (element->pixbuf)
|
||||
g_object_unref (element->pixbuf);
|
||||
element->size = pixel_size;
|
||||
element->pixbuf = gtk_icon_theme_load_icon (icon_theme, name,
|
||||
pixel_size, 0, NULL);
|
||||
}
|
||||
|
||||
return element->pixbuf ? g_object_ref (element->pixbuf) : NULL;
|
||||
}
|
||||
|
||||
|
||||
GdkPixbuf *
|
||||
gtk_file_info_render_icon (const GtkFileInfo *info,
|
||||
GtkWidget *widget,
|
||||
gint pixel_size)
|
||||
{
|
||||
const gchar *separator;
|
||||
GdkPixbuf *pixbuf;
|
||||
GString *icon_name;
|
||||
|
||||
g_return_val_if_fail (info != NULL, NULL);
|
||||
g_return_val_if_fail (widget != NULL, NULL);
|
||||
g_return_val_if_fail (pixel_size > 0, NULL);
|
||||
|
||||
if (info->icon_type != GTK_FILE_ICON_REGULAR)
|
||||
{
|
||||
const char *name = NULL; /* Quiet gcc */
|
||||
|
||||
switch (info->icon_type)
|
||||
{
|
||||
case GTK_FILE_ICON_BLOCK_DEVICE:
|
||||
name ="gnome-fs-blockdev";
|
||||
break;
|
||||
case GTK_FILE_ICON_BROKEN_SYMBOLIC_LINK:
|
||||
name = "gnome-fs-symlink";
|
||||
break;
|
||||
case GTK_FILE_ICON_CHARACTER_DEVICE:
|
||||
name = "gnome-fs-chardev";
|
||||
break;
|
||||
case GTK_FILE_ICON_DIRECTORY:
|
||||
name = "gnome-fs-directory";
|
||||
break;
|
||||
case GTK_FILE_ICON_EXECUTABLE:
|
||||
name ="gnome-fs-executable";
|
||||
break;
|
||||
case GTK_FILE_ICON_FIFO:
|
||||
name = "gnome-fs-fifo";
|
||||
break;
|
||||
case GTK_FILE_ICON_SOCKET:
|
||||
name = "gnome-fs-socket";
|
||||
break;
|
||||
case GTK_FILE_ICON_REGULAR:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
return get_cached_icon (widget, name, pixel_size);
|
||||
}
|
||||
|
||||
if (!info->mime_type)
|
||||
return NULL;
|
||||
|
||||
separator = strchr (info->mime_type, '/');
|
||||
if (!separator)
|
||||
return NULL;
|
||||
|
||||
icon_name = g_string_new ("gnome-mime-");
|
||||
g_string_append_len (icon_name, info->mime_type, separator - info->mime_type);
|
||||
g_string_append_c (icon_name, '-');
|
||||
g_string_append (icon_name, separator + 1);
|
||||
pixbuf = get_cached_icon (widget, icon_name->str, pixel_size);
|
||||
g_string_free (icon_name, TRUE);
|
||||
if (pixbuf)
|
||||
return pixbuf;
|
||||
|
||||
icon_name = g_string_new ("gnome-mime-");
|
||||
g_string_append_len (icon_name, info->mime_type, separator - info->mime_type);
|
||||
pixbuf = get_cached_icon (widget, icon_name->str, pixel_size);
|
||||
g_string_free (icon_name, TRUE);
|
||||
if (pixbuf)
|
||||
return pixbuf;
|
||||
|
||||
return get_cached_icon (widget, "gnome-fs-regular", pixel_size);
|
||||
}
|
||||
|
||||
/*****************************************
|
||||
|
@ -22,7 +22,7 @@
|
||||
#define __GTK_FILE_SYSTEM_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gtk/gtkwidget.h> /* For icon handling */
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@ -50,6 +50,19 @@ typedef enum {
|
||||
GTK_FILE_INFO_ALL = (1 << 7) - 1
|
||||
} GtkFileInfoType;
|
||||
|
||||
/* Icon type, supplemented by MIME type
|
||||
*/
|
||||
typedef enum {
|
||||
GTK_FILE_ICON_REGULAR, /* Use mime type for icon */
|
||||
GTK_FILE_ICON_BLOCK_DEVICE,
|
||||
GTK_FILE_ICON_BROKEN_SYMBOLIC_LINK,
|
||||
GTK_FILE_ICON_CHARACTER_DEVICE,
|
||||
GTK_FILE_ICON_DIRECTORY,
|
||||
GTK_FILE_ICON_EXECUTABLE,
|
||||
GTK_FILE_ICON_FIFO,
|
||||
GTK_FILE_ICON_SOCKET
|
||||
} GtkFileIconType;
|
||||
|
||||
/* GError enumeration for GtkFileSystem
|
||||
*/
|
||||
|
||||
@ -96,9 +109,12 @@ void gtk_file_info_set_modification_time (GtkFileInfo *in
|
||||
gint64 gtk_file_info_get_size (const GtkFileInfo *info);
|
||||
void gtk_file_info_set_size (GtkFileInfo *info,
|
||||
gint64 size);
|
||||
GdkPixbuf * gtk_file_info_get_icon (const GtkFileInfo *info);
|
||||
void gtk_file_info_set_icon (GtkFileInfo *info,
|
||||
GdkPixbuf *icon);
|
||||
void gtk_file_info_set_icon_type (GtkFileInfo *info,
|
||||
GtkFileIconType icon_type);
|
||||
GtkFileIconType gtk_file_info_get_icon_type (const GtkFileInfo *info);
|
||||
GdkPixbuf * gtk_file_info_render_icon (const GtkFileInfo *info,
|
||||
GtkWidget *widget,
|
||||
gint pixel_size);
|
||||
|
||||
/* The base GtkFileSystem interface
|
||||
*/
|
||||
|
@ -35,7 +35,7 @@ typedef struct _GtkFileSystemModel GtkFileSystemModel;
|
||||
|
||||
GType _gtk_file_system_model_get_type (void);
|
||||
|
||||
enum {
|
||||
typedef enum {
|
||||
GTK_FILE_SYSTEM_MODEL_INFO,
|
||||
GTK_FILE_SYSTEM_MODEL_DISPLAY_NAME,
|
||||
GTK_FILE_SYSTEM_MODEL_N_COLUMNS
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include "gtkfilesystem.h"
|
||||
#include "gtkfilesystemunix.h"
|
||||
|
||||
#include "xdgmime/xdgmime.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
@ -66,8 +68,8 @@ struct _GtkFileFolderUnix
|
||||
gchar *filename;
|
||||
};
|
||||
|
||||
GObjectClass *system_parent_class;
|
||||
GObjectClass *folder_parent_class;
|
||||
static GObjectClass *system_parent_class;
|
||||
static GObjectClass *folder_parent_class;
|
||||
|
||||
static void gtk_file_system_unix_class_init (GtkFileSystemUnixClass *class);
|
||||
static void gtk_file_system_unix_iface_init (GtkFileSystemIface *iface);
|
||||
@ -135,7 +137,7 @@ static GtkFileInfo *filename_get_info (const gchar *filename,
|
||||
* GtkFileSystemUnix
|
||||
*/
|
||||
GType
|
||||
_gtk_file_system_unix_get_type (void)
|
||||
gtk_file_system_unix_get_type (void)
|
||||
{
|
||||
static GType file_system_unix_type = 0;
|
||||
|
||||
@ -173,7 +175,7 @@ _gtk_file_system_unix_get_type (void)
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_file_system_unix_new:
|
||||
* gtk_file_system_unix_new:
|
||||
*
|
||||
* Creates a new #GtkFileSystemUnix object. #GtkFileSystemUnix
|
||||
* implements the #GtkFileSystem interface with direct access to
|
||||
@ -182,7 +184,7 @@ _gtk_file_system_unix_get_type (void)
|
||||
* Return value: the new #GtkFileSystemUnix object
|
||||
**/
|
||||
GtkFileSystem *
|
||||
_gtk_file_system_unix_new (void)
|
||||
gtk_file_system_unix_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_FILE_SYSTEM_UNIX, NULL);
|
||||
}
|
||||
@ -678,6 +680,7 @@ filename_get_info (const gchar *filename,
|
||||
GError **error)
|
||||
{
|
||||
GtkFileInfo *info;
|
||||
GtkFileIconType icon_type = GTK_FILE_ICON_REGULAR;
|
||||
struct stat statbuf;
|
||||
|
||||
/* If stat fails, try to fall back to lstat to catch broken links
|
||||
@ -735,9 +738,36 @@ filename_get_info (const gchar *filename,
|
||||
gtk_file_info_set_is_folder (info, S_ISDIR (statbuf.st_mode));
|
||||
}
|
||||
|
||||
if (types & GTK_FILE_INFO_MIME_TYPE)
|
||||
if (types & GTK_FILE_INFO_ICON)
|
||||
{
|
||||
gtk_file_info_set_mime_type (info, "application/octet-stream");
|
||||
if (S_ISBLK (statbuf.st_mode))
|
||||
icon_type = GTK_FILE_ICON_BLOCK_DEVICE;
|
||||
else if (S_ISLNK (statbuf.st_mode))
|
||||
icon_type = GTK_FILE_ICON_BROKEN_SYMBOLIC_LINK;
|
||||
else if (S_ISCHR (statbuf.st_mode))
|
||||
icon_type = GTK_FILE_ICON_CHARACTER_DEVICE;
|
||||
else if (S_ISDIR (statbuf.st_mode))
|
||||
icon_type = GTK_FILE_ICON_DIRECTORY;
|
||||
else if (S_ISFIFO (statbuf.st_mode))
|
||||
icon_type = GTK_FILE_ICON_FIFO;
|
||||
else if (S_ISSOCK (statbuf.st_mode))
|
||||
icon_type = GTK_FILE_ICON_SOCKET;
|
||||
|
||||
gtk_file_info_set_icon_type (info, icon_type);
|
||||
}
|
||||
|
||||
if ((types & GTK_FILE_INFO_MIME_TYPE) ||
|
||||
((types & GTK_FILE_INFO_ICON) && icon_type == GTK_FILE_ICON_REGULAR))
|
||||
{
|
||||
const char *mime_type = xdg_mime_get_mime_type_for_file (filename);
|
||||
gtk_file_info_set_mime_type (info, mime_type);
|
||||
|
||||
if ((types & GTK_FILE_INFO_ICON) && icon_type == GTK_FILE_ICON_REGULAR &&
|
||||
(statbuf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) &&
|
||||
(strcmp (mime_type, XDG_MIME_TYPE_UNKNOWN) == 0 ||
|
||||
strcmp (mime_type, "application/x-executable") == 0 ||
|
||||
strcmp (mime_type, "application/x-shellscript") == 0))
|
||||
gtk_file_info_set_icon_type (info, GTK_FILE_ICON_EXECUTABLE);
|
||||
}
|
||||
|
||||
if (types & GTK_FILE_INFO_MODIFICATION_TIME)
|
||||
@ -750,11 +780,6 @@ filename_get_info (const gchar *filename,
|
||||
gtk_file_info_set_size (info, (gint64)statbuf.st_size);
|
||||
}
|
||||
|
||||
if (types & GTK_FILE_INFO_ICON)
|
||||
{
|
||||
/* NOT YET IMPLEMENTED */
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
|
@ -26,14 +26,14 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_FILE_SYSTEM_UNIX (_gtk_file_system_unix_get_type ())
|
||||
#define GTK_TYPE_FILE_SYSTEM_UNIX (gtk_file_system_unix_get_type ())
|
||||
#define GTK_FILE_SYSTEM_UNIX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_SYSTEM_UNIX, GtkFileSystemUnix))
|
||||
#define GTK_IS_FILE_SYSTEM_UNIX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_FILE_SYSTEM_UNIX))
|
||||
|
||||
typedef struct _GtkFileSystemUnix GtkFileSystemUnix;
|
||||
|
||||
GtkFileSystem *_gtk_file_system_unix_new (void);
|
||||
GType _gtk_file_system_unix_get_type (void);
|
||||
GtkFileSystem *gtk_file_system_unix_new (void);
|
||||
GType gtk_file_system_unix_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
15
gtk/xdgmime/Makefile.am
Normal file
15
gtk/xdgmime/Makefile.am
Normal file
@ -0,0 +1,15 @@
|
||||
INCLUDES = -DXDG_PREFIX=_xdg
|
||||
|
||||
noinst_LTLIBRARIES = libxdgmime.la
|
||||
|
||||
libxdgmime_la_SOURCES = \
|
||||
xdgmime.c \
|
||||
xdgmimeglob.c \
|
||||
xdgmimeint.c \
|
||||
xdgmimemagic.c
|
||||
|
||||
noinst_PROGRAMS = test-mime
|
||||
|
||||
test_mime_LDADD = libxdgmime.la
|
||||
test_mime_SOURCES = test-mime.c
|
||||
|
53
gtk/xdgmime/test-mime.c
Normal file
53
gtk/xdgmime/test-mime.c
Normal file
@ -0,0 +1,53 @@
|
||||
#include "xdgmime.h"
|
||||
#include "xdgmimeglob.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
static void
|
||||
test_individual_glob (const char *glob,
|
||||
XdgGlobType expected_type)
|
||||
{
|
||||
XdgGlobType test_type;
|
||||
|
||||
test_type = _xdg_glob_determine_type (glob);
|
||||
if (test_type != expected_type)
|
||||
{
|
||||
printf ("Test Failed: %s is of type %s, but %s is expected\n",
|
||||
glob,
|
||||
((test_type == XDG_GLOB_LITERAL)?"XDG_GLOB_LITERAL":
|
||||
((test_type == XDG_GLOB_SIMPLE)?"XDG_GLOB_SIMPLE":"XDG_GLOB_FULL")),
|
||||
((expected_type == XDG_GLOB_LITERAL)?"XDG_GLOB_LITERAL":
|
||||
((expected_type == XDG_GLOB_SIMPLE)?"XDG_GLOB_SIMPLE":"XDG_GLOB_COMPLEX")));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_glob_type (void)
|
||||
{
|
||||
test_individual_glob ("*.gif", XDG_GLOB_SIMPLE);
|
||||
test_individual_glob ("Foo*.gif", XDG_GLOB_FULL);
|
||||
test_individual_glob ("*[4].gif", XDG_GLOB_FULL);
|
||||
test_individual_glob ("Makefile", XDG_GLOB_LITERAL);
|
||||
test_individual_glob ("sldkfjvlsdf\\\\slkdjf", XDG_GLOB_FULL);
|
||||
test_individual_glob ("tree.[ch]", XDG_GLOB_FULL);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
const char *result;
|
||||
const char *file_name;
|
||||
int i;
|
||||
|
||||
test_glob_type ();
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
file_name = argv[i];
|
||||
result = xdg_mime_get_mime_type_for_file (file_name);
|
||||
printf ("File \"%s\" has a mime-type of %s\n", file_name, result);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
235
gtk/xdgmime/xdgmime.c
Normal file
235
gtk/xdgmime/xdgmime.c
Normal file
@ -0,0 +1,235 @@
|
||||
/* -*- mode: C; c-file-style: "gnu" -*- */
|
||||
/* xdgmime.c: XDG Mime Spec mime resolver. Based on version 0.11 of the spec.
|
||||
*
|
||||
* More info can be found at http://www.freedesktop.org/standards/
|
||||
*
|
||||
* Copyright (C) 2003 Red Hat, Inc.
|
||||
* Copyright (C) 2003 Jonathan Blandford <jrb@alum.mit.edu>
|
||||
*
|
||||
* Licensed under the Academic Free License version 1.2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xdgmime.h"
|
||||
#include "xdgmimeint.h"
|
||||
#include "xdgmimeglob.h"
|
||||
#include "xdgmimemagic.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
XdgGlobHash *global_hash = NULL;
|
||||
XdgMimeMagic *global_magic = NULL;
|
||||
|
||||
|
||||
static void
|
||||
_xdg_mime_init_from_directory (const char *directory)
|
||||
{
|
||||
char *file_name;
|
||||
|
||||
file_name = malloc (strlen (directory) + strlen ("/mime/globs") + 1);
|
||||
strcpy (file_name, directory);
|
||||
strcat (file_name, "/mime/globs");
|
||||
_xdg_mime_glob_read_from_file (global_hash, file_name);
|
||||
free (file_name);
|
||||
|
||||
file_name = malloc (strlen (directory) + strlen ("/mime/magic") + 1);
|
||||
strcpy (file_name, directory);
|
||||
strcat (file_name, "/mime/magic");
|
||||
_xdg_mime_magic_read_from_file (global_magic, file_name);
|
||||
free (file_name);
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_mime_init (void)
|
||||
{
|
||||
static int initted = 0;
|
||||
|
||||
if (initted == 0)
|
||||
{
|
||||
const char *xdg_config_home;
|
||||
const char *xdg_data_dirs;
|
||||
const char *ptr;
|
||||
|
||||
global_hash = _xdg_glob_hash_new ();
|
||||
global_magic = _xdg_mime_magic_new ();
|
||||
|
||||
/* We look for globs and magic files based upon the XDG Base Directory
|
||||
* Specification
|
||||
*/
|
||||
xdg_config_home = getenv ("XDG_CONFIG_HOME");
|
||||
if (xdg_config_home)
|
||||
{
|
||||
_xdg_mime_init_from_directory (xdg_config_home);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *home;
|
||||
|
||||
home = getenv ("HOME");
|
||||
if (home != NULL)
|
||||
{
|
||||
char *guessed_xdg_home;
|
||||
|
||||
guessed_xdg_home = malloc (strlen (home) + strlen ("/.local/share/") + 1);
|
||||
strcpy (guessed_xdg_home, home);
|
||||
strcat (guessed_xdg_home, "/.local/share/");
|
||||
_xdg_mime_init_from_directory (guessed_xdg_home);
|
||||
free (guessed_xdg_home);
|
||||
}
|
||||
}
|
||||
|
||||
xdg_data_dirs = getenv ("XDG_DATA_DIRS");
|
||||
if (xdg_data_dirs == NULL)
|
||||
xdg_data_dirs = "/usr/local/share/:/usr/share/";
|
||||
|
||||
ptr = xdg_data_dirs;
|
||||
|
||||
while (*ptr != '\000')
|
||||
{
|
||||
const char *end_ptr;
|
||||
char *dir;
|
||||
int len;
|
||||
|
||||
end_ptr = ptr;
|
||||
while (*end_ptr != ':' && *end_ptr != '\000')
|
||||
end_ptr ++;
|
||||
|
||||
if (end_ptr == ptr)
|
||||
{
|
||||
ptr++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*end_ptr == ':')
|
||||
len = end_ptr - ptr;
|
||||
else
|
||||
len = end_ptr - ptr + 1;
|
||||
dir = malloc (len);
|
||||
strncpy (dir, ptr, len);
|
||||
_xdg_mime_init_from_directory (dir);
|
||||
free (dir);
|
||||
|
||||
ptr = end_ptr;
|
||||
}
|
||||
initted = 1;
|
||||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
xdg_mime_get_mime_type_for_data (const void *data,
|
||||
size_t len)
|
||||
{
|
||||
const char *mime_type;
|
||||
|
||||
xdg_mime_init ();
|
||||
|
||||
mime_type = _xdg_mime_magic_lookup_data (global_magic, data, len);
|
||||
|
||||
if (mime_type)
|
||||
return mime_type;
|
||||
|
||||
return XDG_MIME_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
const char *
|
||||
xdg_mime_get_mime_type_for_file (const char *file_name)
|
||||
{
|
||||
const char *mime_type;
|
||||
FILE *file;
|
||||
unsigned char *data;
|
||||
int max_extent;
|
||||
int bytes_read;
|
||||
struct stat statbuf;
|
||||
const char *base_name;
|
||||
|
||||
if (file_name == NULL)
|
||||
return NULL;
|
||||
if (! _xdg_utf8_validate (file_name))
|
||||
return NULL;
|
||||
|
||||
xdg_mime_init ();
|
||||
|
||||
base_name = _xdg_get_base_name (file_name);
|
||||
mime_type = xdg_mime_get_mime_type_from_file_name (base_name);
|
||||
|
||||
if (mime_type != XDG_MIME_TYPE_UNKNOWN)
|
||||
return mime_type;
|
||||
|
||||
if (stat (file_name, &statbuf) != 0)
|
||||
return XDG_MIME_TYPE_UNKNOWN;
|
||||
|
||||
if (!S_ISREG (statbuf.st_mode))
|
||||
return XDG_MIME_TYPE_UNKNOWN;
|
||||
|
||||
/* FIXME: Need to make sure that max_extent isn't totally broken. This could
|
||||
* be large and need getting from a stream instead of just reading it all
|
||||
* in. */
|
||||
max_extent = _xdg_mime_magic_get_buffer_extents (global_magic);
|
||||
data = malloc (max_extent);
|
||||
if (data == NULL)
|
||||
return XDG_MIME_TYPE_UNKNOWN;
|
||||
|
||||
file = fopen (file_name, "r");
|
||||
if (file == NULL)
|
||||
{
|
||||
free (data);
|
||||
return XDG_MIME_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
bytes_read = fread (data, 1, max_extent, file);
|
||||
if (ferror (file))
|
||||
{
|
||||
free (data);
|
||||
fclose (file);
|
||||
return XDG_MIME_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
mime_type = _xdg_mime_magic_lookup_data (global_magic, data, bytes_read);
|
||||
|
||||
free (data);
|
||||
fclose (file);
|
||||
|
||||
if (mime_type)
|
||||
return mime_type;
|
||||
|
||||
return XDG_MIME_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
const char *
|
||||
xdg_mime_get_mime_type_from_file_name (const char *file_name)
|
||||
{
|
||||
const char *mime_type;
|
||||
|
||||
xdg_mime_init ();
|
||||
|
||||
mime_type = _xdg_glob_hash_lookup_file_name (global_hash, file_name);
|
||||
if (mime_type)
|
||||
return mime_type;
|
||||
else
|
||||
return XDG_MIME_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
int
|
||||
xdg_mime_is_valid_mime_type (const char *mime_type)
|
||||
{
|
||||
/* FIXME: We should make this a better test
|
||||
*/
|
||||
return _xdg_utf8_validate (mime_type);
|
||||
}
|
60
gtk/xdgmime/xdgmime.h
Normal file
60
gtk/xdgmime/xdgmime.h
Normal file
@ -0,0 +1,60 @@
|
||||
/* -*- mode: C; c-file-style: "gnu" -*- */
|
||||
/* xdgmime.h: XDG Mime Spec mime resolver. Based on version 0.11 of the spec.
|
||||
*
|
||||
* More info can be found at http://www.freedesktop.org/standards/
|
||||
*
|
||||
* Copyright (C) 2003 Red Hat, Inc.
|
||||
* Copyright (C) 2003 Jonathan Blandford <jrb@alum.mit.edu>
|
||||
*
|
||||
* Licensed under the Academic Free License version 1.2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __XDG_MIME_H__
|
||||
#define __XDG_MIME_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#define XDG_MIME_TYPE_UNKNOWN "application/octet-stream"
|
||||
|
||||
#ifdef XDG_PREFIX
|
||||
#define XDG_ENTRY(func) _XDG_ENTRY2(XDG_PREFIX,func)
|
||||
#define _XDG_ENTRY2(prefix,func) _XDG_ENTRY3(prefix,func)
|
||||
#define _XDG_ENTRY3(prefix,func) prefix##_##func
|
||||
|
||||
#define xdg_mime_get_mime_type_for_data XDG_ENTRY(get_mime_type_for_data)
|
||||
#define xdg_mime_get_mime_type_for_file XDG_ENTRY(get_mime_type_for_file)
|
||||
#define xdg_mime_get_mime_type_from_file_name XDG_ENTRY(get_mime_type_from_file_name)
|
||||
#define xdg_mime_is_valid_mime_type XDG_ENTRY(is_valid_mime_type)
|
||||
#endif
|
||||
|
||||
const char *xdg_mime_get_mime_type_for_data (const void *data,
|
||||
size_t len);
|
||||
const char *xdg_mime_get_mime_type_for_file (const char *file_name);
|
||||
const char *xdg_mime_get_mime_type_from_file_name (const char *file_name);
|
||||
int xdg_mime_is_valid_mime_type (const char *mime_type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __XDG_MIME_H__ */
|
465
gtk/xdgmime/xdgmimeglob.c
Normal file
465
gtk/xdgmime/xdgmimeglob.c
Normal file
@ -0,0 +1,465 @@
|
||||
/* -*- mode: C; c-file-style: "gnu" -*- */
|
||||
/* xdgmime.c: Private file. Datastructure for storing the globs.
|
||||
*
|
||||
* More info can be found at http://www.freedesktop.org/standards/
|
||||
*
|
||||
* Copyright (C) 2003 Red Hat, Inc.
|
||||
* Copyright (C) 2003 Jonathan Blandford <jrb@alum.mit.edu>
|
||||
*
|
||||
* Licensed under the Academic Free License version 1.2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xdgmimeglob.h"
|
||||
#include "xdgmimeint.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <fnmatch.h>
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE (0)
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE (!FALSE)
|
||||
#endif
|
||||
|
||||
typedef struct XdgGlobHashNode XdgGlobHashNode;
|
||||
typedef struct XdgGlobList XdgGlobList;
|
||||
|
||||
struct XdgGlobHashNode
|
||||
{
|
||||
xdg_unichar_t character;
|
||||
const char *mime_type;
|
||||
XdgGlobHashNode *next;
|
||||
XdgGlobHashNode *child;
|
||||
};
|
||||
struct XdgGlobList
|
||||
{
|
||||
const char *data;
|
||||
const char *mime_type;
|
||||
XdgGlobList *next;
|
||||
};
|
||||
|
||||
struct XdgGlobHash
|
||||
{
|
||||
XdgGlobList *literal_list;
|
||||
XdgGlobHashNode *simple_node;
|
||||
XdgGlobList *full_list;
|
||||
};
|
||||
|
||||
|
||||
/* XdgGlobList
|
||||
*/
|
||||
static XdgGlobList *
|
||||
_xdg_glob_list_new (void)
|
||||
{
|
||||
XdgGlobList *new_element;
|
||||
|
||||
new_element = calloc (1, sizeof (XdgGlobList));
|
||||
|
||||
return new_element;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
_xdg_glob_list_free (XdgGlobList *glob_list)
|
||||
{
|
||||
free (glob_list);
|
||||
}
|
||||
#endif
|
||||
|
||||
static XdgGlobList *
|
||||
_xdg_glob_list_append (XdgGlobList *glob_list,
|
||||
void *data,
|
||||
const char *mime_type)
|
||||
{
|
||||
XdgGlobList *new_element;
|
||||
XdgGlobList *tmp_element;
|
||||
|
||||
new_element = _xdg_glob_list_new ();
|
||||
new_element->data = data;
|
||||
new_element->mime_type = mime_type;
|
||||
if (glob_list == NULL)
|
||||
return new_element;
|
||||
|
||||
tmp_element = glob_list;
|
||||
while (tmp_element->next != NULL)
|
||||
tmp_element = tmp_element->next;
|
||||
|
||||
tmp_element->next = new_element;
|
||||
|
||||
return glob_list;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static XdgGlobList *
|
||||
_xdg_glob_list_prepend (XdgGlobList *glob_list,
|
||||
void *data,
|
||||
const char *mime_type)
|
||||
{
|
||||
XdgGlobList *new_element;
|
||||
|
||||
new_element = _xdg_glob_list_new ();
|
||||
new_element->data = data;
|
||||
new_element->next = glob_list;
|
||||
new_element->mime_type = mime_type;
|
||||
|
||||
return new_element;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* XdgGlobHashNode
|
||||
*/
|
||||
|
||||
static XdgGlobHashNode *
|
||||
_xdg_glob_hash_node_new (void)
|
||||
{
|
||||
XdgGlobHashNode *glob_hash_node;
|
||||
|
||||
glob_hash_node = calloc (1, sizeof (XdgGlobHashNode));
|
||||
|
||||
return glob_hash_node;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
_xdg_glob_hash_node_free (XdgGlobHashNode *glob_hash_node)
|
||||
{
|
||||
free (glob_hash_node);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
_xdg_glob_hash_node_dump (XdgGlobHashNode *glob_hash_node,
|
||||
int depth)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < depth; i++)
|
||||
printf (" ");
|
||||
|
||||
printf ("%c", (char)glob_hash_node->character);
|
||||
if (glob_hash_node->mime_type)
|
||||
printf (" - %s\n", glob_hash_node->mime_type);
|
||||
else
|
||||
printf ("\n");
|
||||
if (glob_hash_node->child)
|
||||
_xdg_glob_hash_node_dump (glob_hash_node->child, depth + 1);
|
||||
if (glob_hash_node->next)
|
||||
_xdg_glob_hash_node_dump (glob_hash_node->next, depth);
|
||||
}
|
||||
|
||||
static XdgGlobHashNode *
|
||||
_xdg_glob_hash_insert_text (XdgGlobHashNode *glob_hash_node,
|
||||
const char *text,
|
||||
const char *mime_type)
|
||||
{
|
||||
XdgGlobHashNode *node;
|
||||
xdg_unichar_t character;
|
||||
|
||||
character = _xdg_utf8_to_ucs4 (text);
|
||||
|
||||
if ((glob_hash_node == NULL) ||
|
||||
(character < glob_hash_node->character))
|
||||
{
|
||||
node = _xdg_glob_hash_node_new ();
|
||||
node->character = character;
|
||||
node->next = glob_hash_node;
|
||||
glob_hash_node = node;
|
||||
}
|
||||
else if (character == glob_hash_node->character)
|
||||
{
|
||||
node = glob_hash_node;
|
||||
}
|
||||
else
|
||||
{
|
||||
XdgGlobHashNode *prev_node;
|
||||
int found_node = FALSE;
|
||||
|
||||
/* Look for the first character of text in glob_hash_node, and insert it if we
|
||||
* have to.*/
|
||||
prev_node = glob_hash_node;
|
||||
node = prev_node->next;
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
if (character < node->character)
|
||||
{
|
||||
node = _xdg_glob_hash_node_new ();
|
||||
node->character = character;
|
||||
node->next = prev_node->next;
|
||||
prev_node->next = node;
|
||||
|
||||
found_node = TRUE;
|
||||
break;
|
||||
}
|
||||
else if (character == node->character)
|
||||
{
|
||||
found_node = TRUE;
|
||||
break;
|
||||
}
|
||||
prev_node = node;
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
if (! found_node)
|
||||
{
|
||||
node = _xdg_glob_hash_node_new ();
|
||||
node->character = character;
|
||||
node->next = prev_node->next;
|
||||
prev_node->next = node;
|
||||
}
|
||||
}
|
||||
|
||||
text = _xdg_utf8_next_char (text);
|
||||
if (*text == '\000')
|
||||
{
|
||||
node->mime_type = mime_type;
|
||||
}
|
||||
else
|
||||
{
|
||||
node->child = _xdg_glob_hash_insert_text (node->child, text, mime_type);
|
||||
}
|
||||
return glob_hash_node;
|
||||
}
|
||||
|
||||
static const char *
|
||||
_xdg_glob_hash_node_lookup_file_name (XdgGlobHashNode *glob_hash_node,
|
||||
const char *file_name,
|
||||
int ignore_case)
|
||||
{
|
||||
XdgGlobHashNode *node;
|
||||
xdg_unichar_t character;
|
||||
|
||||
if (glob_hash_node == NULL)
|
||||
return NULL;
|
||||
|
||||
character = _xdg_utf8_to_ucs4 (file_name);
|
||||
if (ignore_case)
|
||||
character = _xdg_ucs4_to_upper(character);
|
||||
|
||||
for (node = glob_hash_node;
|
||||
node && character >= (ignore_case?_xdg_ucs4_to_upper (node->character):node->character);
|
||||
node = node->next)
|
||||
{
|
||||
if (character == (ignore_case?_xdg_ucs4_to_upper (node->character):node->character))
|
||||
{
|
||||
file_name = _xdg_utf8_next_char (file_name);
|
||||
if (*file_name == '\000')
|
||||
return node->mime_type;
|
||||
else
|
||||
return _xdg_glob_hash_node_lookup_file_name (node->child,
|
||||
file_name,
|
||||
ignore_case);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *
|
||||
_xdg_glob_hash_lookup_file_name (XdgGlobHash *glob_hash,
|
||||
const char *file_name)
|
||||
{
|
||||
XdgGlobList *list;
|
||||
const char *mime_type;
|
||||
const char *ptr;
|
||||
/* First, check the literals */
|
||||
|
||||
assert (file_name != NULL);
|
||||
|
||||
for (list = glob_hash->literal_list; list; list = list->next)
|
||||
if (strcmp ((const char *)list->data, file_name) == 0)
|
||||
return list->mime_type;
|
||||
|
||||
for (ptr = file_name; *ptr != '\000'; ptr = _xdg_utf8_next_char (ptr))
|
||||
{
|
||||
if (*ptr == '.')
|
||||
{
|
||||
mime_type = (_xdg_glob_hash_node_lookup_file_name (glob_hash->simple_node, ptr, FALSE));
|
||||
if (mime_type != NULL)
|
||||
return mime_type;
|
||||
}
|
||||
}
|
||||
|
||||
for (ptr = file_name; *ptr != '\000'; ptr = _xdg_utf8_next_char (ptr))
|
||||
{
|
||||
if (*ptr == '.')
|
||||
{
|
||||
mime_type = (_xdg_glob_hash_node_lookup_file_name (glob_hash->simple_node, ptr, TRUE));
|
||||
if (mime_type != NULL)
|
||||
return mime_type;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: Not UTF-8 safe */
|
||||
for (list = glob_hash->full_list; list; list = list->next)
|
||||
if (fnmatch ((const char *)list->data, file_name, 0) == 0)
|
||||
return list->mime_type;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* XdgGlobHash
|
||||
*/
|
||||
|
||||
XdgGlobHash *
|
||||
_xdg_glob_hash_new (void)
|
||||
{
|
||||
XdgGlobHash *glob_hash;
|
||||
|
||||
glob_hash = calloc (1, sizeof (XdgGlobHash));
|
||||
|
||||
return glob_hash;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_xdg_glob_hash_free_nodes (XdgGlobHashNode *node)
|
||||
{
|
||||
|
||||
if (node->child)
|
||||
_xdg_glob_hash_free_nodes (node->child);
|
||||
if (node->next)
|
||||
_xdg_glob_hash_free_nodes (node->next);
|
||||
free (node);
|
||||
}
|
||||
|
||||
void
|
||||
_xdg_glob_hash_free (XdgGlobHash *glob_hash)
|
||||
{
|
||||
_xdg_glob_hash_free_nodes (glob_hash->simple_node);
|
||||
free (glob_hash);
|
||||
}
|
||||
|
||||
|
||||
|
||||
XdgGlobType
|
||||
_xdg_glob_determine_type (const char *glob)
|
||||
{
|
||||
const char *ptr;
|
||||
int maybe_in_simple_glob = FALSE;
|
||||
int first_char = TRUE;
|
||||
|
||||
ptr = glob;
|
||||
|
||||
while (*ptr != '\000')
|
||||
{
|
||||
if (*ptr == '*' && first_char)
|
||||
maybe_in_simple_glob = TRUE;
|
||||
else if (*ptr == '\\' || *ptr == '[' || *ptr == '?' || *ptr == '*')
|
||||
return XDG_GLOB_FULL;
|
||||
|
||||
first_char = FALSE;
|
||||
ptr = _xdg_utf8_next_char (ptr);
|
||||
}
|
||||
if (maybe_in_simple_glob)
|
||||
return XDG_GLOB_SIMPLE;
|
||||
else
|
||||
return XDG_GLOB_LITERAL;
|
||||
}
|
||||
|
||||
/* glob must be valid UTF-8 */
|
||||
void
|
||||
_xdg_glob_hash_append_glob (XdgGlobHash *glob_hash,
|
||||
const char *glob,
|
||||
const char *mime_type)
|
||||
{
|
||||
XdgGlobType type;
|
||||
|
||||
assert (glob_hash != NULL);
|
||||
assert (glob != NULL);
|
||||
|
||||
type = _xdg_glob_determine_type (glob);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case XDG_GLOB_LITERAL:
|
||||
glob_hash->literal_list = _xdg_glob_list_append (glob_hash->literal_list, strdup (glob), strdup (mime_type));
|
||||
break;
|
||||
case XDG_GLOB_SIMPLE:
|
||||
glob_hash->simple_node = _xdg_glob_hash_insert_text (glob_hash->simple_node, glob + 1, strdup (mime_type));
|
||||
break;
|
||||
case XDG_GLOB_FULL:
|
||||
glob_hash->full_list = _xdg_glob_list_append (glob_hash->full_list, strdup (glob), strdup (mime_type));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_xdg_glob_hash_dump (XdgGlobHash *glob_hash)
|
||||
{
|
||||
XdgGlobList *list;
|
||||
printf ("LITERAL STRINGS\n");
|
||||
if (glob_hash->literal_list == NULL)
|
||||
{
|
||||
printf (" None\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (list = glob_hash->literal_list; list; list = list->next)
|
||||
printf (" %s - %s\n", (char *)list->data, list->mime_type);
|
||||
}
|
||||
printf ("\nSIMPLE GLOBS\n");
|
||||
_xdg_glob_hash_node_dump (glob_hash->simple_node, 4);
|
||||
|
||||
printf ("\nFULL GLOBS\n");
|
||||
if (glob_hash->full_list == NULL)
|
||||
{
|
||||
printf (" None\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (list = glob_hash->full_list; list; list = list->next)
|
||||
printf (" %s - %s\n", (char *)list->data, list->mime_type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_xdg_mime_glob_read_from_file (XdgGlobHash *glob_hash,
|
||||
const char *file_name)
|
||||
{
|
||||
FILE *glob_file;
|
||||
char line[255];
|
||||
|
||||
glob_file = fopen (file_name, "r");
|
||||
|
||||
if (glob_file == NULL)
|
||||
return;
|
||||
|
||||
/* FIXME: Not UTF-8 safe. Doesn't work if lines are greater than 255 chars.
|
||||
* Blah */
|
||||
while (fgets (line, 255, glob_file) != NULL)
|
||||
{
|
||||
char *colon;
|
||||
if (line[0] == '#')
|
||||
continue;
|
||||
|
||||
colon = strchr (line, ':');
|
||||
if (colon == NULL)
|
||||
continue;
|
||||
*(colon++) = '\000';
|
||||
colon[strlen (colon) -1] = '\000';
|
||||
_xdg_glob_hash_append_glob (glob_hash, colon, line);
|
||||
}
|
||||
|
||||
fclose (glob_file);
|
||||
}
|
53
gtk/xdgmime/xdgmimeglob.h
Normal file
53
gtk/xdgmime/xdgmimeglob.h
Normal file
@ -0,0 +1,53 @@
|
||||
/* -*- mode: C; c-file-style: "gnu" -*- */
|
||||
/* xdgmime.h: Private file. Datastructure for storing the globs.
|
||||
*
|
||||
* More info can be found at http://www.freedesktop.org/standards/
|
||||
*
|
||||
* Copyright (C) 2003 Red Hat, Inc.
|
||||
* Copyright (C) 2003 Jonathan Blandford <jrb@alum.mit.edu>
|
||||
*
|
||||
* Licensed under the Academic Free License version 1.2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __XDG_MIME_GLOB_H__
|
||||
#define __XDG_MIME_GLOB_H__
|
||||
|
||||
|
||||
typedef struct XdgGlobHash XdgGlobHash;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
XDG_GLOB_LITERAL, /* Makefile */
|
||||
XDG_GLOB_SIMPLE, /* *.gif */
|
||||
XDG_GLOB_FULL, /* x*.[ch] */
|
||||
} XdgGlobType;
|
||||
|
||||
|
||||
void _xdg_mime_glob_read_from_file (XdgGlobHash *glob_hash,
|
||||
const char *file_name);
|
||||
XdgGlobHash *_xdg_glob_hash_new (void);
|
||||
void _xdg_glob_hash_free (XdgGlobHash *glob_hash);
|
||||
const char *_xdg_glob_hash_lookup_file_name (XdgGlobHash *glob_hash,
|
||||
const char *text);
|
||||
void _xdg_glob_hash_append_glob (XdgGlobHash *glob_hash,
|
||||
const char *glob,
|
||||
const char *mime_type);
|
||||
XdgGlobType _xdg_glob_determine_type (const char *glob);
|
||||
void _xdg_glob_hash_dump (XdgGlobHash *glob_hash);
|
||||
|
||||
#endif /* __XDG_MIME_GLOB_H__ */
|
124
gtk/xdgmime/xdgmimeint.c
Normal file
124
gtk/xdgmime/xdgmimeint.c
Normal file
@ -0,0 +1,124 @@
|
||||
|
||||
#include "xdgmimeint.h"
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE (0)
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE (!FALSE)
|
||||
#endif
|
||||
|
||||
const unsigned char utf8_skip_data[256] = {
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1
|
||||
};
|
||||
|
||||
const char * const utf8_skip = utf8_skip_data;
|
||||
|
||||
|
||||
|
||||
/* Returns the number of unprocessed characters. */
|
||||
xdg_unichar_t
|
||||
_xdg_utf8_to_ucs4(const char *source)
|
||||
{
|
||||
xdg_unichar_t ucs32;
|
||||
if( ! ( *source & 0x80 ) )
|
||||
{
|
||||
ucs32 = *source;
|
||||
}
|
||||
else
|
||||
{
|
||||
int bytelength = 0;
|
||||
xdg_unichar_t result;
|
||||
if ( ! *source & 0x40 )
|
||||
{
|
||||
ucs32 = *source;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ! *source & 0x20 )
|
||||
{
|
||||
result = *source++ & 0x1F;
|
||||
bytelength = 2;
|
||||
}
|
||||
else if ( ! *source & 0x10 )
|
||||
{
|
||||
result = *source++ & 0x0F;
|
||||
bytelength = 3;
|
||||
}
|
||||
else if ( ! *source & 0x08 )
|
||||
{
|
||||
result = *source++ & 0x07;
|
||||
bytelength = 4;
|
||||
}
|
||||
else if ( ! *source & 0x04 )
|
||||
{
|
||||
result = *source++ & 0x03;
|
||||
bytelength = 5;
|
||||
}
|
||||
else if ( ! *source & 0x02 )
|
||||
{
|
||||
result = *source++ & 0x01;
|
||||
bytelength = 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = *source++;
|
||||
bytelength = 1;
|
||||
}
|
||||
|
||||
for ( bytelength --; bytelength > 0; bytelength -- )
|
||||
{
|
||||
result <<= 6;
|
||||
result |= *source++ & 0x3F;
|
||||
}
|
||||
ucs32 = result;
|
||||
}
|
||||
}
|
||||
return ucs32;
|
||||
}
|
||||
|
||||
|
||||
/* hullo. this is great code. don't rewrite it */
|
||||
|
||||
xdg_unichar_t
|
||||
_xdg_ucs4_to_upper (xdg_unichar_t source)
|
||||
{
|
||||
/* FIXME: Do a real to_upper sometime */
|
||||
/* CaseFolding-3.2.0.txt has a table of rules. */
|
||||
if ((source & 0xFF) == source)
|
||||
return (xdg_unichar_t) toupper ((char) source);
|
||||
return source;
|
||||
}
|
||||
|
||||
int
|
||||
_xdg_utf8_validate (const char *source)
|
||||
{
|
||||
/* FIXME: actually write */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
const char *
|
||||
_xdg_get_base_name (const char *file_name)
|
||||
{
|
||||
const char *base_name;
|
||||
|
||||
if (file_name == NULL)
|
||||
return NULL;
|
||||
|
||||
base_name = strrchr (file_name, '/');
|
||||
|
||||
if (base_name == NULL)
|
||||
return file_name;
|
||||
else
|
||||
return base_name + 1;
|
||||
}
|
54
gtk/xdgmime/xdgmimeint.h
Normal file
54
gtk/xdgmime/xdgmimeint.h
Normal file
@ -0,0 +1,54 @@
|
||||
/* -*- mode: C; c-file-style: "gnu" -*- */
|
||||
/* xdgmimeint.h: Internal defines and functions.
|
||||
*
|
||||
* More info can be found at http://www.freedesktop.org/standards/
|
||||
*
|
||||
* Copyright (C) 2003 Red Hat, Inc.
|
||||
* Copyright (C) 2003 Jonathan Blandford <jrb@alum.mit.edu>
|
||||
*
|
||||
* Licensed under the Academic Free License version 1.2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __XDG_MIME_INT_H__
|
||||
#define __XDG_MIME_INT_H__
|
||||
|
||||
/* FIXME: Should be configure check */
|
||||
typedef unsigned int xdg_unichar_t;
|
||||
typedef unsigned char xdg_uchar8_t;
|
||||
typedef unsigned short xdg_uint16_t;
|
||||
typedef unsigned int xdg_uint32_t;
|
||||
|
||||
|
||||
#define SWAP_BE16_TO_LE16(val) (xdg_uint16_t)(((xdg_uint16_t)(val) << 8)|((xdg_uint16_t)(val) >> 8))
|
||||
|
||||
#define SWAP_BE32_TO_LE32(val) (xdg_uint32_t)((((xdg_uint32_t)(val) & 0xFF000000U) >> 24) | \
|
||||
(((xdg_uint32_t)(val) & 0x00FF0000U) >> 8) | \
|
||||
(((xdg_uint32_t)(val) & 0x0000FF00U) << 8) | \
|
||||
(((xdg_uint32_t)(val) & 0x000000FFU) << 24))
|
||||
/* UTF-8 utils
|
||||
*/
|
||||
const char *const utf8_skip;
|
||||
#define _xdg_utf8_next_char(p) (char *)((p) + utf8_skip[*(unsigned char *)(p)])
|
||||
#define _xdg_utf8_char_size(p) (int) (utf8_skip[*(unsigned char *)(p)])
|
||||
|
||||
xdg_unichar_t _xdg_utf8_to_ucs4 (const char *source);
|
||||
xdg_unichar_t _xdg_ucs4_to_upper (xdg_unichar_t source);
|
||||
int _xdg_utf8_validate (const char *source);
|
||||
const char *_xdg_get_base_name (const char *file_name);
|
||||
|
||||
#endif /* __XDG_MIME_INT_H__ */
|
733
gtk/xdgmime/xdgmimemagic.c
Normal file
733
gtk/xdgmime/xdgmimemagic.c
Normal file
@ -0,0 +1,733 @@
|
||||
|
||||
/* -*- mode: C; c-file-style: "gnu" -*- */
|
||||
/* xdgmimemagic.: Private file. Datastructure for storing magic.
|
||||
*
|
||||
* More info can be found at http://www.freedesktop.org/standards/
|
||||
*
|
||||
* Copyright (C) 2003 Red Hat, Inc.
|
||||
* Copyright (C) 2003 Jonathan Blandford <jrb@alum.mit.edu>
|
||||
*
|
||||
* Licensed under the Academic Free License version 1.2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xdgmimemagic.h"
|
||||
#include "xdgmimeint.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE (0)
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE (!FALSE)
|
||||
#endif
|
||||
|
||||
extern int errno;
|
||||
|
||||
typedef struct XdgMimeMagicMatch XdgMimeMagicMatch;
|
||||
typedef struct XdgMimeMagicMatchlet XdgMimeMagicMatchlet;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
XDG_MIME_MAGIC_SECTION,
|
||||
XDG_MIME_MAGIC_MAGIC,
|
||||
XDG_MIME_MAGIC_ERROR,
|
||||
XDG_MIME_MAGIC_EOF
|
||||
} XdgMimeMagicState;
|
||||
|
||||
struct XdgMimeMagicMatch
|
||||
{
|
||||
const char *mime_type;
|
||||
int priority;
|
||||
XdgMimeMagicMatchlet *matchlet;
|
||||
XdgMimeMagicMatch *next;
|
||||
};
|
||||
|
||||
|
||||
struct XdgMimeMagicMatchlet
|
||||
{
|
||||
int indent;
|
||||
int offset;
|
||||
unsigned int value_length;
|
||||
unsigned char *value;
|
||||
unsigned char *mask;
|
||||
unsigned int range_length;
|
||||
unsigned int word_size;
|
||||
XdgMimeMagicMatchlet *next;
|
||||
};
|
||||
|
||||
|
||||
struct XdgMimeMagic
|
||||
{
|
||||
XdgMimeMagicMatch *match_list;
|
||||
int max_extent;
|
||||
};
|
||||
|
||||
static XdgMimeMagicMatch *
|
||||
_xdg_mime_magic_match_new (void)
|
||||
{
|
||||
return calloc (1, sizeof (XdgMimeMagicMatch));
|
||||
}
|
||||
|
||||
|
||||
static XdgMimeMagicMatchlet *
|
||||
_xdg_mime_magic_matchlet_new (void)
|
||||
{
|
||||
XdgMimeMagicMatchlet *matchlet;
|
||||
|
||||
matchlet = malloc (sizeof (XdgMimeMagicMatchlet));
|
||||
|
||||
matchlet->indent = 0;
|
||||
matchlet->offset = 0;
|
||||
matchlet->value_length = 0;
|
||||
matchlet->value = NULL;
|
||||
matchlet->mask = NULL;
|
||||
matchlet->range_length = 1;
|
||||
matchlet->word_size = 1;
|
||||
matchlet->next = NULL;
|
||||
|
||||
return matchlet;
|
||||
}
|
||||
|
||||
void
|
||||
_xdg_mime_magic_match_free (XdgMimeMagicMatch *mime_magic_match)
|
||||
{
|
||||
if (mime_magic_match)
|
||||
{
|
||||
if (mime_magic_match->mime_type)
|
||||
free ((char *)mime_magic_match->mime_type);
|
||||
free (mime_magic_match);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_xdg_mime_magic_matchlet_free (XdgMimeMagicMatchlet *mime_magic_matchlet)
|
||||
{
|
||||
if (mime_magic_matchlet)
|
||||
{
|
||||
if (mime_magic_matchlet->next)
|
||||
_xdg_mime_magic_matchlet_free (mime_magic_matchlet->next);
|
||||
if (mime_magic_matchlet->value)
|
||||
free (mime_magic_matchlet->value);
|
||||
if (mime_magic_matchlet->mask)
|
||||
free (mime_magic_matchlet->mask);
|
||||
free (mime_magic_matchlet);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Reads in a hunk of data until a newline character or a '\000' is hit. The
|
||||
* returned string is null terminated, and doesn't include the newline.
|
||||
*/
|
||||
static unsigned char *
|
||||
_xdg_mime_magic_read_to_newline (FILE *magic_file,
|
||||
int *end_of_file)
|
||||
{
|
||||
unsigned char *retval;
|
||||
int c;
|
||||
int len, pos;
|
||||
|
||||
len = 128;
|
||||
pos = 0;
|
||||
retval = malloc (len);
|
||||
*end_of_file = FALSE;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
c = fgetc (magic_file);
|
||||
if (c == EOF)
|
||||
{
|
||||
*end_of_file = TRUE;
|
||||
break;
|
||||
}
|
||||
if (c == '\n' || c == '\000')
|
||||
break;
|
||||
retval[pos++] = (unsigned char) c;
|
||||
if (pos % 128 == 127)
|
||||
{
|
||||
len = len + 128;
|
||||
retval = realloc (retval, len);
|
||||
}
|
||||
}
|
||||
|
||||
retval[pos] = '\000';
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Returns the number read from the file, or -1 if no number could be read.
|
||||
*/
|
||||
static int
|
||||
_xdg_mime_magic_read_a_number (FILE *magic_file,
|
||||
int *end_of_file)
|
||||
{
|
||||
/* LONG_MAX is about 20 characters on my system */
|
||||
#define MAX_NUMBER_SIZE 30
|
||||
char number_string[MAX_NUMBER_SIZE];
|
||||
int pos = 0;
|
||||
int c;
|
||||
int retval = -1;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
c = fgetc (magic_file);
|
||||
|
||||
if (c == EOF)
|
||||
{
|
||||
*end_of_file = TRUE;
|
||||
break;
|
||||
}
|
||||
if (! isdigit ((char) c))
|
||||
{
|
||||
ungetc (c, magic_file);
|
||||
break;
|
||||
}
|
||||
number_string[pos] = (char) c;
|
||||
pos++;
|
||||
if (pos == MAX_NUMBER_SIZE)
|
||||
break;
|
||||
}
|
||||
if (pos > 0)
|
||||
{
|
||||
number_string[pos] = '\000';
|
||||
retval = strtol (number_string, NULL, 10);
|
||||
if ((retval == LONG_MIN || retval == LONG_MAX) &&
|
||||
(errno == ERANGE))
|
||||
return -1;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Headers are of the format:
|
||||
* [<priority>:<mime-type>]
|
||||
*/
|
||||
static XdgMimeMagicState
|
||||
_xdg_mime_magic_parse_header (FILE *magic_file, XdgMimeMagicMatch *match)
|
||||
{
|
||||
int c;
|
||||
char *buffer;
|
||||
char *end_ptr;
|
||||
int end_of_file = 0;
|
||||
|
||||
assert (magic_file);
|
||||
assert (match);
|
||||
|
||||
c = fgetc (magic_file);
|
||||
if (c == EOF)
|
||||
return XDG_MIME_MAGIC_EOF;
|
||||
if (c != '[')
|
||||
return XDG_MIME_MAGIC_ERROR;
|
||||
|
||||
match->priority = _xdg_mime_magic_read_a_number (magic_file, &end_of_file);
|
||||
if (end_of_file)
|
||||
return XDG_MIME_MAGIC_EOF;
|
||||
if (match->priority == -1)
|
||||
return XDG_MIME_MAGIC_ERROR;
|
||||
|
||||
c = fgetc (magic_file);
|
||||
if (c == EOF)
|
||||
return XDG_MIME_MAGIC_EOF;
|
||||
if (c != ':')
|
||||
return XDG_MIME_MAGIC_ERROR;
|
||||
|
||||
buffer = _xdg_mime_magic_read_to_newline (magic_file, &end_of_file);
|
||||
if (end_of_file)
|
||||
return XDG_MIME_MAGIC_EOF;
|
||||
|
||||
end_ptr = buffer;
|
||||
while (*end_ptr != ']' && *end_ptr != '\000' && *end_ptr != '\n')
|
||||
end_ptr++;
|
||||
if (*end_ptr != ']')
|
||||
{
|
||||
free (buffer);
|
||||
return XDG_MIME_MAGIC_ERROR;
|
||||
}
|
||||
*end_ptr = '\000';
|
||||
|
||||
match->mime_type = strdup (buffer);
|
||||
free (buffer);
|
||||
|
||||
return XDG_MIME_MAGIC_MAGIC;
|
||||
}
|
||||
|
||||
static XdgMimeMagicState
|
||||
_xdg_mime_magic_parse_error (FILE *magic_file)
|
||||
{
|
||||
int c;
|
||||
|
||||
while (1)
|
||||
{
|
||||
c = fgetc (magic_file);
|
||||
if (c == EOF)
|
||||
return XDG_MIME_MAGIC_EOF;
|
||||
if (c == '\n')
|
||||
return XDG_MIME_MAGIC_SECTION;
|
||||
}
|
||||
}
|
||||
|
||||
/* Headers are of the format:
|
||||
* [ indent ] ">" start-offset "=" value
|
||||
* [ "&" mask ] [ "~" word-size ] [ "+" range-length ] "\n"
|
||||
*/
|
||||
static XdgMimeMagicState
|
||||
_xdg_mime_magic_parse_magic_line (FILE *magic_file,
|
||||
XdgMimeMagicMatch *match)
|
||||
{
|
||||
XdgMimeMagicMatchlet *matchlet;
|
||||
int c;
|
||||
int end_of_file;
|
||||
int indent = 0;
|
||||
int bytes_read;
|
||||
|
||||
assert (magic_file);
|
||||
|
||||
/* Sniff the buffer to make sure it's a valid line */
|
||||
c = fgetc (magic_file);
|
||||
if (c == EOF)
|
||||
return XDG_MIME_MAGIC_EOF;
|
||||
else if (c == '[')
|
||||
{
|
||||
ungetc (c, magic_file);
|
||||
return XDG_MIME_MAGIC_SECTION;
|
||||
}
|
||||
else if (c == '\n')
|
||||
return XDG_MIME_MAGIC_MAGIC;
|
||||
|
||||
/* At this point, it must be a digit or a '>' */
|
||||
end_of_file = FALSE;
|
||||
if (isdigit (c))
|
||||
{
|
||||
ungetc (c, magic_file);
|
||||
indent = _xdg_mime_magic_read_a_number (magic_file, &end_of_file);
|
||||
if (end_of_file)
|
||||
return XDG_MIME_MAGIC_EOF;
|
||||
if (indent == -1)
|
||||
return XDG_MIME_MAGIC_ERROR;
|
||||
c = fgetc (magic_file);
|
||||
if (c == EOF)
|
||||
return XDG_MIME_MAGIC_EOF;
|
||||
}
|
||||
|
||||
if (c != '>')
|
||||
return XDG_MIME_MAGIC_ERROR;
|
||||
|
||||
matchlet = _xdg_mime_magic_matchlet_new ();
|
||||
matchlet->indent = indent;
|
||||
matchlet->offset = _xdg_mime_magic_read_a_number (magic_file, &end_of_file);
|
||||
if (end_of_file)
|
||||
{
|
||||
_xdg_mime_magic_matchlet_free (matchlet);
|
||||
return XDG_MIME_MAGIC_EOF;
|
||||
}
|
||||
if (matchlet->offset == -1)
|
||||
{
|
||||
_xdg_mime_magic_matchlet_free (matchlet);
|
||||
return XDG_MIME_MAGIC_ERROR;
|
||||
}
|
||||
c = fgetc (magic_file);
|
||||
if (c == EOF)
|
||||
{
|
||||
_xdg_mime_magic_matchlet_free (matchlet);
|
||||
return XDG_MIME_MAGIC_EOF;
|
||||
}
|
||||
else if (c != '=')
|
||||
{
|
||||
_xdg_mime_magic_matchlet_free (matchlet);
|
||||
return XDG_MIME_MAGIC_ERROR;
|
||||
}
|
||||
|
||||
/* Next two bytes determine how long the value is */
|
||||
matchlet->value_length = 0;
|
||||
c = fgetc (magic_file);
|
||||
if (c == EOF)
|
||||
{
|
||||
_xdg_mime_magic_matchlet_free (matchlet);
|
||||
return XDG_MIME_MAGIC_EOF;
|
||||
}
|
||||
matchlet->value_length = c & 0xFF;
|
||||
matchlet->value_length = matchlet->value_length << 8;
|
||||
|
||||
c = fgetc (magic_file);
|
||||
if (c == EOF)
|
||||
{
|
||||
_xdg_mime_magic_matchlet_free (matchlet);
|
||||
return XDG_MIME_MAGIC_EOF;
|
||||
}
|
||||
matchlet->value_length = matchlet->value_length + (c & 0xFF);
|
||||
|
||||
matchlet->value = malloc (matchlet->value_length);
|
||||
|
||||
/* OOM */
|
||||
if (matchlet->value == NULL)
|
||||
{
|
||||
_xdg_mime_magic_matchlet_free (matchlet);
|
||||
return XDG_MIME_MAGIC_ERROR;
|
||||
}
|
||||
bytes_read = fread (matchlet->value, 1, matchlet->value_length, magic_file);
|
||||
if (bytes_read != matchlet->value_length)
|
||||
{
|
||||
_xdg_mime_magic_matchlet_free (matchlet);
|
||||
if (feof (magic_file))
|
||||
return XDG_MIME_MAGIC_EOF;
|
||||
else
|
||||
return XDG_MIME_MAGIC_ERROR;
|
||||
}
|
||||
|
||||
c = fgetc (magic_file);
|
||||
if (c == '&')
|
||||
{
|
||||
matchlet->mask = malloc (matchlet->value_length);
|
||||
/* OOM */
|
||||
if (matchlet->mask == NULL)
|
||||
{
|
||||
_xdg_mime_magic_matchlet_free (matchlet);
|
||||
return XDG_MIME_MAGIC_ERROR;
|
||||
}
|
||||
bytes_read = fread (matchlet->mask, 1, matchlet->value_length, magic_file);
|
||||
if (bytes_read != matchlet->value_length)
|
||||
{
|
||||
_xdg_mime_magic_matchlet_free (matchlet);
|
||||
if (feof (magic_file))
|
||||
return XDG_MIME_MAGIC_EOF;
|
||||
else
|
||||
return XDG_MIME_MAGIC_ERROR;
|
||||
}
|
||||
c = fgetc (magic_file);
|
||||
}
|
||||
|
||||
if (c == '~')
|
||||
{
|
||||
matchlet->word_size = _xdg_mime_magic_read_a_number (magic_file, &end_of_file);
|
||||
if (end_of_file)
|
||||
{
|
||||
_xdg_mime_magic_matchlet_free (matchlet);
|
||||
return XDG_MIME_MAGIC_EOF;
|
||||
}
|
||||
if (matchlet->word_size != 0 &&
|
||||
matchlet->word_size != 1 &&
|
||||
matchlet->word_size != 2 &&
|
||||
matchlet->word_size != 4)
|
||||
{
|
||||
_xdg_mime_magic_matchlet_free (matchlet);
|
||||
return XDG_MIME_MAGIC_ERROR;
|
||||
}
|
||||
c = fgetc (magic_file);
|
||||
}
|
||||
|
||||
if (c == '+')
|
||||
{
|
||||
matchlet->range_length = _xdg_mime_magic_read_a_number (magic_file, &end_of_file);
|
||||
if (end_of_file)
|
||||
{
|
||||
_xdg_mime_magic_matchlet_free (matchlet);
|
||||
return XDG_MIME_MAGIC_EOF;
|
||||
}
|
||||
if (matchlet->range_length == -1)
|
||||
{
|
||||
_xdg_mime_magic_matchlet_free (matchlet);
|
||||
return XDG_MIME_MAGIC_ERROR;
|
||||
}
|
||||
c = fgetc (magic_file);
|
||||
}
|
||||
|
||||
|
||||
if (c == '\n')
|
||||
{
|
||||
/* We clean up the matchlet, byte swapping if needed */
|
||||
if (matchlet->word_size > 1)
|
||||
{
|
||||
int i;
|
||||
if (matchlet->value_length % matchlet->word_size != 0)
|
||||
{
|
||||
_xdg_mime_magic_matchlet_free (matchlet);
|
||||
return XDG_MIME_MAGIC_ERROR;
|
||||
}
|
||||
/* FIXME: need to get this defined in a <config.h> style file */
|
||||
#if LITTLE_ENDIAN
|
||||
for (i = 0; i < matchlet->value_length; i = i + matchlet->word_size)
|
||||
{
|
||||
if (matchlet->word_size == 2)
|
||||
*((xdg_uint16_t *) matchlet->value + i) = SWAP_BE16_TO_LE16 (*((xdg_uint16_t *) (matchlet->value + i)));
|
||||
else if (matchlet->word_size == 4)
|
||||
*((xdg_uint32_t *) matchlet->value + i) = SWAP_BE32_TO_LE32 (*((xdg_uint32_t *) (matchlet->value + i)));
|
||||
if (matchlet->mask)
|
||||
{
|
||||
if (matchlet->word_size == 2)
|
||||
*((xdg_uint16_t *) matchlet->mask + i) = SWAP_BE16_TO_LE16 (*((xdg_uint16_t *) (matchlet->mask + i)));
|
||||
else if (matchlet->word_size == 4)
|
||||
*((xdg_uint32_t *) matchlet->mask + i) = SWAP_BE32_TO_LE32 (*((xdg_uint32_t *) (matchlet->mask + i)));
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
matchlet->next = match->matchlet;
|
||||
match->matchlet = matchlet;
|
||||
|
||||
|
||||
return XDG_MIME_MAGIC_MAGIC;
|
||||
}
|
||||
|
||||
_xdg_mime_magic_matchlet_free (matchlet);
|
||||
if (c == EOF)
|
||||
return XDG_MIME_MAGIC_EOF;
|
||||
|
||||
return XDG_MIME_MAGIC_ERROR;
|
||||
}
|
||||
|
||||
static int
|
||||
_xdg_mime_magic_matchlet_compare_to_data (XdgMimeMagicMatchlet *matchlet,
|
||||
const void *data,
|
||||
size_t len)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = matchlet->offset; i <= matchlet->offset + matchlet->range_length; i++)
|
||||
{
|
||||
int valid_matchlet = TRUE;
|
||||
|
||||
if (i + matchlet->value_length > len)
|
||||
return FALSE;
|
||||
|
||||
if (matchlet->mask)
|
||||
{
|
||||
for (j = 0; j < matchlet->value_length; j++)
|
||||
{
|
||||
if ((matchlet->value[j] & matchlet->mask[j]) !=
|
||||
((((unsigned char *) data)[j + i]) & matchlet->mask[j]))
|
||||
{
|
||||
valid_matchlet = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (j = 0; j < matchlet->value_length; j++)
|
||||
{
|
||||
if (matchlet->value[j] != ((unsigned char *) data)[j + i])
|
||||
{
|
||||
valid_matchlet = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (valid_matchlet)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int
|
||||
_xdg_mime_magic_matchlet_compare_level (XdgMimeMagicMatchlet *matchlet,
|
||||
const void *data,
|
||||
size_t len,
|
||||
int indent)
|
||||
{
|
||||
while (matchlet != NULL && matchlet->indent == indent)
|
||||
{
|
||||
if (_xdg_mime_magic_matchlet_compare_to_data (matchlet, data, len))
|
||||
{
|
||||
if (matchlet->next == NULL ||
|
||||
matchlet->next->indent <= indent)
|
||||
return TRUE;
|
||||
|
||||
if (_xdg_mime_magic_matchlet_compare_level (matchlet->next,
|
||||
data,
|
||||
len,
|
||||
indent + 1))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
matchlet = matchlet->next;
|
||||
}
|
||||
while (matchlet && matchlet->indent > indent);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int
|
||||
_xdg_mime_magic_match_compare_to_data (XdgMimeMagicMatch *match,
|
||||
const void *data,
|
||||
size_t len)
|
||||
{
|
||||
return _xdg_mime_magic_matchlet_compare_level (match->matchlet, data, len, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
_xdg_mime_magic_insert_match (XdgMimeMagic *mime_magic,
|
||||
XdgMimeMagicMatch *match)
|
||||
{
|
||||
XdgMimeMagicMatch *list;
|
||||
|
||||
if (mime_magic->match_list == NULL)
|
||||
{
|
||||
mime_magic->match_list = match;
|
||||
return;
|
||||
}
|
||||
|
||||
if (match->priority < mime_magic->match_list->priority)
|
||||
{
|
||||
match->next = mime_magic->match_list;
|
||||
mime_magic->match_list = match;
|
||||
return;
|
||||
}
|
||||
|
||||
list = mime_magic->match_list;
|
||||
while (list->next != NULL)
|
||||
{
|
||||
if (list->next->priority > match->priority)
|
||||
{
|
||||
match->next = list->next;
|
||||
list->next = match;
|
||||
return;
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
list->next = match;
|
||||
match->next = NULL;
|
||||
}
|
||||
|
||||
XdgMimeMagic *
|
||||
_xdg_mime_magic_new (void)
|
||||
{
|
||||
return calloc (1, sizeof (XdgMimeMagic));
|
||||
}
|
||||
|
||||
void
|
||||
_xdg_mime_magic_free (XdgMimeMagic *mime_magic)
|
||||
{
|
||||
if (mime_magic)
|
||||
free (mime_magic);
|
||||
}
|
||||
|
||||
int
|
||||
_xdg_mime_magic_get_buffer_extents (XdgMimeMagic *mime_magic)
|
||||
{
|
||||
return mime_magic->max_extent;
|
||||
}
|
||||
|
||||
const char *
|
||||
_xdg_mime_magic_lookup_data (XdgMimeMagic *mime_magic,
|
||||
const void *data,
|
||||
size_t len)
|
||||
{
|
||||
XdgMimeMagicMatch *match;
|
||||
|
||||
for (match = mime_magic->match_list; match; match = match->next)
|
||||
{
|
||||
if (_xdg_mime_magic_match_compare_to_data (match, data, len))
|
||||
{
|
||||
return match->mime_type;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_xdg_mime_update_mime_magic_extents (XdgMimeMagic *mime_magic)
|
||||
{
|
||||
XdgMimeMagicMatch *match;
|
||||
int max_extent = 0;
|
||||
|
||||
for (match = mime_magic->match_list; match; match = match->next)
|
||||
{
|
||||
XdgMimeMagicMatchlet *matchlet;
|
||||
|
||||
for (matchlet = match->matchlet; matchlet; matchlet = matchlet->next)
|
||||
{
|
||||
int extent;
|
||||
|
||||
extent = matchlet->value_length + matchlet->offset + matchlet->range_length;
|
||||
if (max_extent < extent)
|
||||
max_extent = extent;
|
||||
}
|
||||
}
|
||||
|
||||
mime_magic->max_extent = max_extent;
|
||||
}
|
||||
|
||||
static void
|
||||
_xdg_mime_magic_read_magic_file (XdgMimeMagic *mime_magic,
|
||||
FILE *magic_file)
|
||||
{
|
||||
XdgMimeMagicState state;
|
||||
XdgMimeMagicMatch *match = NULL; /* Quiet compiler */
|
||||
|
||||
state = XDG_MIME_MAGIC_SECTION;
|
||||
|
||||
while (state != XDG_MIME_MAGIC_EOF)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case XDG_MIME_MAGIC_SECTION:
|
||||
match = _xdg_mime_magic_match_new ();
|
||||
state = _xdg_mime_magic_parse_header (magic_file, match);
|
||||
if (state == XDG_MIME_MAGIC_EOF || state == XDG_MIME_MAGIC_ERROR)
|
||||
_xdg_mime_magic_match_free (match);
|
||||
break;
|
||||
case XDG_MIME_MAGIC_MAGIC:
|
||||
state = _xdg_mime_magic_parse_magic_line (magic_file, match);
|
||||
if (state == XDG_MIME_MAGIC_SECTION)
|
||||
_xdg_mime_magic_insert_match (mime_magic, match);
|
||||
else if (state == XDG_MIME_MAGIC_EOF || state == XDG_MIME_MAGIC_ERROR)
|
||||
_xdg_mime_magic_match_free (match);
|
||||
break;
|
||||
case XDG_MIME_MAGIC_ERROR:
|
||||
state = _xdg_mime_magic_parse_error (magic_file);
|
||||
break;
|
||||
case XDG_MIME_MAGIC_EOF:
|
||||
default:
|
||||
/* Make the compiler happy */
|
||||
assert (0);
|
||||
}
|
||||
}
|
||||
_xdg_mime_update_mime_magic_extents (mime_magic);
|
||||
}
|
||||
|
||||
void
|
||||
_xdg_mime_magic_read_from_file (XdgMimeMagic *mime_magic,
|
||||
const char *file_name)
|
||||
{
|
||||
FILE *magic_file;
|
||||
char header[12];
|
||||
|
||||
magic_file = fopen (file_name, "r");
|
||||
|
||||
if (magic_file == NULL)
|
||||
return;
|
||||
|
||||
fread (header, 1, 12, magic_file);
|
||||
|
||||
if (memcmp ("MIME-Magic\0\n", header, 12) == 0)
|
||||
_xdg_mime_magic_read_magic_file (mime_magic, magic_file);
|
||||
fclose (magic_file);
|
||||
}
|
43
gtk/xdgmime/xdgmimemagic.h
Normal file
43
gtk/xdgmime/xdgmimemagic.h
Normal file
@ -0,0 +1,43 @@
|
||||
/* -*- mode: C; c-file-style: "gnu" -*- */
|
||||
/* xdgmimemagic.h: Private file. Datastructure for storing the globs.
|
||||
*
|
||||
* More info can be found at http://www.freedesktop.org/standards/
|
||||
*
|
||||
* Copyright (C) 2003 Red Hat, Inc.
|
||||
* Copyright (C) 2003 Jonathan Blandford <jrb@alum.mit.edu>
|
||||
*
|
||||
* Licensed under the Academic Free License version 1.2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __XDG_MIME_MAGIC_H__
|
||||
#define __XDG_MIME_MAGIC_H__
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
typedef struct XdgMimeMagic XdgMimeMagic;
|
||||
|
||||
XdgMimeMagic *_xdg_mime_magic_new (void);
|
||||
void _xdg_mime_magic_read_from_file (XdgMimeMagic *mime_magic,
|
||||
const char *file_name);
|
||||
void _xdg_mime_magic_free (XdgMimeMagic *mime_magic);
|
||||
int _xdg_mime_magic_get_buffer_extents (XdgMimeMagic *mime_magic);
|
||||
const char *_xdg_mime_magic_lookup_data (XdgMimeMagic *mime_magic,
|
||||
const void *data,
|
||||
size_t len);
|
||||
|
||||
#endif /* __XDG_MIME_MAGIC_H__ */
|
@ -56,9 +56,9 @@ main (int argc, char **argv)
|
||||
gtk_init (&argc, &argv);
|
||||
|
||||
#ifdef USE_GNOME_VFS
|
||||
file_system = _gtk_file_system_gnome_vfs_new ();
|
||||
file_system = gtk_file_system_gnome_vfs_new ();
|
||||
#else
|
||||
file_system = _gtk_file_system_unix_new ();
|
||||
file_system = gtk_file_system_unix_new ();
|
||||
#endif
|
||||
|
||||
dialog = g_object_new (GTK_TYPE_FILE_CHOOSER_DIALOG,
|
||||
|
Loading…
Reference in New Issue
Block a user