Add new files.
[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   /* special-case these since Unicode thinks they are not spaces */
122   if (c == ' ' || c == '\t' || c == '\n' || c == '\r' ||
123       c == '\f' || c == '\v') /* "the mythical vertical tab" */
124     return TRUE;
125   else
126     {
127       int t = TYPE (c);
128       return (t == G_UNICODE_SPACE_SEPARATOR || t == G_UNICODE_LINE_SEPARATOR
129               || t == G_UNICODE_PARAGRAPH_SEPARATOR);
130     }
131 }
132
133 /**
134  * g_unichar_isupper:
135  * @c: a unicode character
136  * 
137  * Determines if a character is uppercase.
138  * 
139  * Return value: 
140  **/
141 gboolean
142 g_unichar_isupper (gunichar c)
143 {
144   return TYPE (c) == G_UNICODE_UPPERCASE_LETTER;
145 }
146
147 /**
148  * g_unichar_istitle:
149  * @c: a unicode character
150  * 
151  * Determines if a character is titlecase. Some characters in
152  * Unicode which are composites, such as the DZ digraph
153  * have three case variants instead of just two. The titlecase
154  * form is used at the beginning of a word where only the
155  * first letter is capitalized. The titlecase form of the DZ
156  * digraph is U+01F2 LATIN CAPITAL LETTTER D WITH SMALL LETTER Z
157  * 
158  * Return value: %TRUE if the character is titlecase.
159  **/
160 gboolean
161 g_unichar_istitle (gunichar c)
162 {
163   unsigned int i;
164   for (i = 0; i < asize (title_table); ++i)
165     if (title_table[i][0] == c)
166       return 1;
167   return 0;
168 }
169
170 /**
171  * g_unichar_isxdigit:
172  * @c: a unicode character.
173  * 
174  * Determines if a characters is a hexidecimal digit
175  * 
176  * Return value: %TRUE if the character is a hexidecimal digit.
177  **/
178 gboolean
179 g_unichar_isxdigit (gunichar c)
180 {
181   int t = TYPE (c);
182   return ((c >= 'a' && c <= 'f')
183           || (c >= 'A' && c <= 'F')
184           || ISDIGIT (t));
185 }
186
187 /**
188  * g_unichar_isdefined:
189  * @c: a unicode character
190  * 
191  * Determines if a given character is assigned in the Unicode
192  * standard
193  *
194  * Return value: %TRUE if the character has an assigned value.
195  **/
196 gboolean
197 g_unichar_isdefined (gunichar c)
198 {
199   int t = TYPE (c);
200   return t != G_UNICODE_UNASSIGNED;
201 }
202
203 /**
204  * g_unichar_iswide:
205  * @c: a unicode character
206  * 
207  * Determines if a character is typically rendered in a double-width
208  * cell.
209  * 
210  * Return value: %TRUE if the character is wide.
211  **/
212 /* This function stolen from Markus Kuhn <Markus.Kuhn@cl.cam.ac.uk>.  */
213 gboolean
214 g_unichar_iswide (gunichar c)
215 {
216   if (c < 0x1100)
217     return 0;
218
219   return ((c >= 0x1100 && c <= 0x115f)     /* Hangul Jamo */
220           || (c >= 0x2e80 && c <= 0xa4cf && (c & ~0x0011) != 0x300a &&
221               c != 0x303f)                 /* CJK ... Yi */
222           || (c >= 0xac00 && c <= 0xd7a3)  /* Hangul Syllables */
223           || (c >= 0xf900 && c <= 0xfaff)  /* CJK Compatibility Ideographs */
224           || (c >= 0xfe30 && c <= 0xfe6f)  /* CJK Compatibility Forms */
225           || (c >= 0xff00 && c <= 0xff5f)  /* Fullwidth Forms */
226           || (c >= 0xffe0 && c <= 0xffe6));
227 }
228
229 /**
230  * g_unichar_toupper:
231  * @c: a unicode character
232  * 
233  * Convert a character to uppercase.
234  * 
235  * Return value: the result of converting @c to uppercase.
236  *               If @c is not an lowercase or titlecase character,
237  *               @c is returned unchanged.
238  **/
239 gunichar
240 g_unichar_toupper (gunichar c)
241 {
242   int t = TYPE (c);
243   if (t == G_UNICODE_LOWERCASE_LETTER)
244     return ATTTABLE (c >> 8, c & 0xff);
245   else if (t == G_UNICODE_TITLECASE_LETTER)
246     {
247       unsigned int i;
248       for (i = 0; i < asize (title_table); ++i)
249         {
250           if (title_table[i][0] == c)
251             return title_table[i][1];
252         }
253     }
254   return c;
255 }
256
257 /**
258  * g_unichar_tolower:
259  * @c: a unicode character.
260  * 
261  * Convert a character to lower case
262  * 
263  * Return value: the result of converting @c to lower case.
264  *               If @c is not an upperlower or titlecase character,
265  *               @c is returned unchanged.
266  **/
267 gunichar
268 g_unichar_tolower (gunichar c)
269 {
270   int t = TYPE (c);
271   if (t == G_UNICODE_UPPERCASE_LETTER)
272     return ATTTABLE (c >> 8, c & 0xff);
273   else if (t == G_UNICODE_TITLECASE_LETTER)
274     {
275       unsigned int i;
276       for (i = 0; i < asize (title_table); ++i)
277         {
278           if (title_table[i][0] == c)
279             return title_table[i][2];
280         }
281     }
282   return c;
283 }
284
285 /**
286  * g_unichar_totitle:
287  * @c: a unicode character
288  * 
289  * Convert a character to the titlecase
290  * 
291  * Return value: the result of converting @c to titlecase.
292  *               If @c is not an uppercase or lowercase character,
293  *               @c is returned unchanged.
294  **/
295 gunichar
296 g_unichar_totitle (gunichar c)
297 {
298   unsigned int i;
299   for (i = 0; i < asize (title_table); ++i)
300     {
301       if (title_table[i][0] == c || title_table[i][1] == c
302           || title_table[i][2] == c)
303         return title_table[i][0];
304     }
305   return (TYPE (c) == G_UNICODE_LOWERCASE_LETTER
306           ? ATTTABLE (c >> 8, c & 0xff)
307           : c);
308 }
309
310 /**
311  * g_unichar_xdigit_value:
312  * @c: a unicode character
313  *
314  * Determines the numeric value of a character as a decimal
315  * degital.
316  *
317  * Return value: If @c is a decimal digit (according to
318  * `g_unichar_isdigit'), its numeric value. Otherwise, -1.
319  **/
320 int
321 g_unichar_digit_value (gunichar c)
322 {
323   if (TYPE (c) == G_UNICODE_DECIMAL_NUMBER)
324     return ATTTABLE (c >> 8, c & 0xff);
325   return -1;
326 }
327
328 /**
329  * g_unichar_xdigit_value:
330  * @c: a unicode character
331  *
332  * Determines the numeric value of a character as a hexidecimal
333  * degital.
334  *
335  * Return value: If @c is a hex digit (according to
336  * `g_unichar_isxdigit'), its numeric value. Otherwise, -1.
337  **/
338 int
339 g_unichar_xdigit_value (gunichar c)
340 {
341   if (c >= 'A' && c <= 'F')
342     return c - 'A' + 1;
343   if (c >= 'a' && c <= 'f')
344     return c - 'a' + 1;
345   if (TYPE (c) == G_UNICODE_DECIMAL_NUMBER)
346     return ATTTABLE (c >> 8, c & 0xff);
347   return -1;
348 }
349
350 /**
351  * g_unichar_type:
352  * @c: a unicode character
353  * 
354  * Classifies a unicode character by type.
355  * 
356  * Return value: the typ of the character.
357  **/
358 GUnicodeType
359 g_unichar_type (gunichar c)
360 {
361   return TYPE (c);
362 }