svn path=/trunk/; revision=5482
[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 /**
418  * g_unichar_iswide:
419  * @c: a Unicode character
420  * 
421  * Determines if a character is typically rendered in a double-width
422  * cell.
423  * 
424  * Return value: %TRUE if the character is wide
425  **/
426 /* This function stolen from Markus Kuhn <Markus.Kuhn@cl.cam.ac.uk>.  */
427 gboolean
428 g_unichar_iswide (gunichar c)
429 {
430   if (c < 0x1100)
431     return FALSE;
432
433   return (c <= 0x115f  /* Hangul Jamo init. consonants */ 
434           || c == 0x2329 || c == 0x232a     /* angle brackets */
435           || (c >= 0x2e80 && c <= 0xa4cf && (c < 0x302a || c > 0x302f) 
436               && c != 0x303f && c != 0x3099 && c!= 0x309a) /* CJK ... Yi */
437           || (c >= 0xac00 && c <= 0xd7a3)   /* Hangul Syllables */
438           || (c >= 0xf900 && c <= 0xfaff)   /* CJK Compatibility Ideographs */
439           || (c >= 0xfe30 && c <= 0xfe6f)   /* CJK Compatibility Forms */
440           || (c >= 0xff00 && c <= 0xff60)   /* Fullwidth Forms */
441           || (c >= 0xffe0 && c <= 0xffe6)   /* Fullwidth Forms */
442           || (c >= 0x20000 && c <= 0x2fffd) /* CJK extra stuff */
443           || (c >= 0x30000 && c <= 0x3fffd));
444 }
445
446
447 struct Interval
448 {
449   gunichar start, end;
450 };
451
452 static int
453 interval_compare (const void *key, const void *elt)
454 {
455   gunichar c = GPOINTER_TO_UINT (key);
456   struct Interval *interval = (struct Interval *)elt;
457
458   if (c < interval->start)
459     return -1;
460   if (c > interval->end)
461     return +1;
462
463   return 0;
464 }
465
466 /**
467  * g_unichar_iswide_cjk:
468  * @c: a Unicode character
469  * 
470  * Determines if a character is typically rendered in a double-width
471  * cell under legacy East Asian locales.  If a character is wide according to
472  * g_unichar_iswide(), then it is also reported wide with this function, but
473  * the converse is not necessarily true.  See the
474  * <ulink url="http://www.unicode.org/reports/tr11/">Unicode Standard
475  * Annex #11</ulink> for details.
476  * 
477  * Return value: %TRUE if the character is wide in legacy East Asian locales
478  *
479  * Since: 2.12
480  */
481 /* This function stolen from Markus Kuhn <Markus.Kuhn@cl.cam.ac.uk>.  */
482 gboolean
483 g_unichar_iswide_cjk (gunichar c)
484 {
485   /* sorted list of non-overlapping intervals of East Asian Ambiguous
486    * characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c" */
487   static const struct Interval ambiguous[] = {
488     { 0x00A1, 0x00A1 }, { 0x00A4, 0x00A4 }, { 0x00A7, 0x00A8 },
489     { 0x00AA, 0x00AA }, { 0x00AE, 0x00AE }, { 0x00B0, 0x00B4 },
490     { 0x00B6, 0x00BA }, { 0x00BC, 0x00BF }, { 0x00C6, 0x00C6 },
491     { 0x00D0, 0x00D0 }, { 0x00D7, 0x00D8 }, { 0x00DE, 0x00E1 },
492     { 0x00E6, 0x00E6 }, { 0x00E8, 0x00EA }, { 0x00EC, 0x00ED },
493     { 0x00F0, 0x00F0 }, { 0x00F2, 0x00F3 }, { 0x00F7, 0x00FA },
494     { 0x00FC, 0x00FC }, { 0x00FE, 0x00FE }, { 0x0101, 0x0101 },
495     { 0x0111, 0x0111 }, { 0x0113, 0x0113 }, { 0x011B, 0x011B },
496     { 0x0126, 0x0127 }, { 0x012B, 0x012B }, { 0x0131, 0x0133 },
497     { 0x0138, 0x0138 }, { 0x013F, 0x0142 }, { 0x0144, 0x0144 },
498     { 0x0148, 0x014B }, { 0x014D, 0x014D }, { 0x0152, 0x0153 },
499     { 0x0166, 0x0167 }, { 0x016B, 0x016B }, { 0x01CE, 0x01CE },
500     { 0x01D0, 0x01D0 }, { 0x01D2, 0x01D2 }, { 0x01D4, 0x01D4 },
501     { 0x01D6, 0x01D6 }, { 0x01D8, 0x01D8 }, { 0x01DA, 0x01DA },
502     { 0x01DC, 0x01DC }, { 0x0251, 0x0251 }, { 0x0261, 0x0261 },
503     { 0x02C4, 0x02C4 }, { 0x02C7, 0x02C7 }, { 0x02C9, 0x02CB },
504     { 0x02CD, 0x02CD }, { 0x02D0, 0x02D0 }, { 0x02D8, 0x02DB },
505     { 0x02DD, 0x02DD }, { 0x02DF, 0x02DF }, { 0x0391, 0x03A1 },
506     { 0x03A3, 0x03A9 }, { 0x03B1, 0x03C1 }, { 0x03C3, 0x03C9 },
507     { 0x0401, 0x0401 }, { 0x0410, 0x044F }, { 0x0451, 0x0451 },
508     { 0x2010, 0x2010 }, { 0x2013, 0x2016 }, { 0x2018, 0x2019 },
509     { 0x201C, 0x201D }, { 0x2020, 0x2022 }, { 0x2024, 0x2027 },
510     { 0x2030, 0x2030 }, { 0x2032, 0x2033 }, { 0x2035, 0x2035 },
511     { 0x203B, 0x203B }, { 0x203E, 0x203E }, { 0x2074, 0x2074 },
512     { 0x207F, 0x207F }, { 0x2081, 0x2084 }, { 0x20AC, 0x20AC },
513     { 0x2103, 0x2103 }, { 0x2105, 0x2105 }, { 0x2109, 0x2109 },
514     { 0x2113, 0x2113 }, { 0x2116, 0x2116 }, { 0x2121, 0x2122 },
515     { 0x2126, 0x2126 }, { 0x212B, 0x212B }, { 0x2153, 0x2154 },
516     { 0x215B, 0x215E }, { 0x2160, 0x216B }, { 0x2170, 0x2179 },
517     { 0x2190, 0x2199 }, { 0x21B8, 0x21B9 }, { 0x21D2, 0x21D2 },
518     { 0x21D4, 0x21D4 }, { 0x21E7, 0x21E7 }, { 0x2200, 0x2200 },
519     { 0x2202, 0x2203 }, { 0x2207, 0x2208 }, { 0x220B, 0x220B },
520     { 0x220F, 0x220F }, { 0x2211, 0x2211 }, { 0x2215, 0x2215 },
521     { 0x221A, 0x221A }, { 0x221D, 0x2220 }, { 0x2223, 0x2223 },
522     { 0x2225, 0x2225 }, { 0x2227, 0x222C }, { 0x222E, 0x222E },
523     { 0x2234, 0x2237 }, { 0x223C, 0x223D }, { 0x2248, 0x2248 },
524     { 0x224C, 0x224C }, { 0x2252, 0x2252 }, { 0x2260, 0x2261 },
525     { 0x2264, 0x2267 }, { 0x226A, 0x226B }, { 0x226E, 0x226F },
526     { 0x2282, 0x2283 }, { 0x2286, 0x2287 }, { 0x2295, 0x2295 },
527     { 0x2299, 0x2299 }, { 0x22A5, 0x22A5 }, { 0x22BF, 0x22BF },
528     { 0x2312, 0x2312 }, { 0x2460, 0x24E9 }, { 0x24EB, 0x254B },
529     { 0x2550, 0x2573 }, { 0x2580, 0x258F }, { 0x2592, 0x2595 },
530     { 0x25A0, 0x25A1 }, { 0x25A3, 0x25A9 }, { 0x25B2, 0x25B3 },
531     { 0x25B6, 0x25B7 }, { 0x25BC, 0x25BD }, { 0x25C0, 0x25C1 },
532     { 0x25C6, 0x25C8 }, { 0x25CB, 0x25CB }, { 0x25CE, 0x25D1 },
533     { 0x25E2, 0x25E5 }, { 0x25EF, 0x25EF }, { 0x2605, 0x2606 },
534     { 0x2609, 0x2609 }, { 0x260E, 0x260F }, { 0x2614, 0x2615 },
535     { 0x261C, 0x261C }, { 0x261E, 0x261E }, { 0x2640, 0x2640 },
536     { 0x2642, 0x2642 }, { 0x2660, 0x2661 }, { 0x2663, 0x2665 },
537     { 0x2667, 0x266A }, { 0x266C, 0x266D }, { 0x266F, 0x266F },
538     { 0x273D, 0x273D }, { 0x2776, 0x277F }, { 0xE000, 0xF8FF },
539     { 0xFFFD, 0xFFFD }, { 0xF0000, 0xFFFFD }, { 0x100000, 0x10FFFD }
540   };
541
542   if (g_unichar_iswide (c))
543     return TRUE;
544
545   if (bsearch (GUINT_TO_POINTER (c), ambiguous, G_N_ELEMENTS (ambiguous), sizeof ambiguous[0],
546                interval_compare))
547     return TRUE;
548
549   return FALSE;
550 }
551
552
553 /**
554  * g_unichar_toupper:
555  * @c: a Unicode character
556  * 
557  * Converts a character to uppercase.
558  * 
559  * Return value: the result of converting @c to uppercase.
560  *               If @c is not an lowercase or titlecase character,
561  *               or has no upper case equivalent @c is returned unchanged.
562  **/
563 gunichar
564 g_unichar_toupper (gunichar c)
565 {
566   int t = TYPE (c);
567   if (t == G_UNICODE_LOWERCASE_LETTER)
568     {
569       gunichar val = ATTTABLE (c >> 8, c & 0xff);
570       if (val >= 0x1000000)
571         {
572           const gchar *p = special_case_table + val - 0x1000000;
573           val = g_utf8_get_char (p);
574         }
575       /* Some lowercase letters, e.g., U+000AA, FEMININE ORDINAL INDICATOR,
576        * do not have an uppercase equivalent, in which case val will be
577        * zero. 
578        */
579       return val ? val : c;
580     }
581   else if (t == G_UNICODE_TITLECASE_LETTER)
582     {
583       unsigned int i;
584       for (i = 0; i < G_N_ELEMENTS (title_table); ++i)
585         {
586           if (title_table[i][0] == c)
587             return title_table[i][1];
588         }
589     }
590   return c;
591 }
592
593 /**
594  * g_unichar_tolower:
595  * @c: a Unicode character.
596  * 
597  * Converts a character to lower case.
598  * 
599  * Return value: the result of converting @c to lower case.
600  *               If @c is not an upperlower or titlecase character,
601  *               or has no lowercase equivalent @c is returned unchanged.
602  **/
603 gunichar
604 g_unichar_tolower (gunichar c)
605 {
606   int t = TYPE (c);
607   if (t == G_UNICODE_UPPERCASE_LETTER)
608     {
609       gunichar val = ATTTABLE (c >> 8, c & 0xff);
610       if (val >= 0x1000000)
611         {
612           const gchar *p = special_case_table + val - 0x1000000;
613           return g_utf8_get_char (p);
614         }
615       else
616         {
617           /* Not all uppercase letters are guaranteed to have a lowercase
618            * equivalent.  If this is the case, val will be zero. */
619           return val ? val : c;
620         }
621     }
622   else if (t == G_UNICODE_TITLECASE_LETTER)
623     {
624       unsigned int i;
625       for (i = 0; i < G_N_ELEMENTS (title_table); ++i)
626         {
627           if (title_table[i][0] == c)
628             return title_table[i][2];
629         }
630     }
631   return c;
632 }
633
634 /**
635  * g_unichar_totitle:
636  * @c: a Unicode character
637  * 
638  * Converts a character to the titlecase.
639  * 
640  * Return value: the result of converting @c to titlecase.
641  *               If @c is not an uppercase or lowercase character,
642  *               @c is returned unchanged.
643  **/
644 gunichar
645 g_unichar_totitle (gunichar c)
646 {
647   unsigned int i;
648   for (i = 0; i < G_N_ELEMENTS (title_table); ++i)
649     {
650       if (title_table[i][0] == c || title_table[i][1] == c
651           || title_table[i][2] == c)
652         return title_table[i][0];
653     }
654     
655   if (TYPE (c) == G_UNICODE_LOWERCASE_LETTER)
656     return g_unichar_toupper (c);
657
658   return c;
659 }
660
661 /**
662  * g_unichar_digit_value:
663  * @c: a Unicode character
664  *
665  * Determines the numeric value of a character as a decimal
666  * digit.
667  *
668  * Return value: If @c is a decimal digit (according to
669  * g_unichar_isdigit()), its numeric value. Otherwise, -1.
670  **/
671 int
672 g_unichar_digit_value (gunichar c)
673 {
674   if (TYPE (c) == G_UNICODE_DECIMAL_NUMBER)
675     return ATTTABLE (c >> 8, c & 0xff);
676   return -1;
677 }
678
679 /**
680  * g_unichar_xdigit_value:
681  * @c: a Unicode character
682  *
683  * Determines the numeric value of a character as a hexidecimal
684  * digit.
685  *
686  * Return value: If @c is a hex digit (according to
687  * g_unichar_isxdigit()), its numeric value. Otherwise, -1.
688  **/
689 int
690 g_unichar_xdigit_value (gunichar c)
691 {
692   if (c >= 'A' && c <= 'F')
693     return c - 'A' + 10;
694   if (c >= 'a' && c <= 'f')
695     return c - 'a' + 10;
696   if (TYPE (c) == G_UNICODE_DECIMAL_NUMBER)
697     return ATTTABLE (c >> 8, c & 0xff);
698   return -1;
699 }
700
701 /**
702  * g_unichar_type:
703  * @c: a Unicode character
704  * 
705  * Classifies a Unicode character by type.
706  * 
707  * Return value: the type of the character.
708  **/
709 GUnicodeType
710 g_unichar_type (gunichar c)
711 {
712   return TYPE (c);
713 }
714
715 /*
716  * Case mapping functions
717  */
718
719 typedef enum {
720   LOCALE_NORMAL,
721   LOCALE_TURKIC,
722   LOCALE_LITHUANIAN
723 } LocaleType;
724
725 static LocaleType
726 get_locale_type (void)
727 {
728 #ifdef G_OS_WIN32
729   char *tem = g_win32_getlocale ();
730   char locale[2];
731
732   locale[0] = tem[0];
733   locale[1] = tem[1];
734   g_free (tem);
735 #else
736   const char *locale = setlocale (LC_CTYPE, NULL);
737 #endif
738
739   switch (locale[0])
740     {
741    case 'a':
742       if (locale[1] == 'z')
743         return LOCALE_TURKIC;
744       break;
745     case 'l':
746       if (locale[1] == 't')
747         return LOCALE_LITHUANIAN;
748       break;
749     case 't':
750       if (locale[1] == 'r')
751         return LOCALE_TURKIC;
752       break;
753     }
754
755   return LOCALE_NORMAL;
756 }
757
758 static gint
759 output_marks (const char **p_inout,
760               char        *out_buffer,
761               gboolean     remove_dot)
762 {
763   const char *p = *p_inout;
764   gint len = 0;
765   
766   while (*p)
767     {
768       gunichar c = g_utf8_get_char (p);
769       
770       if (ISMARK (TYPE (c)))
771         {
772           if (!remove_dot || c != 0x307 /* COMBINING DOT ABOVE */)
773             len += g_unichar_to_utf8 (c, out_buffer ? out_buffer + len : NULL);
774           p = g_utf8_next_char (p);
775         }
776       else
777         break;
778     }
779
780   *p_inout = p;
781   return len;
782 }
783
784 static gint
785 output_special_case (gchar *out_buffer,
786                      int    offset,
787                      int    type,
788                      int    which)
789 {
790   const gchar *p = special_case_table + offset;
791   gint len;
792
793   if (type != G_UNICODE_TITLECASE_LETTER)
794     p = g_utf8_next_char (p);
795
796   if (which == 1)
797     p += strlen (p) + 1;
798
799   len = strlen (p);
800   if (out_buffer)
801     memcpy (out_buffer, p, len);
802
803   return len;
804 }
805
806 static gsize
807 real_toupper (const gchar *str,
808               gssize       max_len,
809               gchar       *out_buffer,
810               LocaleType   locale_type)
811 {
812   const gchar *p = str;
813   const char *last = NULL;
814   gsize len = 0;
815   gboolean last_was_i = FALSE;
816
817   while ((max_len < 0 || p < str + max_len) && *p)
818     {
819       gunichar c = g_utf8_get_char (p);
820       int t = TYPE (c);
821       gunichar val;
822
823       last = p;
824       p = g_utf8_next_char (p);
825
826       if (locale_type == LOCALE_LITHUANIAN)
827         {
828           if (c == 'i')
829             last_was_i = TRUE;
830           else 
831             {
832               if (last_was_i)
833                 {
834                   /* Nasty, need to remove any dot above. Though
835                    * I think only E WITH DOT ABOVE occurs in practice
836                    * which could simplify this considerably.
837                    */
838                   gsize decomp_len, i;
839                   gunichar *decomp;
840
841                   decomp = g_unicode_canonical_decomposition (c, &decomp_len);
842                   for (i=0; i < decomp_len; i++)
843                     {
844                       if (decomp[i] != 0x307 /* COMBINING DOT ABOVE */)
845                         len += g_unichar_to_utf8 (g_unichar_toupper (decomp[i]), out_buffer ? out_buffer + len : NULL);
846                     }
847                   g_free (decomp);
848                   
849                   len += output_marks (&p, out_buffer ? out_buffer + len : NULL, TRUE);
850
851                   continue;
852                 }
853
854               if (!ISMARK (t))
855                 last_was_i = FALSE;
856             }
857         }
858       
859       if (locale_type == LOCALE_TURKIC && c == 'i')
860         {
861           /* i => LATIN CAPITAL LETTER I WITH DOT ABOVE */
862           len += g_unichar_to_utf8 (0x130, out_buffer ? out_buffer + len : NULL); 
863         }
864       else if (c == 0x0345)     /* COMBINING GREEK YPOGEGRAMMENI */
865         {
866           /* Nasty, need to move it after other combining marks .. this would go away if
867            * we normalized first.
868            */
869           len += output_marks (&p, out_buffer ? out_buffer + len : NULL, FALSE);
870
871           /* And output as GREEK CAPITAL LETTER IOTA */
872           len += g_unichar_to_utf8 (0x399, out_buffer ? out_buffer + len : NULL);         
873         }
874       else if (IS (t,
875                    OR (G_UNICODE_LOWERCASE_LETTER,
876                    OR (G_UNICODE_TITLECASE_LETTER,
877                   0))))
878         {
879           val = ATTTABLE (c >> 8, c & 0xff);
880
881           if (val >= 0x1000000)
882             {
883               len += output_special_case (out_buffer ? out_buffer + len : NULL, val - 0x1000000, t,
884                                           t == G_UNICODE_LOWERCASE_LETTER ? 0 : 1);
885             }
886           else
887             {
888               if (t == G_UNICODE_TITLECASE_LETTER)
889                 {
890                   unsigned int i;
891                   for (i = 0; i < G_N_ELEMENTS (title_table); ++i)
892                     {
893                       if (title_table[i][0] == c)
894                         {
895                           val = title_table[i][1];
896                           break;
897                         }
898                     }
899                 }
900
901               /* Some lowercase letters, e.g., U+000AA, FEMININE ORDINAL INDICATOR,
902                * do not have an uppercase equivalent, in which case val will be
903                * zero. */
904               len += g_unichar_to_utf8 (val ? val : c, out_buffer ? out_buffer + len : NULL);
905             }
906         }
907       else
908         {
909           gsize char_len = g_utf8_skip[*(guchar *)last];
910
911           if (out_buffer)
912             memcpy (out_buffer + len, last, char_len);
913
914           len += char_len;
915         }
916
917     }
918
919   return len;
920 }
921
922 /**
923  * g_utf8_strup:
924  * @str: a UTF-8 encoded string
925  * @len: length of @str, in bytes, or -1 if @str is nul-terminated.
926  * 
927  * Converts all Unicode characters in the string that have a case
928  * to uppercase. The exact manner that this is done depends
929  * on the current locale, and may result in the number of
930  * characters in the string increasing. (For instance, the
931  * German ess-zet will be changed to SS.)
932  * 
933  * Return value: a newly allocated string, with all characters
934  *    converted to uppercase.  
935  **/
936 gchar *
937 g_utf8_strup (const gchar *str,
938               gssize       len)
939 {
940   gsize result_len;
941   LocaleType locale_type;
942   gchar *result;
943
944   g_return_val_if_fail (str != NULL, NULL);
945
946   locale_type = get_locale_type ();
947   
948   /*
949    * We use a two pass approach to keep memory management simple
950    */
951   result_len = real_toupper (str, len, NULL, locale_type);
952   result = g_malloc (result_len + 1);
953   real_toupper (str, len, result, locale_type);
954   result[result_len] = '\0';
955
956   return result;
957 }
958
959 /* traverses the string checking for characters with combining class == 230
960  * until a base character is found */
961 static gboolean
962 has_more_above (const gchar *str)
963 {
964   const gchar *p = str;
965   gint combining_class;
966
967   while (*p)
968     {
969       combining_class = _g_unichar_combining_class (g_utf8_get_char (p));
970       if (combining_class == 230)
971         return TRUE;
972       else if (combining_class == 0)
973         break;
974
975       p = g_utf8_next_char (p);
976     }
977
978   return FALSE;
979 }
980
981 static gsize
982 real_tolower (const gchar *str,
983               gssize       max_len,
984               gchar       *out_buffer,
985               LocaleType   locale_type)
986 {
987   const gchar *p = str;
988   const char *last = NULL;
989   gsize len = 0;
990
991   while ((max_len < 0 || p < str + max_len) && *p)
992     {
993       gunichar c = g_utf8_get_char (p);
994       int t = TYPE (c);
995       gunichar val;
996
997       last = p;
998       p = g_utf8_next_char (p);
999
1000       if (locale_type == LOCALE_TURKIC && c == 'I')
1001         {
1002           if (g_utf8_get_char (p) == 0x0307)
1003             {
1004               /* I + COMBINING DOT ABOVE => i (U+0069) */
1005               len += g_unichar_to_utf8 (0x0069, out_buffer ? out_buffer + len : NULL); 
1006               p = g_utf8_next_char (p);
1007             }
1008           else
1009             {
1010               /* I => LATIN SMALL LETTER DOTLESS I */
1011               len += g_unichar_to_utf8 (0x131, out_buffer ? out_buffer + len : NULL); 
1012             }
1013         }
1014       /* Introduce an explicit dot above when lowercasing capital I's and J's
1015        * whenever there are more accents above. [SpecialCasing.txt] */
1016       else if (locale_type == LOCALE_LITHUANIAN && 
1017                (c == 0x00cc || c == 0x00cd || c == 0x0128))
1018         {
1019           len += g_unichar_to_utf8 (0x0069, out_buffer ? out_buffer + len : NULL); 
1020           len += g_unichar_to_utf8 (0x0307, out_buffer ? out_buffer + len : NULL); 
1021
1022           switch (c)
1023             {
1024             case 0x00cc: 
1025               len += g_unichar_to_utf8 (0x0300, out_buffer ? out_buffer + len : NULL); 
1026               break;
1027             case 0x00cd: 
1028               len += g_unichar_to_utf8 (0x0301, out_buffer ? out_buffer + len : NULL); 
1029               break;
1030             case 0x0128: 
1031               len += g_unichar_to_utf8 (0x0303, out_buffer ? out_buffer + len : NULL); 
1032               break;
1033             }
1034         }
1035       else if (locale_type == LOCALE_LITHUANIAN && 
1036                (c == 'I' || c == 'J' || c == 0x012e) && 
1037                has_more_above (p))
1038         {
1039           len += g_unichar_to_utf8 (g_unichar_tolower (c), out_buffer ? out_buffer + len : NULL); 
1040           len += g_unichar_to_utf8 (0x0307, out_buffer ? out_buffer + len : NULL); 
1041         }
1042       else if (c == 0x03A3)     /* GREEK CAPITAL LETTER SIGMA */
1043         {
1044           if ((max_len < 0 || p < str + max_len) && *p)
1045             {
1046               gunichar next_c = g_utf8_get_char (p);
1047               int next_type = TYPE(next_c);
1048
1049               /* SIGMA mapps differently depending on whether it is
1050                * final or not. The following simplified test would
1051                * fail in the case of combining marks following the
1052                * sigma, but I don't think that occurs in real text.
1053                * The test here matches that in ICU.
1054                */
1055               if (ISALPHA (next_type)) /* Lu,Ll,Lt,Lm,Lo */
1056                 val = 0x3c3;    /* GREEK SMALL SIGMA */
1057               else
1058                 val = 0x3c2;    /* GREEK SMALL FINAL SIGMA */
1059             }
1060           else
1061             val = 0x3c2;        /* GREEK SMALL FINAL SIGMA */
1062
1063           len += g_unichar_to_utf8 (val, out_buffer ? out_buffer + len : NULL);
1064         }
1065       else if (IS (t,
1066                    OR (G_UNICODE_UPPERCASE_LETTER,
1067                    OR (G_UNICODE_TITLECASE_LETTER,
1068                   0))))
1069         {
1070           val = ATTTABLE (c >> 8, c & 0xff);
1071
1072           if (val >= 0x1000000)
1073             {
1074               len += output_special_case (out_buffer ? out_buffer + len : NULL, val - 0x1000000, t, 0);
1075             }
1076           else
1077             {
1078               if (t == G_UNICODE_TITLECASE_LETTER)
1079                 {
1080                   unsigned int i;
1081                   for (i = 0; i < G_N_ELEMENTS (title_table); ++i)
1082                     {
1083                       if (title_table[i][0] == c)
1084                         {
1085                           val = title_table[i][2];
1086                           break;
1087                         }
1088                     }
1089                 }
1090
1091               /* Not all uppercase letters are guaranteed to have a lowercase
1092                * equivalent.  If this is the case, val will be zero. */
1093               len += g_unichar_to_utf8 (val ? val : c, out_buffer ? out_buffer + len : NULL);
1094             }
1095         }
1096       else
1097         {
1098           gsize char_len = g_utf8_skip[*(guchar *)last];
1099
1100           if (out_buffer)
1101             memcpy (out_buffer + len, last, char_len);
1102
1103           len += char_len;
1104         }
1105
1106     }
1107
1108   return len;
1109 }
1110
1111 /**
1112  * g_utf8_strdown:
1113  * @str: a UTF-8 encoded string
1114  * @len: length of @str, in bytes, or -1 if @str is nul-terminated.
1115  * 
1116  * Converts all Unicode characters in the string that have a case
1117  * to lowercase. The exact manner that this is done depends
1118  * on the current locale, and may result in the number of
1119  * characters in the string changing.
1120  * 
1121  * Return value: a newly allocated string, with all characters
1122  *    converted to lowercase.  
1123  **/
1124 gchar *
1125 g_utf8_strdown (const gchar *str,
1126                 gssize       len)
1127 {
1128   gsize result_len;
1129   LocaleType locale_type;
1130   gchar *result;
1131
1132   g_return_val_if_fail (str != NULL, NULL);
1133
1134   locale_type = get_locale_type ();
1135   
1136   /*
1137    * We use a two pass approach to keep memory management simple
1138    */
1139   result_len = real_tolower (str, len, NULL, locale_type);
1140   result = g_malloc (result_len + 1);
1141   real_tolower (str, len, result, locale_type);
1142   result[result_len] = '\0';
1143
1144   return result;
1145 }
1146
1147 /**
1148  * g_utf8_casefold:
1149  * @str: a UTF-8 encoded string
1150  * @len: length of @str, in bytes, or -1 if @str is nul-terminated.
1151  * 
1152  * Converts a string into a form that is independent of case. The
1153  * result will not correspond to any particular case, but can be
1154  * compared for equality or ordered with the results of calling
1155  * g_utf8_casefold() on other strings.
1156  * 
1157  * Note that calling g_utf8_casefold() followed by g_utf8_collate() is
1158  * only an approximation to the correct linguistic case insensitive
1159  * ordering, though it is a fairly good one. Getting this exactly
1160  * right would require a more sophisticated collation function that
1161  * takes case sensitivity into account. GLib does not currently
1162  * provide such a function.
1163  * 
1164  * Return value: a newly allocated string, that is a
1165  *   case independent form of @str.
1166  **/
1167 gchar *
1168 g_utf8_casefold (const gchar *str,
1169                  gssize       len)
1170 {
1171   GString *result;
1172   const char *p;
1173
1174   g_return_val_if_fail (str != NULL, NULL);
1175
1176   result = g_string_new (NULL);
1177   p = str;
1178   while ((len < 0 || p < str + len) && *p)
1179     {
1180       gunichar ch = g_utf8_get_char (p);
1181
1182       int start = 0;
1183       int end = G_N_ELEMENTS (casefold_table);
1184
1185       if (ch >= casefold_table[start].ch &&
1186           ch <= casefold_table[end - 1].ch)
1187         {
1188           while (TRUE)
1189             {
1190               int half = (start + end) / 2;
1191               if (ch == casefold_table[half].ch)
1192                 {
1193                   g_string_append (result, casefold_table[half].data);
1194                   goto next;
1195                 }
1196               else if (half == start)
1197                 break;
1198               else if (ch > casefold_table[half].ch)
1199                 start = half;
1200               else
1201                 end = half;
1202             }
1203         }
1204
1205       g_string_append_unichar (result, g_unichar_tolower (ch));
1206       
1207     next:
1208       p = g_utf8_next_char (p);
1209     }
1210
1211   return g_string_free (result, FALSE); 
1212 }
1213
1214 /**
1215  * g_unichar_get_mirror_char:
1216  * @ch: a Unicode character
1217  * @mirrored_ch: location to store the mirrored character
1218  * 
1219  * In Unicode, some characters are <firstterm>mirrored</firstterm>. This
1220  * means that their images are mirrored horizontally in text that is laid
1221  * out from right to left. For instance, "(" would become its mirror image,
1222  * ")", in right-to-left text.
1223  *
1224  * If @ch has the Unicode mirrored property and there is another unicode
1225  * character that typically has a glyph that is the mirror image of @ch's
1226  * glyph and @mirrored_ch is set, it puts that character in the address
1227  * pointed to by @mirrored_ch.  Otherwise the original character is put.
1228  *
1229  * Return value: %TRUE if @ch has a mirrored character, %FALSE otherwise
1230  *
1231  * Since: 2.4
1232  **/
1233 gboolean
1234 g_unichar_get_mirror_char (gunichar ch,
1235                            gunichar *mirrored_ch)
1236 {
1237   gboolean found;
1238   gunichar mirrored;
1239
1240   mirrored = GLIB_GET_MIRRORING(ch);
1241
1242   found = ch != mirrored;
1243   if (mirrored_ch)
1244     *mirrored_ch = mirrored;
1245
1246   return found;
1247
1248 }
1249
1250 #define G_SCRIPT_TABLE_MIDPOINT (G_N_ELEMENTS (g_script_table) / 2)
1251
1252 static inline GUnicodeScript
1253 g_unichar_get_script_bsearch (gunichar ch)
1254 {
1255   int lower = 0;
1256   int upper = G_N_ELEMENTS (g_script_table) - 1;
1257   static int saved_mid = G_SCRIPT_TABLE_MIDPOINT;
1258   int mid = saved_mid;
1259
1260
1261   do 
1262     {
1263       if (ch < g_script_table[mid].start)
1264         upper = mid - 1;
1265       else if (ch >= g_script_table[mid].start + g_script_table[mid].chars)
1266         lower = mid + 1;
1267       else
1268         return g_script_table[saved_mid = mid].script;
1269
1270       mid = (lower + upper) / 2;
1271     }
1272   while (lower <= upper);
1273
1274   return G_UNICODE_SCRIPT_UNKNOWN;
1275 }
1276
1277 /**
1278  * g_unichar_get_script:
1279  * @ch: a Unicode character
1280  * 
1281  * Looks up the #GUnicodeScript for a particular character (as defined 
1282  * by Unicode Standard Annex #24). No check is made for @ch being a
1283  * valid Unicode character; if you pass in invalid character, the
1284  * result is undefined.
1285  * 
1286  * Return value: the #GUnicodeScript for the character.
1287  *
1288  * Since: 2.14
1289  */
1290 GUnicodeScript
1291 g_unichar_get_script (gunichar ch)
1292 {
1293   if (ch < G_EASY_SCRIPTS_RANGE)
1294     return g_script_easy_table[ch];
1295   else 
1296     return g_unichar_get_script_bsearch (ch); 
1297 }
1298
1299
1300 #define __G_UNIPROP_C__
1301 #include "galiasdef.c"