applied patch from Andreas Persenius <ndap@swipnet.se> that updates the
[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 "glib.h"
23 #include "gunichartables.h"
24
25 #include <config.h>
26
27 #include <stddef.h>
28
29 #define asize(x)  ((sizeof (x)) / sizeof (x[0]))
30
31 #define ATTTABLE(Page, Char) \
32   ((attr_table[Page] == 0) ? 0 : (attr_table[Page][Char]))
33
34 /* We cheat a bit and cast type values to (char *).  We detect these
35    using the &0xff trick.  */
36 #define TTYPE(Page, Char) \
37   (((((int) type_table[Page]) & 0xff) == ((int) type_table[Page])) \
38    ? ((int) (type_table[Page])) \
39    : (type_table[Page][Char]))
40
41 #define TYPE(Char) (((Char) > (G_UNICODE_LAST_CHAR)) ? G_UNICODE_UNASSIGNED : TTYPE ((Char) >> 8, (Char) & 0xff))
42
43 #define ISDIGIT(Type) ((Type) == G_UNICODE_DECIMAL_NUMBER \
44                        || (Type) == G_UNICODE_LETTER_NUMBER \
45                        || (Type) == G_UNICODE_OTHER_NUMBER)
46
47 #define ISALPHA(Type) ((Type) == G_UNICODE_LOWERCASE_LETTER \
48                        || (Type) == G_UNICODE_UPPERCASE_LETTER \
49                        || (Type) == G_UNICODE_TITLECASE_LETTER \
50                        || (Type) == G_UNICODE_MODIFIER_LETTER \
51                        || (Type) == G_UNICODE_OTHER_LETTER)
52
53 gboolean
54 g_unichar_isalnum (gunichar c)
55 {
56   int t = TYPE (c);
57   return ISDIGIT (t) || ISALPHA (t);
58 }
59
60 gboolean
61 g_unichar_isalpha (gunichar c)
62 {
63   int t = TYPE (c);
64   return ISALPHA (t);
65 }
66
67 gboolean
68 g_unichar_iscntrl (gunichar c)
69 {
70   return TYPE (c) == G_UNICODE_CONTROL;
71 }
72
73 gboolean
74 g_unichar_isdigit (gunichar c)
75 {
76   return TYPE (c) == G_UNICODE_DECIMAL_NUMBER;
77 }
78
79 gboolean
80 g_unichar_isgraph (gunichar c)
81 {
82   int t = TYPE (c);
83   return (t != G_UNICODE_CONTROL
84           && t != G_UNICODE_FORMAT
85           && t != G_UNICODE_UNASSIGNED
86           && t != G_UNICODE_PRIVATE_USE
87           && t != G_UNICODE_SURROGATE
88           && t != G_UNICODE_SPACE_SEPARATOR);
89 }
90
91 gboolean
92 g_unichar_islower (gunichar c)
93 {
94   return TYPE (c) == G_UNICODE_LOWERCASE_LETTER;
95 }
96
97 gboolean
98 g_unichar_isprint (gunichar c)
99 {
100   int t = TYPE (c);
101   return (t != G_UNICODE_CONTROL
102           && t != G_UNICODE_FORMAT
103           && t != G_UNICODE_UNASSIGNED
104           && t != G_UNICODE_PRIVATE_USE
105           && t != G_UNICODE_SURROGATE);
106 }
107
108 gboolean
109 g_unichar_ispunct (gunichar c)
110 {
111   int t = TYPE (c);
112   return (t == G_UNICODE_CONNECT_PUNCTUATION || t == G_UNICODE_DASH_PUNCTUATION
113           || t == G_UNICODE_CLOSE_PUNCTUATION || t == G_UNICODE_FINAL_PUNCTUATION
114           || t == G_UNICODE_INITIAL_PUNCTUATION || t == G_UNICODE_OTHER_PUNCTUATION
115           || t == G_UNICODE_OPEN_PUNCTUATION);
116 }
117
118 gboolean
119 g_unichar_isspace (gunichar c)
120 {
121   int t = TYPE (c);
122   return (t == G_UNICODE_SPACE_SEPARATOR || t == G_UNICODE_LINE_SEPARATOR
123           || t == G_UNICODE_PARAGRAPH_SEPARATOR);
124 }
125
126 /**
127  * g_unichar_isupper:
128  * @c: a unicode character
129  * 
130  * Determines if a character is uppercase.
131  * 
132  * Return value: 
133  **/
134 gboolean
135 g_unichar_isupper (gunichar c)
136 {
137   return TYPE (c) == G_UNICODE_UPPERCASE_LETTER;
138 }
139
140 /**
141  * g_unichar_istitle:
142  * @c: a unicode character
143  * 
144  * Determines if a character is titlecase. Some characters in
145  * Unicode which are composites, such as the DZ digraph
146  * have three case variants instead of just two. The titlecase
147  * form is used at the beginning of a word where only the
148  * first letter is capitalized. The titlecase form of the DZ
149  * digraph is U+01F2 LATIN CAPITAL LETTTER D WITH SMALL LETTER Z
150  * 
151  * Return value: %TRUE if the character is titlecase.
152  **/
153 gboolean
154 g_unichar_istitle (gunichar c)
155 {
156   unsigned int i;
157   for (i = 0; i < asize (title_table); ++i)
158     if (title_table[i][0] == c)
159       return 1;
160   return 0;
161 }
162
163 /**
164  * g_unichar_isxdigit:
165  * @c: a unicode character.
166  * 
167  * Determines if a characters is a hexidecimal digit
168  * 
169  * Return value: %TRUE if the character is a hexidecimal digit.
170  **/
171 gboolean
172 g_unichar_isxdigit (gunichar c)
173 {
174   int t = TYPE (c);
175   return ((c >= 'a' && c <= 'f')
176           || (c >= 'A' && c <= 'F')
177           || ISDIGIT (t));
178 }
179
180 /**
181  * g_unichar_isdefined:
182  * @c: a unicode character
183  * 
184  * Determines if a given character is assigned in the Unicode
185  * standard
186  *
187  * Return value: %TRUE if the character has an assigned value.
188  **/
189 gboolean
190 g_unichar_isdefined (gunichar c)
191 {
192   int t = TYPE (c);
193   return t != G_UNICODE_UNASSIGNED;
194 }
195
196 /**
197  * g_unichar_iswide:
198  * @c: a unicode character
199  * 
200  * Determines if a character is typically rendered in a double-width
201  * cell.
202  * 
203  * Return value: %TRUE if the character is wide.
204  **/
205 /* This function stolen from Markus Kuhn <Markus.Kuhn@cl.cam.ac.uk>.  */
206 gboolean
207 g_unichar_iswide (gunichar c)
208 {
209   if (c < 0x1100)
210     return 0;
211
212   return ((c >= 0x1100 && c <= 0x115f)     /* Hangul Jamo */
213           || (c >= 0x2e80 && c <= 0xa4cf && (c & ~0x0011) != 0x300a &&
214               c != 0x303f)                 /* CJK ... Yi */
215           || (c >= 0xac00 && c <= 0xd7a3)  /* Hangul Syllables */
216           || (c >= 0xf900 && c <= 0xfaff)  /* CJK Compatibility Ideographs */
217           || (c >= 0xfe30 && c <= 0xfe6f)  /* CJK Compatibility Forms */
218           || (c >= 0xff00 && c <= 0xff5f)  /* Fullwidth Forms */
219           || (c >= 0xffe0 && c <= 0xffe6));
220 }
221
222 /**
223  * g_unichar_toupper:
224  * @c: a unicode character
225  * 
226  * Convert a character to uppercase.
227  * 
228  * Return value: the result of converting @c to uppercase.
229  *               If @c is not an lowercase or titlecase character,
230  *               @c is returned unchanged.
231  **/
232 gunichar
233 g_unichar_toupper (gunichar c)
234 {
235   int t = TYPE (c);
236   if (t == G_UNICODE_LOWERCASE_LETTER)
237     return ATTTABLE (c >> 8, c & 0xff);
238   else if (t == G_UNICODE_TITLECASE_LETTER)
239     {
240       unsigned int i;
241       for (i = 0; i < asize (title_table); ++i)
242         {
243           if (title_table[i][0] == c)
244             return title_table[i][1];
245         }
246     }
247   return c;
248 }
249
250 /**
251  * g_unichar_tolower:
252  * @c: a unicode character.
253  * 
254  * Convert a character to lower case
255  * 
256 e * Return value: the result of converting @c to lower case.
257  *               If @c is not an upperlower or titlecase character,
258  *               @c is returned unchanged.
259  **/
260 gunichar
261 g_unichar_tolower (gunichar c)
262 {
263   int t = TYPE (c);
264   if (t == G_UNICODE_UPPERCASE_LETTER)
265     return ATTTABLE (c >> 8, c & 0xff);
266   else if (t == G_UNICODE_TITLECASE_LETTER)
267     {
268       unsigned int i;
269       for (i = 0; i < asize (title_table); ++i)
270         {
271           if (title_table[i][0] == c)
272             return title_table[i][2];
273         }
274     }
275   return c;
276 }
277
278 /**
279  * g_unichar_totitle:
280  * @c: a unicode character
281  * 
282  * Convert a character to the titlecase
283  * 
284  * Return value: the result of converting @c to titlecase.
285  *               If @c is not an uppercase or lowercase character,
286  *               @c is returned unchanged.
287  **/
288 gunichar
289 g_unichar_totitle (gunichar c)
290 {
291   unsigned int i;
292   for (i = 0; i < asize (title_table); ++i)
293     {
294       if (title_table[i][0] == c || title_table[i][1] == c
295           || title_table[i][2] == c)
296         return title_table[i][0];
297     }
298   return (TYPE (c) == G_UNICODE_LOWERCASE_LETTER
299           ? ATTTABLE (c >> 8, c & 0xff)
300           : c);
301 }
302
303 /**
304  * g_unichar_xdigit_value:
305  * @c: a unicode character
306  *
307  * Determines the numeric value of a character as a decimal
308  * degital.
309  *
310  * Return value: If @c is a decimal digit (according to
311  * `g_unichar_isdigit'), its numeric value. Otherwise, -1.
312  **/
313 int
314 g_unichar_digit_value (gunichar c)
315 {
316   if (TYPE (c) == G_UNICODE_DECIMAL_NUMBER)
317     return ATTTABLE (c >> 8, c & 0xff);
318   return -1;
319 }
320
321 /**
322  * g_unichar_xdigit_value:
323  * @c: a unicode character
324  *
325  * Determines the numeric value of a character as a hexidecimal
326  * degital.
327  *
328  * Return value: If @c is a hex digit (according to
329  * `g_unichar_isxdigit'), its numeric value. Otherwise, -1.
330  **/
331 int
332 g_unichar_xdigit_value (gunichar c)
333 {
334   if (c >= 'A' && c <= 'F')
335     return c - 'A' + 1;
336   if (c >= 'a' && c <= 'f')
337     return c - 'a' + 1;
338   if (TYPE (c) == G_UNICODE_DECIMAL_NUMBER)
339     return ATTTABLE (c >> 8, c & 0xff);
340   return -1;
341 }
342
343 /**
344  * g_unichar_type:
345  * @c: a unicode character
346  * 
347  * Classifies a unicode character by type.
348  * 
349  * Return value: the typ of the character.
350  **/
351 GUnicodeType
352 g_unichar_type (gunichar c)
353 {
354   return TYPE (c);
355 }