ae194c354631cff318b59a0e196a7a8c10261a30
[platform/upstream/glib.git] / glib / guniprop.c
1 /* guniprop.c - Unicode character properties.
2  *
3  * Copyright (C) 1999 Tom Tromey
4  * Copyright (C) 2000 Red Hat, Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #include "config.h"
23
24 #include <stdlib.h>
25 #include <stddef.h>
26 #include <string.h>
27 #include <locale.h>
28
29 #include "glib.h"
30 #include "gunichartables.h"
31 #include "gmirroringtable.h"
32 #include "gscripttable.h"
33 #include "gunicodeprivate.h"
34 #include "galias.h"
35
36 #define ATTR_TABLE(Page) (((Page) <= G_UNICODE_LAST_PAGE_PART1) \
37                           ? attr_table_part1[Page] \
38                           : attr_table_part2[(Page) - 0xe00])
39
40 #define ATTTABLE(Page, Char) \
41   ((ATTR_TABLE(Page) == G_UNICODE_MAX_TABLE_INDEX) ? 0 : (attr_data[ATTR_TABLE(Page)][Char]))
42
43 #define TTYPE_PART1(Page, Char) \
44   ((type_table_part1[Page] >= G_UNICODE_MAX_TABLE_INDEX) \
45    ? (type_table_part1[Page] - G_UNICODE_MAX_TABLE_INDEX) \
46    : (type_data[type_table_part1[Page]][Char]))
47
48 #define TTYPE_PART2(Page, Char) \
49   ((type_table_part2[Page] >= G_UNICODE_MAX_TABLE_INDEX) \
50    ? (type_table_part2[Page] - G_UNICODE_MAX_TABLE_INDEX) \
51    : (type_data[type_table_part2[Page]][Char]))
52
53 #define TYPE(Char) \
54   (((Char) <= G_UNICODE_LAST_CHAR_PART1) \
55    ? TTYPE_PART1 ((Char) >> 8, (Char) & 0xff) \
56    : (((Char) >= 0xe0000 && (Char) <= G_UNICODE_LAST_CHAR) \
57       ? TTYPE_PART2 (((Char) - 0xe0000) >> 8, (Char) & 0xff) \
58       : G_UNICODE_UNASSIGNED))
59
60
61 #define IS(Type, Class) (((guint)1 << (Type)) & (Class))
62 #define OR(Type, Rest)  (((guint)1 << (Type)) | (Rest))
63
64
65
66 #define ISALPHA(Type)   IS ((Type),                             \
67                             OR (G_UNICODE_LOWERCASE_LETTER,     \
68                             OR (G_UNICODE_UPPERCASE_LETTER,     \
69                             OR (G_UNICODE_TITLECASE_LETTER,     \
70                             OR (G_UNICODE_MODIFIER_LETTER,      \
71                             OR (G_UNICODE_OTHER_LETTER,         0))))))
72
73 #define ISALDIGIT(Type) IS ((Type),                             \
74                             OR (G_UNICODE_DECIMAL_NUMBER,       \
75                             OR (G_UNICODE_LETTER_NUMBER,        \
76                             OR (G_UNICODE_OTHER_NUMBER,         \
77                             OR (G_UNICODE_LOWERCASE_LETTER,     \
78                             OR (G_UNICODE_UPPERCASE_LETTER,     \
79                             OR (G_UNICODE_TITLECASE_LETTER,     \
80                             OR (G_UNICODE_MODIFIER_LETTER,      \
81                             OR (G_UNICODE_OTHER_LETTER,         0)))))))))
82
83 #define ISMARK(Type)    IS ((Type),                             \
84                             OR (G_UNICODE_NON_SPACING_MARK,     \
85                             OR (G_UNICODE_COMBINING_MARK,       \
86                             OR (G_UNICODE_ENCLOSING_MARK,       0))))
87
88 #define ISZEROWIDTHTYPE(Type)   IS ((Type),                     \
89                             OR (G_UNICODE_NON_SPACING_MARK,     \
90                             OR (G_UNICODE_ENCLOSING_MARK,       \
91                             OR (G_UNICODE_FORMAT,               0))))
92
93 /**
94  * g_unichar_isalnum:
95  * @c: a Unicode character
96  * 
97  * Determines whether a character is alphanumeric.
98  * Given some UTF-8 text, obtain a character value
99  * with g_utf8_get_char().
100  * 
101  * Return value: %TRUE if @c is an alphanumeric character
102  **/
103 gboolean
104 g_unichar_isalnum (gunichar c)
105 {
106   return ISALDIGIT (TYPE (c)) ? TRUE : FALSE;
107 }
108
109 /**
110  * g_unichar_isalpha:
111  * @c: a Unicode character
112  * 
113  * Determines whether a character is alphabetic (i.e. a letter).
114  * Given some UTF-8 text, obtain a character value with
115  * g_utf8_get_char().
116  * 
117  * Return value: %TRUE if @c is an alphabetic character
118  **/
119 gboolean
120 g_unichar_isalpha (gunichar c)
121 {
122   return ISALPHA (TYPE (c)) ? TRUE : FALSE;
123 }
124
125
126 /**
127  * g_unichar_iscntrl:
128  * @c: a Unicode character
129  * 
130  * Determines whether a character is a control character.
131  * Given some UTF-8 text, obtain a character value with
132  * g_utf8_get_char().
133  * 
134  * Return value: %TRUE if @c is a control character
135  **/
136 gboolean
137 g_unichar_iscntrl (gunichar c)
138 {
139   return TYPE (c) == G_UNICODE_CONTROL;
140 }
141
142 /**
143  * g_unichar_isdigit:
144  * @c: a Unicode character
145  * 
146  * Determines whether a character is numeric (i.e. a digit).  This
147  * covers ASCII 0-9 and also digits in other languages/scripts.  Given
148  * some UTF-8 text, obtain a character value with g_utf8_get_char().
149  * 
150  * Return value: %TRUE if @c is a digit
151  **/
152 gboolean
153 g_unichar_isdigit (gunichar c)
154 {
155   return TYPE (c) == G_UNICODE_DECIMAL_NUMBER;
156 }
157
158
159 /**
160  * g_unichar_isgraph:
161  * @c: a Unicode character
162  * 
163  * Determines whether a character is printable and not a space
164  * (returns %FALSE for control characters, format characters, and
165  * spaces). g_unichar_isprint() is similar, but returns %TRUE for
166  * spaces. Given some UTF-8 text, obtain a character value with
167  * g_utf8_get_char().
168  * 
169  * Return value: %TRUE if @c is printable unless it's a space
170  **/
171 gboolean
172 g_unichar_isgraph (gunichar c)
173 {
174   return !IS (TYPE(c),
175               OR (G_UNICODE_CONTROL,
176               OR (G_UNICODE_FORMAT,
177               OR (G_UNICODE_UNASSIGNED,
178               OR (G_UNICODE_PRIVATE_USE,
179               OR (G_UNICODE_SURROGATE,
180               OR (G_UNICODE_SPACE_SEPARATOR,
181              0)))))));
182 }
183
184 /**
185  * g_unichar_islower:
186  * @c: a Unicode character
187  * 
188  * Determines whether a character is a lowercase letter.
189  * Given some UTF-8 text, obtain a character value with
190  * g_utf8_get_char().
191  * 
192  * Return value: %TRUE if @c is a lowercase letter
193  **/
194 gboolean
195 g_unichar_islower (gunichar c)
196 {
197   return TYPE (c) == G_UNICODE_LOWERCASE_LETTER;
198 }
199
200
201 /**
202  * g_unichar_isprint:
203  * @c: a Unicode character
204  * 
205  * Determines whether a character is printable.
206  * Unlike g_unichar_isgraph(), returns %TRUE for spaces.
207  * Given some UTF-8 text, obtain a character value with
208  * g_utf8_get_char().
209  * 
210  * Return value: %TRUE if @c is printable
211  **/
212 gboolean
213 g_unichar_isprint (gunichar c)
214 {
215   return !IS (TYPE(c),
216               OR (G_UNICODE_CONTROL,
217               OR (G_UNICODE_FORMAT,
218               OR (G_UNICODE_UNASSIGNED,
219               OR (G_UNICODE_PRIVATE_USE,
220               OR (G_UNICODE_SURROGATE,
221              0))))));
222 }
223
224 /**
225  * g_unichar_ispunct:
226  * @c: a Unicode character
227  * 
228  * Determines whether a character is punctuation or a symbol.
229  * Given some UTF-8 text, obtain a character value with
230  * g_utf8_get_char().
231  * 
232  * Return value: %TRUE if @c is a punctuation or symbol character
233  **/
234 gboolean
235 g_unichar_ispunct (gunichar c)
236 {
237   return IS (TYPE(c),
238              OR (G_UNICODE_CONNECT_PUNCTUATION,
239              OR (G_UNICODE_DASH_PUNCTUATION,
240              OR (G_UNICODE_CLOSE_PUNCTUATION,
241              OR (G_UNICODE_FINAL_PUNCTUATION,
242              OR (G_UNICODE_INITIAL_PUNCTUATION,
243              OR (G_UNICODE_OTHER_PUNCTUATION,
244              OR (G_UNICODE_OPEN_PUNCTUATION,
245              OR (G_UNICODE_CURRENCY_SYMBOL,
246              OR (G_UNICODE_MODIFIER_SYMBOL,
247              OR (G_UNICODE_MATH_SYMBOL,
248              OR (G_UNICODE_OTHER_SYMBOL,
249             0)))))))))))) ? TRUE : FALSE;
250 }
251
252 /**
253  * g_unichar_isspace:
254  * @c: a Unicode character
255  * 
256  * Determines whether a character is a space, tab, or line separator
257  * (newline, carriage return, etc.).  Given some UTF-8 text, obtain a
258  * character value with g_utf8_get_char().
259  *
260  * (Note: don't use this to do word breaking; you have to use
261  * Pango or equivalent to get word breaking right, the algorithm
262  * is fairly complex.)
263  *  
264  * Return value: %TRUE if @c is a space character
265  **/
266 gboolean
267 g_unichar_isspace (gunichar c)
268 {
269   switch (c)
270     {
271       /* special-case these since Unicode thinks they are not spaces */
272     case '\t':
273     case '\n':
274     case '\r':
275     case '\f':
276       return TRUE;
277       break;
278       
279     default:
280       {
281         return IS (TYPE(c),
282                    OR (G_UNICODE_SPACE_SEPARATOR,
283                    OR (G_UNICODE_LINE_SEPARATOR,
284                    OR (G_UNICODE_PARAGRAPH_SEPARATOR,
285                   0)))) ? TRUE : FALSE;
286       }
287       break;
288     }
289 }
290
291 /**
292  * g_unichar_ismark:
293  * @c: a Unicode character
294  *
295  * Determines whether a character is a mark (non-spacing mark,
296  * combining mark, or enclosing mark in Unicode speak).
297  * Given some UTF-8 text, obtain a character value
298  * with g_utf8_get_char().
299  *
300  * Note: in most cases where isalpha characters are allowed,
301  * ismark characters should be allowed to as they are essential
302  * for writing most European languages as well as many non-Latin
303  * scripts.
304  *
305  * Return value: %TRUE if @c is a mark character
306  *
307  * Since: 2.14
308  **/
309 gboolean
310 g_unichar_ismark (gunichar c)
311 {
312   return ISMARK (TYPE (c));
313 }
314
315 /**
316  * g_unichar_isupper:
317  * @c: a Unicode character
318  * 
319  * Determines if a character is uppercase.
320  * 
321  * Return value: %TRUE if @c is an uppercase character
322  **/
323 gboolean
324 g_unichar_isupper (gunichar c)
325 {
326   return TYPE (c) == G_UNICODE_UPPERCASE_LETTER;
327 }
328
329 /**
330  * g_unichar_istitle:
331  * @c: a Unicode character
332  * 
333  * Determines if a character is titlecase. Some characters in
334  * Unicode which are composites, such as the DZ digraph
335  * have three case variants instead of just two. The titlecase
336  * form is used at the beginning of a word where only the
337  * first letter is capitalized. The titlecase form of the DZ
338  * digraph is U+01F2 LATIN CAPITAL LETTTER D WITH SMALL LETTER Z.
339  * 
340  * Return value: %TRUE if the character is titlecase
341  **/
342 gboolean
343 g_unichar_istitle (gunichar c)
344 {
345   unsigned int i;
346   for (i = 0; i < G_N_ELEMENTS (title_table); ++i)
347     if (title_table[i][0] == c)
348       return TRUE;
349   return FALSE;
350 }
351
352 /**
353  * g_unichar_isxdigit:
354  * @c: a Unicode character.
355  * 
356  * Determines if a character is a hexidecimal digit.
357  * 
358  * Return value: %TRUE if the character is a hexadecimal digit
359  **/
360 gboolean
361 g_unichar_isxdigit (gunichar c)
362 {
363   return ((c >= 'a' && c <= 'f')
364           || (c >= 'A' && c <= 'F')
365           || (TYPE (c) == G_UNICODE_DECIMAL_NUMBER));
366 }
367
368 /**
369  * g_unichar_isdefined:
370  * @c: a Unicode character
371  * 
372  * Determines if a given character is assigned in the Unicode
373  * standard.
374  *
375  * Return value: %TRUE if the character has an assigned value
376  **/
377 gboolean
378 g_unichar_isdefined (gunichar c)
379 {
380   return TYPE (c) != G_UNICODE_UNASSIGNED;
381 }
382
383 /**
384  * g_unichar_iszerowidth:
385  * @c: a Unicode character
386  * 
387  * Determines if a given character typically takes zero width when rendered.
388  * The return value is %TRUE for all non-spacing and enclosing marks
389  * (e.g., combining accents), format characters, zero-width
390  * space, but not U+00AD SOFT HYPHEN.
391  *
392  * A typical use of this function is with one of g_unichar_iswide() or
393  * g_unichar_iswide_cjk() to determine the number of cells a string occupies
394  * when displayed on a grid display (terminals).  However, note that not all
395  * terminals support zero-width rendering of zero-width marks.
396  *
397  * Return value: %TRUE if the character has zero width
398  *
399  * Since: 2.14
400  **/
401 gboolean
402 g_unichar_iszerowidth (gunichar c)
403 {
404   if (G_UNLIKELY (c == 0x00AD))
405     return FALSE;
406
407   if (G_UNLIKELY (ISZEROWIDTHTYPE (TYPE (c))))
408     return TRUE;
409
410   if (G_UNLIKELY ((c >= 0x1160 && c < 0x1200) ||
411                   c == 0x200B))
412     return TRUE;
413
414   return FALSE;
415 }
416
417 struct Interval
418 {
419   gunichar start, end;
420 };
421
422 static int
423 interval_compare (const void *key, const void *elt)
424 {
425   gunichar c = GPOINTER_TO_UINT (key);
426   struct Interval *interval = (struct Interval *)elt;
427
428   if (c < interval->start)
429     return -1;
430   if (c > interval->end)
431     return +1;
432
433   return 0;
434 }
435
436 /**
437  * g_unichar_iswide:
438  * @c: a Unicode character
439  * 
440  * Determines if a character is typically rendered in a double-width
441  * cell.
442  * 
443  * Return value: %TRUE if the character is wide
444  **/
445 gboolean
446 g_unichar_iswide (gunichar c)
447 {
448   /* sorted list of intervals of East_Asian_Width = W and F characters
449    * from Unicode 5.1.0.  produced by mungling output of:
450    * grep ';[FW]\>' EastAsianWidth.txt */
451   static const struct Interval wide[] = {
452     {0x1100, 0x1159}, {0x115F, 0x115F}, {0x2329, 0x232A}, {0x2E80, 0x2E99},
453     {0x2E9B, 0x2EF3}, {0x2F00, 0x2FD5}, {0x2FF0, 0x2FFB}, {0x3000, 0x303E},
454     {0x3041, 0x3096}, {0x3099, 0x30FF}, {0x3105, 0x312D}, {0x3131, 0x318E},
455     {0x3190, 0x31B7}, {0x31C0, 0x31E3}, {0x31F0, 0x321E}, {0x3220, 0x3243},
456     {0x3250, 0x32FE}, {0x3300, 0x4DB5}, {0x4E00, 0x9FC3}, {0xA000, 0xA48C},
457     {0xA490, 0xA4C6}, {0xAC00, 0xD7A3}, {0xF900, 0xFA2D}, {0xFA30, 0xFA6A},
458     {0xFA70, 0xFAD9}, {0xFE10, 0xFE19}, {0xFE30, 0xFE52}, {0xFE54, 0xFE66},
459     {0xFE68, 0xFE6B}, {0xFF01, 0xFF60}, {0xFFE0, 0xFFE6}, {0x20000, 0x2FFFD},
460     {0x30000, 0x3FFFD}
461   };
462
463   if (bsearch (GUINT_TO_POINTER (c), wide, G_N_ELEMENTS (wide), sizeof wide[0],
464                interval_compare))
465     return TRUE;
466
467   return FALSE;
468 }
469
470
471 /**
472  * g_unichar_iswide_cjk:
473  * @c: a Unicode character
474  * 
475  * Determines if a character is typically rendered in a double-width
476  * cell under legacy East Asian locales.  If a character is wide according to
477  * g_unichar_iswide(), then it is also reported wide with this function, but
478  * the converse is not necessarily true.  See the
479  * <ulink url="http://www.unicode.org/reports/tr11/">Unicode Standard
480  * Annex #11</ulink> for details.
481  * 
482  * Return value: %TRUE if the character is wide in legacy East Asian locales
483  *
484  * Since: 2.12
485  */
486 gboolean
487 g_unichar_iswide_cjk (gunichar c)
488 {
489   /* sorted list of intervals of East_Asian_Width = A and F characters
490    * from Unicode 5.1.0.  produced by mungling output of:
491    * grep ';[A]\>' EastAsianWidth.txt */
492   static const struct Interval ambiguous[] = {
493     {0x00A1, 0x00A1}, {0x00A4, 0x00A4}, {0x00A7, 0x00A8}, {0x00AA, 0x00AA},
494     {0x00AD, 0x00AE}, {0x00B0, 0x00B4}, {0x00B6, 0x00BA}, {0x00BC, 0x00BF},
495     {0x00C6, 0x00C6}, {0x00D0, 0x00D0}, {0x00D7, 0x00D8}, {0x00DE, 0x00E1},
496     {0x00E6, 0x00E6}, {0x00E8, 0x00EA}, {0x00EC, 0x00ED}, {0x00F0, 0x00F0},
497     {0x00F2, 0x00F3}, {0x00F7, 0x00FA}, {0x00FC, 0x00FC}, {0x00FE, 0x00FE},
498     {0x0101, 0x0101}, {0x0111, 0x0111}, {0x0113, 0x0113}, {0x011B, 0x011B},
499     {0x0126, 0x0127}, {0x012B, 0x012B}, {0x0131, 0x0133}, {0x0138, 0x0138},
500     {0x013F, 0x0142}, {0x0144, 0x0144}, {0x0148, 0x014B}, {0x014D, 0x014D},
501     {0x0152, 0x0153}, {0x0166, 0x0167}, {0x016B, 0x016B}, {0x01CE, 0x01CE},
502     {0x01D0, 0x01D0}, {0x01D2, 0x01D2}, {0x01D4, 0x01D4}, {0x01D6, 0x01D6},
503     {0x01D8, 0x01D8}, {0x01DA, 0x01DA}, {0x01DC, 0x01DC}, {0x0251, 0x0251},
504     {0x0261, 0x0261}, {0x02C4, 0x02C4}, {0x02C7, 0x02C7}, {0x02C9, 0x02CB},
505     {0x02CD, 0x02CD}, {0x02D0, 0x02D0}, {0x02D8, 0x02DB}, {0x02DD, 0x02DD},
506     {0x02DF, 0x02DF}, {0x0300, 0x036F}, {0x0391, 0x03A1}, {0x03A3, 0x03A9},
507     {0x03B1, 0x03C1}, {0x03C3, 0x03C9}, {0x0401, 0x0401}, {0x0410, 0x044F},
508     {0x0451, 0x0451}, {0x2010, 0x2010}, {0x2013, 0x2016}, {0x2018, 0x2019},
509     {0x201C, 0x201D}, {0x2020, 0x2022}, {0x2024, 0x2027}, {0x2030, 0x2030},
510     {0x2032, 0x2033}, {0x2035, 0x2035}, {0x203B, 0x203B}, {0x203E, 0x203E},
511     {0x2074, 0x2074}, {0x207F, 0x207F}, {0x2081, 0x2084}, {0x20AC, 0x20AC},
512     {0x2103, 0x2103}, {0x2105, 0x2105}, {0x2109, 0x2109}, {0x2113, 0x2113},
513     {0x2116, 0x2116}, {0x2121, 0x2122}, {0x2126, 0x2126}, {0x212B, 0x212B},
514     {0x2153, 0x2154}, {0x215B, 0x215E}, {0x2160, 0x216B}, {0x2170, 0x2179},
515     {0x2190, 0x2199}, {0x21B8, 0x21B9}, {0x21D2, 0x21D2}, {0x21D4, 0x21D4},
516     {0x21E7, 0x21E7}, {0x2200, 0x2200}, {0x2202, 0x2203}, {0x2207, 0x2208},
517     {0x220B, 0x220B}, {0x220F, 0x220F}, {0x2211, 0x2211}, {0x2215, 0x2215},
518     {0x221A, 0x221A}, {0x221D, 0x2220}, {0x2223, 0x2223}, {0x2225, 0x2225},
519     {0x2227, 0x222C}, {0x222E, 0x222E}, {0x2234, 0x2237}, {0x223C, 0x223D},
520     {0x2248, 0x2248}, {0x224C, 0x224C}, {0x2252, 0x2252}, {0x2260, 0x2261},
521     {0x2264, 0x2267}, {0x226A, 0x226B}, {0x226E, 0x226F}, {0x2282, 0x2283},
522     {0x2286, 0x2287}, {0x2295, 0x2295}, {0x2299, 0x2299}, {0x22A5, 0x22A5},
523     {0x22BF, 0x22BF}, {0x2312, 0x2312}, {0x2460, 0x24E9}, {0x24EB, 0x254B},
524     {0x2550, 0x2573}, {0x2580, 0x258F}, {0x2592, 0x2595}, {0x25A0, 0x25A1},
525     {0x25A3, 0x25A9}, {0x25B2, 0x25B3}, {0x25B6, 0x25B7}, {0x25BC, 0x25BD},
526     {0x25C0, 0x25C1}, {0x25C6, 0x25C8}, {0x25CB, 0x25CB}, {0x25CE, 0x25D1},
527     {0x25E2, 0x25E5}, {0x25EF, 0x25EF}, {0x2605, 0x2606}, {0x2609, 0x2609},
528     {0x260E, 0x260F}, {0x2614, 0x2615}, {0x261C, 0x261C}, {0x261E, 0x261E},
529     {0x2640, 0x2640}, {0x2642, 0x2642}, {0x2660, 0x2661}, {0x2663, 0x2665},
530     {0x2667, 0x266A}, {0x266C, 0x266D}, {0x266F, 0x266F}, {0x273D, 0x273D},
531     {0x2776, 0x277F}, {0xE000, 0xF8FF}, {0xFE00, 0xFE0F}, {0xFFFD, 0xFFFD},
532     {0xE0100, 0xE01EF}, {0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD}
533   };
534
535   if (g_unichar_iswide (c))
536     return TRUE;
537
538   if (bsearch (GUINT_TO_POINTER (c), ambiguous, G_N_ELEMENTS (ambiguous), sizeof ambiguous[0],
539                interval_compare))
540     return TRUE;
541
542   return FALSE;
543 }
544
545
546 /**
547  * g_unichar_toupper:
548  * @c: a Unicode character
549  * 
550  * Converts a character to uppercase.
551  * 
552  * Return value: the result of converting @c to uppercase.
553  *               If @c is not an lowercase or titlecase character,
554  *               or has no upper case equivalent @c is returned unchanged.
555  **/
556 gunichar
557 g_unichar_toupper (gunichar c)
558 {
559   int t = TYPE (c);
560   if (t == G_UNICODE_LOWERCASE_LETTER)
561     {
562       gunichar val = ATTTABLE (c >> 8, c & 0xff);
563       if (val >= 0x1000000)
564         {
565           const gchar *p = special_case_table + val - 0x1000000;
566           val = g_utf8_get_char (p);
567         }
568       /* Some lowercase letters, e.g., U+000AA, FEMININE ORDINAL INDICATOR,
569        * do not have an uppercase equivalent, in which case val will be
570        * zero. 
571        */
572       return val ? val : c;
573     }
574   else if (t == G_UNICODE_TITLECASE_LETTER)
575     {
576       unsigned int i;
577       for (i = 0; i < G_N_ELEMENTS (title_table); ++i)
578         {
579           if (title_table[i][0] == c)
580             return title_table[i][1];
581         }
582     }
583   return c;
584 }
585
586 /**
587  * g_unichar_tolower:
588  * @c: a Unicode character.
589  * 
590  * Converts a character to lower case.
591  * 
592  * Return value: the result of converting @c to lower case.
593  *               If @c is not an upperlower or titlecase character,
594  *               or has no lowercase equivalent @c is returned unchanged.
595  **/
596 gunichar
597 g_unichar_tolower (gunichar c)
598 {
599   int t = TYPE (c);
600   if (t == G_UNICODE_UPPERCASE_LETTER)
601     {
602       gunichar val = ATTTABLE (c >> 8, c & 0xff);
603       if (val >= 0x1000000)
604         {
605           const gchar *p = special_case_table + val - 0x1000000;
606           return g_utf8_get_char (p);
607         }
608       else
609         {
610           /* Not all uppercase letters are guaranteed to have a lowercase
611            * equivalent.  If this is the case, val will be zero. */
612           return val ? val : c;
613         }
614     }
615   else if (t == G_UNICODE_TITLECASE_LETTER)
616     {
617       unsigned int i;
618       for (i = 0; i < G_N_ELEMENTS (title_table); ++i)
619         {
620           if (title_table[i][0] == c)
621             return title_table[i][2];
622         }
623     }
624   return c;
625 }
626
627 /**
628  * g_unichar_totitle:
629  * @c: a Unicode character
630  * 
631  * Converts a character to the titlecase.
632  * 
633  * Return value: the result of converting @c to titlecase.
634  *               If @c is not an uppercase or lowercase character,
635  *               @c is returned unchanged.
636  **/
637 gunichar
638 g_unichar_totitle (gunichar c)
639 {
640   unsigned int i;
641   for (i = 0; i < G_N_ELEMENTS (title_table); ++i)
642     {
643       if (title_table[i][0] == c || title_table[i][1] == c
644           || title_table[i][2] == c)
645         return title_table[i][0];
646     }
647     
648   if (TYPE (c) == G_UNICODE_LOWERCASE_LETTER)
649     return g_unichar_toupper (c);
650
651   return c;
652 }
653
654 /**
655  * g_unichar_digit_value:
656  * @c: a Unicode character
657  *
658  * Determines the numeric value of a character as a decimal
659  * digit.
660  *
661  * Return value: If @c is a decimal digit (according to
662  * g_unichar_isdigit()), its numeric value. Otherwise, -1.
663  **/
664 int
665 g_unichar_digit_value (gunichar c)
666 {
667   if (TYPE (c) == G_UNICODE_DECIMAL_NUMBER)
668     return ATTTABLE (c >> 8, c & 0xff);
669   return -1;
670 }
671
672 /**
673  * g_unichar_xdigit_value:
674  * @c: a Unicode character
675  *
676  * Determines the numeric value of a character as a hexidecimal
677  * digit.
678  *
679  * Return value: If @c is a hex digit (according to
680  * g_unichar_isxdigit()), its numeric value. Otherwise, -1.
681  **/
682 int
683 g_unichar_xdigit_value (gunichar c)
684 {
685   if (c >= 'A' && c <= 'F')
686     return c - 'A' + 10;
687   if (c >= 'a' && c <= 'f')
688     return c - 'a' + 10;
689   if (TYPE (c) == G_UNICODE_DECIMAL_NUMBER)
690     return ATTTABLE (c >> 8, c & 0xff);
691   return -1;
692 }
693
694 /**
695  * g_unichar_type:
696  * @c: a Unicode character
697  * 
698  * Classifies a Unicode character by type.
699  * 
700  * Return value: the type of the character.
701  **/
702 GUnicodeType
703 g_unichar_type (gunichar c)
704 {
705   return TYPE (c);
706 }
707
708 /*
709  * Case mapping functions
710  */
711
712 typedef enum {
713   LOCALE_NORMAL,
714   LOCALE_TURKIC,
715   LOCALE_LITHUANIAN
716 } LocaleType;
717
718 static LocaleType
719 get_locale_type (void)
720 {
721 #ifdef G_OS_WIN32
722   char *tem = g_win32_getlocale ();
723   char locale[2];
724
725   locale[0] = tem[0];
726   locale[1] = tem[1];
727   g_free (tem);
728 #else
729   const char *locale = setlocale (LC_CTYPE, NULL);
730 #endif
731
732   switch (locale[0])
733     {
734    case 'a':
735       if (locale[1] == 'z')
736         return LOCALE_TURKIC;
737       break;
738     case 'l':
739       if (locale[1] == 't')
740         return LOCALE_LITHUANIAN;
741       break;
742     case 't':
743       if (locale[1] == 'r')
744         return LOCALE_TURKIC;
745       break;
746     }
747
748   return LOCALE_NORMAL;
749 }
750
751 static gint
752 output_marks (const char **p_inout,
753               char        *out_buffer,
754               gboolean     remove_dot)
755 {
756   const char *p = *p_inout;
757   gint len = 0;
758   
759   while (*p)
760     {
761       gunichar c = g_utf8_get_char (p);
762       
763       if (ISMARK (TYPE (c)))
764         {
765           if (!remove_dot || c != 0x307 /* COMBINING DOT ABOVE */)
766             len += g_unichar_to_utf8 (c, out_buffer ? out_buffer + len : NULL);
767           p = g_utf8_next_char (p);
768         }
769       else
770         break;
771     }
772
773   *p_inout = p;
774   return len;
775 }
776
777 static gint
778 output_special_case (gchar *out_buffer,
779                      int    offset,
780                      int    type,
781                      int    which)
782 {
783   const gchar *p = special_case_table + offset;
784   gint len;
785
786   if (type != G_UNICODE_TITLECASE_LETTER)
787     p = g_utf8_next_char (p);
788
789   if (which == 1)
790     p += strlen (p) + 1;
791
792   len = strlen (p);
793   if (out_buffer)
794     memcpy (out_buffer, p, len);
795
796   return len;
797 }
798
799 static gsize
800 real_toupper (const gchar *str,
801               gssize       max_len,
802               gchar       *out_buffer,
803               LocaleType   locale_type)
804 {
805   const gchar *p = str;
806   const char *last = NULL;
807   gsize len = 0;
808   gboolean last_was_i = FALSE;
809
810   while ((max_len < 0 || p < str + max_len) && *p)
811     {
812       gunichar c = g_utf8_get_char (p);
813       int t = TYPE (c);
814       gunichar val;
815
816       last = p;
817       p = g_utf8_next_char (p);
818
819       if (locale_type == LOCALE_LITHUANIAN)
820         {
821           if (c == 'i')
822             last_was_i = TRUE;
823           else 
824             {
825               if (last_was_i)
826                 {
827                   /* Nasty, need to remove any dot above. Though
828                    * I think only E WITH DOT ABOVE occurs in practice
829                    * which could simplify this considerably.
830                    */
831                   gsize decomp_len, i;
832                   gunichar *decomp;
833
834                   decomp = g_unicode_canonical_decomposition (c, &decomp_len);
835                   for (i=0; i < decomp_len; i++)
836                     {
837                       if (decomp[i] != 0x307 /* COMBINING DOT ABOVE */)
838                         len += g_unichar_to_utf8 (g_unichar_toupper (decomp[i]), out_buffer ? out_buffer + len : NULL);
839                     }
840                   g_free (decomp);
841                   
842                   len += output_marks (&p, out_buffer ? out_buffer + len : NULL, TRUE);
843
844                   continue;
845                 }
846
847               if (!ISMARK (t))
848                 last_was_i = FALSE;
849             }
850         }
851       
852       if (locale_type == LOCALE_TURKIC && c == 'i')
853         {
854           /* i => LATIN CAPITAL LETTER I WITH DOT ABOVE */
855           len += g_unichar_to_utf8 (0x130, out_buffer ? out_buffer + len : NULL); 
856         }
857       else if (c == 0x0345)     /* COMBINING GREEK YPOGEGRAMMENI */
858         {
859           /* Nasty, need to move it after other combining marks .. this would go away if
860            * we normalized first.
861            */
862           len += output_marks (&p, out_buffer ? out_buffer + len : NULL, FALSE);
863
864           /* And output as GREEK CAPITAL LETTER IOTA */
865           len += g_unichar_to_utf8 (0x399, out_buffer ? out_buffer + len : NULL);         
866         }
867       else if (IS (t,
868                    OR (G_UNICODE_LOWERCASE_LETTER,
869                    OR (G_UNICODE_TITLECASE_LETTER,
870                   0))))
871         {
872           val = ATTTABLE (c >> 8, c & 0xff);
873
874           if (val >= 0x1000000)
875             {
876               len += output_special_case (out_buffer ? out_buffer + len : NULL, val - 0x1000000, t,
877                                           t == G_UNICODE_LOWERCASE_LETTER ? 0 : 1);
878             }
879           else
880             {
881               if (t == G_UNICODE_TITLECASE_LETTER)
882                 {
883                   unsigned int i;
884                   for (i = 0; i < G_N_ELEMENTS (title_table); ++i)
885                     {
886                       if (title_table[i][0] == c)
887                         {
888                           val = title_table[i][1];
889                           break;
890                         }
891                     }
892                 }
893
894               /* Some lowercase letters, e.g., U+000AA, FEMININE ORDINAL INDICATOR,
895                * do not have an uppercase equivalent, in which case val will be
896                * zero. */
897               len += g_unichar_to_utf8 (val ? val : c, out_buffer ? out_buffer + len : NULL);
898             }
899         }
900       else
901         {
902           gsize char_len = g_utf8_skip[*(guchar *)last];
903
904           if (out_buffer)
905             memcpy (out_buffer + len, last, char_len);
906
907           len += char_len;
908         }
909
910     }
911
912   return len;
913 }
914
915 /**
916  * g_utf8_strup:
917  * @str: a UTF-8 encoded string
918  * @len: length of @str, in bytes, or -1 if @str is nul-terminated.
919  * 
920  * Converts all Unicode characters in the string that have a case
921  * to uppercase. The exact manner that this is done depends
922  * on the current locale, and may result in the number of
923  * characters in the string increasing. (For instance, the
924  * German ess-zet will be changed to SS.)
925  * 
926  * Return value: a newly allocated string, with all characters
927  *    converted to uppercase.  
928  **/
929 gchar *
930 g_utf8_strup (const gchar *str,
931               gssize       len)
932 {
933   gsize result_len;
934   LocaleType locale_type;
935   gchar *result;
936
937   g_return_val_if_fail (str != NULL, NULL);
938
939   locale_type = get_locale_type ();
940   
941   /*
942    * We use a two pass approach to keep memory management simple
943    */
944   result_len = real_toupper (str, len, NULL, locale_type);
945   result = g_malloc (result_len + 1);
946   real_toupper (str, len, result, locale_type);
947   result[result_len] = '\0';
948
949   return result;
950 }
951
952 /* traverses the string checking for characters with combining class == 230
953  * until a base character is found */
954 static gboolean
955 has_more_above (const gchar *str)
956 {
957   const gchar *p = str;
958   gint combining_class;
959
960   while (*p)
961     {
962       combining_class = g_unichar_combining_class (g_utf8_get_char (p));
963       if (combining_class == 230)
964         return TRUE;
965       else if (combining_class == 0)
966         break;
967
968       p = g_utf8_next_char (p);
969     }
970
971   return FALSE;
972 }
973
974 static gsize
975 real_tolower (const gchar *str,
976               gssize       max_len,
977               gchar       *out_buffer,
978               LocaleType   locale_type)
979 {
980   const gchar *p = str;
981   const char *last = NULL;
982   gsize len = 0;
983
984   while ((max_len < 0 || p < str + max_len) && *p)
985     {
986       gunichar c = g_utf8_get_char (p);
987       int t = TYPE (c);
988       gunichar val;
989
990       last = p;
991       p = g_utf8_next_char (p);
992
993       if (locale_type == LOCALE_TURKIC && c == 'I')
994         {
995           if (g_utf8_get_char (p) == 0x0307)
996             {
997               /* I + COMBINING DOT ABOVE => i (U+0069) */
998               len += g_unichar_to_utf8 (0x0069, out_buffer ? out_buffer + len : NULL); 
999               p = g_utf8_next_char (p);
1000             }
1001           else
1002             {
1003               /* I => LATIN SMALL LETTER DOTLESS I */
1004               len += g_unichar_to_utf8 (0x131, out_buffer ? out_buffer + len : NULL); 
1005             }
1006         }
1007       /* Introduce an explicit dot above when lowercasing capital I's and J's
1008        * whenever there are more accents above. [SpecialCasing.txt] */
1009       else if (locale_type == LOCALE_LITHUANIAN && 
1010                (c == 0x00cc || c == 0x00cd || c == 0x0128))
1011         {
1012           len += g_unichar_to_utf8 (0x0069, out_buffer ? out_buffer + len : NULL); 
1013           len += g_unichar_to_utf8 (0x0307, out_buffer ? out_buffer + len : NULL); 
1014
1015           switch (c)
1016             {
1017             case 0x00cc: 
1018               len += g_unichar_to_utf8 (0x0300, out_buffer ? out_buffer + len : NULL); 
1019               break;
1020             case 0x00cd: 
1021               len += g_unichar_to_utf8 (0x0301, out_buffer ? out_buffer + len : NULL); 
1022               break;
1023             case 0x0128: 
1024               len += g_unichar_to_utf8 (0x0303, out_buffer ? out_buffer + len : NULL); 
1025               break;
1026             }
1027         }
1028       else if (locale_type == LOCALE_LITHUANIAN && 
1029                (c == 'I' || c == 'J' || c == 0x012e) && 
1030                has_more_above (p))
1031         {
1032           len += g_unichar_to_utf8 (g_unichar_tolower (c), out_buffer ? out_buffer + len : NULL); 
1033           len += g_unichar_to_utf8 (0x0307, out_buffer ? out_buffer + len : NULL); 
1034         }
1035       else if (c == 0x03A3)     /* GREEK CAPITAL LETTER SIGMA */
1036         {
1037           if ((max_len < 0 || p < str + max_len) && *p)
1038             {
1039               gunichar next_c = g_utf8_get_char (p);
1040               int next_type = TYPE(next_c);
1041
1042               /* SIGMA mapps differently depending on whether it is
1043                * final or not. The following simplified test would
1044                * fail in the case of combining marks following the
1045                * sigma, but I don't think that occurs in real text.
1046                * The test here matches that in ICU.
1047                */
1048               if (ISALPHA (next_type)) /* Lu,Ll,Lt,Lm,Lo */
1049                 val = 0x3c3;    /* GREEK SMALL SIGMA */
1050               else
1051                 val = 0x3c2;    /* GREEK SMALL FINAL SIGMA */
1052             }
1053           else
1054             val = 0x3c2;        /* GREEK SMALL FINAL SIGMA */
1055
1056           len += g_unichar_to_utf8 (val, out_buffer ? out_buffer + len : NULL);
1057         }
1058       else if (IS (t,
1059                    OR (G_UNICODE_UPPERCASE_LETTER,
1060                    OR (G_UNICODE_TITLECASE_LETTER,
1061                   0))))
1062         {
1063           val = ATTTABLE (c >> 8, c & 0xff);
1064
1065           if (val >= 0x1000000)
1066             {
1067               len += output_special_case (out_buffer ? out_buffer + len : NULL, val - 0x1000000, t, 0);
1068             }
1069           else
1070             {
1071               if (t == G_UNICODE_TITLECASE_LETTER)
1072                 {
1073                   unsigned int i;
1074                   for (i = 0; i < G_N_ELEMENTS (title_table); ++i)
1075                     {
1076                       if (title_table[i][0] == c)
1077                         {
1078                           val = title_table[i][2];
1079                           break;
1080                         }
1081                     }
1082                 }
1083
1084               /* Not all uppercase letters are guaranteed to have a lowercase
1085                * equivalent.  If this is the case, val will be zero. */
1086               len += g_unichar_to_utf8 (val ? val : c, out_buffer ? out_buffer + len : NULL);
1087             }
1088         }
1089       else
1090         {
1091           gsize char_len = g_utf8_skip[*(guchar *)last];
1092
1093           if (out_buffer)
1094             memcpy (out_buffer + len, last, char_len);
1095
1096           len += char_len;
1097         }
1098
1099     }
1100
1101   return len;
1102 }
1103
1104 /**
1105  * g_utf8_strdown:
1106  * @str: a UTF-8 encoded string
1107  * @len: length of @str, in bytes, or -1 if @str is nul-terminated.
1108  * 
1109  * Converts all Unicode characters in the string that have a case
1110  * to lowercase. The exact manner that this is done depends
1111  * on the current locale, and may result in the number of
1112  * characters in the string changing.
1113  * 
1114  * Return value: a newly allocated string, with all characters
1115  *    converted to lowercase.  
1116  **/
1117 gchar *
1118 g_utf8_strdown (const gchar *str,
1119                 gssize       len)
1120 {
1121   gsize result_len;
1122   LocaleType locale_type;
1123   gchar *result;
1124
1125   g_return_val_if_fail (str != NULL, NULL);
1126
1127   locale_type = get_locale_type ();
1128   
1129   /*
1130    * We use a two pass approach to keep memory management simple
1131    */
1132   result_len = real_tolower (str, len, NULL, locale_type);
1133   result = g_malloc (result_len + 1);
1134   real_tolower (str, len, result, locale_type);
1135   result[result_len] = '\0';
1136
1137   return result;
1138 }
1139
1140 /**
1141  * g_utf8_casefold:
1142  * @str: a UTF-8 encoded string
1143  * @len: length of @str, in bytes, or -1 if @str is nul-terminated.
1144  * 
1145  * Converts a string into a form that is independent of case. The
1146  * result will not correspond to any particular case, but can be
1147  * compared for equality or ordered with the results of calling
1148  * g_utf8_casefold() on other strings.
1149  * 
1150  * Note that calling g_utf8_casefold() followed by g_utf8_collate() is
1151  * only an approximation to the correct linguistic case insensitive
1152  * ordering, though it is a fairly good one. Getting this exactly
1153  * right would require a more sophisticated collation function that
1154  * takes case sensitivity into account. GLib does not currently
1155  * provide such a function.
1156  * 
1157  * Return value: a newly allocated string, that is a
1158  *   case independent form of @str.
1159  **/
1160 gchar *
1161 g_utf8_casefold (const gchar *str,
1162                  gssize       len)
1163 {
1164   GString *result;
1165   const char *p;
1166
1167   g_return_val_if_fail (str != NULL, NULL);
1168
1169   result = g_string_new (NULL);
1170   p = str;
1171   while ((len < 0 || p < str + len) && *p)
1172     {
1173       gunichar ch = g_utf8_get_char (p);
1174
1175       int start = 0;
1176       int end = G_N_ELEMENTS (casefold_table);
1177
1178       if (ch >= casefold_table[start].ch &&
1179           ch <= casefold_table[end - 1].ch)
1180         {
1181           while (TRUE)
1182             {
1183               int half = (start + end) / 2;
1184               if (ch == casefold_table[half].ch)
1185                 {
1186                   g_string_append (result, casefold_table[half].data);
1187                   goto next;
1188                 }
1189               else if (half == start)
1190                 break;
1191               else if (ch > casefold_table[half].ch)
1192                 start = half;
1193               else
1194                 end = half;
1195             }
1196         }
1197
1198       g_string_append_unichar (result, g_unichar_tolower (ch));
1199       
1200     next:
1201       p = g_utf8_next_char (p);
1202     }
1203
1204   return g_string_free (result, FALSE); 
1205 }
1206
1207 /**
1208  * g_unichar_get_mirror_char:
1209  * @ch: a Unicode character
1210  * @mirrored_ch: location to store the mirrored character
1211  * 
1212  * In Unicode, some characters are <firstterm>mirrored</firstterm>. This
1213  * means that their images are mirrored horizontally in text that is laid
1214  * out from right to left. For instance, "(" would become its mirror image,
1215  * ")", in right-to-left text.
1216  *
1217  * If @ch has the Unicode mirrored property and there is another unicode
1218  * character that typically has a glyph that is the mirror image of @ch's
1219  * glyph and @mirrored_ch is set, it puts that character in the address
1220  * pointed to by @mirrored_ch.  Otherwise the original character is put.
1221  *
1222  * Return value: %TRUE if @ch has a mirrored character, %FALSE otherwise
1223  *
1224  * Since: 2.4
1225  **/
1226 gboolean
1227 g_unichar_get_mirror_char (gunichar ch,
1228                            gunichar *mirrored_ch)
1229 {
1230   gboolean found;
1231   gunichar mirrored;
1232
1233   mirrored = GLIB_GET_MIRRORING(ch);
1234
1235   found = ch != mirrored;
1236   if (mirrored_ch)
1237     *mirrored_ch = mirrored;
1238
1239   return found;
1240
1241 }
1242
1243 #define G_SCRIPT_TABLE_MIDPOINT (G_N_ELEMENTS (g_script_table) / 2)
1244
1245 static inline GUnicodeScript
1246 g_unichar_get_script_bsearch (gunichar ch)
1247 {
1248   int lower = 0;
1249   int upper = G_N_ELEMENTS (g_script_table) - 1;
1250   static int saved_mid = G_SCRIPT_TABLE_MIDPOINT;
1251   int mid = saved_mid;
1252
1253
1254   do 
1255     {
1256       if (ch < g_script_table[mid].start)
1257         upper = mid - 1;
1258       else if (ch >= g_script_table[mid].start + g_script_table[mid].chars)
1259         lower = mid + 1;
1260       else
1261         return g_script_table[saved_mid = mid].script;
1262
1263       mid = (lower + upper) / 2;
1264     }
1265   while (lower <= upper);
1266
1267   return G_UNICODE_SCRIPT_UNKNOWN;
1268 }
1269
1270 /**
1271  * g_unichar_get_script:
1272  * @ch: a Unicode character
1273  * 
1274  * Looks up the #GUnicodeScript for a particular character (as defined 
1275  * by Unicode Standard Annex #24). No check is made for @ch being a
1276  * valid Unicode character; if you pass in invalid character, the
1277  * result is undefined.
1278  *
1279  * This function is equivalent to pango_script_for_unichar() and the
1280  * two are interchangeable.
1281  * 
1282  * Return value: the #GUnicodeScript for the character.
1283  *
1284  * Since: 2.14
1285  */
1286 GUnicodeScript
1287 g_unichar_get_script (gunichar ch)
1288 {
1289   if (ch < G_EASY_SCRIPTS_RANGE)
1290     return g_script_easy_table[ch];
1291   else 
1292     return g_unichar_get_script_bsearch (ch); 
1293 }
1294
1295
1296 #define __G_UNIPROP_C__
1297 #include "galiasdef.c"