330 lines
8.6 KiB
C
330 lines
8.6 KiB
C
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
|
|
/* Copyright (C) 1998 Redhat Software Inc.
|
|
* Authors: Jonathan Blandford <jrb@redhat.com>
|
|
*/
|
|
#include <config.h>
|
|
#include "capplet-widget.h"
|
|
#include "gnome.h"
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <dirent.h>
|
|
#include <regex.h>
|
|
#include <ctype.h>
|
|
#include "edit-window.h"
|
|
#include "mime-data.h"
|
|
#include "mime-info.h"
|
|
/* Prototypes */
|
|
static void mime_fill_from_file (const char *filename);
|
|
static void mime_load_from_dir (const char *mime_info_dir, gboolean system_dir);
|
|
static void add_to_key (char *mime_type, char *def);
|
|
static char *get_priority (char *def, int *priority);
|
|
|
|
|
|
/* Global variables */
|
|
static char *current_lang;
|
|
static GHashTable *mime_types = NULL;
|
|
static GtkWidget *clist = NULL;
|
|
|
|
/* Initialization functions */
|
|
static char *
|
|
get_priority (char *def, int *priority)
|
|
{
|
|
*priority = 0;
|
|
|
|
if (*def == ','){
|
|
def++;
|
|
if (*def == '1'){
|
|
*priority = 0;
|
|
def++;
|
|
} else if (*def == '2'){
|
|
*priority = 1;
|
|
def++;
|
|
}
|
|
}
|
|
|
|
while (*def && *def == ':')
|
|
def++;
|
|
|
|
return def;
|
|
}
|
|
static void
|
|
add_to_key (char *mime_type, char *def)
|
|
{
|
|
int priority = 1;
|
|
char *s, *p, *ext;
|
|
int used;
|
|
MimeInfo *info;
|
|
|
|
info = g_hash_table_lookup (mime_types, (const void *) mime_type);
|
|
if (info == NULL) {
|
|
info = g_malloc (sizeof (MimeInfo));
|
|
info->mime_type = g_strdup (mime_type);
|
|
info->regex[0] = NULL;
|
|
info->regex[1] = NULL;
|
|
info->ext[0] = NULL;
|
|
info->ext[1] = NULL;
|
|
info->regex_readable[0] = NULL;
|
|
info->regex_readable[1] = NULL;
|
|
info->ext_readable[0] = NULL;
|
|
info->ext_readable[1] = NULL;
|
|
info->keys = gnome_mime_get_keys (mime_type);
|
|
g_hash_table_insert (mime_types, mime_type, info);
|
|
}
|
|
if (strncmp (def, "ext", 3) == 0){
|
|
char *tokp;
|
|
|
|
def += 3;
|
|
def = get_priority (def, &priority);
|
|
s = p = g_strdup (def);
|
|
|
|
used = 0;
|
|
|
|
while ((ext = strtok_r (s, " \t\n\r,", &tokp)) != NULL){
|
|
/* FIXME: We really need to check for duplicates before entering this. */
|
|
info->ext[priority] = g_list_prepend (info->ext[priority], ext);
|
|
used = 1;
|
|
s = NULL;
|
|
}
|
|
if (!used)
|
|
g_free (p);
|
|
}
|
|
|
|
if (strncmp (def, "regex", 5) == 0){
|
|
regex_t *regex;
|
|
|
|
regex = g_new (regex_t, 1);
|
|
def += 5;
|
|
def = get_priority (def, &priority);
|
|
|
|
while (*def && isspace (*def))
|
|
def++;
|
|
|
|
if (!*def)
|
|
return;
|
|
if (regcomp (regex, def, REG_EXTENDED | REG_NOSUB))
|
|
g_free (regex);
|
|
else {
|
|
info->regex[priority] = regex;
|
|
g_free (info->regex_readable[priority]);
|
|
info->regex_readable[priority] = g_strdup (def);
|
|
}
|
|
}
|
|
}
|
|
static void
|
|
mime_fill_from_file (const char *filename)
|
|
{
|
|
FILE *f;
|
|
char buf [1024];
|
|
char *current_key;
|
|
gboolean used;
|
|
|
|
g_assert (filename != NULL);
|
|
|
|
f = fopen (filename, "r");
|
|
if (!f)
|
|
return;
|
|
|
|
current_key = NULL;
|
|
used = FALSE;
|
|
while (fgets (buf, sizeof (buf), f)){
|
|
char *p;
|
|
|
|
if (buf [0] == '#')
|
|
continue;
|
|
|
|
/* Trim trailing spaces */
|
|
for (p = buf + strlen (buf) - 1; p >= buf; p--){
|
|
if (isspace (*p) || *p == '\n')
|
|
*p = 0;
|
|
else
|
|
break;
|
|
}
|
|
|
|
if (!buf [0])
|
|
continue;
|
|
|
|
if (buf [0] == '\t' || buf [0] == ' '){
|
|
if (current_key){
|
|
char *p = buf;
|
|
|
|
while (*p && isspace (*p))
|
|
p++;
|
|
|
|
if (*p == 0)
|
|
continue;
|
|
|
|
add_to_key (current_key, p);
|
|
used = TRUE;
|
|
}
|
|
} else {
|
|
if (!used && current_key)
|
|
g_free (current_key);
|
|
current_key = g_strdup (buf);
|
|
if (current_key [strlen (current_key)-1] == ':')
|
|
current_key [strlen (current_key)-1] = 0;
|
|
|
|
used = FALSE;
|
|
}
|
|
}
|
|
fclose (f);
|
|
}
|
|
|
|
static void
|
|
mime_load_from_dir (const char *mime_info_dir, gboolean system_dir)
|
|
{
|
|
DIR *dir;
|
|
struct dirent *dent;
|
|
const int extlen = sizeof (".mime") - 1;
|
|
char *filename;
|
|
|
|
dir = opendir (mime_info_dir);
|
|
if (!dir)
|
|
return;
|
|
if (system_dir) {
|
|
filename = g_concat_dir_and_file (mime_info_dir, "gnome.mime");
|
|
mime_fill_from_file (filename);
|
|
g_free (filename);
|
|
}
|
|
while ((dent = readdir (dir)) != NULL){
|
|
|
|
int len = strlen (dent->d_name);
|
|
|
|
if (len <= extlen)
|
|
continue;
|
|
|
|
if (strcmp (dent->d_name + len - extlen, ".mime"))
|
|
continue;
|
|
if (system_dir && !strcmp (dent->d_name, "gnome.mime"))
|
|
continue;
|
|
if (!system_dir && !strcmp (dent->d_name, "user.mime"))
|
|
continue;
|
|
|
|
filename = g_concat_dir_and_file (mime_info_dir, dent->d_name);
|
|
mime_fill_from_file (filename);
|
|
g_free (filename);
|
|
}
|
|
if (!system_dir) {
|
|
filename = g_concat_dir_and_file (mime_info_dir, "user.mime");
|
|
mime_fill_from_file (filename);
|
|
g_free (filename);
|
|
}
|
|
closedir (dir);
|
|
}
|
|
static void
|
|
add_mime_vals_to_clist (gchar *mime_type, gpointer mi, gpointer cl)
|
|
{
|
|
/* we also finalize the MimeInfo structure here, now that we're done
|
|
* loading it */
|
|
static gchar *text[2];
|
|
GList *list;
|
|
GString *extension;
|
|
gint row;
|
|
|
|
extension = g_string_new ("");
|
|
for (list = ((MimeInfo *) mi)->ext[0];list; list=list->next) {
|
|
g_string_append (extension, (gchar *) list->data);
|
|
if (list->next != NULL)
|
|
g_string_append (extension, ", ");
|
|
}
|
|
((MimeInfo *) mi)->ext_readable[0] = extension->str;
|
|
g_string_free (extension, FALSE);
|
|
|
|
extension = g_string_new ("");
|
|
for (list = ((MimeInfo *) mi)->ext[1];list; list=list->next) {
|
|
g_string_append (extension, (gchar *) list->data);
|
|
if (list->next)
|
|
g_string_append (extension, ", ");
|
|
}
|
|
((MimeInfo *) mi)->ext_readable[1] = extension->str;
|
|
g_string_free (extension, FALSE);
|
|
|
|
if (((MimeInfo *) mi)->ext[0]) {
|
|
extension = g_string_new ((((MimeInfo *) mi)->ext_readable[0]));
|
|
if (((MimeInfo *) mi)->ext[1]) {
|
|
g_string_append (extension, ", ");
|
|
g_string_append (extension, (((MimeInfo *) mi)->ext_readable[1]));
|
|
}
|
|
} else if (((MimeInfo *) mi)->ext[1])
|
|
extension = g_string_new ((((MimeInfo *) mi)->ext_readable[1]));
|
|
else
|
|
extension = g_string_new ("");
|
|
|
|
text[0] = ((MimeInfo *) mi)->mime_type;
|
|
text[1] = extension->str;
|
|
|
|
row = gtk_clist_insert (GTK_CLIST (cl), 1, text);
|
|
gtk_clist_set_row_data (GTK_CLIST (cl), row, mi);
|
|
g_string_free (extension, TRUE);
|
|
}
|
|
|
|
static void
|
|
selected_row_callback (GtkWidget *widget, gint row, gint column, GdkEvent *event, gpointer data)
|
|
{
|
|
MimeInfo *mi;
|
|
if (column < 0)
|
|
return;
|
|
|
|
mi = (MimeInfo *) gtk_clist_get_row_data (GTK_CLIST (widget),row);
|
|
|
|
if (event && event->type == GDK_2BUTTON_PRESS)
|
|
launch_edit_window (mi);
|
|
}
|
|
|
|
/* public functions */
|
|
void
|
|
edit_clicked ()
|
|
{
|
|
MimeInfo *mi;
|
|
gint row = 0;
|
|
|
|
if (GTK_CLIST (clist)->selection)
|
|
row = GPOINTER_TO_INT ((GTK_CLIST (clist)->selection)->data);
|
|
else
|
|
return;
|
|
mi = (MimeInfo *) gtk_clist_get_row_data (GTK_CLIST (clist), row);
|
|
if (mi)
|
|
launch_edit_window (mi);
|
|
}
|
|
|
|
GtkWidget *
|
|
get_mime_clist (void)
|
|
{
|
|
GtkWidget *retval;
|
|
gchar *titles[2];
|
|
|
|
titles[0] = "Mime Type";
|
|
titles[1] = "Extension";
|
|
retval = gtk_scrolled_window_new (NULL, NULL);
|
|
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (retval),
|
|
GTK_POLICY_AUTOMATIC,
|
|
GTK_POLICY_AUTOMATIC);
|
|
clist = gtk_clist_new_with_titles (2, titles);
|
|
gtk_signal_connect (GTK_OBJECT (clist),
|
|
"select_row",
|
|
GTK_SIGNAL_FUNC (selected_row_callback),
|
|
NULL);
|
|
gtk_clist_set_selection_mode (GTK_CLIST (clist), GTK_SELECTION_BROWSE);
|
|
gtk_clist_set_auto_sort (GTK_CLIST (clist), TRUE);
|
|
if (clist)
|
|
g_hash_table_foreach (mime_types, (GHFunc) add_mime_vals_to_clist, clist);
|
|
gtk_clist_columns_autosize (GTK_CLIST (clist));
|
|
gtk_clist_select_row (GTK_CLIST (clist), 0, 0);
|
|
gtk_container_add (GTK_CONTAINER (retval), clist);
|
|
return retval;
|
|
}
|
|
void
|
|
init_mime_type (void)
|
|
{
|
|
char *mime_info_dir;
|
|
|
|
mime_types = g_hash_table_new (g_str_hash, g_str_equal);
|
|
|
|
mime_info_dir = gnome_unconditional_datadir_file ("mime-info");
|
|
mime_load_from_dir (mime_info_dir, TRUE);
|
|
g_free (mime_info_dir);
|
|
|
|
mime_info_dir = g_concat_dir_and_file (gnome_util_user_home (), ".gnome/mime-info");
|
|
mime_load_from_dir (mime_info_dir, FALSE);
|
|
g_free (mime_info_dir);
|
|
init_mime_info ();
|
|
}
|