From 7d645ccc5300e04d2398965b077371b323149336 Mon Sep 17 00:00:00 2001 From: axel Date: Tue, 24 Jan 2006 01:45:00 +1000 Subject: [PATCH] Use gettext to translate mimedb command. Also try to respect users locale setting when choosing language on file descriptions. darcs-hash:20060123154500-ac50b-2a2eb9c24f41d2bbe05fc4c40dca31aaaca71979.gz --- mimedb.c | 189 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 165 insertions(+), 24 deletions(-) diff --git a/mimedb.c b/mimedb.c index bd3b75ec2..a77f1a06b 100644 --- a/mimedb.c +++ b/mimedb.c @@ -30,11 +30,18 @@ license. Read the source code of the library for more information. #include #include #include +#include +#include + #ifdef HAVE_GETOPT_H #include #endif +#if HAVE_LIBINTL_H +#include +#endif + #include "xdgmime.h" #include "util.h" @@ -53,20 +60,30 @@ license. Read the source code of the library for more information. #define MIME_SUFFIX ".xml" /** - Start tag for comment + Start tag for langauge-specific comment */ -#define START_TAG "" +#define START_TAG "" /** End tab for comment */ -#define STOP_TAG "" +#define STOP_TAG "" /** File contains cached list of mime actions */ #define DESKTOP_DEFAULT "applications/defaults.list" +/** + Size for temporary string buffer used to make a regex for language + specific descriptions +*/ +#define BUFF_SIZE 1024 + +/* + Program name +*/ +#define MIMEDB "mimedb" /** All types of input and output possible @@ -82,6 +99,8 @@ enum } ; +static regex_t *start_re=0, *stop_re=0; + /** Error flag. Non-zero if something bad happened. */ @@ -101,6 +120,12 @@ static int launch_len=0; */ static int launch_pos=0; +#if HAVE_GETTEXT +#define _(string) gettext(string) +#else +#define _(string) (string) +#endif + /** Dynamically generated function, made from the documentation in doc_src. */ @@ -115,7 +140,7 @@ void *my_malloc( size_t s ) if( !s ) { error=1; - fprintf( stderr, "mimedb: Out of memory\n" ); + fprintf( stderr, _("%s: Out of memory\n"), MIMEDB ); } return res; } @@ -129,7 +154,7 @@ char *my_strdup( char *s ) if( !s ) { error=1; - fprintf( stderr, "mimedb: Out of memory\n" ); + fprintf( stderr, _("%s: Out of memory\n"), MIMEDB ); } return res; } @@ -364,11 +389,56 @@ static char *munge( char *in ) } in++; } - fprintf( stderr, "mimedb: Unknown error in munge()\n" ); + fprintf( stderr, _( "%s: Unknown error in munge()\n"), MIMEDB ); error=1; return 0; } +/** + Return a regular expression that matches all strings specifying the current locale +*/ +static char *get_lang_re() +{ + + static char buff[BUFF_SIZE]; + const char *lang = setlocale( LC_MESSAGES, 0 ); + int close=0; + char *out=buff; + + if( (1+strlen(lang)*4) >= BUFF_SIZE ) + { + fprintf( stderr, _( "%s: Locale string too long\n"), MIMEDB ); + error = 1; + return 0; + } + + for( ; *lang; lang++ ) + { + switch( *lang ) + { + case '@': + case '.': + case '_': + if( close ) + *out++ = ')'; + + close=1; + *out++ = '('; + *out++ = '|'; + *out++ = *lang; + break; + + default: + *out++ = *lang; + } + } + + if( close ) + *out++ = ')'; + *out++=0; + return buff; +} + /** Get description for a specified mimetype. */ @@ -380,8 +450,36 @@ static char *get_description( const char *mimetype ) int fd; struct stat st; char *contents; - char *start, *stop; + char *start=0, *stop=0; + if( !start_re ) + { + char *lang; + char buff[BUFF_SIZE]; + + lang = get_lang_re(); + if( !lang ) + return 0; + + snprintf( buff, BUFF_SIZE, START_TAG, lang, lang ); + + start_re = my_malloc( sizeof(regex_t)); + stop_re = my_malloc( sizeof(regex_t)); + + if( regcomp( start_re, buff, REG_EXTENDED ) || + regcomp( stop_re, STOP_TAG, REG_EXTENDED ) ) + { + fprintf( stderr, _( "%s: Could not compile regular expressions\n"), MIMEDB ); + error=1; + + free( start_re ); + free( stop_re ); + start_re = stop_re = 0; + + return 0; + } + } + fn_part = my_malloc( strlen(MIME_DIR) + strlen( mimetype) + strlen(MIME_SUFFIX) + 1 ); if( !fn_part ) @@ -436,15 +534,40 @@ static char *get_description( const char *mimetype ) free( fn ); contents[st.st_size]=0; - - start = strstr( contents, START_TAG ); - if( start ) + regmatch_t match[1]; + int w = -1; + + start=contents; + + /* + On multiple matches, use the longest match, should be a pretty + good heuristic for best match... + */ + while( !regexec(start_re, start, 1, match, 0) ) { - start += strlen(START_TAG); - stop = strstr( start, STOP_TAG ); - if( stop ) + int new_w = match[0].rm_eo - match[0].rm_so; + + if( new_w > w ) { + /* + New match is for a longer match then the previous + match, so we use the new match + */ + w=new_w; + start += match[0].rm_eo; + } + } + + if( w != -1 ) + { + if( !regexec(stop_re, start, 1, match, 0) ) + { + /* + We've found the beginning and the end of a suitable description + */ char *res; + + stop = start + match[0].rm_so; *stop = '\0'; res = munge( start ); free( contents ); @@ -452,7 +575,7 @@ static char *get_description( const char *mimetype ) } } free( contents ); - fprintf( stderr, "mimedb: No description for type %s\n", mimetype ); + fprintf( stderr, _( "%s: No description for type %s\n"), MIMEDB, mimetype ); error=1; return 0; @@ -516,7 +639,7 @@ static char *get_action( const char *mimetype ) if( !launcher ) { - fprintf( stderr, "Could not parse launcher string %s\n", launcher_str ); + fprintf( stderr, _("%s: Could not parse launcher string '%s'\n"), MIMEDB, launcher_str ); error=1; return 0; } @@ -549,7 +672,7 @@ static char *get_action( const char *mimetype ) if( !launcher_command_str ) { fprintf( stderr, - "mimedb: Default launcher %s does not specify how to start\n", + _( "%s: Default launcher '%s' does not specify how to start\n"), MIMEDB, launcher_filename ); free( launcher_filename ); return 0; @@ -929,7 +1052,7 @@ static void launch( char *filter, array_list_t *files, int fileno ) } default: - fprintf( stderr, "Unsupported switch %c in launch string %s\n", *filter, filter_org ); + fprintf( stderr, _("%s: Unsupported switch '%c' in launch string '%s'\n"), MIMEDB, *filter, filter_org ); launch_len=0; break; @@ -950,7 +1073,7 @@ static void launch( char *filter, array_list_t *files, int fileno ) case -1: { launch_len = 0; - fprintf( stderr, "mimedb: Out of memory\n" ); + fprintf( stderr, _( "%s: Out of memory\n"), MIMEDB ); return; } case 0: @@ -996,6 +1119,15 @@ static void clear_entry( const void *key, const void *val ) } +static void locale_init() +{ + setlocale( LC_ALL, "" ); +#if HAVE_GETTEXT + bindtextdomain( PACKAGE_NAME, LOCALEDIR ); + textdomain( PACKAGE_NAME ); +#endif +} + /** Main function. Parses options and calls helper function for any heavy lifting. @@ -1011,8 +1143,9 @@ int main (int argc, char *argv[]) int i; hash_table_t launch_hash; - + locale_init(); + /* Parse options */ @@ -1118,7 +1251,7 @@ int main (int argc, char *argv[]) exit(0); case 'v': - printf( "mimedb, version %s\n", PACKAGE_VERSION ); + printf( _("%s, version %s\n"), MIMEDB, PACKAGE_VERSION ); exit( 0 ); case '?': @@ -1129,7 +1262,7 @@ int main (int argc, char *argv[]) if( ( output_type == LAUNCH )&&(input_type==MIMETYPE)) { - fprintf( stderr, "Can not launch a mimetype\n" ); + fprintf( stderr, _("%s: Can not launch a mimetype\n"), MIMEDB ); print_help(); exit(1); } @@ -1161,7 +1294,7 @@ int main (int argc, char *argv[]) mimetype = xdg_mime_unalias_mime_type (mimetype); if( !mimetype ) { - fprintf( stderr, "mimedb: Could not parse mimetype from argument %s\n", argv[i] ); + fprintf( stderr, _( "%s: Could not parse mimetype from argument '%s'\n"), MIMEDB, argv[i] ); error=1; return 1; } @@ -1227,7 +1360,7 @@ int main (int argc, char *argv[]) /* Perform the actual launching */ - if( output_type == LAUNCH ) + if( output_type == LAUNCH && !error ) { int i; array_list_t mimes; @@ -1239,7 +1372,7 @@ int main (int argc, char *argv[]) array_list_t *files = (array_list_t *)hash_get( &launch_hash, mimetype ); if( !files ) { - fprintf( stderr, "mimedb: Unknown error\n" ); + fprintf( stderr, _( "%s: Unknown error\n"), MIMEDB ); error=1; break; } @@ -1260,6 +1393,14 @@ int main (int argc, char *argv[]) if( launch_buff ) free( launch_buff ); + if( start_re ) + { + regfree( start_re ); + regfree( stop_re ); + free( start_re ); + free( stop_re ); + } + xdg_mime_shutdown(); return error;