Add discussion point for XIM/UTF-8 locales.
[fvwm.git] / libs / FBidi.c
blob734240040e75c99f27f09e90518a55c331264a62
1 /* -*-c-*- */
2 /* Copyright (C) 2002 Mikhael Goikhman */
3 /* This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * FBidi.c - interface to Bidi, we use fribidi implementation here.
20 * See FBidi.h for some comments on this interface.
23 #include "config.h"
25 #include "FBidi.h"
27 #if HAVE_BIDI
29 #include "safemalloc.h"
30 #include "BidiJoin.h"
31 #include <fribidi/fribidi.h>
32 #include <stdio.h>
34 Bool FBidiIsApplicable(const char *charset)
36 if (fribidi_parse_charset((char *)charset) ==
37 FRIBIDI_CHAR_SET_NOT_FOUND)
39 return False;
41 return True;
44 char *FBidiConvert(
45 const char *logical_str, const char *charset, int str_len,
46 Bool *is_rtl, int *out_len, superimpose_char_t *comb_chars,
47 int *l_to_v)
49 char *visual_str;
50 FriBidiCharSet fribidi_charset;
51 FriBidiChar *logical_unicode_str;
52 FriBidiChar *visual_unicode_str;
53 FriBidiCharType pbase_dir = FRIBIDI_TYPE_ON;
54 FriBidiStrIndex *pos_l_to_v;
55 int i;
57 if (logical_str == NULL || charset == NULL)
59 return NULL;
61 if (str_len < 0)
63 str_len = strlen(logical_str);
65 if (is_rtl != NULL)
67 *is_rtl = False;
70 fribidi_charset = fribidi_parse_charset((char *)charset);
71 if (fribidi_charset == FRIBIDI_CHAR_SET_NOT_FOUND)
73 return NULL;
76 /* it is possible that we allocate a bit more here, if utf-8 */
77 logical_unicode_str =
78 (FriBidiChar *)safemalloc((str_len + 1) * sizeof(FriBidiChar));
80 /* convert to unicode first */
81 str_len = fribidi_charset_to_unicode(
82 fribidi_charset, (char *)logical_str, str_len,
83 logical_unicode_str);
85 visual_unicode_str =
86 (FriBidiChar *)safemalloc((str_len + 1) * sizeof(FriBidiChar));
88 /* apply bidi algorithm, convert logical string to visual string */
89 /* also keep track of how characters are reordered here, to reorder
90 combing characters accordingly */
91 pos_l_to_v =
92 (FriBidiStrIndex *)safemalloc((str_len + 1) *
93 sizeof(FriBidiStrIndex));
94 fribidi_log2vis(
95 logical_unicode_str, str_len, &pbase_dir,
96 visual_unicode_str, pos_l_to_v, NULL, NULL);
98 /* remap mapping from logical to visual to "compensate" for BIDI */
99 if (comb_chars != NULL)
101 for (i = 0;
102 comb_chars[i].c.byte1 != 0 ||
103 comb_chars[i].c.byte2 != 0;
104 i++)
106 /* if input string is zero characters => only
107 combining chars, set position to zero */
108 comb_chars[i].position =
109 str_len != 0 ?
110 pos_l_to_v[comb_chars[i].position] : 0;
114 if (l_to_v != NULL)
116 /* values in the previuos mapping gives the position of
117 input characters after combining step */
118 /* mapping from BIDI conversion maps from the positions in
119 the output from combining */
120 int orig_len;
121 int *l_to_v_temp;
122 for (i = 0; l_to_v[i] != -1; i++)
125 orig_len = i;
126 l_to_v_temp = (int *)safemalloc(orig_len * sizeof(int));
127 for (i = 0; i < orig_len; i++)
129 l_to_v_temp[i] = pos_l_to_v[l_to_v[i]];
131 for (i = 0; i < orig_len; i++)
133 l_to_v[i] = l_to_v_temp[i];
135 free(l_to_v_temp);
137 free(pos_l_to_v);
140 /* character shape/join - will get pulled into fribidi with time */
141 str_len = shape_n_join(visual_unicode_str, str_len);
143 visual_str = (char *)safemalloc((4 * str_len + 1) * sizeof(char));
145 /* convert from unicode finally */
146 *out_len = fribidi_unicode_to_charset(
147 fribidi_charset, visual_unicode_str, str_len, visual_str);
149 if (is_rtl != NULL && pbase_dir == FRIBIDI_TYPE_RTL)
151 *is_rtl = True;
154 free(logical_unicode_str);
155 free(visual_unicode_str);
156 return visual_str;
159 #endif /* HAVE_BIDI */