(root)/
fribidi-1.0.13/
lib/
fribidi.c
       1  /* FriBidi
       2   * fribidi.c - Unicode bidirectional and Arabic joining/shaping algorithms
       3   *
       4   * Authors:
       5   *   Behdad Esfahbod, 2001, 2002, 2004
       6   *   Dov Grobgeld, 1999, 2000
       7   *
       8   * Copyright (C) 2004 Sharif FarsiWeb, Inc
       9   * Copyright (C) 2001,2002 Behdad Esfahbod
      10   * Copyright (C) 1999,2000 Dov Grobgeld
      11   * 
      12   * This library is free software; you can redistribute it and/or
      13   * modify it under the terms of the GNU Lesser General Public
      14   * License as published by the Free Software Foundation; either
      15   * version 2.1 of the License, or (at your option) any later version.
      16   * 
      17   * This library is distributed in the hope that it will be useful,
      18   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      19   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      20   * Lesser General Public License for more details.
      21   * 
      22   * You should have received a copy of the GNU Lesser General Public License
      23   * along with this library, in a file named COPYING; if not, write to the
      24   * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
      25   * Boston, MA 02110-1301, USA
      26   * 
      27   * For licensing issues, contact <fribidi.license@gmail.com>.
      28   */
      29  
      30  #include "common.h"
      31  
      32  #include <fribidi.h>
      33  
      34  #ifdef DEBUG
      35  static int flag_debug = false;
      36  #endif
      37  
      38  FRIBIDI_ENTRY fribidi_boolean
      39  fribidi_debug_status (
      40    void
      41  )
      42  {
      43  #ifdef DEBUG
      44    return flag_debug;
      45  #else
      46    return false;
      47  #endif
      48  }
      49  
      50  FRIBIDI_ENTRY fribidi_boolean
      51  fribidi_set_debug (
      52    /* input */
      53    fribidi_boolean state
      54  )
      55  {
      56  #ifdef DEBUG
      57    return flag_debug = state;
      58  #else
      59    return false;
      60  #endif
      61  }
      62  
      63  FRIBIDI_ENTRY FriBidiStrIndex
      64  fribidi_remove_bidi_marks (
      65    FriBidiChar *str,
      66    const FriBidiStrIndex len,
      67    FriBidiStrIndex *positions_to_this,
      68    FriBidiStrIndex *position_from_this_list,
      69    FriBidiLevel *embedding_levels
      70  )
      71  {
      72    register FriBidiStrIndex i, j = 0;
      73    fribidi_boolean private_from_this = false;
      74    fribidi_boolean status = false;
      75  
      76    if UNLIKELY
      77      (len == 0 || str == NULL)
      78      {
      79        status = true;
      80        goto out;
      81      }
      82  
      83    DBG ("in fribidi_remove_bidi_marks");
      84  
      85    fribidi_assert (str);
      86  
      87    /* If to_this is not NULL, we must have from_this as well. If it is
      88       not given by the caller, we have to make a private instance of it. */
      89    if (positions_to_this && !position_from_this_list)
      90      {
      91        position_from_this_list = fribidi_malloc (sizeof
      92  						(position_from_this_list[0]) *
      93  						len);
      94        if UNLIKELY
      95  	(!position_from_this_list) goto out;
      96        private_from_this = true;
      97        for (i = 0; i < len; i++)
      98  	position_from_this_list[positions_to_this[i]] = i;
      99      }
     100  
     101    for (i = 0; i < len; i++)
     102      if (!FRIBIDI_IS_EXPLICIT_OR_BN (fribidi_get_bidi_type (str[i]))
     103          && !FRIBIDI_IS_ISOLATE (fribidi_get_bidi_type (str[i]))
     104  	&& str[i] != FRIBIDI_CHAR_LRM && str[i] != FRIBIDI_CHAR_RLM)
     105        {
     106  	str[j] = str[i];
     107  	if (embedding_levels)
     108  	  embedding_levels[j] = embedding_levels[i];
     109  	if (position_from_this_list)
     110  	  position_from_this_list[j] = position_from_this_list[i];
     111  	j++;
     112        }
     113  
     114    /* Convert the from_this list to to_this */
     115    if (positions_to_this)
     116      {
     117        for (i = 0; i < len; i++)
     118  	positions_to_this[i] = -1;
     119        for (i = 0; i < len; i++)
     120  	positions_to_this[position_from_this_list[i]] = i;
     121      }
     122  
     123    status = true;
     124  
     125  out:
     126  
     127    if (private_from_this)
     128      fribidi_free (position_from_this_list);
     129  
     130    return status ? j : -1;
     131  }
     132  
     133  /* Local array size, used for stack-based local arrays */
     134  #define LOCAL_LIST_SIZE 128
     135  static FriBidiFlags flags = FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC;
     136  
     137  
     138  FRIBIDI_ENTRY FriBidiLevel
     139  fribidi_log2vis (
     140    /* input */
     141    const FriBidiChar *str,
     142    const FriBidiStrIndex len,
     143    /* input and output */
     144    FriBidiParType *pbase_dir,
     145    /* output */
     146    FriBidiChar *visual_str,
     147    FriBidiStrIndex *positions_L_to_V,
     148    FriBidiStrIndex *positions_V_to_L,
     149    FriBidiLevel *embedding_levels
     150  )
     151  {
     152    register FriBidiStrIndex i;
     153    FriBidiLevel max_level = 0;
     154    fribidi_boolean private_V_to_L = false;
     155    fribidi_boolean private_embedding_levels = false;
     156    fribidi_boolean status = false;
     157    FriBidiArabicProp local_ar_props[LOCAL_LIST_SIZE];
     158    FriBidiArabicProp *ar_props = NULL;
     159    FriBidiLevel local_embedding_levels[LOCAL_LIST_SIZE];
     160    FriBidiCharType local_bidi_types[LOCAL_LIST_SIZE];
     161    FriBidiCharType *bidi_types = NULL;
     162    FriBidiBracketType local_bracket_types[LOCAL_LIST_SIZE];
     163    FriBidiBracketType *bracket_types = NULL;
     164    FriBidiStrIndex local_positions_V_to_L[LOCAL_LIST_SIZE];
     165  
     166    if UNLIKELY
     167      (len == 0)
     168      {
     169        status = true;
     170        goto out;
     171      }
     172  
     173    DBG ("in fribidi_log2vis");
     174  
     175    fribidi_assert (str);
     176    fribidi_assert (pbase_dir);
     177  
     178    if (len < LOCAL_LIST_SIZE)
     179      bidi_types = local_bidi_types;
     180    else
     181      bidi_types = fribidi_malloc (len * sizeof bidi_types[0]);
     182    if (!bidi_types)
     183      goto out;
     184  
     185    fribidi_get_bidi_types (str, len, bidi_types);
     186  
     187    if (len < LOCAL_LIST_SIZE)
     188      bracket_types = local_bracket_types;
     189    else
     190      bracket_types = fribidi_malloc (len * sizeof bracket_types[0]);
     191      
     192    if (!bracket_types)
     193      goto out;
     194  
     195    fribidi_get_bracket_types (str, len, bidi_types,
     196                               /* output */
     197                               bracket_types);
     198    if (!embedding_levels)
     199      {
     200        if (len < LOCAL_LIST_SIZE)
     201          embedding_levels = local_embedding_levels;
     202        else
     203          embedding_levels = fribidi_malloc (len * sizeof embedding_levels[0]);
     204        if (!embedding_levels)
     205  	goto out;
     206        private_embedding_levels = true;
     207      }
     208  
     209    max_level = fribidi_get_par_embedding_levels_ex (bidi_types,
     210                                                     bracket_types,
     211                                                     len,
     212                                                     pbase_dir,
     213                                                     embedding_levels) - 1;
     214    if UNLIKELY
     215      (max_level < 0) goto out;
     216  
     217    /* If l2v is to be calculated we must have v2l as well. If it is not
     218       given by the caller, we have to make a private instance of it. */
     219    if (positions_L_to_V && !positions_V_to_L)
     220      {
     221        if (len < LOCAL_LIST_SIZE)
     222          positions_V_to_L = local_positions_V_to_L;
     223        else
     224          positions_V_to_L =
     225  	(FriBidiStrIndex *) fribidi_malloc (sizeof (FriBidiStrIndex) * len);
     226        if (!positions_V_to_L)
     227  	goto out;
     228        private_V_to_L = true;
     229      }
     230  
     231    /* Set up the ordering array to identity order */
     232    if (positions_V_to_L)
     233      {
     234        for (i = 0; i < len; i++)
     235  	positions_V_to_L[i] = i;
     236      }
     237  
     238  
     239    if (visual_str)
     240      {
     241        /* Using memcpy instead
     242        for (i = len - 1; i >= 0; i--)
     243  	visual_str[i] = str[i];
     244        */
     245        memcpy (visual_str, str, len * sizeof (*visual_str));
     246  
     247        /* Arabic joining */
     248        if (len < LOCAL_LIST_SIZE)
     249          ar_props = local_ar_props;
     250        else
     251          ar_props = fribidi_malloc (len * sizeof ar_props[0]);
     252        fribidi_get_joining_types (str, len, ar_props);
     253        fribidi_join_arabic (bidi_types, len, embedding_levels, ar_props);
     254  
     255        fribidi_shape (flags, embedding_levels, len, ar_props, visual_str);
     256      }
     257  
     258    /* line breaking goes here, but we assume one line in this function */
     259  
     260    /* and this should be called once per line, but again, we assume one
     261     * line in this deprecated function */
     262    status =
     263      fribidi_reorder_line (flags, bidi_types, len, 0, *pbase_dir,
     264  			  embedding_levels, visual_str,
     265  			  positions_V_to_L);
     266  
     267    /* Convert the v2l list to l2v */
     268    if (positions_L_to_V)
     269      {
     270        for (i = 0; i < len; i++)
     271  	positions_L_to_V[i] = -1;
     272        for (i = 0; i < len; i++)
     273  	positions_L_to_V[positions_V_to_L[i]] = i;
     274      }
     275  
     276  out:
     277  
     278    if (private_V_to_L && positions_V_to_L != local_positions_V_to_L)
     279      fribidi_free (positions_V_to_L);
     280  
     281    if (private_embedding_levels && embedding_levels != local_embedding_levels)
     282      fribidi_free (embedding_levels);
     283  
     284    if (ar_props && ar_props != local_ar_props)
     285      fribidi_free (ar_props);
     286  
     287    if (bidi_types && bidi_types != local_bidi_types)
     288      fribidi_free (bidi_types);
     289  
     290    if (bracket_types && bracket_types != local_bracket_types)
     291      fribidi_free (bracket_types);
     292  
     293    return status ? max_level + 1 : 0;
     294  }
     295  
     296  const char *fribidi_unicode_version = FRIBIDI_UNICODE_VERSION;
     297  
     298  const char *fribidi_version_info =
     299    "(" FRIBIDI_NAME ") " FRIBIDI_VERSION "\n"
     300    "interface version " FRIBIDI_INTERFACE_VERSION_STRING ",\n"
     301    "Unicode Character Database version " FRIBIDI_UNICODE_VERSION ",\n"
     302    "Configure options"
     303  #ifdef DEBUG
     304    " --enable-debug"
     305  #endif /* DEBUG */
     306    ".\n\n"
     307    "Copyright (C) 2004  Sharif FarsiWeb, Inc.\n"
     308    "Copyright (C) 2001, 2002, 2004, 2005  Behdad Esfahbod\n"
     309    "Copyright (C) 1999, 2000, 2017, 2018, 2019  Dov Grobgeld\n"
     310    FRIBIDI_NAME " comes with NO WARRANTY, to the extent permitted by law.\n"
     311    "You may redistribute copies of " FRIBIDI_NAME " under\n"
     312    "the terms of the GNU Lesser General Public License.\n"
     313    "For more information about these matters, see the file named COPYING.\n\n"
     314    "Written by Behdad Esfahbod and Dov Grobgeld.\n";
     315  
     316  /* Editor directions:
     317   * vim:textwidth=78:tabstop=8:shiftwidth=2:autoindent:cindent
     318   */