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