* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
+#include <config.h>
#include <stdio.h>
#include <glib.h>
+#include <unicode-data.h>
#include <errno.h>
-#ifdef _MSC_VER
-/* FIXME */
-#define CODESET 1
-#include <Windows.h>
-typedef int iconv_t;
-#else
-#include <langinfo.h>
-#include <iconv.h>
+#ifndef G_OS_WIN32
+# ifdef HAVE_LOCALCHARSET_H
+# include <localcharset.h>
+# endif
#endif
-static char *my_charset;
-static gboolean is_utf8;
+const char *my_charset;
+
+/*
+ * Character set conversion
+ */
GUnicodeType
g_unichar_type (gunichar c)
{
- g_error ("%s", "g_unichar_type is not implemented");
+ int i;
+
+ guint16 cp = (guint16) c;
+ for (i = 0; i < unicode_category_ranges_count; i++) {
+ if (cp < unicode_category_ranges [i].start)
+ continue;
+ if (unicode_category_ranges [i].end <= cp)
+ continue;
+ return unicode_category [i] [cp - unicode_category_ranges [i].start];
+ }
+
+ /*
+ // 3400-4DB5: OtherLetter
+ // 4E00-9FC3: OtherLetter
+ // AC00-D7A3: OtherLetter
+ // D800-DFFF: OtherSurrogate
+ // E000-F8FF: OtherPrivateUse
+ // 20000-2A6D6 OtherLetter
+ // F0000-FFFFD OtherPrivateUse
+ // 100000-10FFFD OtherPrivateUse
+ */
+ if (0x3400 <= cp && cp < 0x4DB5)
+ return G_UNICODE_OTHER_LETTER;
+ if (0x4E00 <= cp && cp < 0x9FC3)
+ return G_UNICODE_OTHER_LETTER;
+ if (0xAC00<= cp && cp < 0xD7A3)
+ return G_UNICODE_OTHER_LETTER;
+ if (0xD800 <= cp && cp < 0xDFFF)
+ return G_UNICODE_SURROGATE;
+ if (0xE000 <= cp && cp < 0xF8FF)
+ return G_UNICODE_PRIVATE_USE;
+ /* since the argument is UTF-16, we cannot check beyond FFFF */
+
+ /* It should match any of above */
return 0;
}
+GUnicodeBreakType
+g_unichar_break_type (gunichar c)
+{
+ // MOONLIGHT_FIXME
+ return G_UNICODE_BREAK_UNKNOWN;
+}
+
+gunichar
+g_unichar_case (gunichar c, gboolean upper)
+{
+ gint8 i, i2;
+ guint32 cp = (guint32) c, v;
+
+ for (i = 0; i < simple_case_map_ranges_count; i++) {
+ if (cp < simple_case_map_ranges [i].start)
+ return c;
+ if (simple_case_map_ranges [i].end <= cp)
+ continue;
+ if (c < 0x10000) {
+ const guint16 *tab = upper ? simple_upper_case_mapping_lowarea [i] : simple_lower_case_mapping_lowarea [i];
+ v = tab [cp - simple_case_map_ranges [i].start];
+ } else {
+ const guint32 *tab;
+ i2 = (gint8)(i - (upper ? simple_upper_case_mapping_lowarea_table_count : simple_lower_case_mapping_lowarea_table_count));
+ tab = upper ? simple_upper_case_mapping_higharea [i2] : simple_lower_case_mapping_higharea [i2];
+ v = tab [cp - simple_case_map_ranges [i].start];
+ }
+ return v != 0 ? (gunichar) v : c;
+ }
+ return c;
+}
+
+gunichar
+g_unichar_toupper (gunichar c)
+{
+ return g_unichar_case (c, TRUE);
+}
+
gunichar
g_unichar_tolower (gunichar c)
{
- g_error ("%s", "g_unichar_type is not implemented");
- return 0;
+ return g_unichar_case (c, FALSE);
+}
+
+gunichar
+g_unichar_totitle (gunichar c)
+{
+ guint8 i;
+ guint32 cp;
+
+ cp = (guint32) c;
+ for (i = 0; i < simple_titlecase_mapping_count; i++) {
+ if (simple_titlecase_mapping [i].codepoint == cp)
+ return simple_titlecase_mapping [i].title;
+ if (simple_titlecase_mapping [i].codepoint > cp)
+ /* it is ordered, hence no more match */
+ break;
+ }
+ return g_unichar_toupper (c);
}
gboolean
return -1;
}
-gchar *
-g_convert (const gchar *str, gssize len,
- const gchar *to_codeset, const gchar *from_codeset,
- gsize *bytes_read, gsize *bytes_written, GError **error)
+gboolean
+g_unichar_isspace (gunichar c)
{
- char *result = NULL;
-#ifdef G_OS_WIN32
-#else
- iconv_t convertor;
- char *buffer, *output;
- const char *strptr = (const char *) str;
- size_t str_len = len == -1 ? strlen (str) : len;
- size_t buffer_size;
- size_t left, out_left;
-
- convertor = iconv_open (to_codeset, from_codeset);
- if (convertor == (iconv_t) -1){
- *bytes_written = 0;
- *bytes_read = 0;
- return NULL;
- }
+ GUnicodeType type = g_unichar_type (c);
+ if (type == G_UNICODE_LINE_SEPARATOR ||
+ type == G_UNICODE_PARAGRAPH_SEPARATOR ||
+ type == G_UNICODE_SPACE_SEPARATOR)
+ return TRUE;
- buffer_size = str_len + 1 + 8;
- buffer = g_malloc (buffer_size);
- out_left = str_len;
- output = buffer;
- left = str_len;
- while (left > 0){
- int res = iconv (convertor, (char **) &strptr, &left, &output, &out_left);
- if (res == (size_t) -1){
- if (errno == E2BIG){
- char *n;
- size_t extra_space = 8 + left;
- size_t output_used = output - buffer;
-
- buffer_size += extra_space;
-
- n = g_realloc (buffer, buffer_size);
-
- if (n == NULL){
- if (error != NULL)
- *error = g_error_new (NULL, G_CONVERT_ERROR_FAILED, "No memory left");
- g_free (buffer);
- result = NULL;
- goto leave;
- }
- buffer = n;
- out_left += extra_space;
- output = buffer + output_used;
- } else if (errno == EILSEQ){
- if (error != NULL)
- *error = g_error_new (NULL, G_CONVERT_ERROR_ILLEGAL_SEQUENCE, "Invalid multi-byte sequence on input");
- result = NULL;
- g_free (buffer);
- goto leave;
- } else if (errno == EINVAL){
- if (error != NULL)
- *error = g_error_new (NULL, G_CONVERT_ERROR_PARTIAL_INPUT, "Partial character sequence");
- result = NULL;
- g_free (buffer);
- goto leave;
- }
- }
- }
- if (bytes_read != NULL)
- *bytes_read = strptr - str;
- if (bytes_written != NULL)
- *bytes_written = output - buffer;
- *output = 0;
- result = buffer;
- leave:
- iconv_close (convertor);
-#endif
- return result;
+ return FALSE;
}
+
/*
* This is broken, and assumes an UTF8 system, but will do for eglib's first user
*/
return res;
}
+#ifndef G_OS_WIN32
+static gboolean is_utf8;
+
gboolean
g_get_charset (G_CONST_RETURN char **charset)
{
-#ifdef G_OS_WIN32
- static char buf[14];
- sprintf (buf, "CP%u", GetACP ());
- *charset = buf;
- is_utf8 = FALSE;
+ if (my_charset == NULL) {
+ /* These shouldn't be heap allocated */
+#if defined(HAVE_LOCALCHARSET_H)
+ my_charset = locale_charset ();
#else
- if (my_charset == NULL){
- my_charset = g_strdup (nl_langinfo (CODESET));
+ my_charset = "UTF-8";
+#endif
is_utf8 = strcmp (my_charset, "UTF-8") == 0;
}
if (charset != NULL)
*charset = my_charset;
-#endif
return is_utf8;
}
+#endif /* G_OS_WIN32 */
gchar *
g_locale_to_utf8 (const gchar *opsysstring, gssize len, gsize *bytes_read, gsize *bytes_written, GError **error)
return g_convert (utf8string, len, my_charset, "UTF-8", bytes_read, bytes_written, error);
}
-/**
- * g_utf8_validate
- * @utf: Pointer to putative UTF-8 encoded string.
- *
- * Checks @utf for being valid UTF-8. @utf is assumed to be
- * null-terminated. This function is not super-strict, as it will
- * allow longer UTF-8 sequences than necessary. Note that Java is
- * capable of producing these sequences if provoked. Also note, this
- * routine checks for the 4-byte maximum size, but does not check for
- * 0x10ffff maximum value.
- *
- * Return value: true if @utf is valid.
- **/
-gboolean
-g_utf8_validate (const gchar *utf, gssize max_len, const gchar **end)
-{
- int ix;
-
- g_return_val_if_fail (utf != NULL, FALSE);
-
- if (max_len == -1)
- max_len = strlen (utf);
-
- /*
- * utf is a string of 1, 2, 3 or 4 bytes. The valid strings
- * are as follows (in "bit format"):
- * 0xxxxxxx valid 1-byte
- * 110xxxxx 10xxxxxx valid 2-byte
- * 1110xxxx 10xxxxxx 10xxxxxx valid 3-byte
- * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx valid 4-byte
- */
- for (ix = 0; ix < max_len;) { /* string is 0-terminated */
- unsigned char c;
-
- c = utf[ix];
- if ((c & 0x80) == 0x00) { /* 1-byte code, starts with 10 */
- ix++;
- } else if ((c & 0xe0) == 0xc0) {/* 2-byte code, starts with 110 */
- if (((ix+1) >= max_len) || (utf[ix+1] & 0xc0 ) != 0x80){
- if (end != NULL)
- *end = &utf [ix];
- return FALSE;
- }
- ix += 2;
- } else if ((c & 0xf0) == 0xe0) {/* 3-byte code, starts with 1110 */
- if (((ix + 2) >= max_len) ||
- ((utf[ix+1] & 0xc0) != 0x80) ||
- ((utf[ix+2] & 0xc0) != 0x80)){
- if (end != NULL)
- *end = &utf [ix];
- return FALSE;
- }
- ix += 3;
- } else if ((c & 0xf8) == 0xf0) {/* 4-byte code, starts with 11110 */
- if (((ix + 3) >= max_len) ||
- ((utf[ix+1] & 0xc0) != 0x80) ||
- ((utf[ix+2] & 0xc0) != 0x80) ||
- ((utf[ix+3] & 0xc0) != 0x80)){
- if (end != NULL)
- *end = &utf [ix];
- return FALSE;
- }
- ix += 4;
- } else {/* unknown encoding */
- if (end != NULL)
- *end = &utf [ix];
- return FALSE;
- }
- }
-
- return TRUE;
-}