/* -*-c-*- */
/* Copyright (C) 2002 Mikhael Goikhman */
/* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* FBidi.c - interface to Bidi, we use fribidi implementation here.
* See FBidi.h for some comments on this interface.
*/
#include "config.h"
#include "FBidi.h"
#if HAVE_BIDI
#include "safemalloc.h"
#include "BidiJoin.h"
#include <fribidi/fribidi.h>
#include <fribidi/fribidi_types.h>
#include <stdio.h>
Bool FBidiIsApplicable(const char *charset)
{
if (fribidi_parse_charset((char *)charset) ==
FRIBIDI_CHAR_SET_NOT_FOUND)
{
return False;
}
return True;
}
char *FBidiConvert(
const char *logical_str, const char *charset, int str_len,
Bool *is_rtl, int *out_len, superimpose_char_t *comb_chars,
int *l_to_v)
{
char *visual_str;
FriBidiCharSet fribidi_charset;
FriBidiChar *logical_unicode_str;
FriBidiChar *visual_unicode_str;
FriBidiCharType pbase_dir = FRIBIDI_TYPE_ON;
FriBidiStrIndex *pos_l_to_v;
int i;
if (logical_str == NULL || charset == NULL)
{
return NULL;
}
if (str_len < 0)
{
str_len = strlen(logical_str);
}
if (is_rtl != NULL)
{
*is_rtl = False;
}
fribidi_charset = fribidi_parse_charset((char *)charset);
if (fribidi_charset == FRIBIDI_CHAR_SET_NOT_FOUND)
{
return NULL;
}
/* it is possible that we allocate a bit more here, if utf-8 */
logical_unicode_str =
(FriBidiChar *)safemalloc((str_len + 1) * sizeof(FriBidiChar));
/* convert to unicode first */
str_len = fribidi_charset_to_unicode(
fribidi_charset, (char *)logical_str, str_len,
logical_unicode_str);
visual_unicode_str =
(FriBidiChar *)safemalloc((str_len + 1) * sizeof(FriBidiChar));
/* apply bidi algorithm, convert logical string to visual string */
/* also keep track of how characters are reordered here, to reorder
combing characters accordingly */
pos_l_to_v =
(FriBidiStrIndex *)safemalloc((str_len + 1) *
sizeof(FriBidiStrIndex));
fribidi_log2vis(
logical_unicode_str, str_len, &pbase_dir,
visual_unicode_str, pos_l_to_v, NULL, NULL);
/* remap mapping from logical to visual to "compensate" for BIDI */
if (comb_chars != NULL)
{
for (i = 0;
comb_chars[i].c.byte1 != 0 ||
comb_chars[i].c.byte2 != 0;
i++)
{
/* if input string is zero characters => only
combining chars, set position to zero */
comb_chars[i].position =
str_len != 0 ?
pos_l_to_v[comb_chars[i].position] : 0;
}
}
if (l_to_v != NULL)
{
/* values in the previuos mapping gives the position of
input characters after combining step */
/* mapping from BIDI conversion maps from the positions in
the output from combining */
int orig_len;
int *l_to_v_temp;
for (i = 0; l_to_v[i] != -1; i++)
{
}
orig_len = i;
l_to_v_temp = (int *)safemalloc(orig_len * sizeof(int));
for (i = 0; i < orig_len; i++)
{
l_to_v_temp[i] = pos_l_to_v[l_to_v[i]];
}
for (i = 0; i < orig_len; i++)
{
l_to_v[i] = l_to_v_temp[i];
}
free(l_to_v_temp);
}
free(pos_l_to_v);
/* character shape/join - will get pulled into fribidi with time */
str_len = shape_n_join(visual_unicode_str, str_len);
visual_str = (char *)safemalloc((4 * str_len + 1) * sizeof(char));
/* convert from unicode finally */
*out_len = fribidi_unicode_to_charset(
fribidi_charset, visual_unicode_str, str_len, visual_str);
if (is_rtl != NULL && pbase_dir == FRIBIDI_TYPE_RTL)
{
*is_rtl = True;
}
free(logical_unicode_str);
free(visual_unicode_str);
return visual_str;
}
#endif /* HAVE_BIDI */
syntax highlighted by Code2HTML, v. 0.9.1