⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xdgmimeglob.c

📁 台湾人开发的Linux下的文件管理器
💻 C
字号:
/* -*- mode: C; c-file-style: "gnu" -*- *//* xdgmimeglob.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 2.0 * Or under the following terms: * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */#ifdef HAVE_CONFIG_H#include <config.h>#endif#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)#endiftypedef 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;}/* Frees glob_list and all of it's children */static void_xdg_glob_list_free ( XdgGlobList *glob_list ){    XdgGlobList * ptr, *next;    ptr = glob_list;    while ( ptr != NULL )    {        next = ptr->next;        if ( ptr->data )            free ( ( void * ) ptr->data );        if ( ptr->mime_type )            free ( ( void * ) ptr->mime_type );        free ( ptr );        ptr = next;    }}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 0static 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 0static 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 );}#endifstatic 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' )    {        if ( node->mime_type )        {            if ( strcmp ( node->mime_type, mime_type ) )            {                XdgGlobHashNode * child;                int found_node = FALSE;                child = node->child;                while ( child && child->character == '\0' )                {                    if ( strcmp ( child->mime_type, mime_type ) == 0 )                    {                        found_node = TRUE;                        break;                    }                    child = child->next;                }                if ( !found_node )                {                    child = _xdg_glob_hash_node_new ();                    child->character = '\000';                    child->mime_type = strdup( mime_type );                    child->child = NULL;                    child->next = node->child;                    node->child = child;                }            }        }        else        {            node->mime_type = strdup( mime_type );        }    }    else    {        node->child = _xdg_glob_hash_insert_text ( node->child, text, mime_type );    }    return glob_hash_node;}static int_xdg_glob_hash_node_lookup_file_name ( XdgGlobHashNode *glob_hash_node,                                       const char *file_name,                                       int ignore_case,                                       const char *mime_types[],                                       int n_mime_types ){    int n;    XdgGlobHashNode *node;    xdg_unichar_t character;    if ( glob_hash_node == NULL )        return 0;    character = _xdg_utf8_to_ucs4 ( file_name );    if ( ignore_case )        character = _xdg_ucs4_to_lower( character );    for ( node = glob_hash_node; node && character >= node->character; node = node->next )    {        if ( character == node->character )        {            file_name = _xdg_utf8_next_char ( file_name );            if ( *file_name == '\000' )            {                n = 0;                mime_types[ n++ ] = node->mime_type;                node = node->child;                while ( n < n_mime_types && node && node->character == 0 )                {                    mime_types[ n++ ] = node->mime_type;                    node = node->next;                }            }            else            {                n = _xdg_glob_hash_node_lookup_file_name ( node->child,                                                           file_name,                                                           ignore_case,                                                           mime_types,                                                           n_mime_types );            }            return n;        }    }    return 0;}int_xdg_glob_hash_lookup_file_name ( XdgGlobHash *glob_hash,                                  const char *file_name,                                  const char *mime_types[],                                  int n_mime_types ){    XdgGlobList * list;    const char *ptr;    char stopchars[ 128 ];    int i, n;    XdgGlobHashNode *node;    /* First, check the literals */    assert ( file_name != NULL && n_mime_types > 0 );    for ( list = glob_hash->literal_list; list; list = list->next )    {        if ( strcmp ( ( const char * ) list->data, file_name ) == 0 )        {            mime_types[ 0 ] = list->mime_type;            return 1;        }    }    i = 0;    for ( node = glob_hash->simple_node; node; node = node->next )    {        if ( node->character < 128 )            stopchars[ i++ ] = ( char ) node->character;    }    stopchars[ i ] = '\0';    ptr = strpbrk ( file_name, stopchars );    while ( ptr )    {        n = _xdg_glob_hash_node_lookup_file_name ( glob_hash->simple_node, ptr, FALSE,                                                   mime_types, n_mime_types );        if ( n > 0 )            return n;        n = _xdg_glob_hash_node_lookup_file_name ( glob_hash->simple_node, ptr, TRUE,                                                   mime_types, n_mime_types );        if ( n > 0 )            return n;        ptr = strpbrk ( ptr + 1, stopchars );    }    /* FIXME: Not UTF-8 safe */    n = 0;    for ( list = glob_hash->full_list; list && n < n_mime_types; list = list->next )    {        if ( fnmatch ( ( const char * ) list->data, file_name, 0 ) == 0 )            mime_types[ n++ ] = list->mime_type;    }    return n;}/* 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 )    {        if ( node->child )            _xdg_glob_hash_free_nodes ( node->child );        if ( node->next )            _xdg_glob_hash_free_nodes ( node->next );        if ( node->mime_type )            free ( ( void * ) node->mime_type );        free ( node );    }}void_xdg_glob_hash_free ( XdgGlobHash *glob_hash ){    _xdg_glob_list_free ( glob_hash->literal_list );    _xdg_glob_list_free ( glob_hash->full_list );    _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, 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;    }}#if 0void_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 );    }}#endifvoid_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 );    /* Add some missing but frequently seen globs */    glob_hash->simple_node = _xdg_glob_hash_insert_text ( glob_hash->simple_node,                                                          ".dll", "application/x-ms-dos-executable" );    glob_hash->simple_node = _xdg_glob_hash_insert_text ( glob_hash->simple_node,                                                          ".ini", XDG_MIME_TYPE_PLAIN_TEXT );}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -