From 911229f29ebec95e5f0576f303c670e59889f295 Mon Sep 17 00:00:00 2001 From: Thomas Leonard Date: Thu, 17 Jan 2002 14:09:14 +0000 Subject: [PATCH] r1101: Big changes to internationalisation for pinboards and panels to fix problems with incompatible character sets (reported by Arnaud Calvo). --- ROX-Filer/Help/Changes | 5 + ROX-Filer/Help/TODO | 4 +- ROX-Filer/src/Makefile.in | 26 ++-- ROX-Filer/src/gconvert.c | 300 ++++++++++++++++++++++++++++++++++++++++++++++ ROX-Filer/src/gconvert.h | 123 +++++++++++++++++++ ROX-Filer/src/gunicode.h | 280 +++++++++++++++++++++++++++++++++++++++++++ ROX-Filer/src/panel.c | 32 ++++- ROX-Filer/src/pinboard.c | 31 ++++- ROX-Filer/src/support.c | 29 +++++ ROX-Filer/src/support.h | 2 + 10 files changed, 810 insertions(+), 22 deletions(-) create mode 100644 ROX-Filer/src/gconvert.c create mode 100644 ROX-Filer/src/gconvert.h create mode 100644 ROX-Filer/src/gunicode.h diff --git a/ROX-Filer/Help/Changes b/ROX-Filer/Help/Changes index 3eb6d02a..e57b99d1 100644 --- a/ROX-Filer/Help/Changes +++ b/ROX-Filer/Help/Changes @@ -2,6 +2,11 @@ A RISC OS-like filer for X by Thomas Leonard +17-Jan-2001 +~~~~~~~~~~~ +Big changes to internationalisation for pinboards and panels to fix problems +with incompatible character sets (reported by Arnaud Calvo). + 16-Jan-2001 ~~~~~~~~~~~ Converter for old-format config files now stops if the file looks like diff --git a/ROX-Filer/Help/TODO b/ROX-Filer/Help/TODO index 9d223e8d..19ab61b6 100644 --- a/ROX-Filer/Help/TODO +++ b/ROX-Filer/Help/TODO @@ -32,6 +32,8 @@ Gtk+ 2.0: - Action window log doesn't scroll properly (GTK bugs?) - Spawning shell scripts sometimes gives Bad Address (glib bug) +FEATURES FOR 1.3 + Rescanning sometimes causes the display to scroll (automounter problem). Panel sometimes won't accept drops: @@ -39,8 +41,6 @@ Panel sometimes won't accept drops: - Start sawfish. Panel no longer accepts drops. - Same thing happens with gnome-terminal => sawfish bug (WM_STATE)? -FEATURES FOR 1.3 - Allow command-line arguments for executation pinboard/panel icons. Opening an AVFS directory with left-click should reuse the same window. diff --git a/ROX-Filer/src/Makefile.in b/ROX-Filer/src/Makefile.in index 90517edb..1a4926ff 100644 --- a/ROX-Filer/src/Makefile.in +++ b/ROX-Filer/src/Makefile.in @@ -20,19 +20,19 @@ EXEC = ${PLATFORM_DIR}/${PROG} PROG = ROX-Filer -SRCS = action.c appinfo.c appmenu.c bind.c choices.c collection.c dir.c \ - diritem.c display.c dnd.c filer.c find.c fscache.c gtksavebox.c \ - gui_support.c i18n.c icon.c infobox.c main.c menu.c minibuffer.c \ - modechange.c mount.c options.c panel.c pinboard.c pixmaps.c \ - remote.c rox_gettext.c run.c support.c sc.c session.c toolbar.c \ - type.c usericons.c - -OBJECTS = action.o appinfo.o appmenu.o bind.o choices.o collection.o dir.o \ - diritem.o display.o dnd.o filer.o find.o fscache.o gtksavebox.o \ - gui_support.o i18n.o icon.o infobox.o main.o menu.o minibuffer.o \ - modechange.o mount.o options.o panel.o pinboard.o pixmaps.o \ - remote.o rox_gettext.o run.o support.o sc.o session.o toolbar.o \ - type.o usericons.o +SRCS = action.c appinfo.c appmenu.c bind.c choices.c collection.c \ + dir.c diritem.c display.c dnd.c filer.c find.c fscache.c \ + gconvert.c gtksavebox.c gui_support.c i18n.c icon.c infobox.c \ + main.c menu.c minibuffer.c modechange.c mount.c options.c \ + panel.c pinboard.c pixmaps.c remote.c rox_gettext.c run.c \ + support.c sc.c session.c toolbar.c type.c usericons.c + +OBJECTS = action.o appinfo.o appmenu.o bind.o choices.o collection.o \ + dir.o diritem.o display.o dnd.o filer.o find.o fscache.o \ + gconvert.o gtksavebox.o gui_support.o i18n.o icon.o infobox.o \ + main.o menu.o minibuffer.o modechange.o mount.o options.o \ + panel.o pinboard.o pixmaps.o remote.o rox_gettext.o run.o \ + support.o sc.o session.o toolbar.o type.o usericons.o ############ Things to keep the same diff --git a/ROX-Filer/src/gconvert.c b/ROX-Filer/src/gconvert.c new file mode 100644 index 00000000..70288bc7 --- /dev/null +++ b/ROX-Filer/src/gconvert.c @@ -0,0 +1,300 @@ +/* + * $Id$ + * + * ROX-Filer, filer for the ROX desktop project + * + * 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; either version 2 of the License, or (at your option) + * any later version. + * + * 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., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* This code is taken from glib2 and has been converted to the GPL, as allowed + * under the terms of the LGPL. Removed lots of stuff! When we move fully to + * glib2, this file will disappear. + * + * gconvert.c: Convert between character sets using iconv + * Copyright Red Hat Inc., 2000 + * Authors: Havoc Pennington , Owen Taylor +#include +#include +#include + +#include +#include + +#include "global.h" + +#include "gconvert.h" + +static gboolean +g_utf8_get_charset_internal (const char **a) +{ + const char *charset = getenv("CHARSET"); + + if (charset && *charset) + { + *a = charset; + + if (charset && strstr (charset, "UTF-8")) + return TRUE; + else + return FALSE; + } + + /* Assume this for compatibility at present. */ + *a = "iso-8859-1"; + + return FALSE; +} + +static int utf8_locale_cache = -1; +static const char *utf8_charset_cache = NULL; + +gboolean +g_get_charset (const char **charset) +{ + if (utf8_locale_cache != -1) + { + if (charset) + *charset = utf8_charset_cache; + return utf8_locale_cache; + } + utf8_locale_cache = g_utf8_get_charset_internal (&utf8_charset_cache); + if (charset) + *charset = utf8_charset_cache; + return utf8_locale_cache; +} + +/* unicode_strchr */ + + +#if defined(USE_LIBICONV) && !defined (_LIBICONV_H) +#error libiconv in use but included iconv.h not from libiconv +#endif +#if !defined(USE_LIBICONV) && defined (_LIBICONV_H) +#error libiconv not in use but included iconv.h is from libiconv +#endif + +size_t +g_iconv (GIConv converter, + gchar **inbuf, + gsize *inbytes_left, + gchar **outbuf, + gsize *outbytes_left) +{ + iconv_t cd = (iconv_t)converter; + + return iconv (cd, inbuf, inbytes_left, outbuf, outbytes_left); +} + +gint +g_iconv_close (GIConv converter) +{ + iconv_t cd = (iconv_t)converter; + + return iconv_close (cd); +} + +static GIConv +open_converter (const gchar *to_codeset, + const gchar *from_codeset, + GError **error) +{ + GIConv cd = (GIConv) iconv_open (to_codeset, from_codeset); + + if (cd == (iconv_t) -1) + { + /* Something went wrong. */ + if (errno == EINVAL) + g_warning("Conversion from character set '%s' to '%s' is not supported", + from_codeset, to_codeset); + else + g_warning("Could not open converter from '%s' to '%s': %s", + from_codeset, to_codeset, strerror (errno)); + } + + return cd; + +} + +gchar* +g_convert (const gchar *str, + gssize len, + const gchar *to_codeset, + const gchar *from_codeset, + gsize *bytes_read, + gsize *bytes_written, + GError **error) +{ + gchar *res; + GIConv cd; + + g_return_val_if_fail (str != NULL, NULL); + g_return_val_if_fail (to_codeset != NULL, NULL); + g_return_val_if_fail (from_codeset != NULL, NULL); + + cd = open_converter (to_codeset, from_codeset, error); + + if (cd == (GIConv) -1) + { + if (bytes_read) + *bytes_read = 0; + + if (bytes_written) + *bytes_written = 0; + + return NULL; + } + + res = g_convert_with_iconv (str, len, cd, + bytes_read, bytes_written, + error); + + g_iconv_close (cd); + + return res; +} + +gchar* +g_convert_with_iconv (const gchar *str, + gssize len, + GIConv converter, + gsize *bytes_read, + gsize *bytes_written, + GError **error) +{ + gchar *dest; + gchar *outp; + const gchar *p; + gsize inbytes_remaining; + gsize outbytes_remaining; + gsize err; + gsize outbuf_size; + gboolean have_error = FALSE; + + g_return_val_if_fail (str != NULL, NULL); + g_return_val_if_fail (converter != (GIConv) -1, NULL); + + if (len < 0) + len = strlen (str); + + p = str; + inbytes_remaining = len; + outbuf_size = len + 1; /* + 1 for nul in case len == 1 */ + + outbytes_remaining = outbuf_size - 1; /* -1 for nul */ + outp = dest = g_malloc (outbuf_size); + + again: + + err = g_iconv (converter, (char **)&p, &inbytes_remaining, &outp, &outbytes_remaining); + + if (err == (size_t) -1) + { + switch (errno) + { + case EINVAL: + /* Incomplete text, do not report an error */ + break; + case E2BIG: + { + size_t used = outp - dest; + + outbuf_size *= 2; + dest = g_realloc (dest, outbuf_size); + + outp = dest + used; + outbytes_remaining = outbuf_size - used - 1; /* -1 for nul */ + + goto again; + } + case EILSEQ: + g_warning("Invalid byte sequence in conversion input"); + have_error = TRUE; + break; + default: + g_warning("Error during conversion: %s", strerror (errno)); + have_error = TRUE; + break; + } + } + + *outp = '\0'; + + if (bytes_read) + *bytes_read = p - str; + else + { + if ((p - str) != len) + { + if (!have_error) + { + g_warning("Partial character sequence at end of input"); + have_error = TRUE; + } + } + } + + if (bytes_written) + *bytes_written = outp - dest; /* Doesn't include '\0' */ + + if (have_error) + { + g_free (dest); + return NULL; + } + else + return dest; +} + +gchar * +g_locale_to_utf8 (const gchar *opsysstring, + gssize len, + gsize *bytes_read, + gsize *bytes_written, + GError **error) +{ + const char *charset; + + if (g_get_charset (&charset)) + return g_strdup (opsysstring); + else + return g_convert (opsysstring, len, + "UTF-8", charset, bytes_read, bytes_written, error); +} + +gchar * +g_locale_from_utf8 (const gchar *utf8string, + gssize len, + gsize *bytes_read, + gsize *bytes_written, + GError **error) +{ + const gchar *charset; + + if (g_get_charset (&charset)) + return g_strdup (utf8string); + else + return g_convert (utf8string, len, + charset, "UTF-8", bytes_read, bytes_written, error); +} + +#endif diff --git a/ROX-Filer/src/gconvert.h b/ROX-Filer/src/gconvert.h new file mode 100644 index 00000000..1bea473d --- /dev/null +++ b/ROX-Filer/src/gconvert.h @@ -0,0 +1,123 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * 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. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +#ifndef __G_CONVERT_H__ +#define __G_CONVERT_H__ + +#ifndef FAKE_GERROR +# define FAKE_GERROR +typedef void *GError; +#endif + +#include /* For size_t */ + +typedef enum +{ + G_CONVERT_ERROR_NO_CONVERSION, + G_CONVERT_ERROR_ILLEGAL_SEQUENCE, + G_CONVERT_ERROR_FAILED, + G_CONVERT_ERROR_PARTIAL_INPUT, + G_CONVERT_ERROR_BAD_URI, + G_CONVERT_ERROR_NOT_ABSOLUTE_PATH +} GConvertError; + +#define G_CONVERT_ERROR g_convert_error_quark() +GQuark g_convert_error_quark (void); + +/* Thin wrappers around iconv + */ +typedef struct _GIConv *GIConv; + +GIConv g_iconv_open (const gchar *to_codeset, + const gchar *from_codeset); +size_t g_iconv (GIConv converter, + gchar **inbuf, + gsize *inbytes_left, + gchar **outbuf, + gsize *outbytes_left); +gint g_iconv_close (GIConv converter); + + +gchar* g_convert (const gchar *str, + gssize len, + const gchar *to_codeset, + const gchar *from_codeset, + gsize *bytes_read, + gsize *bytes_written, + GError **error); +gchar* g_convert_with_iconv (const gchar *str, + gssize len, + GIConv converter, + gsize *bytes_read, + gsize *bytes_written, + GError **error); +gchar* g_convert_with_fallback (const gchar *str, + gssize len, + const gchar *to_codeset, + const gchar *from_codeset, + gchar *fallback, + gsize *bytes_read, + gsize *bytes_written, + GError **error); + + +/* Convert between libc's idea of strings and UTF-8. + */ +gchar* g_locale_to_utf8 (const gchar *opsysstring, + gssize len, + gsize *bytes_read, + gsize *bytes_written, + GError **error); +gchar* g_locale_from_utf8 (const gchar *utf8string, + gssize len, + gsize *bytes_read, + gsize *bytes_written, + GError **error); + +/* Convert between the operating system (or C runtime) + * representation of file names and UTF-8. + */ +gchar* g_filename_to_utf8 (const gchar *opsysstring, + gssize len, + gsize *bytes_read, + gsize *bytes_written, + GError **error); +gchar* g_filename_from_utf8 (const gchar *utf8string, + gssize len, + gsize *bytes_read, + gsize *bytes_written, + GError **error); + +gchar *g_filename_from_uri (const char *uri, + char **hostname, + GError **error); + +gchar *g_filename_to_uri (const char *filename, + char *hostname, + GError **error); + + +#endif /* __G_CONVERT_H__ */ diff --git a/ROX-Filer/src/gunicode.h b/ROX-Filer/src/gunicode.h new file mode 100644 index 00000000..7ba6d60e --- /dev/null +++ b/ROX-Filer/src/gunicode.h @@ -0,0 +1,280 @@ +/* gunicode.h - Unicode manipulation functions + * + * Copyright (C) 1999, 2000 Tom Tromey + * Copyright 2000 Red Hat, Inc. + * + * The Gnome 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. + * + * The Gnome 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 the Gnome Library; see the file COPYING.LIB. If not, + * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __G_UNICODE_H__ +#define __G_UNICODE_H__ + +#include + +#ifndef FAKE_GERROR +# define FAKE_GERROR +typedef void *GError; +#endif + +typedef guint32 gunichar; +typedef guint16 gunichar2; + +/* These are the possible character classifications. + * See http://www.unicode.org/Public/UNIDATA/UnicodeData.html + */ +typedef enum +{ + G_UNICODE_CONTROL, + G_UNICODE_FORMAT, + G_UNICODE_UNASSIGNED, + G_UNICODE_PRIVATE_USE, + G_UNICODE_SURROGATE, + G_UNICODE_LOWERCASE_LETTER, + G_UNICODE_MODIFIER_LETTER, + G_UNICODE_OTHER_LETTER, + G_UNICODE_TITLECASE_LETTER, + G_UNICODE_UPPERCASE_LETTER, + G_UNICODE_COMBINING_MARK, + G_UNICODE_ENCLOSING_MARK, + G_UNICODE_NON_SPACING_MARK, + G_UNICODE_DECIMAL_NUMBER, + G_UNICODE_LETTER_NUMBER, + G_UNICODE_OTHER_NUMBER, + G_UNICODE_CONNECT_PUNCTUATION, + G_UNICODE_DASH_PUNCTUATION, + G_UNICODE_CLOSE_PUNCTUATION, + G_UNICODE_FINAL_PUNCTUATION, + G_UNICODE_INITIAL_PUNCTUATION, + G_UNICODE_OTHER_PUNCTUATION, + G_UNICODE_OPEN_PUNCTUATION, + G_UNICODE_CURRENCY_SYMBOL, + G_UNICODE_MODIFIER_SYMBOL, + G_UNICODE_MATH_SYMBOL, + G_UNICODE_OTHER_SYMBOL, + G_UNICODE_LINE_SEPARATOR, + G_UNICODE_PARAGRAPH_SEPARATOR, + G_UNICODE_SPACE_SEPARATOR +} GUnicodeType; + +/* These are the possible line break classifications. + * See http://www.unicode.org/unicode/reports/tr14/ + */ +typedef enum +{ + G_UNICODE_BREAK_MANDATORY, + G_UNICODE_BREAK_CARRIAGE_RETURN, + G_UNICODE_BREAK_LINE_FEED, + G_UNICODE_BREAK_COMBINING_MARK, + G_UNICODE_BREAK_SURROGATE, + G_UNICODE_BREAK_ZERO_WIDTH_SPACE, + G_UNICODE_BREAK_INSEPARABLE, + G_UNICODE_BREAK_NON_BREAKING_GLUE, + G_UNICODE_BREAK_CONTINGENT, + G_UNICODE_BREAK_SPACE, + G_UNICODE_BREAK_AFTER, + G_UNICODE_BREAK_BEFORE, + G_UNICODE_BREAK_BEFORE_AND_AFTER, + G_UNICODE_BREAK_HYPHEN, + G_UNICODE_BREAK_NON_STARTER, + G_UNICODE_BREAK_OPEN_PUNCTUATION, + G_UNICODE_BREAK_CLOSE_PUNCTUATION, + G_UNICODE_BREAK_QUOTATION, + G_UNICODE_BREAK_EXCLAMATION, + G_UNICODE_BREAK_IDEOGRAPHIC, + G_UNICODE_BREAK_NUMERIC, + G_UNICODE_BREAK_INFIX_SEPARATOR, + G_UNICODE_BREAK_SYMBOL, + G_UNICODE_BREAK_ALPHABETIC, + G_UNICODE_BREAK_PREFIX, + G_UNICODE_BREAK_POSTFIX, + G_UNICODE_BREAK_COMPLEX_CONTEXT, + G_UNICODE_BREAK_AMBIGUOUS, + G_UNICODE_BREAK_UNKNOWN +} GUnicodeBreakType; + +/* Returns TRUE if current locale uses UTF-8 charset. If CHARSET is + * not null, sets *CHARSET to the name of the current locale's + * charset. This value is statically allocated, and should be copied + * in case the locale's charset will be changed later using setlocale() + * or in some other way. + */ +gboolean g_get_charset (const char **charset); + +/* These are all analogs of the functions. + */ +gboolean g_unichar_isalnum (gunichar c) G_GNUC_CONST; +gboolean g_unichar_isalpha (gunichar c) G_GNUC_CONST; +gboolean g_unichar_iscntrl (gunichar c) G_GNUC_CONST; +gboolean g_unichar_isdigit (gunichar c) G_GNUC_CONST; +gboolean g_unichar_isgraph (gunichar c) G_GNUC_CONST; +gboolean g_unichar_islower (gunichar c) G_GNUC_CONST; +gboolean g_unichar_isprint (gunichar c) G_GNUC_CONST; +gboolean g_unichar_ispunct (gunichar c) G_GNUC_CONST; +gboolean g_unichar_isspace (gunichar c) G_GNUC_CONST; +gboolean g_unichar_isupper (gunichar c) G_GNUC_CONST; +gboolean g_unichar_isxdigit (gunichar c) G_GNUC_CONST; +gboolean g_unichar_istitle (gunichar c) G_GNUC_CONST; +gboolean g_unichar_isdefined (gunichar c) G_GNUC_CONST; +gboolean g_unichar_iswide (gunichar c) G_GNUC_CONST; + +/* More functions. These convert between the three cases. + * See the Unicode book to understand title case. */ +gunichar g_unichar_toupper (gunichar c) G_GNUC_CONST; +gunichar g_unichar_tolower (gunichar c) G_GNUC_CONST; +gunichar g_unichar_totitle (gunichar c) G_GNUC_CONST; + +/* If C is a digit (according to `g_unichar_isdigit'), then return its + numeric value. Otherwise return -1. */ +gint g_unichar_digit_value (gunichar c) G_GNUC_CONST; + +gint g_unichar_xdigit_value (gunichar c) G_GNUC_CONST; + +/* Return the Unicode character type of a given character. */ +GUnicodeType g_unichar_type (gunichar c) G_GNUC_CONST; + +/* Return the line break property for a given character */ +GUnicodeBreakType g_unichar_break_type (gunichar c) G_GNUC_CONST; + + +/* Compute canonical ordering of a string in-place. This rearranges + decomposed characters in the string according to their combining + classes. See the Unicode manual for more information. */ +void g_unicode_canonical_ordering (gunichar *string, + gsize len); + +/* Compute canonical decomposition of a character. Returns g_malloc()d + string of Unicode characters. RESULT_LEN is set to the resulting + length of the string. */ +gunichar *g_unicode_canonical_decomposition (gunichar ch, + gsize *result_len); + +/* Array of skip-bytes-per-initial character. + */ +const gchar * const g_utf8_skip; + +#define g_utf8_next_char(p) (char *)((p) + g_utf8_skip[*(guchar *)(p)]) + +gunichar g_utf8_get_char (const gchar *p); +gunichar g_utf8_get_char_validated (const gchar *p, + gssize max_len); + +gchar* g_utf8_offset_to_pointer (const gchar *str, + glong offset); +glong g_utf8_pointer_to_offset (const gchar *str, + const gchar *pos); +gchar* g_utf8_prev_char (const gchar *p); +gchar* g_utf8_find_next_char (const gchar *p, + const gchar *end); +gchar* g_utf8_find_prev_char (const gchar *str, + const gchar *p); + +glong g_utf8_strlen (const gchar *p, + gssize max); + +/* Copies n characters from src to dest */ +gchar* g_utf8_strncpy (gchar *dest, + const gchar *src, + gsize n); + +/* Find the UTF-8 character corresponding to ch, in string p. These + functions are equivalants to strchr and strrchr */ +gchar* g_utf8_strchr (const gchar *p, + gssize len, + gunichar c); +gchar* g_utf8_strrchr (const gchar *p, + gssize len, + gunichar c); + +gunichar2 *g_utf8_to_utf16 (const gchar *str, + glong len, + glong *items_read, + glong *items_written, + GError **error); +gunichar * g_utf8_to_ucs4 (const gchar *str, + glong len, + glong *items_read, + glong *items_written, + GError **error); +gunichar * g_utf8_to_ucs4_fast (const gchar *str, + glong len, + glong *items_written); +gunichar * g_utf16_to_ucs4 (const gunichar2 *str, + glong len, + glong *items_read, + glong *items_written, + GError **error); +gchar* g_utf16_to_utf8 (const gunichar2 *str, + glong len, + glong *items_read, + glong *items_written, + GError **error); +gunichar2 *g_ucs4_to_utf16 (const gunichar *str, + glong len, + glong *items_read, + glong *items_written, + GError **error); +gchar* g_ucs4_to_utf8 (const gunichar *str, + glong len, + glong *items_read, + glong *items_written, + GError **error); + +/* Convert a single character into UTF-8. outbuf must have at + * least 6 bytes of space. Returns the number of bytes in the + * result. + */ +gint g_unichar_to_utf8 (gunichar c, + gchar *outbuf); + +/* Validate a UTF8 string, return TRUE if valid, put pointer to + * first invalid char in **end + */ + +gboolean g_utf8_validate (const gchar *str, + gssize max_len, + const gchar **end); + +/* Validate a Unicode character */ +gboolean g_unichar_validate (gunichar ch); + +gchar *g_utf8_strup (const gchar *str, + gssize len); +gchar *g_utf8_strdown (const gchar *str, + gssize len); +gchar *g_utf8_casefold (const gchar *str, + gssize len); + +typedef enum { + G_NORMALIZE_DEFAULT, + G_NORMALIZE_NFD = G_NORMALIZE_DEFAULT, + G_NORMALIZE_DEFAULT_COMPOSE, + G_NORMALIZE_NFC = G_NORMALIZE_DEFAULT_COMPOSE, + G_NORMALIZE_ALL, + G_NORMALIZE_NFKD = G_NORMALIZE_ALL, + G_NORMALIZE_ALL_COMPOSE, + G_NORMALIZE_NFKC = G_NORMALIZE_ALL_COMPOSE +} GNormalizeMode; + +gchar *g_utf8_normalize (const gchar *str, + gssize len, + GNormalizeMode mode); + +gint g_utf8_collate (const gchar *str1, + const gchar *str2); +gchar *g_utf8_collate_key (const gchar *str, + gssize len); + +#endif /* __G_UNICODE_H__ */ diff --git a/ROX-Filer/src/panel.c b/ROX-Filer/src/panel.c index 99c2a127..5f77086b 100644 --- a/ROX-Filer/src/panel.c +++ b/ROX-Filer/src/panel.c @@ -412,6 +412,7 @@ static void panel_load_from_xml(Panel *panel, xmlDocPtr doc) static char *pan_from_file(guchar *line) { guchar *sep, *leaf; + gchar *u8_path, *u8_leaf; g_return_val_if_fail(line != NULL, NULL); g_return_val_if_fail(loading_panel != NULL, NULL); @@ -428,13 +429,15 @@ static char *pan_from_file(guchar *line) else leaf = NULL; - panel_add_item(loading_panel, - sep + 1, - leaf, - sep[0] == '>'); - + u8_path = to_utf8(sep + 1); + u8_leaf = to_utf8(leaf); g_free(leaf); + panel_add_item(loading_panel, u8_path, u8_leaf, sep[0] == '>'); + + g_free(u8_path); + g_free(u8_leaf); + return NULL; } @@ -484,7 +487,17 @@ static void panel_add_item(Panel *panel, icon->selected = FALSE; if (name) + { +#ifndef GTK2 + gchar *loc_name; + + loc_name = from_utf8(name); + icon->item = diritem_new(loc_name); + g_free(loc_name); +#else icon->item = diritem_new(name); +#endif + } else { guchar *slash; @@ -898,7 +911,16 @@ static void make_widgets(xmlNodePtr side, GList *widgets) tree = xmlNewTextChild(side, NULL, "icon", icon->src_path); +#ifndef GTK2 + { + gchar *u8; + u8 = to_utf8(icon->item->leafname); + xmlSetProp(tree, "label", u8); + g_free(u8); + } +#else xmlSetProp(tree, "label", icon->item->leafname); +#endif } if (widgets) diff --git a/ROX-Filer/src/pinboard.c b/ROX-Filer/src/pinboard.c index b8954649..7c8ed9f7 100644 --- a/ROX-Filer/src/pinboard.c +++ b/ROX-Filer/src/pinboard.c @@ -281,6 +281,8 @@ void pinboard_activate(guchar *name) * if 'corner' is FALSE, and as the top-left corner of where the icon * image should be if it is TRUE. * 'name' is the name to use. If NULL then the leafname of path is used. + * + * names are in UTF-8. */ void pinboard_pin(guchar *path, guchar *name, int x, int y) { @@ -311,7 +313,17 @@ void pinboard_pin(guchar *path, guchar *name, int x, int y) name = icon->path; } +#ifndef GTK2 + { + gchar *loc_name; + + loc_name = from_utf8(name); + icon->item = diritem_new(loc_name); + g_free(loc_name); + } +#else icon->item = diritem_new(name); +#endif diritem_restat(icon->path, icon->item); icon->win = gtk_window_new(GTK_WINDOW_DIALOG); @@ -1059,6 +1071,7 @@ static void pinboard_load_from_xml(xmlDocPtr doc) static char *pin_from_file(guchar *line) { guchar *leaf = NULL; + gchar *u8_path, *u8_leaf; int x, y, n; if (*line == '<') @@ -1083,9 +1096,14 @@ static char *pin_from_file(guchar *line) if (sscanf(line, " %d , %d , %n", &x, &y, &n) < 2) return NULL; /* Ignore format errors */ - pinboard_pin(line + n, leaf, x, y); - + u8_path = to_utf8(line + n); + u8_leaf = to_utf8(leaf); g_free(leaf); + + pinboard_pin(u8_path, u8_leaf, x, y); + + g_free(u8_path); + g_free(u8_leaf); return NULL; } @@ -1216,7 +1234,16 @@ void pinboard_save(void) xmlSetProp(tree, "y", tmp); g_free(tmp); +#ifndef GTK2 + { + gchar *u8; + u8 = to_utf8(icon->item->leafname); + xmlSetProp(tree, "label", u8); + g_free(u8); + } +#else xmlSetProp(tree, "label", icon->item->leafname); +#endif } save_new = g_strconcat(save, ".new", NULL); diff --git a/ROX-Filer/src/support.c b/ROX-Filer/src/support.c index c77c5bf0..864b70a1 100644 --- a/ROX-Filer/src/support.c +++ b/ROX-Filer/src/support.c @@ -47,6 +47,10 @@ #include "my_vfs.h" #include "fscache.h" +#ifndef GTK2 +# include "gconvert.h" +#endif + static GHashTable *uid_hash = NULL; /* UID -> User name */ static GHashTable *gid_hash = NULL; /* GID -> Group name */ @@ -1299,6 +1303,31 @@ gchar *icon_convert_path(gchar *path) return retval; } +/* Convert string 'src' from the current locale to UTF-8. + * If conversion fails, try again using iso-8859-1 -> UTF-8. + */ +gchar *to_utf8(gchar *src) +{ + gchar *retval; + + if (!src) + return NULL; + + retval = g_locale_to_utf8(src, -1, NULL, NULL, NULL); + if (retval) + return retval; + + return g_convert(src, -1, "UTF-8", "iso-8859-1", NULL, NULL, NULL); +} + +/* Convert string 'src' to the current locale from UTF-8. + * If conversion fails, try again using iso-8859-1 -> UTF-8. + */ +gchar *from_utf8(gchar *src) +{ + return src ? g_locale_from_utf8(src, -1, NULL, NULL, NULL) : NULL; +} + /**************************************************************** * INTERNAL FUNCTIONS * ****************************************************************/ diff --git a/ROX-Filer/src/support.h b/ROX-Filer/src/support.h index 592473d9..58cbfab8 100644 --- a/ROX-Filer/src/support.h +++ b/ROX-Filer/src/support.h @@ -49,6 +49,8 @@ int text_to_boolean(const char *text, int defvalue); void set_to_null(gpointer *data); char *readlink_dup(char *path); gchar *icon_convert_path(gchar *path); +gchar *to_utf8(gchar *src); +gchar *from_utf8(gchar *src); #if defined(GTK2) || defined(THUMBS_USE_LIBPNG) char *md5_hash(char *message); -- 2.11.4.GIT