update to 0.19.7
[platform/upstream/fribidi.git] / charset / fribidi-char-sets-cap-rtl.c
1 /* FriBidi
2  * fribidi-char-sets-cap-rtl.c - CapRTL character set conversion routines
3  *
4  * $Id: fribidi-char-sets-cap-rtl.c,v 1.12 2006-01-22 10:12:17 behdad Exp $
5  * $Author: behdad $
6  * $Date: 2006-01-22 10:12:17 $
7  * $Revision: 1.12 $
8  * $Source: /home/behdad/src/fdo/fribidi/togit/git/../fribidi/fribidi2/charset/fribidi-char-sets-cap-rtl.c,v $
9  *
10  * Authors:
11  *   Behdad Esfahbod, 2001, 2002, 2004
12  *   Dov Grobgeld, 1999, 2000
13  *
14  * Copyright (C) 2004 Sharif FarsiWeb, Inc
15  * Copyright (C) 2001,2002 Behdad Esfahbod
16  * Copyright (C) 1999,2000 Dov Grobgeld
17  * 
18  * This library is free software; you can redistribute it and/or
19  * modify it under the terms of the GNU Lesser General Public
20  * License as published by the Free Software Foundation; either
21  * version 2.1 of the License, or (at your option) any later version.
22  * 
23  * This library is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
26  * Lesser General Public License for more details.
27  * 
28  * You should have received a copy of the GNU Lesser General Public License
29  * along with this library, in a file named COPYING; if not, write to the
30  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
31  * Boston, MA 02110-1301, USA
32  * 
33  * For licensing issues, contact <license@farsiweb.info>.
34  */
35
36 #include <common.h>
37
38 #include <fribidi-char-sets-cap-rtl.h>
39
40 #include <fribidi-unicode.h>
41 #include <fribidi-mirroring.h>
42 #include <fribidi-bidi-types.h>
43
44 #include <bidi-types.h>
45
46 #include <stdio.h>
47
48 enum
49 {
50 # define _FRIBIDI_ADD_TYPE(TYPE,SYMBOL) TYPE = FRIBIDI_TYPE_##TYPE,
51 # include "fribidi-bidi-types-list.h"
52 # undef _FRIBIDI_ADD_TYPE
53   _FRIBIDI_MAX_TYPES_VALUE
54 };
55
56 enum
57 {
58 # define _FRIBIDI_ADD_TYPE(TYPE,SYMBOL) DUMMY_##TYPE,
59 # include "fribidi-bidi-types-list.h"
60 # undef _FRIBIDI_ADD_TYPE
61   _FRIBIDI_NUM_TYPES
62 };
63
64 static FriBidiCharType CapRTLCharTypes[] = {
65 /* *INDENT-OFF* */
66   ON, ON, ON, ON, LTR,RTL,ON, ON, ON, ON, ON, ON, ON, BS, RLO,RLE, /* 00-0f */
67   LRO,LRE,PDF,WS, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON, ON,  /* 10-1f */
68   WS, ON, ON, ON, ET, ON, ON, ON, ON, ON, ON, ET, CS, ON, ES, ES,  /* 20-2f */
69   EN, EN, EN, EN, EN, EN, AN, AN, AN, AN, CS, ON, ON, ON, ON, ON,  /* 30-3f */
70   RTL,AL, AL, AL, AL, AL, AL, RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL, /* 40-4f */
71   RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,RTL,ON, BS, ON, BN, ON,  /* 50-5f */
72   NSM,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR, /* 60-6f */
73   LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,LTR,ON, SS, ON, WS, ON,  /* 70-7f */
74 /* *INDENT-ON* */
75 };
76
77 #define CAPRTL_CHARS (int)(sizeof CapRTLCharTypes / sizeof CapRTLCharTypes[0])
78
79 static FriBidiChar *caprtl_to_unicode = NULL;
80
81 static void
82 init_cap_rtl (
83   void
84 )
85 {
86   int request[_FRIBIDI_NUM_TYPES];
87   FriBidiCharType to_type[_FRIBIDI_NUM_TYPES];
88   int num_types = 0, count = 0;
89   FriBidiCharType i;
90   char mark[CAPRTL_CHARS];
91
92   caprtl_to_unicode =
93     (FriBidiChar *) fribidi_malloc (CAPRTL_CHARS *
94                                     sizeof caprtl_to_unicode[0]);
95   for (i = 0; i < CAPRTL_CHARS; i++)
96     if (CapRTLCharTypes[i] == fribidi_get_bidi_type (i))
97       {
98         caprtl_to_unicode[i] = i;
99         mark[i] = 1;
100       }
101     else
102       {
103         int j;
104
105         caprtl_to_unicode[i] = FRIBIDI_UNICODE_CHARS;
106         mark[i] = 0;
107         if (fribidi_get_mirror_char (i, NULL))
108           {
109             DBG ("warning: I could not map mirroring character map to itself in CapRTL");
110           }
111
112         for (j = 0; j < num_types; j++)
113           if (to_type[j] == CapRTLCharTypes[i])
114             break;
115         if (j == num_types)
116           {
117             num_types++;
118             to_type[j] = CapRTLCharTypes[i];
119             request[j] = 0;
120           }
121         request[j]++;
122         count++;
123       }
124   for (i = 0; i < 0x10000 && count; i++)        /* Assign BMP chars to CapRTL entries */
125     if (!fribidi_get_mirror_char (i, NULL) && !(i < CAPRTL_CHARS && mark[i]))
126       {
127         int j, k;
128         FriBidiCharType t = fribidi_get_bidi_type (i);
129         for (j = 0; j < num_types; j++)
130           if (to_type[j] == t)
131             break;
132         if (!request[j])        /* Do not need this type */
133           continue;
134         for (k = 0; k < CAPRTL_CHARS; k++)
135           if (caprtl_to_unicode[k] == FRIBIDI_UNICODE_CHARS
136               && to_type[j] == CapRTLCharTypes[k])
137             {
138               request[j]--;
139               count--;
140               caprtl_to_unicode[k] = i;
141               break;
142             }
143       }
144   if (count)
145     {
146       int j;
147
148       DBG ("warning: could not find a mapping for CapRTL to Unicode:");
149       for (j = 0; j < num_types; j++)
150         if (request[j])
151           {
152             DBG2 ("  need this type: %s", fribidi_get_bidi_type_name (to_type[j]));
153           }
154     }
155 }
156
157 static char
158 fribidi_unicode_to_cap_rtl_c (
159   /* input */
160   FriBidiChar uch
161 )
162 {
163   int i;
164
165   if (!caprtl_to_unicode)
166     init_cap_rtl ();
167
168   for (i = 0; i < CAPRTL_CHARS; i++)
169     if (uch == caprtl_to_unicode[i])
170       return (unsigned char) i;
171   return '?';
172 }
173
174 FriBidiStrIndex
175 fribidi_cap_rtl_to_unicode (
176   /* input */
177   const char *s,
178   FriBidiStrIndex len,
179   /* output */
180   FriBidiChar *us
181 )
182 {
183   FriBidiStrIndex i, j;
184
185   if (!caprtl_to_unicode)
186     init_cap_rtl ();
187
188   j = 0;
189   for (i = 0; i < len; i++)
190     {
191       char ch;
192
193       ch = s[i];
194       if (ch == '_')
195         {
196           switch (ch = s[++i])
197             {
198             case '>':
199               us[j++] = FRIBIDI_CHAR_LRM;
200               break;
201             case '<':
202               us[j++] = FRIBIDI_CHAR_RLM;
203               break;
204             case 'l':
205               us[j++] = FRIBIDI_CHAR_LRE;
206               break;
207             case 'r':
208               us[j++] = FRIBIDI_CHAR_RLE;
209               break;
210             case 'o':
211               us[j++] = FRIBIDI_CHAR_PDF;
212               break;
213             case 'L':
214               us[j++] = FRIBIDI_CHAR_LRO;
215               break;
216             case 'R':
217               us[j++] = FRIBIDI_CHAR_RLO;
218               break;
219             case '_':
220               us[j++] = '_';
221               break;
222             default:
223               us[j++] = '_';
224               i--;
225               break;
226             }
227         }
228       else
229         us[j++] = caprtl_to_unicode[(int) s[i]];
230     }
231
232   return j;
233 }
234
235 FriBidiStrIndex
236 fribidi_unicode_to_cap_rtl (
237   /* input */
238   const FriBidiChar *us,
239   FriBidiStrIndex len,
240   /* output */
241   char *s
242 )
243 {
244   FriBidiStrIndex i;
245   int j;
246
247   j = 0;
248   for (i = 0; i < len; i++)
249     {
250       FriBidiChar ch = us[i];
251       if (!FRIBIDI_IS_EXPLICIT (fribidi_get_bidi_type (ch)) && ch != '_'
252           && ch != FRIBIDI_CHAR_LRM && ch != FRIBIDI_CHAR_RLM)
253         s[j++] = fribidi_unicode_to_cap_rtl_c (ch);
254       else
255         {
256           s[j++] = '_';
257           switch (ch)
258             {
259             case FRIBIDI_CHAR_LRM:
260               s[j++] = '>';
261               break;
262             case FRIBIDI_CHAR_RLM:
263               s[j++] = '<';
264               break;
265             case FRIBIDI_CHAR_LRE:
266               s[j++] = 'l';
267               break;
268             case FRIBIDI_CHAR_RLE:
269               s[j++] = 'r';
270               break;
271             case FRIBIDI_CHAR_PDF:
272               s[j++] = 'o';
273               break;
274             case FRIBIDI_CHAR_LRO:
275               s[j++] = 'L';
276               break;
277             case FRIBIDI_CHAR_RLO:
278               s[j++] = 'R';
279               break;
280             case '_':
281               s[j++] = '_';
282               break;
283             default:
284               j--;
285               if (ch < 256)
286                 s[j++] = fribidi_unicode_to_cap_rtl_c (ch);
287               else
288                 s[j++] = '?';
289               break;
290             }
291         }
292     }
293   s[j] = 0;
294
295   return j;
296 }
297
298 const char *
299 fribidi_char_set_desc_cap_rtl (
300   void
301 )
302 {
303   static char *s = 0;
304   int l, i, j;
305
306   if (s)
307     return s;
308
309   l = 10000;
310   s = (char *) fribidi_malloc (l);
311   i = 0;
312   i += sprintf (s + i,          /*l - i, */
313                 "CapRTL is a character set for testing with the reference\n"
314                 "implementation, with explicit marks escape strings, and\n"
315                 "the property that contains all unicode character types in\n"
316                 "ASCII range 1-127.\n"
317                 "\n"
318                 "Warning: CapRTL character types are subject to change.\n"
319                 "\n" "CapRTL's character types:\n");
320   for (j = 0; j < CAPRTL_CHARS; j++)
321     {
322       if (j % 4 == 0)
323         s[i++] = '\n';
324       i += sprintf (s + i, /*l - i, */ "  * 0x%02x %c%c %-3s ", j,
325                     j < 0x20 ? '^' : ' ',
326                     j < 0x20 ? j + '@' : j < 0x7f ? j : ' ',
327                     fribidi_get_bidi_type_name (CapRTLCharTypes[j]));
328     }
329   i += sprintf (s + i,          /*l - i, */
330                 "\n\n"
331                 "Escape sequences:\n"
332                 "  Character `_' is used to escape explicit marks. The list is:\n"
333                 "    * _>  LRM\n" "    * _<  RLM\n"
334                 "    * _l  LRE\n" "    * _r  RLE\n"
335                 "    * _L  LRO\n" "    * _R  RLO\n"
336                 "    * _o  PDF\n" "    * __  `_' itself\n" "\n");
337   return s;
338 }
339
340 /* Editor directions:
341  * vim:textwidth=78:tabstop=8:shiftwidth=2:autoindent:cindent
342  */