comparison audacious/util.c @ 2184:7d40f0a290b9 trunk

[svn] - break out string-related functions from util.c
author nenolod
date Wed, 20 Dec 2006 06:45:56 -0800
parents 299651a8f107
children 165a62fdb49e
comparison
equal deleted inserted replaced
2183:76b4dfc5f4e7 2184:7d40f0a290b9
61 #include <libudet_c.h> 61 #include <libudet_c.h>
62 #endif 62 #endif
63 #endif 63 #endif
64 64
65 static GQuark quark_popup_data; 65 static GQuark quark_popup_data;
66
67
68 /*
69 * escape_shell_chars()
70 *
71 * Escapes characters that are special to the shell inside double quotes.
72 */
73
74 gchar *
75 escape_shell_chars(const gchar * string)
76 {
77 const gchar *special = "$`\"\\"; /* Characters to escape */
78 const gchar *in = string;
79 gchar *out, *escaped;
80 gint num = 0;
81
82 while (*in != '\0')
83 if (strchr(special, *in++))
84 num++;
85
86 escaped = g_malloc(strlen(string) + num + 1);
87
88 in = string;
89 out = escaped;
90
91 while (*in != '\0') {
92 if (strchr(special, *in))
93 *out++ = '\\';
94 *out++ = *in++;
95 }
96 *out = '\0';
97
98 return escaped;
99 }
100 66
101 67
102 /* 68 /*
103 * find <file> in directory <dirname> or subdirectories. return 69 * find <file> in directory <dirname> or subdirectories. return
104 * pointer to complete filename which has to be freed by calling 70 * pointer to complete filename which has to be freed by calling
1409 } while (n > 0); 1375 } while (n > 0);
1410 1376
1411 return count; 1377 return count;
1412 } 1378 }
1413 1379
1414 static gchar *
1415 str_twenty_to_space(gchar * str)
1416 {
1417 gchar *match, *match_end;
1418
1419 g_return_val_if_fail(str != NULL, NULL);
1420
1421 while ((match = strstr(str, "%20"))) {
1422 match_end = match + 3;
1423 *match++ = ' ';
1424 while (*match_end)
1425 *match++ = *match_end++;
1426 *match = 0;
1427 }
1428
1429 return str;
1430 }
1431
1432 static gchar *
1433 str_replace_char(gchar * str, gchar old, gchar new)
1434 {
1435 gchar *match;
1436
1437 g_return_val_if_fail(str != NULL, NULL);
1438
1439 match = str;
1440 while ((match = strchr(match, old)))
1441 *match = new;
1442
1443 return str;
1444 }
1445
1446 gchar *
1447 str_append(gchar * str, const gchar * add_str)
1448 {
1449 return str_replace(str, g_strconcat(str, add_str, NULL));
1450 }
1451
1452 gchar *
1453 str_replace(gchar * str, gchar * new_str)
1454 {
1455 g_free(str);
1456 return new_str;
1457 }
1458
1459 void
1460 str_replace_in(gchar ** str, gchar * new_str)
1461 {
1462 *str = str_replace(*str, new_str);
1463 }
1464
1465
1466 gboolean
1467 str_has_prefix_nocase(const gchar * str, const gchar * prefix)
1468 {
1469 return (strncasecmp(str, prefix, strlen(prefix)) == 0);
1470 }
1471
1472 gboolean
1473 str_has_suffix_nocase(const gchar * str, const gchar * suffix)
1474 {
1475 return (strcasecmp(str + strlen(str) - strlen(suffix), suffix) == 0);
1476 }
1477
1478 gboolean
1479 str_has_suffixes_nocase(const gchar * str, gchar * const *suffixes)
1480 {
1481 gchar *const *suffix;
1482
1483 g_return_val_if_fail(str != NULL, FALSE);
1484 g_return_val_if_fail(suffixes != NULL, FALSE);
1485
1486 for (suffix = suffixes; *suffix; suffix++)
1487 if (str_has_suffix_nocase(str, *suffix))
1488 return TRUE;
1489
1490 return FALSE;
1491 }
1492
1493 gchar *
1494 str_to_utf8_fallback(const gchar * str)
1495 {
1496 gchar *out_str, *convert_str, *chr;
1497
1498 /* NULL in NULL out */
1499 if (!str)
1500 return NULL;
1501
1502 convert_str = g_strdup(str);
1503 for (chr = convert_str; *chr; chr++) {
1504 if (*chr & 0x80)
1505 *chr = '?';
1506 }
1507
1508 out_str = g_strconcat(convert_str, _(" (invalid UTF-8)"), NULL);
1509 g_free(convert_str);
1510
1511 return out_str;
1512 }
1513
1514 gchar *
1515 filename_to_utf8(const gchar * filename)
1516 {
1517 gchar *out_str;
1518
1519 /* NULL in NULL out */
1520 if (!filename)
1521 return NULL;
1522
1523 if ((out_str = g_filename_to_utf8(filename, -1, NULL, NULL, NULL)))
1524 return out_str;
1525
1526 return str_to_utf8_fallback(filename);
1527 }
1528
1529 gchar *
1530 str_to_utf8(const gchar * str)
1531 {
1532 gchar *out_str;
1533
1534 /* NULL in NULL out */
1535 if (!str)
1536 return NULL;
1537
1538 /* Note: Currently, playlist calls this function repeatedly, even
1539 * if the string is already converted into utf-8.
1540 * chardet_to_utf8() would convert a valid utf-8 string into a
1541 * different utf-8 string, if fallback encodings were supplied and
1542 * the given string could be treated as a string in one of fallback
1543 * encodings. To avoid this, the order of evaluation has been
1544 * changed. (It might cause a drawback?)
1545 */
1546 /* chardet encoding detector */
1547 if ((out_str = chardet_to_utf8(str, strlen(str), NULL, NULL, NULL)))
1548 return out_str;
1549
1550 /* already UTF-8? */
1551 if (g_utf8_validate(str, -1, NULL))
1552 return g_strdup(str);
1553
1554 /* assume encoding associated with locale */
1555 if ((out_str = g_locale_to_utf8(str, -1, NULL, NULL, NULL)))
1556 return out_str;
1557
1558 /* all else fails, we mask off character codes >= 128,
1559 replace with '?' */
1560 return str_to_utf8_fallback(str);
1561 }
1562
1563
1564 const gchar *
1565 str_skip_chars(const gchar * str, const gchar * chars)
1566 {
1567 while (strchr(chars, *str))
1568 str++;
1569 return str;
1570 }
1571
1572 gchar *
1573 convert_title_text(gchar * title)
1574 {
1575 g_return_val_if_fail(title != NULL, NULL);
1576
1577 if (cfg.convert_slash)
1578 str_replace_char(title, '\\', '/');
1579
1580 if (cfg.convert_underscore)
1581 str_replace_char(title, '_', ' ');
1582
1583 if (cfg.convert_twenty)
1584 str_twenty_to_space(title);
1585
1586 return title;
1587 }
1588
1589
1590 gboolean 1380 gboolean
1591 dir_foreach(const gchar * path, DirForeachFunc function, 1381 dir_foreach(const gchar * path, DirForeachFunc function,
1592 gpointer user_data, GError ** error) 1382 gpointer user_data, GError ** error)
1593 { 1383 {
1594 GError *error_out = NULL; 1384 GError *error_out = NULL;
1683 GtkWidget *item, *menu_; 1473 GtkWidget *item, *menu_;
1684 1474
1685 item = gtk_item_factory_get_widget(menu, item_path); 1475 item = gtk_item_factory_get_widget(menu, item_path);
1686 menu_ = gtk_item_factory_get_widget(submenu, ""); 1476 menu_ = gtk_item_factory_get_widget(submenu, "");
1687 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu_); 1477 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu_);
1688 }
1689
1690
1691 gchar *chardet_to_utf8(const gchar *str, gssize len,
1692 gsize *arg_bytes_read, gsize *arg_bytes_write, GError **arg_error)
1693 {
1694 #ifdef USE_CHARDET
1695 char *det = NULL, *encoding = NULL;
1696 #endif
1697 gchar *ret = NULL;
1698 gsize *bytes_read, *bytes_write;
1699 GError **error;
1700 gsize my_bytes_read, my_bytes_write;
1701
1702 bytes_read = arg_bytes_read ? arg_bytes_read : &my_bytes_read;
1703 bytes_write = arg_bytes_write ? arg_bytes_write : &my_bytes_write;
1704 error = arg_error ? arg_error : NULL;
1705
1706 #ifdef USE_CHARDET
1707 if(cfg.chardet_detector)
1708 det = cfg.chardet_detector;
1709
1710 if(det){
1711 if(!strncasecmp("japanese", det, sizeof("japanese"))) {
1712 encoding = (char *)guess_jp(str, strlen(str));
1713 if (!encoding)
1714 goto fallback;
1715 } else if(!strncasecmp("taiwanese", det, sizeof("taiwanese"))) {
1716 encoding = (char *)guess_tw(str, strlen(str));
1717 if (!encoding)
1718 goto fallback;
1719 } else if(!strncasecmp("chinese", det, sizeof("chinese"))) {
1720 encoding = (char *)guess_cn(str, strlen(str));
1721 if (!encoding)
1722 goto fallback;
1723 } else if(!strncasecmp("korean", det, sizeof("korean"))) {
1724 encoding = (char *)guess_kr(str, strlen(str));
1725 if (!encoding)
1726 goto fallback;
1727 } else if(!strncasecmp("russian", det, sizeof("russian"))) {
1728 rcd_russian_charset res = rcdGetRussianCharset(str, strlen(str));
1729 switch(res) {
1730 case RUSSIAN_CHARSET_WIN:
1731 encoding = "CP1251";
1732 break;
1733 case RUSSIAN_CHARSET_ALT:
1734 encoding = "CP866";
1735 break;
1736 case RUSSIAN_CHARSET_KOI:
1737 encoding = "KOI8-R";
1738 break;
1739 case RUSSIAN_CHARSET_UTF8:
1740 encoding = "UTF-8";
1741 break;
1742 }
1743 if (!encoding)
1744 goto fallback;
1745 #ifdef HAVE_UDET
1746 } else if (!strncasecmp("universal", det, sizeof("universal"))) {
1747 encoding = (char *)detectCharset((char *)str, strlen(str));
1748 if (!encoding)
1749 goto fallback;
1750 #endif
1751 } else /* none, invalid */
1752 goto fallback;
1753
1754 ret = g_convert(str, len, "UTF-8", encoding, bytes_read, bytes_write, error);
1755 }
1756
1757 fallback:
1758 #endif
1759 if(!ret && cfg.chardet_fallback){
1760 gchar **encs=NULL, **enc=NULL;
1761 encs = g_strsplit_set(cfg.chardet_fallback, " ,:;|/", 0);
1762
1763 if(encs){
1764 enc = encs;
1765 for(enc=encs; *enc ; enc++){
1766 ret = g_convert(str, len, "UTF-8", *enc, bytes_read, bytes_write, error);
1767 if(len == *bytes_read){
1768 break;
1769 }
1770 }
1771 g_strfreev(encs);
1772 }
1773 }
1774
1775 #ifdef USE_CHARDET
1776 /* many tag libraries return 2byte latin1 utf8 character as
1777 converted 8bit iso-8859-1 character, if they are asked to return
1778 latin1 string.
1779 */
1780 if(!ret){
1781 ret = g_convert(str, len, "UTF-8", "ISO-8859-1", bytes_read, bytes_write, error);
1782 }
1783 #endif
1784
1785 if(ret){
1786 if(g_utf8_validate(ret, -1, NULL))
1787 return ret;
1788 else {
1789 g_free(ret);
1790 ret = NULL;
1791 }
1792 }
1793
1794 return NULL; /* if I have no idea, return NULL. */
1795 } 1478 }
1796 1479
1797 /* 1480 /*
1798 * Resizes a GDK pixmap. 1481 * Resizes a GDK pixmap.
1799 */ 1482 */