Mercurial > audlegacy
diff src/audacious/strings.c @ 2313:3149d4b1a9a9 trunk
[svn] - objective-make autodepend fixes
- move all sourcecode into src/ and adjust Makefiles accordingly
author | nenolod |
---|---|
date | Fri, 12 Jan 2007 11:43:40 -0800 |
parents | |
children | 593fd166af00 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/audacious/strings.c Fri Jan 12 11:43:40 2007 -0800 @@ -0,0 +1,384 @@ +/* Audacious + * Copyright (C) 2005-2007 Audacious development team. + * + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 2 of the License. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#define WEIRD_UTF_16_PLAYLIST_ENCODING + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#define NEED_GLADE +#include "util.h" + +#include <glib.h> +#include <glib/gi18n.h> +#include <glade/glade.h> +#include <gtk/gtk.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "platform/smartinclude.h" +#include <gdk/gdkkeysyms.h> +#include <X11/Xlib.h> +//#include <sys/ipc.h> +#include <unistd.h> +#include <errno.h> + +#ifdef HAVE_FTS_H +# include <fts.h> +#endif + +#include "glade.h" +#include "input.h" +#include "main.h" +#include "playback.h" +#include "playlist.h" +#include "ui_playlist.h" + +#ifdef USE_CHARDET + #include "../libguess/libguess.h" + #include "../librcd/librcd.h" +#ifdef HAVE_UDET + #include <libudet_c.h> +#endif +#endif + +static GQuark quark_popup_data; + + +/* + * escape_shell_chars() + * + * Escapes characters that are special to the shell inside double quotes. + */ + +gchar * +escape_shell_chars(const gchar * string) +{ + const gchar *special = "$`\"\\"; /* Characters to escape */ + const gchar *in = string; + gchar *out, *escaped; + gint num = 0; + + while (*in != '\0') + if (strchr(special, *in++)) + num++; + + escaped = g_malloc(strlen(string) + num + 1); + + in = string; + out = escaped; + + while (*in != '\0') { + if (strchr(special, *in)) + *out++ = '\\'; + *out++ = *in++; + } + *out = '\0'; + + return escaped; +} + +static gchar * +str_twenty_to_space(gchar * str) +{ + gchar *match, *match_end; + + g_return_val_if_fail(str != NULL, NULL); + + while ((match = strstr(str, "%20"))) { + match_end = match + 3; + *match++ = ' '; + while (*match_end) + *match++ = *match_end++; + *match = 0; + } + + return str; +} + +static gchar * +str_replace_char(gchar * str, gchar old, gchar new) +{ + gchar *match; + + g_return_val_if_fail(str != NULL, NULL); + + match = str; + while ((match = strchr(match, old))) + *match = new; + + return str; +} + +gchar * +str_append(gchar * str, const gchar * add_str) +{ + return str_replace(str, g_strconcat(str, add_str, NULL)); +} + +gchar * +str_replace(gchar * str, gchar * new_str) +{ + g_free(str); + return new_str; +} + +void +str_replace_in(gchar ** str, gchar * new_str) +{ + *str = str_replace(*str, new_str); +} + + +gboolean +str_has_prefix_nocase(const gchar * str, const gchar * prefix) +{ + return (strncasecmp(str, prefix, strlen(prefix)) == 0); +} + +gboolean +str_has_suffix_nocase(const gchar * str, const gchar * suffix) +{ + return (strcasecmp(str + strlen(str) - strlen(suffix), suffix) == 0); +} + +gboolean +str_has_suffixes_nocase(const gchar * str, gchar * const *suffixes) +{ + gchar *const *suffix; + + g_return_val_if_fail(str != NULL, FALSE); + g_return_val_if_fail(suffixes != NULL, FALSE); + + for (suffix = suffixes; *suffix; suffix++) + if (str_has_suffix_nocase(str, *suffix)) + return TRUE; + + return FALSE; +} + +gchar * +str_to_utf8_fallback(const gchar * str) +{ + gchar *out_str, *convert_str, *chr; + + /* NULL in NULL out */ + if (!str) + return NULL; + + convert_str = g_strdup(str); + for (chr = convert_str; *chr; chr++) { + if (*chr & 0x80) + *chr = '?'; + } + + out_str = g_strconcat(convert_str, _(" (invalid UTF-8)"), NULL); + g_free(convert_str); + + return out_str; +} + +gchar * +filename_to_utf8(const gchar * filename) +{ + gchar *out_str; + + /* NULL in NULL out */ + if (!filename) + return NULL; + + if ((out_str = g_filename_to_utf8(filename, -1, NULL, NULL, NULL))) + return out_str; + + return str_to_utf8_fallback(filename); +} + +gchar * +str_to_utf8(const gchar * str) +{ + gchar *out_str; + + /* NULL in NULL out */ + if (!str) + return NULL; + + /* Note: Currently, playlist calls this function repeatedly, even + * if the string is already converted into utf-8. + * chardet_to_utf8() would convert a valid utf-8 string into a + * different utf-8 string, if fallback encodings were supplied and + * the given string could be treated as a string in one of fallback + * encodings. To avoid this, the order of evaluation has been + * changed. (It might cause a drawback?) + */ + /* chardet encoding detector */ + if ((out_str = chardet_to_utf8(str, strlen(str), NULL, NULL, NULL))) + return out_str; + + /* already UTF-8? */ + if (g_utf8_validate(str, -1, NULL)) + return g_strdup(str); + + /* assume encoding associated with locale */ + if ((out_str = g_locale_to_utf8(str, -1, NULL, NULL, NULL))) + return out_str; + + /* all else fails, we mask off character codes >= 128, + replace with '?' */ + return str_to_utf8_fallback(str); +} + + +const gchar * +str_skip_chars(const gchar * str, const gchar * chars) +{ + while (strchr(chars, *str)) + str++; + return str; +} + +gchar * +convert_title_text(gchar * title) +{ + g_return_val_if_fail(title != NULL, NULL); + + if (cfg.convert_slash) + str_replace_char(title, '\\', '/'); + + if (cfg.convert_underscore) + str_replace_char(title, '_', ' '); + + if (cfg.convert_twenty) + str_twenty_to_space(title); + + return title; +} + +gchar *chardet_to_utf8(const gchar *str, gssize len, + gsize *arg_bytes_read, gsize *arg_bytes_write, GError **arg_error) +{ +#ifdef USE_CHARDET + char *det = NULL, *encoding = NULL; +#endif + gchar *ret = NULL; + gsize *bytes_read, *bytes_write; + GError **error; + gsize my_bytes_read, my_bytes_write; + + bytes_read = arg_bytes_read ? arg_bytes_read : &my_bytes_read; + bytes_write = arg_bytes_write ? arg_bytes_write : &my_bytes_write; + error = arg_error ? arg_error : NULL; + +#ifdef USE_CHARDET + if(cfg.chardet_detector) + det = cfg.chardet_detector; + + if(det){ + if(!strncasecmp("japanese", det, sizeof("japanese"))) { + encoding = (char *)guess_jp(str, strlen(str)); + if (!encoding) + goto fallback; + } else if(!strncasecmp("taiwanese", det, sizeof("taiwanese"))) { + encoding = (char *)guess_tw(str, strlen(str)); + if (!encoding) + goto fallback; + } else if(!strncasecmp("chinese", det, sizeof("chinese"))) { + encoding = (char *)guess_cn(str, strlen(str)); + if (!encoding) + goto fallback; + } else if(!strncasecmp("korean", det, sizeof("korean"))) { + encoding = (char *)guess_kr(str, strlen(str)); + if (!encoding) + goto fallback; + } else if(!strncasecmp("russian", det, sizeof("russian"))) { + rcd_russian_charset res = rcdGetRussianCharset(str, strlen(str)); + switch(res) { + case RUSSIAN_CHARSET_WIN: + encoding = "CP1251"; + break; + case RUSSIAN_CHARSET_ALT: + encoding = "CP866"; + break; + case RUSSIAN_CHARSET_KOI: + encoding = "KOI8-R"; + break; + case RUSSIAN_CHARSET_UTF8: + encoding = "UTF-8"; + break; + } + if (!encoding) + goto fallback; +#ifdef HAVE_UDET + } else if (!strncasecmp("universal", det, sizeof("universal"))) { + encoding = (char *)detectCharset((char *)str, strlen(str)); + if (!encoding) + goto fallback; +#endif + } else /* none, invalid */ + goto fallback; + + ret = g_convert(str, len, "UTF-8", encoding, bytes_read, bytes_write, error); + } + +fallback: +#endif + if(!ret && cfg.chardet_fallback){ + gchar **encs=NULL, **enc=NULL; + encs = g_strsplit_set(cfg.chardet_fallback, " ,:;|/", 0); + + if(encs){ + enc = encs; + for(enc=encs; *enc ; enc++){ + ret = g_convert(str, len, "UTF-8", *enc, bytes_read, bytes_write, error); + if(len == *bytes_read){ + break; + } + } + g_strfreev(encs); + } + } + +#ifdef USE_CHARDET + /* many tag libraries return 2byte latin1 utf8 character as + converted 8bit iso-8859-1 character, if they are asked to return + latin1 string. + */ + if(!ret){ + ret = g_convert(str, len, "UTF-8", "ISO-8859-1", bytes_read, bytes_write, error); + } +#endif + + if(ret){ + if(g_utf8_validate(ret, -1, NULL)) + return ret; + else { + g_free(ret); + ret = NULL; + } + } + + return NULL; /* if I have no idea, return NULL. */ +}