T168_111\appl\Text\FriBidi文件:第5~16

common.h、、、、、、、、、、、、、、、、、、、、、、、、、

/* FriBidi
 * common.h - common include for library sources
 *
 * $Id: common.h,v 1.20 2008-04-08 21:38:23 behdad Exp $
 * $Author: behdad $
 * $Date: 2008-04-08 21:38:23 $
 * $Revision: 1.20 $
 * $Source: /cvs/fribidi/fribidi2/lib/common.h,v $
 *
 * Author:
 *   Behdad Esfahbod, 2004
 *
 * Copyright (C) 2004 Sharif FarsiWeb, Inc.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library 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
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library, in a file named COPYING; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA
 *
 * For licensing issues, contact <license@farsiweb.info>.
 */
#ifndef _COMMON_H
#define _COMMON_H

#include "config.h"

#include "fribidi-common.h"

/* FRIBIDI_PRIVATESPACE is a macro used to name library internal symbols. */
#ifndef FRIBIDI_PRIVATESPACE
# define FRIBIDI_PRIVATESPACE1(A,B) A##B
# define FRIBIDI_PRIVATESPACE0(A,B) FRIBIDI_PRIVATESPACE1(A,B)
# define FRIBIDI_PRIVATESPACE(SYMBOL) FRIBIDI_PRIVATESPACE0(_,FRIBIDI_NAMESPACE(_##SYMBOL##__internal__))
#endif /* !FRIBIDI_PRIVATESPACE */

#if (defined(WIN32)) || (defined(_WIN32_WCE))
# define FRIBIDI_ENTRY __declspec(dllexport)
#endif /* WIN32 */

#if FRIBIDI_USE_GLIB+0
# ifndef SIZEOF_LONG
#  define SIZEOF_LONG GLIB_SIZEOF_LONG
# endif    /* !SIZEOF_LONG */
# ifndef SIZEOF_VOID_P
#  define SIZEOF_VOID_P GLIB_SIZEOF_VOID_P
# endif    /* !SIZEOF_VOID_P */
# ifndef __FRIBIDI_DOC
#  include <glib/gmem.h>
# endif    /* !__FRIBIDI_DOC */
# ifndef fribidi_malloc
#  define fribidi_malloc g_try_malloc
#  define fribidi_free g_free
# endif    /* !fribidi_malloc */
# ifndef fribidi_assert
#  ifndef __FRIBIDI_DOC
#   include <glib/gmessages.h>
#  endif /* !__FRIBIDI_DOC */
#  define fribidi_assert g_assert
# endif    /* !fribidi_assert */
# ifndef __FRIBIDI_DOC
#  include <glib/gmacros.h>
# endif    /* !__FRIBIDI_DOC */
# ifndef FRIBIDI_BEGIN_STMT
#  define FRIBIDI_BEGIN_STMT G_STMT_START {
#  define FRIBIDI_END_STMT } G_STMT_END
# endif    /* !FRIBIDI_BEGIN_STMT */
# ifndef LIKELY
#  define LIKELY G_LIKELY
#  define UNLIKELY G_UNLIKELY
# endif    /* !LIKELY */
# ifndef false
#  define false FALSE
# endif    /* !false */
# ifndef true
#  define true TRUE
# endif    /* !true */
#endif /* FRIBIDI_USE_GLIB */

#ifndef false
# define false (0)
# endif    /* !false */
# ifndef true
#  define true (!false)
# endif    /* !true */

#ifndef NULL
#  ifdef __cplusplus
#    define NULL        (0L)
#  else    /* !__cplusplus */
#    define NULL        ((void*) 0)
#  endif /* !__cplusplus */
#endif /* !NULL */

/* fribidi_malloc and fribidi_free should be used instead of malloc and free. 
 * No need to include any headers. */
#ifndef fribidi_malloc
# if HAVE_STDLIB_H
#  ifndef __FRIBIDI_DOC
#   include <stdlib.h>
#  endif /* __FRIBIDI_DOC */
#  define fribidi_malloc malloc
# else /* !HAVE_STDLIB_H */
#  define fribidi_malloc (void *) malloc
# endif    /* !HAVE_STDLIB_H */
# define fribidi_free free
#else /* fribidi_malloc */
# ifndef fribidi_free
#  error You should define fribidi_free too when you define fribidi_malloc.
# endif    /* !fribidi_free */
#endif /* fribidi_malloc */

#if HAVE_STRING_H+0
# if !STDC_HEADERS && HAVE_MEMORY_H
#  include <memory.h>
# endif
# include <string.h>
#endif
#if HAVE_STRINGS_H+0
# include <strings.h>
#endif

/* FRIBIDI_CHUNK_SIZE is the number of bytes in each chunk of memory being
 * allocated for data structure pools. */
#ifndef FRIBIDI_CHUNK_SIZE
# if HAVE_ASM_PAGE_H
#  ifndef __FRIBIDI_DOC
#   include <asm/page.h>
#  endif /* __FRIBIDI_DOC */
#  define FRIBIDI_CHUNK_SIZE (PAGE_SIZE - 16)
# else /* !HAVE_ASM_PAGE_H */
#  define FRIBIDI_CHUNK_SIZE (4096 - 16)
# endif    /* !HAVE_ASM_PAGE_H */
#else /* FRIBIDI_CHUNK_SIZE */
# if FRIBIDI_CHUNK_SIZE < 256
#  error FRIBIDI_CHUNK_SIZE now should define the size of a chunk in bytes.
# endif    /* FRIBIDI_CHUNK_SIZE < 256 */
#endif /* FRIBIDI_CHUNK_SIZE */

/* FRIBIDI_BEGIN_STMT should be used at the beginning of your macro
 * definitions that are to behave like simple statements.  Use
 * FRIBIDI_END_STMT at the end of the macro after the semicolon or brace. */
#ifndef FRIBIDI_BEGIN_STMT
# define FRIBIDI_BEGIN_STMT do {
# define FRIBIDI_END_STMT } while (0)
#endif /* !FRIBIDI_BEGIN_STMT */

/* LIKEYLY and UNLIKELY are used to give a hint on branch prediction to the
 * compiler. */
#ifndef LIKELY
# define LIKELY
# define UNLIKELY
#endif /* !LIKELY */

#ifndef FRIBIDI_EMPTY_STMT
# define FRIBIDI_EMPTY_STMT FRIBIDI_BEGIN_STMT (void) 0; FRIBIDI_END_STMT
#endif /* !FRIBIDI_EMPTY_STMT */

#if HAVE_STRINGIZE+0
# define STRINGIZE(symbol) #symbol
#else /* !HAVE_STRINGIZE */
# define STRINGIZE(symbol) (no stringize operator available)
#endif /* !HAVE_STRINGIZE */

/* As per recommendation of GNU Coding Standards. */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif /* !_GNU_SOURCE */

#include "debug.h"

#endif /* !_COMMON_H */
/* Editor directions:
 * vim:textwidth=78:tabstop=8:shiftwidth=2:autoindent:cindent
 */
 

config.h   、、、、、、、、、、、、、、、、、、、、、、、、、、、、

#ifndef _CONFIG_H
#define _CONFIG_H

/* Define to 1 if you want to include debug code in the library */
#define DEBUG 0

/* Define to 1 if you don't have the "fribidi-config.h" header file. */
#define DONT_HAVE_FRIBIDI_CONFIG_H 0

/* Define to 1 if you don't have the "fribidi-unicode-version.h" header file. */
#define DONT_HAVE_FRIBIDI_UNICODE_VERSION_H 0

/* Define to 1 if you have the "fribidi-custom.h" header file. */
#define HAVE_FRIBIDI_CUSTOM_H 0

/* Define to 1 if you have the <asm/page.h> header file. */
#define HAVE_ASM_PAGE_H 0

/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H

/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H

/* Define to 1 if you have the `memmove' function. */
#undef HAVE_MEMMOVE

/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 0

/* Define to 1 if you have the `memset' function. */
#undef HAVE_MEMSET

/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H

/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1

/* Define to 1 if you have the `strdup' function. */
#undef HAVE_STRDUP

/* Define to 1 if cpp supports the ANSI # stringizing operator. */
#define HAVE_STRINGIZE 1

/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 0

/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1

/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H

/* Define to 1 if you have the <sys/times.h> header file. */
#undef HAVE_SYS_TIMES_H

/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H

/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H

/* Define to 1 if you have the <wchar.h> header file. */
#undef HAVE_WCHAR_H

/* Define to the sub-directory in which libtool stores uninstalled libraries.
   */
#undef LT_OBJDIR

/* Name of package */
#undef PACKAGE

/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT

/* Define to the full name of this package. */
#undef PACKAGE_NAME

/* Define to the full name and version of this package. */
#undef PACKAGE_STRING

/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME

/* Define to the version of this package. */
#undef PACKAGE_VERSION

/* Define as the return type of signal handlers (`int' or `void'). */
#undef RETSIGTYPE

/* The size of `int', as computed by sizeof. */
#define SIZEOF_INT 4

/* The size of `short', as computed by sizeof. */
#undef SIZEOF_SHORT

/* The size of `void *', as computed by sizeof. */
#undef SIZEOF_VOID_P

/* The size of `wchar_t', as computed by sizeof. */
#define SIZEOF_WCHAR_T 2

/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 0

/* Define to 1 if you want to use simple mallocs instead of memory chunks */
#define USE_SIMPLE_MALLOC 0

/* Version number of package */
#undef VERSION

/* Define to empty if `const' does not conform to ANSI C. */
#undef const

#endif /* !_CONFIG_H */
 

debug.h  、、、、、、、、、、、、、、、、、、、、、、、、、、、、

/* FriBidi
 * debug.h - debug-only interfaces
 *
 * $Id: debug.h,v 1.10 2006/01/31 03:23:12 behdad Exp $
 * $Author: behdad $
 * $Date: 2006/01/31 03:23:12 $
 * $Revision: 1.10 $
 * $Source: /cvs/fribidi/fribidi2/lib/debug.h,v $
 *
 * Author:
 *   Behdad Esfahbod, 2001, 2002, 2004
 *
 * Copyright (C) 2004 Sharif FarsiWeb, Inc.
 * Copyright (C) 2001,2002 Behdad Esfahbod
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library 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
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library, in a file named COPYING; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA
 *
 * For licensing issues, contact <license@farsiweb.info>.
 */
#ifndef _DEBUG_H
#define _DEBUG_H

#include "common.h"

#include "fribidi-types.h"

#include "fribidi-begindecls.h"

#if DEBUG+0

/* These definitions should only be used in DEBUG mode: */
#ifndef __LINE__
# define __LINE__ 0
#endif /* !__LINE__ */
#ifndef __FILE__
# define __FILE__ "unknown"
#endif /* !__FILE__ */

#ifndef FRIBIDI_FPRINTF
# ifndef __FRIBIDI_DOC
#  include <stdio.h>
# endif    /* !__FRIBIDI_DOC */
# define FRIBIDI_FPRINTF fprintf
# define FRIBIDI_STDERR_ stderr,
#endif /* !FRIBIDI_FPRINTF */

#ifndef MSG
#define MSG(s) \
    FRIBIDI_BEGIN_STMT \
    FRIBIDI_FPRINTF(FRIBIDI_STDERR_ s); \
    FRIBIDI_END_STMT
#define MSG2(s, t) \
    FRIBIDI_BEGIN_STMT \
    FRIBIDI_FPRINTF(FRIBIDI_STDERR_ s, t); \
    FRIBIDI_END_STMT
#define MSG5(s, t, u, v, w) \
    FRIBIDI_BEGIN_STMT \
    FRIBIDI_FPRINTF(FRIBIDI_STDERR_ s, t, u, v, w); \
    FRIBIDI_END_STMT
#endif /* !MSG */

#ifndef DBG
# define DBG(s) \
    FRIBIDI_BEGIN_STMT \
    if (fribidi_debug_status()) { MSG(FRIBIDI ": " s "\n"); } \
    FRIBIDI_END_STMT
# define DBG2(s, t) \
    FRIBIDI_BEGIN_STMT \
    if (fribidi_debug_status()) { MSG2(FRIBIDI ": " s "\n", t); } \
    FRIBIDI_END_STMT
#endif /* !DBG */

#ifndef fribidi_assert
# define fribidi_assert(cond) \
    FRIBIDI_BEGIN_STMT \
    if (!(cond)) { \
        DBG(__FILE__ ":" STRINGIZE(__LINE__) ": " \
            "assertion failed (" STRINGIZE(cond) ")"); \
    } \
    FRIBIDI_END_STMT
#endif /* !fribidi_assert */

#else /* !DEBUG */

#ifndef DBG
# define DBG(s)            FRIBIDI_EMPTY_STMT
# define DBG2(s, t)        FRIBIDI_EMPTY_STMT
#endif /* !DBG */
#ifndef fribidi_assert
# define fribidi_assert(cond)    FRIBIDI_EMPTY_STMT
#endif /* !fribidi_assert */

#endif /* !DEBUG */

#include "fribidi-enddecls.h"

#endif /* !_DEBUG_H */
/* Editor directions:
 * vim:textwidth=78:tabstop=8:shiftwidth=2:autoindent:cindent
 */
 

fribidi.c  、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

/* FriBidi
 * fribidi.c - Unicode bidirectional and Arabic joining/shaping algorithms
 *
 * $Id: fribidi.c,v 1.18 2006/01/31 03:23:13 behdad Exp $
 * $Author: behdad $
 * $Date: 2006/01/31 03:23:13 $
 * $Revision: 1.18 $
 * $Source: /cvs/fribidi/fribidi2/lib/fribidi.c,v $
 *
 * Authors:
 *   Behdad Esfahbod, 2001, 2002, 2004
 *   Dov Grobgeld, 1999, 2000
 *
 * Copyright (C) 2004 Sharif FarsiWeb, Inc
 * Copyright (C) 2001,2002 Behdad Esfahbod
 * Copyright (C) 1999,2000 Dov Grobgeld
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library 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
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library, in a file named COPYING; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA
 * 
 * For licensing issues, contact <license@farsiweb.info>.
 */

#include "common.h"

#include "fribidi.h"

#if DEBUG+0
static int flag_debug = false;
#endif

FRIBIDI_ENTRY fribidi_boolean
fribidi_debug_status (
  void
)
{
#if DEBUG+0
  return flag_debug;
#else
  return false;
#endif
}

FRIBIDI_ENTRY fribidi_boolean
fribidi_set_debug (
  /* input */
  fribidi_boolean state
)
{
#if DEBUG+0
  return flag_debug = state;
#else
  return false;
#endif
}

const char *fribidi_unicode_version = FRIBIDI_UNICODE_VERSION;

const char *fribidi_version_info =
  "(" FRIBIDI_NAME ") " FRIBIDI_VERSION "\n"
  "interface version " FRIBIDI_INTERFACE_VERSION_STRING ",\n"
  "Unicode Character Database version " FRIBIDI_UNICODE_VERSION ",\n"
  "Configure options"
#if DEBUG+0
  " --enable-debug"
#endif /* DEBUG */
#if USE_SIMPLE_MALLOC+0
  " --enable-malloc"
#endif /* USE_SIMPLE_MALLOC */
#if FRIBIDI_CHARSETS+0
#else
  " --disable-charsets"
#endif /* !FRIBIDI_CHARSETS */
#if FRIBIDI_USE_GLIB+0
  " --with-glib"
#else /* !FRIBIDI_USE_GLIB */
  " --without-glib"
#endif /* !FRIBIDI_USE_GLIB */
  ".\n\n"
  "Copyright (C) 2004  Sharif FarsiWeb, Inc.\n"
  "Copyright (C) 2001, 2002, 2004, 2005  Behdad Esfahbod\n"
  "Copyright (C) 1999, 2000  Dov Grobgeld\n"
  FRIBIDI_NAME " comes with NO WARRANTY, to the extent permitted by law.\n"
  "You may redistribute copies of " FRIBIDI_NAME " under\n"
  "the terms of the GNU Lesser General Public License.\n"
  "For more information about these matters, see the file named COPYING.\n\n"
  "Written by Behdad Esfahbod and Dov Grobgeld.\n";

/* Editor directions:
 * vim:textwidth=78:tabstop=8:shiftwidth=2:autoindent:cindent
 */
 

fribidi.h  、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

/* FriBidi
 * fribidi.h - Unicode bidirectional and Arabic joining/shaping algorithms
 *
 * $Id: fribidi.h,v 1.10 2006/01/31 03:23:13 behdad Exp $
 * $Author: behdad $
 * $Date: 2006/01/31 03:23:13 $
 * $Revision: 1.10 $
 * $Source: /cvs/fribidi/fribidi2/lib/fribidi.h,v $
 *
 * Author:
 *   Behdad Esfahbod, 2004
 *
 * Copyright (C) 2004 Sharif FarsiWeb, Inc
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library 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
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library, in a file named COPYING; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA
 * 
 * For licensing issues, contact <license@farsiweb.info>.
 */
#ifndef _FRIBIDI_H
#define _FRIBIDI_H

#include "fribidi-common.h"

#include "fribidi-unicode.h"
#include "fribidi-types.h"
#include "fribidi-flags.h"
#include "fribidi-bidi-types.h"
#include "fribidi-bidi.h"
#include "fribidi-joining-types.h"
#include "fribidi-joining.h"
#include "fribidi-mirroring.h"
#include "fribidi-arabic.h"
#include "fribidi-shape.h"


#if FRIBIDI_CHARSETS+0
# include "fribidi-char-sets.h"
#endif                /* FRIBIDI_CHARSETS */


#if FRIBIDI_NO_DEPRECATED+0
#else
# include "fribidi-deprecated.h"
#endif                /* !FRIBIDI_NO_DEPRECATED */


#include "fribidi-begindecls.h"

#define fribidi_version_info FRIBIDI_NAMESPACE(version_info)
/* An string containing the version information of the library. */
     extern const char *fribidi_version_info;

#include "fribidi-enddecls.h"

#endif /* !_FRIBIDI_H */
/* Editor directions:
 * vim:textwidth=78:tabstop=8:shiftwidth=2:autoindent:cindent
 */
 

fribidi-arabic.c  、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

/* fribidi-arabic.c - Arabic shaping
 *
 * Copyright (C) 2005  Behdad Esfahbod
 *
 * This file is part of GNU FriBidi.
 * 
 * GNU FriBidi is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1
 * of the License, or (at your option) any later version.
 * 
 * GNU FriBidi 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 Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with GNU FriBidi; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * 
 * For licensing issues, contact <license@farsiweb.info> or write to
 * Sharif FarsiWeb, Inc., PO Box 13445-389, Tehran, Iran.
 */
/* $Id: fribidi-arabic.c,v 1.3 2007/04/05 16:14:39 behdad Exp $
 * $Author: behdad $
 * $Date: 2007/04/05 16:14:39 $
 * $Revision: 1.3 $
 * $Source: /cvs/fribidi/fribidi2/lib/fribidi-arabic.c,v $
 *
 * Author(s):
 *   Behdad Esfahbod, 2005
 */

#include "common.h"

#if HAVE_STDLIB_H+0
# include <stdlib.h>
#endif


#include "fribidi-arabic.h"
#include "fribidi-unicode.h"


typedef struct _PairMap {
  FriBidiChar pair[2], to;
} PairMap;


#define FRIBIDI_ACCESS_SHAPE_TABLE(table,min,max,x,shape) (table), (min), (max)
# define FRIBIDI_ACCESS_SHAPE_TABLE_REAL(table,min,max,x,shape) \
    (((x)<(min)||(x)>(max))?(x):(table)[(x)-(min)][(shape)])

#include "arabic-shaping.tab.i"
#include "arabic-misc.tab.i"


static void
fribidi_shape_arabic_joining (
  /* input */
  const FriBidiChar table[][4],
  FriBidiChar min,
  FriBidiChar max,
  const FriBidiStrIndex len,
  const FriBidiArabicProp *ar_props,
  /* input and output */
  FriBidiChar *str
)
{
  register FriBidiStrIndex i;

  for (i = 0; i < len; i++)
    if (FRIBIDI_ARAB_SHAPES(ar_props[i]))
      str[i] = FRIBIDI_ACCESS_SHAPE_TABLE_REAL (table, min, max, str[i], FRIBIDI_JOIN_SHAPE (ar_props[i]));
}

static int
comp_PairMap (const void *pa, const void *pb)
{
  PairMap *a = (PairMap *)pa;
  PairMap *b = (PairMap *)pb;

  if (a->pair[0] != b->pair[0])
    return a->pair[0] < b->pair[0] ? -1 : +1;
  else
    return a->pair[1] < b->pair[1] ? -1 :
           a->pair[1] > b->pair[1] ? +1 :
       0;
}


static FriBidiChar
find_pair_match (const PairMap *table, int size, FriBidiChar first, FriBidiChar second)
{
  PairMap *match;
  PairMap x;
  x.pair[0] = first;
  x.pair[1] = second;
  x.to = 0;
  match = bsearch (&x, table, size, sizeof (table[0]), comp_PairMap);
  return match ? match->to : 0;
}

#define PAIR_MATCH(table,len,first,second) \
    ((first)<(table[0].pair[0])||(first)>(table[len-1].pair[0])?0: \
     find_pair_match(table, len, first, second))

static void
fribidi_shape_arabic_ligature (
  /* input */
  const PairMap *table,
  int size,
  const FriBidiLevel *embedding_levels,
  const FriBidiStrIndex len,
  /* input and output */
  FriBidiArabicProp *ar_props,
  FriBidiChar *str
)
{
  /* TODO: This doesn't form ligatures for even-level Arabic text.
   * no big problem though. */
  register FriBidiStrIndex i;

  for (i = 0; i < len - 1; i++) {
    register FriBidiChar c;
    if (FRIBIDI_LEVEL_IS_RTL(embedding_levels[i]) &&
    embedding_levels[i] == embedding_levels[i+1] &&
    (c = PAIR_MATCH(table, size, str[i], str[i+1])))
      {
    str[i] = FRIBIDI_CHAR_FILL;
    FRIBIDI_SET_BITS(ar_props[i], FRIBIDI_MASK_LIGATURED);
    str[i+1] = c;
      }
  }
}

#define DO_LIGATURING(table, levels, len, ar_props, str) \
    fribidi_shape_arabic_ligature ((table), sizeof(table)/sizeof((table)[0]), levels, len, ar_props, str)

#define DO_SHAPING(tablemacro, len, ar_props, str) \
    fribidi_shape_arabic_joining (tablemacro(,), len, ar_props, str);
    

FRIBIDI_ENTRY void
fribidi_shape_arabic (
  /* input */
  FriBidiFlags flags,
  const FriBidiLevel *embedding_levels,
  const FriBidiStrIndex len,
  /* input and output */
  FriBidiArabicProp *ar_props,
  FriBidiChar *str
)
{
  DBG ("in fribidi_shape_arabic");

  if UNLIKELY
    (len == 0 || !str) return;

  DBG ("in fribidi_shape");

  fribidi_assert (ar_props);

  if (FRIBIDI_TEST_BITS (flags, FRIBIDI_FLAG_SHAPE_ARAB_PRES))
    {
      DO_SHAPING (FRIBIDI_GET_ARABIC_SHAPE_PRES, len, ar_props, str);
    }

  if (FRIBIDI_TEST_BITS (flags, FRIBIDI_FLAG_SHAPE_ARAB_LIGA))
    {
      DO_LIGATURING (mandatory_liga_table, embedding_levels, len, ar_props, str);
    }

  if (FRIBIDI_TEST_BITS (flags, FRIBIDI_FLAG_SHAPE_ARAB_CONSOLE))
    {
      DO_LIGATURING (console_liga_table, embedding_levels, len, ar_props, str);
      DO_SHAPING (FRIBIDI_GET_ARABIC_SHAPE_NSM, len, ar_props, str);
    }
}

/* Editor directions:
 * Local Variables:
 *   mode: c
 *   c-basic-offset: 2
 *   indent-tabs-mode: t
 *   tab-width: 8
 * End:
 * vim: textwidth=78: autoindent: cindent: shiftwidth=2: tabstop=8:
 */
 

fribidi-arabic.h   、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

/* fribidi-arabic.h - do Arabic shaping to presentation forms
 *
 * Copyright (C) 2005  Behdad Esfahbod
 * 
 * This file is part of GNU FriBidi.
 * 
 * GNU FriBidi is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1
 * of the License, or (at your option) any later version.
 * 
 * GNU FriBidi 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 Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with GNU FriBidi; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * 
 * For licensing issues, contact <license@farsiweb.info> or write to
 * Sharif FarsiWeb, Inc., PO Box 13445-389, Tehran, Iran.
 */
/* $Id: fribidi-arabic.h,v 1.1 2005/11/03 01:39:01 behdad Exp $
 * $Author: behdad $
 * $Date: 2005/11/03 01:39:01 $
 * $Revision: 1.1 $
 * $Source: /cvs/fribidi/fribidi2/lib/fribidi-arabic.h,v $
 *
 * Author(s):
 *   Behdad Esfahbod, 2005
 */
#ifndef _FRIBIDI_ARABIC_H
#define _FRIBIDI_ARABIC_H

#include "fribidi-common.h"

#include "fribidi-types.h"
#include "fribidi-flags.h"
#include "fribidi-bidi-types.h"
#include "fribidi-joining.h"

#include "fribidi-begindecls.h"


#define fribidi_shape_arabic FRIBIDI_NAMESPACE(shape_arabic)
/* fribidi_shape_arabic - do Arabic shaping
 *
 * The actual shaping that is done depends on the flags set.  Only flags
 * starting with FRIBIDI_FLAG_SHAPE_ARAB_ affect this function.
 * Currently these are:
 *
 *    * FRIBIDI_FLAG_SHAPE_MIRRORING: Do mirroring.
 *    * FRIBIDI_FLAG_SHAPE_ARAB_PRES: Shape Arabic characters to their
 *                    presentation form glyphs.
 *    * FRIBIDI_FLAG_SHAPE_ARAB_LIGA: Form mandatory Arabic ligatures.
 *    * FRIBIDI_FLAG_SHAPE_ARAB_CONSOLE: Perform additional Arabic shaping
 *                       suitable for text rendered on
 *                       grid terminals with no mark
 *                       rendering capabilities.
 *
 * Of the above, FRIBIDI_FLAG_SHAPE_ARAB_CONSOLE is only used in special
 * cases, but the rest are recommended in any enviroment that doesn't have
 * other means for doing Arabic shaping.  The set of extra flags that enable
 * this level of Arabic support has a shortcut named FRIBIDI_FLAGS_ARABIC.
 */
FRIBIDI_ENTRY void
fribidi_shape_arabic (
  FriBidiFlags flags, /* shaping flags */
  const FriBidiLevel *embedding_levels,
  const FriBidiStrIndex len,    /* input string length */
  FriBidiArabicProp *ar_props, /* input/output Arabic properties as
                * computed by fribidi_join_arabic */
  FriBidiChar *str        /* string to shape */
);

#include "fribidi-enddecls.h"

#endif /* !_FRIBIDI_ARABIC_H */
/* Editor directions:
 * Local Variables:
 *   mode: c
 *   c-basic-offset: 2
 *   indent-tabs-mode: t
 *   tab-width: 8
 * End:
 * vim: textwidth=78: autoindent: cindent: shiftwidth=2: tabstop=8:
 */
 

fribidi-begindecls.h  、、、、、、、、、、、、、、、、、、、、、、、、、、

#ifdef FRIBIDI_BEGIN_DECLS
FRIBIDI_BEGIN_DECLS
#endif /* FRIBIDI_BEGIN_DECLS */
 

fribidi-bidi.c   、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

/* FriBidi
 * fribidi-bidi.c - bidirectional algorithm
 *
 * $Id: fribidi-bidi.c,v 1.21 2007/03/15 18:09:25 behdad Exp $
 * $Author: behdad $
 * $Date: 2007/03/15 18:09:25 $
 * $Revision: 1.21 $
 * $Source: /cvs/fribidi/fribidi2/lib/fribidi-bidi.c,v $
 *
 * Authors:
 *   Behdad Esfahbod, 2001, 2002, 2004
 *   Dov Grobgeld, 1999, 2000
 *
 * Copyright (C) 2004 Sharif FarsiWeb, Inc
 * Copyright (C) 2001,2002 Behdad Esfahbod
 * Copyright (C) 1999,2000 Dov Grobgeld
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library 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
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library, in a file named COPYING; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA
 * 
 * For licensing issues, contact <license@farsiweb.info>.
 */

#include "common.h"

#include "fribidi-bidi.h"
#include "fribidi-mirroring.h"
#include "fribidi-unicode.h"

#include "mem.h"
#include "bidi-types.h"
#include "run.h"

/*
 * This file implements most of Unicode Standard Annex #9, Tracking Number 13.
 */

#ifndef MAX
# define MAX(a,b) ((a) > (b) ? (a) : (b))
#endif /* !MAX */

/* Some convenience macros */
#define RL_TYPE(list) ((list)->type)
#define RL_LEN(list) ((list)->len)
#define RL_POS(list) ((list)->pos)
#define RL_LEVEL(list) ((list)->level)

static FriBidiRun *
merge_with_prev (
  FriBidiRun *second
)
{
  FriBidiRun *first;

  fribidi_assert (second);
  fribidi_assert (second->next);
  first = second->prev;
  fribidi_assert (first);

  first->next = second->next;
  first->next->prev = first;
  RL_LEN (first) += RL_LEN (second);
  free_run (second);
  return first;
}

static void
compact_list (
  FriBidiRun *list
)
{
  fribidi_assert (list);

  if (list->next)
    for_run_list (list, list)
      if (RL_TYPE (list->prev) == RL_TYPE (list)
      && RL_LEVEL (list->prev) == RL_LEVEL (list))
      list = merge_with_prev (list);
}

static void
compact_neutrals (
  FriBidiRun *list
)
{
  fribidi_assert (list);

  if (list->next)
    {
      for_run_list (list, list)
      {
    if (RL_LEVEL (list->prev) == RL_LEVEL (list)
        &&
        ((RL_TYPE
          (list->prev) == RL_TYPE (list)
          || (FRIBIDI_IS_NEUTRAL (RL_TYPE (list->prev))
          && FRIBIDI_IS_NEUTRAL (RL_TYPE (list))))))
      list = merge_with_prev (list);
      }
    }
}

#if DEBUG+0
/*======================================================================
 *  For debugging, define some functions for printing the types and the
 *  levels.
 *----------------------------------------------------------------------*/

static char char_from_level_array[] = {
  '$',                /* -1 == FRIBIDI_SENTINEL, indicating
                 * start or end of string. */
  /* 0-61 == 0-9,a-z,A-Z are the the only valid levels before resolving
   * implicits.  after that the level @ may be appear too. */
  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
  'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
  'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D',
  'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
  'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
  'Y', 'Z',

  '@',                /* 62 == only must appear after resolving
                 * implicits. */

  '!',                /* 63 == FRIBIDI_LEVEL_INVALID, internal error,
                 * this level shouldn't be seen.  */

  '*', '*', '*', '*', '*'    /* >= 64 == overflows, this levels and higher
                 * levels show a real bug!. */
};

#define fribidi_char_from_level(level) char_from_level_array[(level) + 1]

static void
print_types_re (
  const FriBidiRun *pp
)
{
  fribidi_assert (pp);

  MSG ("  Run types  : ");
  for_run_list (pp, pp)
  {
    MSG5 ("%d:%d(%s)[%d] ",
      pp->pos, pp->len, fribidi_get_bidi_type_name (pp->type), pp->level);
  }
  MSG ("\n");
}

static void
print_resolved_levels (
  const FriBidiRun *pp
)
{
  fribidi_assert (pp);

  MSG ("  Res. levels: ");
  for_run_list (pp, pp)
  {
    register FriBidiStrIndex i;
    for (i = RL_LEN (pp); i; i--)
      MSG2 ("%c", fribidi_char_from_level (RL_LEVEL (pp)));
  }
  MSG ("\n");
}

static void
print_resolved_types (
  const FriBidiRun *pp
)
{
  fribidi_assert (pp);

  MSG ("  Res. types : ");
  for_run_list (pp, pp)
  {
    FriBidiStrIndex i;
    for (i = RL_LEN (pp); i; i--)
      MSG2 ("%c", fribidi_char_from_bidi_type (pp->type));
  }
  MSG ("\n");
}

static void
print_bidi_string (
  /* input */
  const FriBidiCharType *bidi_types,
  const FriBidiStrIndex len
)
{
  register FriBidiStrIndex i;

  fribidi_assert (bidi_types);

  MSG ("  Org. types : ");
  for (i = 0; i < len; i++)
    MSG2 ("%c", fribidi_char_from_bidi_type (bidi_types[i]));
  MSG ("\n");
}
#endif /* DEBUG */


/*=========================================================================
 * define macros for push and pop the status in to / out of the stack
 *-------------------------------------------------------------------------*/

/* There are a few little points in pushing into and poping from the status
   stack:
   1. when the embedding level is not valid (more than
   FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL=61), you must reject it, and not to push
   into the stack, but when you see a PDF, you must find the matching code,
   and if it was pushed in the stack, pop it, it means you must pop if and
   only if you have pushed the matching code, the over_pushed var counts the
   number of rejected codes so far.
   2. there's a more confusing point too, when the embedding level is exactly
   FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL-1=60, an LRO or LRE is rejected
   because the new level would be FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL+1=62, that
   is invalid; but an RLO or RLE is accepted because the new level is
   FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL=61, that is valid, so the rejected codes
   may be not continuous in the logical order, in fact there are at most two
   continuous intervals of codes, with an RLO or RLE between them.  To support
   this case, the first_interval var counts the number of rejected codes in
   the first interval, when it is 0, means that there is only one interval.
*/

/* a. If this new level would be valid, then this embedding code is valid.
   Remember (push) the current embedding level and override status.
   Reset current level to this new level, and reset the override status to
   new_override.
   b. If the new level would not be valid, then this code is invalid. Don't
   change the current level or override status.
*/
#define PUSH_STATUS \
    FRIBIDI_BEGIN_STMT \
      if LIKELY(new_level <= FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL) \
        { \
          if UNLIKELY(level == FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL - 1) \
            first_interval = over_pushed; \
          status_stack[stack_size].level = level; \
          status_stack[stack_size].override = override; \
          stack_size++; \
          level = new_level; \
          override = new_override; \
        } else \
      over_pushed++; \
    FRIBIDI_END_STMT

/* If there was a valid matching code, restore (pop) the last remembered
   (pushed) embedding level and directional override.
*/
#define POP_STATUS \
    FRIBIDI_BEGIN_STMT \
      if (stack_size) \
      { \
        if UNLIKELY(over_pushed > first_interval) \
          over_pushed--; \
        else \
          { \
            if LIKELY(over_pushed == first_interval) \
              first_interval = 0; \
            stack_size--; \
            level = status_stack[stack_size].level; \
            override = status_stack[stack_size].override; \
          } \
      } \
    FRIBIDI_END_STMT


/* Return the type of previous run or the SOR, if already at the start of
   a level run. */
#define PREV_TYPE_OR_SOR(pp) \
    ( \
      RL_LEVEL(pp->prev) == RL_LEVEL(pp) ? \
        RL_TYPE(pp->prev) : \
        FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(pp->prev), RL_LEVEL(pp))) \
    )

/* Return the type of next run or the EOR, if already at the end of
   a level run. */
#define NEXT_TYPE_OR_EOR(pp) \
    ( \
      RL_LEVEL(pp->next) == RL_LEVEL(pp) ? \
        RL_TYPE(pp->next) : \
        FRIBIDI_LEVEL_TO_DIR(MAX(RL_LEVEL(pp->next), RL_LEVEL(pp))) \
    )


/* Return the embedding direction of a link. */
#define FRIBIDI_EMBEDDING_DIRECTION(link) \
    FRIBIDI_LEVEL_TO_DIR(RL_LEVEL(link))


FRIBIDI_ENTRY FriBidiParType
fribidi_get_par_direction (
  /* input */
  const FriBidiCharType *bidi_types,
  const FriBidiStrIndex len
)
{
  register FriBidiStrIndex i;

  fribidi_assert (bidi_types);

  for (i = 0; i < len; i++)
    if (FRIBIDI_IS_LETTER (bidi_types[i]))
      return FRIBIDI_IS_RTL (bidi_types[i]) ? FRIBIDI_PAR_RTL :
    FRIBIDI_PAR_LTR;

  return FRIBIDI_PAR_ON;
}

FRIBIDI_ENTRY FriBidiLevel
fribidi_get_par_embedding_levels (
  /* input */
  const FriBidiCharType *bidi_types,
  const FriBidiStrIndex len,
  /* input and output */
  FriBidiParType *pbase_dir,
  /* output */
  FriBidiLevel *embedding_levels
)
{
  FriBidiLevel base_level, max_level = 0;
  FriBidiParType base_dir;
  FriBidiRun *main_run_list = NULL, *explicits_list = NULL, *pp;
  fribidi_boolean status = false;

  if UNLIKELY
    (!len)
    {
      status = true;
      goto out;
    }

  DBG ("in fribidi_get_par_embedding_levels");

  fribidi_assert (bidi_types);
  fribidi_assert (pbase_dir);
  fribidi_assert (embedding_levels);

  /* Determinate character types */
  {
    /* Get run-length encoded character types */
    main_run_list = run_list_encode_bidi_types (bidi_types, len);
    if UNLIKELY
      (!main_run_list) goto out;
  }

  /* Find base level */
  /* If no strong base_dir was found, resort to the weak direction
     that was passed on input. */
  base_level = FRIBIDI_DIR_TO_LEVEL (*pbase_dir);
  if (!FRIBIDI_IS_STRONG (*pbase_dir))
    /* P2. P3. Search for first strong character and use its direction as
       base direction */
    {
      for_run_list (pp, main_run_list) if (FRIBIDI_IS_LETTER (RL_TYPE (pp)))
    {
      base_level = FRIBIDI_DIR_TO_LEVEL (RL_TYPE (pp));
      *pbase_dir = FRIBIDI_LEVEL_TO_DIR (base_level);
      break;
    }
    }
  base_dir = FRIBIDI_LEVEL_TO_DIR (base_level);
  DBG2 ("  base level : %c", fribidi_char_from_level (base_level));
  DBG2 ("  base dir   : %c", fribidi_char_from_bidi_type (base_dir));

# if DEBUG
  if UNLIKELY
    (fribidi_debug_status ())
    {
      print_types_re (main_run_list);
    }
# endif    /* DEBUG */

  /* Explicit Levels and Directions */
  DBG ("explicit levels and directions");
  {
    FriBidiLevel level, new_level;
    FriBidiCharType override, new_override;
    FriBidiStrIndex i;
    int stack_size, over_pushed, first_interval;
    struct
    {
      FriBidiCharType override;    /* only LTR, RTL and ON are valid */
      FriBidiLevel level;
    } *status_stack;
    FriBidiRun temp_link;

/* explicits_list is a list like main_run_list, that holds the explicit
   codes that are removed from main_run_list, to reinsert them later by
   calling the shadow_run_list.
*/
    explicits_list = new_run_list ();
    if UNLIKELY
      (!explicits_list) goto out;

    /* X1. Begin by setting the current embedding level to the paragraph
       embedding level. Set the directional override status to neutral.
       Process each character iteratively, applying rules X2 through X9.
       Only embedding levels from 0 to 61 are valid in this phase. */

    level = base_level;
    override = FRIBIDI_TYPE_ON;
    /* stack */
    stack_size = 0;
    over_pushed = 0;
    first_interval = 0;
    status_stack = fribidi_malloc (sizeof (status_stack[0]) *
                   FRIBIDI_BIDI_MAX_RESOLVED_LEVELS);

    for_run_list (pp, main_run_list)
    {
      FriBidiCharType this_type = RL_TYPE (pp);
      if (FRIBIDI_IS_EXPLICIT_OR_BN (this_type))
    {
      if (FRIBIDI_IS_STRONG (this_type))
        {            /* LRE, RLE, LRO, RLO */
          /* 1. Explicit Embeddings */
          /*   X2. With each RLE, compute the least greater odd
             embedding level. */
          /*   X3. With each LRE, compute the least greater even
             embedding level. */
          /* 2. Explicit Overrides */
          /*   X4. With each RLO, compute the least greater odd
             embedding level. */
          /*   X5. With each LRO, compute the least greater even
             embedding level. */
          new_override = FRIBIDI_EXPLICIT_TO_OVERRIDE_DIR (this_type);
          for (i = RL_LEN (pp); i; i--)
        {
          new_level =
            ((level + FRIBIDI_DIR_TO_LEVEL (this_type) + 2) & ~1) -
            FRIBIDI_DIR_TO_LEVEL (this_type);
          PUSH_STATUS;
        }
        }
      else if (this_type == FRIBIDI_TYPE_PDF)
        {
          /* 3. Terminating Embeddings and overrides */
          /*   X7. With each PDF, determine the matching embedding or
             override code. */
          for (i = RL_LEN (pp); i; i--)
        POP_STATUS;
        }

      /* X9. Remove all RLE, LRE, RLO, LRO, PDF, and BN codes. */
      /* Remove element and add it to explicits_list */
      RL_LEVEL (pp) = FRIBIDI_SENTINEL;
      temp_link.next = pp->next;
      move_node_before (pp, explicits_list);
      pp = &temp_link;
    }
      else
    {
      /* X6. For all types besides RLE, LRE, RLO, LRO, and PDF:
         a. Set the level of the current character to the current
         embedding level.
         b. Whenever the directional override status is not neutral,
         reset the current character type to the directional override
         status. */
      RL_LEVEL (pp) = level;
      if (!FRIBIDI_IS_NEUTRAL (override))
        RL_TYPE (pp) = override;
    }
      /* X8. All explicit directional embeddings and overrides are
         completely terminated at the end of each paragraph. Paragraph
         separators are not included in the embedding. */
      /* This function is running on a single paragraph, so we can do
         X8 after all the input is processed. */
    }

    /* Implementing X8. It has no effect on a single paragraph! */
    level = base_level;
    override = FRIBIDI_TYPE_ON;
    stack_size = 0;
    over_pushed = 0;

    fribidi_free (status_stack);
  }
  /* X10. The remaining rules are applied to each run of characters at the
     same level. For each run, determine the start-of-level-run (sor) and
     end-of-level-run (eor) type, either L or R. This depends on the
     higher of the two levels on either side of the boundary (at the start
     or end of the paragraph, the level of the 'other' run is the base
     embedding level). If the higher level is odd, the type is R, otherwise
     it is L. */
  /* Resolving Implicit Levels can be done out of X10 loop, so only change
     of Resolving Weak Types and Resolving Neutral Types is needed. */

  compact_list (main_run_list);

# if DEBUG
  if UNLIKELY
    (fribidi_debug_status ())
    {
      print_types_re (main_run_list);
      print_bidi_string (bidi_types, len);
      print_resolved_levels (main_run_list);
      print_resolved_types (main_run_list);
    }
# endif    /* DEBUG */

  /* 4. Resolving weak types */
  DBG ("resolving weak types");
  {
    FriBidiCharType last_strong, prev_type_orig;
    fribidi_boolean w4;

    last_strong = base_dir;

    for_run_list (pp, main_run_list)
    {
      register FriBidiCharType prev_type, this_type, next_type;

      prev_type = PREV_TYPE_OR_SOR (pp);
      this_type = RL_TYPE (pp);
      next_type = NEXT_TYPE_OR_EOR (pp);

      if (FRIBIDI_IS_STRONG (prev_type))
    last_strong = prev_type;

      /* W1. NSM
         Examine each non-spacing mark (NSM) in the level run, and change the
         type of the NSM to the type of the previous character. If the NSM
         is at the start of the level run, it will get the type of sor. */
      /* Implementation note: it is important that if the previous character
         is not sor, then we should merge this run with the previous,
         because of rules like W5, that we assume all of a sequence of
         adjacent ETs are in one FriBidiRun. */
      if (this_type == FRIBIDI_TYPE_NSM)
    {
      if (RL_LEVEL (pp->prev) == RL_LEVEL (pp))
        pp = merge_with_prev (pp);
      else
        RL_TYPE (pp) = prev_type;
      continue;        /* As we know the next condition cannot be true. */
    }

      /* W2: European numbers. */
      if (this_type == FRIBIDI_TYPE_EN && last_strong == FRIBIDI_TYPE_AL)
    {
      RL_TYPE (pp) = FRIBIDI_TYPE_AN;

      /* Resolving dependency of loops for rules W1 and W2, so we
         can merge them in one loop. */
      if (next_type == FRIBIDI_TYPE_NSM)
        RL_TYPE (pp->next) = FRIBIDI_TYPE_AN;
    }
    }


    last_strong = base_dir;
    /* Resolving dependency of loops for rules W4 and W5, W5 may
       want to prevent W4 to take effect in the next turn, do this 
       through "w4". */
    w4 = true;
    /* Resolving dependency of loops for rules W4 and W5 with W7,
       W7 may change an EN to L but it sets the prev_type_orig if needed,
       so W4 and W5 in next turn can still do their works. */
    prev_type_orig = FRIBIDI_TYPE_ON;

    for_run_list (pp, main_run_list)
    {
      register FriBidiCharType prev_type, this_type, next_type;

      prev_type = PREV_TYPE_OR_SOR (pp);
      this_type = RL_TYPE (pp);
      next_type = NEXT_TYPE_OR_EOR (pp);

      if (FRIBIDI_IS_STRONG (prev_type))
    last_strong = prev_type;

      /* W3: Change ALs to R. */
      if (this_type == FRIBIDI_TYPE_AL)
    {
      RL_TYPE (pp) = FRIBIDI_TYPE_RTL;
      w4 = true;
      prev_type_orig = FRIBIDI_TYPE_ON;
      continue;
    }

      /* W4. A single european separator changes to a european number.
         A single common separator between two numbers of the same type
         changes to that type. */
      if (w4
      && RL_LEN (pp) == 1 && FRIBIDI_IS_ES_OR_CS (this_type)
      && FRIBIDI_IS_NUMBER (prev_type_orig)
      && prev_type_orig == next_type
      && (prev_type_orig == FRIBIDI_TYPE_EN
          || this_type == FRIBIDI_TYPE_CS))
    {
      RL_TYPE (pp) = prev_type;
      this_type = RL_TYPE (pp);
    }
      w4 = true;

      /* W5. A sequence of European terminators adjacent to European
         numbers changes to All European numbers. */
      if (this_type == FRIBIDI_TYPE_ET
      && (prev_type_orig == FRIBIDI_TYPE_EN
          || next_type == FRIBIDI_TYPE_EN))
    {
      RL_TYPE (pp) = FRIBIDI_TYPE_EN;
      w4 = false;
      this_type = RL_TYPE (pp);
    }

      /* W6. Otherwise change separators and terminators to other neutral. */
      if (FRIBIDI_IS_NUMBER_SEPARATOR_OR_TERMINATOR (this_type))
    RL_TYPE (pp) = FRIBIDI_TYPE_ON;

      /* W7. Change european numbers to L. */
      if (this_type == FRIBIDI_TYPE_EN && last_strong == FRIBIDI_TYPE_LTR)
    {
      RL_TYPE (pp) = FRIBIDI_TYPE_LTR;
      prev_type_orig = (RL_LEVEL (pp) == RL_LEVEL (pp->next) ?
                FRIBIDI_TYPE_EN : FRIBIDI_TYPE_ON);
    }
      else
    prev_type_orig = PREV_TYPE_OR_SOR (pp->next);
    }
  }

  compact_neutrals (main_run_list);

# if DEBUG
  if UNLIKELY
    (fribidi_debug_status ())
    {
      print_resolved_levels (main_run_list);
      print_resolved_types (main_run_list);
    }
# endif    /* DEBUG */

  /* 5. Resolving Neutral Types */
  DBG ("resolving neutral types");
  {
    /* N1. and N2.
       For each neutral, resolve it. */
    for_run_list (pp, main_run_list)
    {
      FriBidiCharType prev_type, this_type, next_type;

      /* "European and Arabic numbers are treated as though they were R"
         FRIBIDI_CHANGE_NUMBER_TO_RTL does this. */
      this_type = FRIBIDI_CHANGE_NUMBER_TO_RTL (RL_TYPE (pp));
      prev_type = FRIBIDI_CHANGE_NUMBER_TO_RTL (PREV_TYPE_OR_SOR (pp));
      next_type = FRIBIDI_CHANGE_NUMBER_TO_RTL (NEXT_TYPE_OR_EOR (pp));

      if (FRIBIDI_IS_NEUTRAL (this_type))
    RL_TYPE (pp) = (prev_type == next_type) ?
      /* N1. */ prev_type :
      /* N2. */ FRIBIDI_EMBEDDING_DIRECTION (pp);
    }
  }

  compact_list (main_run_list);

# if DEBUG
  if UNLIKELY
    (fribidi_debug_status ())
    {
      print_resolved_levels (main_run_list);
      print_resolved_types (main_run_list);
    }
# endif    /* DEBUG */

  /* 6. Resolving implicit levels */
  DBG ("resolving implicit levels");
  {
    max_level = base_level;

    for_run_list (pp, main_run_list)
    {
      FriBidiCharType this_type;
      int level;

      this_type = RL_TYPE (pp);
      level = RL_LEVEL (pp);

      /* I1. Even */
      /* I2. Odd */
      if (FRIBIDI_IS_NUMBER (this_type))
    RL_LEVEL (pp) = (level + 2) & ~1;
      else
    RL_LEVEL (pp) =
      level +
      (FRIBIDI_LEVEL_IS_RTL (level) ^ FRIBIDI_DIR_TO_LEVEL (this_type));

      if (RL_LEVEL (pp) > max_level)
    max_level = RL_LEVEL (pp);
    }
  }

  compact_list (main_run_list);

# if DEBUG
  if UNLIKELY
    (fribidi_debug_status ())
    {
      print_bidi_string (bidi_types, len);
      print_resolved_levels (main_run_list);
      print_resolved_types (main_run_list);
    }
# endif    /* DEBUG */

/* Reinsert the explicit codes & BN's that are already removed, from the
   explicits_list to main_run_list. */
  DBG ("reinserting explicit codes");
  if UNLIKELY
    (explicits_list->next != explicits_list)
    {
      register FriBidiRun *p;
      register fribidi_boolean stat =
    shadow_run_list (main_run_list, explicits_list, true);
      explicits_list = NULL;
      if UNLIKELY
    (!stat) goto out;

      /* Set level of inserted explicit chars to that of their previous
       * char, such that they do not affect reordering. */
      p = main_run_list->next;
      if (p != main_run_list && p->level == FRIBIDI_SENTINEL)
    p->level = base_level;
      for_run_list (p, main_run_list) if (p->level == FRIBIDI_SENTINEL)
    p->level = p->prev->level;
    }

# if DEBUG
  if UNLIKELY
    (fribidi_debug_status ())
    {
      print_types_re (main_run_list);
      print_resolved_levels (main_run_list);
      print_resolved_types (main_run_list);
    }
# endif    /* DEBUG */

  DBG ("reset the embedding levels, 1, 2, 3.");
  {
    register int j, state, pos;
    register FriBidiCharType char_type;
    register FriBidiRun *p, *q, *list;

    /* L1. Reset the embedding levels of some chars:
       1. segment separators,
       2. paragraph separators,
       3. any sequence of whitespace characters preceding a segment
       separator or paragraph separator, and
       ... (to be continued in fribidi_reorder_line()). */
    list = new_run_list ();
    if UNLIKELY
      (!list) goto out;
    q = list;
    state = 1;
    pos = len - 1;
    for (j = len - 1; j >= -1; j--)
      {
    /* close up the open link at the end */
    if (j >= 0)
      char_type = bidi_types[j];
    else
      char_type = FRIBIDI_TYPE_ON;
    if (!state && FRIBIDI_IS_SEPARATOR (char_type))
      {
        state = 1;
        pos = j;
      }
    else if (state && !FRIBIDI_IS_EXPLICIT_OR_SEPARATOR_OR_BN_OR_WS
         (char_type))
      {
        state = 0;
        p = new_run ();
        if UNLIKELY
          (!p)
          {
        free_run_list (list);
        goto out;
          }
        p->pos = j + 1;
        p->len = pos - j;
        p->type = base_dir;
        p->level = base_level;
        move_node_before (p, q);
        q = p;
      }
      }
    if UNLIKELY
      (!shadow_run_list (main_run_list, list, false)) goto out;
  }

# if DEBUG
  if UNLIKELY
    (fribidi_debug_status ())
    {
      print_types_re (main_run_list);
      print_resolved_levels (main_run_list);
      print_resolved_types (main_run_list);
    }
# endif    /* DEBUG */

  {
    FriBidiStrIndex pos = 0;
    for_run_list (pp, main_run_list)
    {
      register FriBidiStrIndex l;
      register FriBidiLevel level = pp->level;
      for (l = pp->len; l; l--)
    embedding_levels[pos++] = level;
    }
  }

  status = true;

out:
  DBG ("leaving fribidi_get_par_embedding_levels");

  if (main_run_list)
    free_run_list (main_run_list);
  if UNLIKELY
    (explicits_list) free_run_list (explicits_list);

  return status ? max_level + 1 : 0;
}


static void
bidi_string_reverse (
  FriBidiChar *str,
  const FriBidiStrIndex len
)
{
  FriBidiStrIndex i;

  fribidi_assert (str);

  for (i = 0; i < len / 2; i++)
    {
      FriBidiChar tmp = str[i];
      str[i] = str[len - 1 - i];
      str[len - 1 - i] = tmp;
    }
}

static void
index_array_reverse (
  FriBidiStrIndex *arr,
  const FriBidiStrIndex len
)
{
  FriBidiStrIndex i;

  fribidi_assert (arr);

  for (i = 0; i < len / 2; i++)
    {
      FriBidiStrIndex tmp = arr[i];
      arr[i] = arr[len - 1 - i];
      arr[len - 1 - i] = tmp;
    }
}


FRIBIDI_ENTRY FriBidiLevel
fribidi_reorder_line (
  /* input */
  FriBidiFlags flags, /* reorder flags */
  const FriBidiCharType *bidi_types,
  const FriBidiStrIndex len,
  const FriBidiStrIndex off,
  const FriBidiParType base_dir,
  /* input and output */
  FriBidiLevel *embedding_levels,
  FriBidiChar *visual_str,
  /* output */
  FriBidiStrIndex *map
)
{
  fribidi_boolean status = false;
  FriBidiLevel max_level = 0;

  if UNLIKELY
    (len == 0)
    {
      status = true;
      goto out;
    }

  DBG ("in fribidi_reorder_line");

  fribidi_assert (bidi_types);
  fribidi_assert (embedding_levels);

  DBG ("reset the embedding levels, 4. whitespace at the end of line");
  {
    register FriBidiStrIndex i;

    /* L1. Reset the embedding levels of some chars:
       4. any sequence of white space characters at the end of the line. */
    for (i = off + len - 1; i >= off &&
     FRIBIDI_IS_EXPLICIT_OR_BN_OR_WS (bidi_types[i]); i--)
      embedding_levels[i] = FRIBIDI_DIR_TO_LEVEL (base_dir);
  }

  /* 7. Reordering resolved levels */
  {
    register FriBidiLevel level;
    register FriBidiStrIndex i;

    /* Reorder both the outstring and the order array */
    {
      if (FRIBIDI_TEST_BITS (flags, FRIBIDI_FLAG_REORDER_NSM))
    {
      /* L3. Reorder NSMs. */
      for (i = off + len - 1; i >= off; i--)
        if (FRIBIDI_LEVEL_IS_RTL (embedding_levels[i])
        && bidi_types[i] == FRIBIDI_TYPE_NSM)
          {
        register FriBidiStrIndex seq_end = i;
        level = embedding_levels[i];

        for (i--; i >= off &&
             FRIBIDI_IS_EXPLICIT_OR_BN_OR_NSM (bidi_types[i])
             && embedding_levels[i] == level; i--)
          ;

        if (i < off || embedding_levels[i] != level)
          {
            i++;
            DBG ("warning: NSM(s) at the beggining of level run");
          }

        if (visual_str)
          {
            bidi_string_reverse (visual_str + i, seq_end - i + 1);
          }
        if (map)
          {
            index_array_reverse (map + i, seq_end - i + 1);
          }
          }
    }

      /* Find max_level of the line.  We don't reuse the paragraph
       * max_level, both for a cleaner API, and that the line max_level
       * may be far less than paragraph max_level. */
      for (i = off + len - 1; i >= off; i--)
    if (embedding_levels[i] > max_level)
      max_level = embedding_levels[i];

      /* L2. Reorder. */
      for (level = max_level; level > 0; level--)
    for (i = off + len - 1; i >= off; i--)
      if (embedding_levels[i] >= level)
        {
          /* Find all stretches that are >= level_idx */
          register FriBidiStrIndex seq_end = i;
          for (i--; i >= off && embedding_levels[i] >= level; i--)
        ;

          if (visual_str)
        bidi_string_reverse (visual_str + i + 1, seq_end - i);
          if (map)
        index_array_reverse (map + i + 1, seq_end - i);
        }
    }

  }

  status = true;

out:

  return status ? max_level + 1 : 0;
}

/* Editor directions:
 * vim:textwidth=78:tabstop=8:shiftwidth=2:autoindent:cindent
 */
 

fribidi-bidi.h  、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

/* FriBidi
 * fribidi-bidi.h - bidirectional algorithm
 *
 * $Id: fribidi-bidi.h,v 1.15 2005/11/03 01:39:01 behdad Exp $
 * $Author: behdad $
 * $Date: 2005/11/03 01:39:01 $
 * $Revision: 1.15 $
 * $Source: /cvs/fribidi/fribidi2/lib/fribidi-bidi.h,v $
 *
 * Authors:
 *   Behdad Esfahbod, 2001, 2002, 2004
 *   Dov Grobgeld, 1999, 2000
 *
 * Copyright (C) 2004 Sharif FarsiWeb, Inc
 * Copyright (C) 2001,2002 Behdad Esfahbod
 * Copyright (C) 1999,2000 Dov Grobgeld
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library 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
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library, in a file named COPYING; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA
 * 
 * For licensing issues, contact <license@farsiweb.info>.
 */
#ifndef _FRIBIDI_BIDI_H
#define _FRIBIDI_BIDI_H

#include "fribidi-common.h"

#include "fribidi-types.h"
#include "fribidi-flags.h"
#include "fribidi-bidi-types.h"

#include "fribidi-begindecls.h"

#define fribidi_get_par_embedding_levels FRIBIDI_NAMESPACE(get_par_embedding_levels)
/* fribidi_get_par_direction - get base paragraph direction
 *
 * This function finds the base direction of a single paragraph,
 * as defined by rule P2 of the Unicode Bidirectional Algorithm available at
 * http://www.unicode.org/reports/tr9/#P2.
 *
 * You typically do not need this function as
 * fribidi_get_par_embedding_levels() knows how to compute base direction
 * itself, but you may need this to implement a more sophisticated paragraph
 * direction handling.  Note that you can pass more than a paragraph to this
 * function and the direction of the first non-neutral paragraph is returned,
 * which is a very good heuristic to set direction of the neutral paragraphs
 * at the beginning of text.  For other neutral paragraphs, you better use the
 * direction of the previous paragraph.
 *
 * Returns: Base pargraph direction.  No weak paragraph direction is returned,
 * only LTR, RTL, or ON.
 */
FRIBIDI_ENTRY FriBidiParType fribidi_get_par_direction (
  const FriBidiCharType *bidi_types,    /* input list of bidi types as returned by
                       fribidi_get_bidi_types() */
  const FriBidiStrIndex len    /* input string length */
);

#define fribidi_get_par_embedding_levels FRIBIDI_NAMESPACE(get_par_embedding_levels)
/* fribidi_get_par_embedding_levels - get bidi embedding levels of a paragraph
 *
 * This function finds the bidi embedding levels of a single paragraph,
 * as defined by the Unicode Bidirectional Algorithm available at
 * http://www.unicode.org/reports/tr9/.  This function implements rules P2 to
 * I1 inclusive, and parts 1 to 3 of L1, except for rule X9 which is
 *  implemented in fribidi_remove_bidi_marks().  Part 4 of L1 is implemented
 *  in fribidi_reorder_line().
 *
 * There are a few macros defined in fribidi-bidi-types.h to work with this
 * embedding levels.
 *
 * Returns: Maximum level found plus one, or zero if any error occured
 * (memory allocation failure most probably).
 */
FRIBIDI_ENTRY FriBidiLevel
fribidi_get_par_embedding_levels (
  const FriBidiCharType *bidi_types,    /* input list of bidi types as returned by
                       fribidi_get_bidi_types() */
  const FriBidiStrIndex len,    /* input string length of the paragraph */
  FriBidiParType *pbase_dir,    /* requested and resolved paragraph
                 * base direction */
  FriBidiLevel *embedding_levels    /* output list of embedding levels */
) FRIBIDI_GNUC_WARN_UNUSED;

#define fribidi_reorder_line FRIBIDI_NAMESPACE(reorder_line)
/* fribidi_reorder_line - reorder a line of logical string to visual
 *
 * This function reorders the characters in a line of text from logical to
 * final visual order.  This function implements part 4 of rule L1, and rules
 * L2 and L3 of the Unicode Bidirectional Algorithm available at
 * http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels.
 *
 * As a side effect it also sets position maps if not NULL.
 *
 * You should provide the resolved paragraph direction and embedding levels as
 * set by fribidi_get_par_embedding_levels().  Also note that the embedding
 * levels may change a bit.  To be exact, the embedding level of any sequence
 * of white space at the end of line is reset to the paragraph embedding level
 * (That is part 4 of rule L1).
 *
 * Note that the bidi types and embedding levels are not reordered.  You can
 * reorder these (or any other) arrays using the map later.  The user is
 * responsible to initialize map to something sensible, like an identity
 * mapping, or pass NULL if no map is needed.
 *
 * There is an optional part to this function, which is whether non-spacing
 * marks for right-to-left parts of the text should be reordered to come after
 * their base characters in the visual string or not.  Most rendering engines
 * expect this behavior, but console-based systems for example do not like it.
 * This is controlled by the FRIBIDI_FLAG_REORDER_NSM flag.  The flag is on
 * in FRIBIDI_FLAGS_DEFAULT.
 *
 * Returns: Maximum level found in this line plus one, or zero if any error
 * occured (memory allocation failure most probably).
 */
     FRIBIDI_ENTRY FriBidiLevel fribidi_reorder_line (
  FriBidiFlags flags, /* reorder flags */
  const FriBidiCharType *bidi_types,    /* input list of bidi types as returned by
                       fribidi_get_bidi_types() */
  const FriBidiStrIndex len,    /* input length of the line */
  const FriBidiStrIndex off,    /* input offset of the beginning of the line
                   in the paragraph */
  const FriBidiParType base_dir,    /* resolved paragraph base direction */
  FriBidiLevel *embedding_levels,    /* input list of embedding levels,
                       as returned by
                       fribidi_get_par_embedding_levels */
  FriBidiChar *visual_str,    /* visual string to reorder */
  FriBidiStrIndex *map        /* a map of string indices which is reordered
                 * to reflect where each glyph ends up. */
) FRIBIDI_GNUC_WARN_UNUSED;

#include "fribidi-enddecls.h"

#endif /* !_FRIBIDI_BIDI_H */
/* Editor directions:
 * vim:textwidth=78:tabstop=8:shiftwidth=2:autoindent:cindent
 */
 

fribidi-bidi-types.c  、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

/* FriBidi
 * fribidi-bidi-types.c - character bidi types
 *
 * $Id: fribidi-bidi-types.c,v 1.9 2006/01/31 03:23:13 behdad Exp $
 * $Author: behdad $
 * $Date: 2006/01/31 03:23:13 $
 * $Revision: 1.9 $
 * $Source: /cvs/fribidi/fribidi2/lib/fribidi-bidi-types.c,v $
 *
 * Authors:
 *   Behdad Esfahbod, 2001, 2002, 2004
 *
 * Copyright (C) 2004 Sharif FarsiWeb, Inc.
 * Copyright (C) 2001,2002 Behdad Esfahbod
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library 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
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library, in a file named COPYING; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA
 *
 * For licensing issues, contact <license@farsiweb.info>.
 */

#include "common.h"

#include "fribidi-bidi-types.h"

#include "bidi-types.h"

enum FriBidiCharTypeLinearEnum
{
# define _FRIBIDI_ADD_TYPE(TYPE,SYMBOL) TYPE,
# include "fribidi-bidi-types-list.h"
# undef _FRIBIDI_ADD_TYPE
  _FRIBIDI_NUM_TYPES
};

#include "bidi-type.tab.i"

/* Map FriBidiCharTypeLinearEnum to FriBidiCharType. */
static const FriBidiCharType linear_enum_to_char_type[] = {
# define _FRIBIDI_ADD_TYPE(TYPE,SYMBOL) FRIBIDI_TYPE_##TYPE,
# include "fribidi-bidi-types-list.h"
# undef _FRIBIDI_ADD_TYPE
};

FRIBIDI_ENTRY FriBidiCharType
fribidi_get_bidi_type (
  /* input */
  FriBidiChar ch
)
{
  return linear_enum_to_char_type[FRIBIDI_GET_BIDI_TYPE (ch)];
}

FRIBIDI_ENTRY void
fribidi_get_bidi_types (
  /* input */
  const FriBidiChar *str,
  const FriBidiStrIndex len,
  /* output */
  FriBidiCharType *btypes
)
{
  register FriBidiStrIndex i = len;
  for (; i; i--)
    {
      *btypes++ = linear_enum_to_char_type[FRIBIDI_GET_BIDI_TYPE (*str)];
      str++;
    }
}

FRIBIDI_ENTRY const char *
fribidi_get_bidi_type_name (
  /* input */
  FriBidiCharType t
)
{
  switch (t)
    {
#   define _FRIBIDI_ADD_TYPE(TYPE,SYMBOL) case FRIBIDI_TYPE_##TYPE: return STRINGIZE(TYPE);
#   define _FRIBIDI_ALL_TYPES
#   include "fribidi-bidi-types-list.h"
#   undef _FRIBIDI_ALL_TYPES
#   undef _FRIBIDI_ADD_TYPE
    default:
      return "?";
    }
}

#if DEBUG+0

char
fribidi_char_from_bidi_type (
  /* input */
  FriBidiCharType t
)
{
  switch (t)
    {
#   define _FRIBIDI_ADD_TYPE(TYPE,SYMBOL) case FRIBIDI_TYPE_##TYPE: return SYMBOL;
#   define _FRIBIDI_ALL_TYPES
#   include "fribidi-bidi-types-list.h"
#   undef _FRIBIDI_ALL_TYPES
#   undef _FRIBIDI_ADD_TYPE
    default:
      return '?';
    }
}

#endif /* DEBUG */

/* Editor directions:
 * vim:textwidth=78:tabstop=8:shiftwidth=2:autoindent:cindent
 */
 

fribidi-bidi-types.h   、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

/* FriBidi
 * fribidi-bidi-types.h - character bidi types
 *
 * $Id: fribidi-bidi-types.h,v 1.15 2008-11-24 17:48:31 behdad Exp $
 * $Author: behdad $
 * $Date: 2008-11-24 17:48:31 $
 * $Revision: 1.15 $
 * $Source: /cvs/fribidi/fribidi2/lib/fribidi-bidi-types.h,v $
 *
 * Author:
 *   Behdad Esfahbod, 2001, 2002, 2004
 *
 * Copyright (C) 2004 Sharif FarsiWeb, Inc.
 * Copyright (C) 2001,2002 Behdad Esfahbod
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library 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
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library, in a file named COPYING; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA
 *
 * For licensing issues, contact <license@farsiweb.info>.
 */
#ifndef _FRIBIDI_BIDI_TYPES_H
#define _FRIBIDI_BIDI_TYPES_H

#include "fribidi-common.h"

#include "fribidi-types.h"

#include "fribidi-begindecls.h"

typedef signed char FriBidiLevel;

/* 
 * Define bit masks that bidi types are based on, each mask has
 * only one bit set.
 */

/* RTL mask better be the least significant bit. */
#define FRIBIDI_MASK_RTL    0x00000001L    /* Is right to left */
#define FRIBIDI_MASK_ARABIC    0x00000002L    /* Is arabic */

/* Each char can be only one of the three following. */
#define FRIBIDI_MASK_STRONG    0x00000010L    /* Is strong */
#define FRIBIDI_MASK_WEAK    0x00000020L    /* Is weak */
#define FRIBIDI_MASK_NEUTRAL    0x00000040L    /* Is neutral */
#define FRIBIDI_MASK_SENTINEL    0x00000080L    /* Is sentinel */
/* Sentinels are not valid chars, just identify the start/end of strings. */

/* Each char can be only one of the five following. */
#define FRIBIDI_MASK_LETTER    0x00000100L    /* Is letter: L, R, AL */
#define FRIBIDI_MASK_NUMBER    0x00000200L    /* Is number: EN, AN */
#define FRIBIDI_MASK_NUMSEPTER    0x00000400L    /* Is separator or terminator: ES, ET, CS */
#define FRIBIDI_MASK_SPACE    0x00000800L    /* Is space: BN, BS, SS, WS */
#define FRIBIDI_MASK_EXPLICIT    0x00001000L    /* Is expilict mark: LRE, RLE, LRO, RLO, PDF */

/* Can be set only if FRIBIDI_MASK_SPACE is also set. */
#define FRIBIDI_MASK_SEPARATOR    0x00002000L    /* Is text separator: BS, SS */
/* Can be set only if FRIBIDI_MASK_EXPLICIT is also set. */
#define FRIBIDI_MASK_OVERRIDE    0x00004000L    /* Is explicit override: LRO, RLO */

/* The following exist to make types pairwise different, some of them can
 * be removed but are here because of efficiency (make queries faster). */

#define FRIBIDI_MASK_ES        0x00010000L
#define FRIBIDI_MASK_ET        0x00020000L
#define FRIBIDI_MASK_CS        0x00040000L

#define FRIBIDI_MASK_NSM    0x00080000L
#define FRIBIDI_MASK_BN        0x00100000L

#define FRIBIDI_MASK_BS        0x00200000L
#define FRIBIDI_MASK_SS        0x00400000L
#define FRIBIDI_MASK_WS        0x00800000L

/* We reserve a single bit for user's private use: we will never use it. */
#define FRIBIDI_MASK_PRIVATE    0x01000000L


/*
 * Define values for FriBidiCharType
 */

/* Strong types */

/* Left-To-Right letter */
#define FRIBIDI_TYPE_LTR_VAL    ( FRIBIDI_MASK_STRONG | FRIBIDI_MASK_LETTER )
/* Right-To-Left letter */
#define FRIBIDI_TYPE_RTL_VAL    ( FRIBIDI_MASK_STRONG | FRIBIDI_MASK_LETTER \
                | FRIBIDI_MASK_RTL)
/* Arabic Letter */
#define FRIBIDI_TYPE_AL_VAL    ( FRIBIDI_MASK_STRONG | FRIBIDI_MASK_LETTER \
                | FRIBIDI_MASK_RTL | FRIBIDI_MASK_ARABIC )
/* Left-to-Right Embedding */
#define FRIBIDI_TYPE_LRE_VAL    ( FRIBIDI_MASK_STRONG | FRIBIDI_MASK_EXPLICIT)
/* Right-to-Left Embedding */
#define FRIBIDI_TYPE_RLE_VAL    ( FRIBIDI_MASK_STRONG | FRIBIDI_MASK_EXPLICIT \
                | FRIBIDI_MASK_RTL )
/* Left-to-Right Override */
#define FRIBIDI_TYPE_LRO_VAL    ( FRIBIDI_MASK_STRONG | FRIBIDI_MASK_EXPLICIT \
                | FRIBIDI_MASK_OVERRIDE )
/* Right-to-Left Override */
#define FRIBIDI_TYPE_RLO_VAL    ( FRIBIDI_MASK_STRONG | FRIBIDI_MASK_EXPLICIT \
                | FRIBIDI_MASK_RTL | FRIBIDI_MASK_OVERRIDE )

/* Weak types */

/* Pop Directional Flag*/
#define FRIBIDI_TYPE_PDF_VAL    ( FRIBIDI_MASK_WEAK | FRIBIDI_MASK_EXPLICIT )
/* European Numeral */
#define FRIBIDI_TYPE_EN_VAL    ( FRIBIDI_MASK_WEAK | FRIBIDI_MASK_NUMBER )
/* Arabic Numeral */
#define FRIBIDI_TYPE_AN_VAL    ( FRIBIDI_MASK_WEAK | FRIBIDI_MASK_NUMBER \
                | FRIBIDI_MASK_ARABIC )
/* European number Separator */
#define FRIBIDI_TYPE_ES_VAL    ( FRIBIDI_MASK_WEAK | FRIBIDI_MASK_NUMSEPTER \
                | FRIBIDI_MASK_ES )
/* European number Terminator */
#define FRIBIDI_TYPE_ET_VAL    ( FRIBIDI_MASK_WEAK | FRIBIDI_MASK_NUMSEPTER \
                | FRIBIDI_MASK_ET )
/* Common Separator */
#define FRIBIDI_TYPE_CS_VAL    ( FRIBIDI_MASK_WEAK | FRIBIDI_MASK_NUMSEPTER \
                | FRIBIDI_MASK_CS )
/* Non Spacing Mark */
#define FRIBIDI_TYPE_NSM_VAL    ( FRIBIDI_MASK_WEAK | FRIBIDI_MASK_NSM )
/* Boundary Neutral */
#define FRIBIDI_TYPE_BN_VAL    ( FRIBIDI_MASK_WEAK | FRIBIDI_MASK_SPACE \
                | FRIBIDI_MASK_BN )

/* Neutral types */

/* Block Separator */
#define FRIBIDI_TYPE_BS_VAL    ( FRIBIDI_MASK_NEUTRAL | FRIBIDI_MASK_SPACE \
                | FRIBIDI_MASK_SEPARATOR | FRIBIDI_MASK_BS )
/* Segment Separator */
#define FRIBIDI_TYPE_SS_VAL    ( FRIBIDI_MASK_NEUTRAL | FRIBIDI_MASK_SPACE \
                | FRIBIDI_MASK_SEPARATOR | FRIBIDI_MASK_SS )
/* WhiteSpace */
#define FRIBIDI_TYPE_WS_VAL    ( FRIBIDI_MASK_NEUTRAL | FRIBIDI_MASK_SPACE \
                | FRIBIDI_MASK_WS )
/* Other Neutral */
#define FRIBIDI_TYPE_ON_VAL    ( FRIBIDI_MASK_NEUTRAL )


/* The following are used in specifying paragraph direction only. */

/* Weak Left-To-Right */
#define FRIBIDI_TYPE_WLTR_VAL    ( FRIBIDI_MASK_WEAK )
/* Weak Right-To-Left */
#define FRIBIDI_TYPE_WRTL_VAL    ( FRIBIDI_MASK_WEAK | FRIBIDI_MASK_RTL )

/* start or end of text (run list) SENTINEL.  Only used internally */
#define FRIBIDI_TYPE_SENTINEL    ( FRIBIDI_MASK_SENTINEL )

/* Private types for applications.  More private types can be obtained by
 * summing up from this one. */
#define FRIBIDI_TYPE_PRIVATE    ( FRIBIDI_MASK_PRIVATE )


/* Define Enums only if sizeof(int) == 4 (UTF-32), and not compiling C++.
 * The problem with C++ is that then casts between int32 and enum will fail!
 */
#if defined(__FRIBIDI_DOC)/* || (FRIBIDI_SIZEOF_INT+0 == 4 && !defined(__cplusplus))*/

typedef enum
{
# define _FRIBIDI_ADD_TYPE(TYPE,SYMBOL) \
    FRIBIDI_TYPE_##TYPE = FRIBIDI_TYPE_##TYPE##_VAL,
# include "fribidi-bidi-types-list.h"
# undef _FRIBIDI_ADD_TYPE
  _FRIBIDI_TYPE_SENTINEL = FRIBIDI_TYPE_SENTINEL    /* Don't use this */
} FriBidiCharType;

typedef enum
{
# define _FRIBIDI_PAR_TYPES
# define _FRIBIDI_ADD_TYPE(TYPE,SYMBOL) \
    FRIBIDI_PAR_##TYPE = FRIBIDI_TYPE_##TYPE##_VAL,
# include "fribidi-bidi-types-list.h"
# undef _FRIBIDI_ADD_TYPE
# undef _FRIBIDI_PAR_TYPES
  _FRIBIDI_PAR_SENTINEL = FRIBIDI_TYPE_SENTINEL    /* Don't use this */
} FriBidiParType;

#else

typedef fribidi_uint32 FriBidiCharType;
# define FRIBIDI_TYPE_LTR    FRIBIDI_TYPE_LTR_VAL
# define FRIBIDI_TYPE_RTL    FRIBIDI_TYPE_RTL_VAL
# define FRIBIDI_TYPE_AL    FRIBIDI_TYPE_AL_VAL
# define FRIBIDI_TYPE_EN    FRIBIDI_TYPE_EN_VAL
# define FRIBIDI_TYPE_AN    FRIBIDI_TYPE_AN_VAL
# define FRIBIDI_TYPE_ES    FRIBIDI_TYPE_ES_VAL
# define FRIBIDI_TYPE_ET    FRIBIDI_TYPE_ET_VAL
# define FRIBIDI_TYPE_CS    FRIBIDI_TYPE_CS_VAL
# define FRIBIDI_TYPE_NSM    FRIBIDI_TYPE_NSM_VAL
# define FRIBIDI_TYPE_BN    FRIBIDI_TYPE_BN_VAL
# define FRIBIDI_TYPE_BS    FRIBIDI_TYPE_BS_VAL
# define FRIBIDI_TYPE_SS    FRIBIDI_TYPE_SS_VAL
# define FRIBIDI_TYPE_WS    FRIBIDI_TYPE_WS_VAL
# define FRIBIDI_TYPE_ON    FRIBIDI_TYPE_ON_VAL
# define FRIBIDI_TYPE_LRE    FRIBIDI_TYPE_LRE_VAL
# define FRIBIDI_TYPE_RLE    FRIBIDI_TYPE_RLE_VAL
# define FRIBIDI_TYPE_LRO    FRIBIDI_TYPE_LRO_VAL
# define FRIBIDI_TYPE_RLO    FRIBIDI_TYPE_RLO_VAL
# define FRIBIDI_TYPE_PDF    FRIBIDI_TYPE_PDF_VAL

typedef fribidi_uint32 FriBidiParType;
# define FRIBIDI_PAR_LTR    FRIBIDI_TYPE_LTR_VAL
# define FRIBIDI_PAR_RTL    FRIBIDI_TYPE_RTL_VAL
# define FRIBIDI_PAR_ON        FRIBIDI_TYPE_ON_VAL
# define FRIBIDI_PAR_WLTR    FRIBIDI_TYPE_WLTR_VAL
# define FRIBIDI_PAR_WRTL    FRIBIDI_TYPE_WRTL_VAL

#endif

/* Please don't use these two type names, use FRIBIDI_PAR_* form instead. */
#define FRIBIDI_TYPE_WLTR    FRIBIDI_PAR_WLTR
#define FRIBIDI_TYPE_WRTL    FRIBIDI_PAR_WRTL


/*
 * Defining macros for needed queries, It is fully dependent on the 
 * implementation of FriBidiCharType.
 */


/* Is right-to-left level? */
#define FRIBIDI_LEVEL_IS_RTL(lev) ((lev) & 1)

/* Return the bidi type corresponding to the direction of the level number,
   FRIBIDI_TYPE_LTR for evens and FRIBIDI_TYPE_RTL for odds. */
#define FRIBIDI_LEVEL_TO_DIR(lev)    \
    (FRIBIDI_LEVEL_IS_RTL (lev) ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR)

/* Return the minimum level of the direction, 0 for FRIBIDI_TYPE_LTR and
   1 for FRIBIDI_TYPE_RTL and FRIBIDI_TYPE_AL. */
#define FRIBIDI_DIR_TO_LEVEL(dir)    \
    ((FriBidiLevel) (FRIBIDI_IS_RTL (dir) ? 1 : 0))

/* Is right to left: RTL, AL, RLE, RLO? */
#define FRIBIDI_IS_RTL(p)      ((p) & FRIBIDI_MASK_RTL)
/* Is arabic: AL, AN? */
#define FRIBIDI_IS_ARABIC(p)   ((p) & FRIBIDI_MASK_ARABIC)

/* Is strong? */
#define FRIBIDI_IS_STRONG(p)   ((p) & FRIBIDI_MASK_STRONG)
/* Is weak? */
#define FRIBIDI_IS_WEAK(p)     ((p) & FRIBIDI_MASK_WEAK)
/* Is neutral? */
#define FRIBIDI_IS_NEUTRAL(p)  ((p) & FRIBIDI_MASK_NEUTRAL)
/* Is sentinel? */
#define FRIBIDI_IS_SENTINEL(p) ((p) & FRIBIDI_MASK_SENTINEL)

/* Is letter: L, R, AL? */
#define FRIBIDI_IS_LETTER(p)   ((p) & FRIBIDI_MASK_LETTER)
/* Is number: EN, AN? */
#define FRIBIDI_IS_NUMBER(p)   ((p) & FRIBIDI_MASK_NUMBER)
/* Is number separator or terminator: ES, ET, CS? */
#define FRIBIDI_IS_NUMBER_SEPARATOR_OR_TERMINATOR(p) \
    ((p) & FRIBIDI_MASK_NUMSEPTER)
/* Is space: BN, BS, SS, WS? */
#define FRIBIDI_IS_SPACE(p)    ((p) & FRIBIDI_MASK_SPACE)
/* Is explicit mark: LRE, RLE, LRO, RLO, PDF? */
#define FRIBIDI_IS_EXPLICIT(p) ((p) & FRIBIDI_MASK_EXPLICIT)

/* Is text separator: BS, SS? */
#define FRIBIDI_IS_SEPARATOR(p) ((p) & FRIBIDI_MASK_SEPARATOR)

/* Is explicit override: LRO, RLO? */
#define FRIBIDI_IS_OVERRIDE(p) ((p) & FRIBIDI_MASK_OVERRIDE)

/* Some more: */

/* Is left to right letter: LTR? */
#define FRIBIDI_IS_LTR_LETTER(p) \
    ((p) & (FRIBIDI_MASK_LETTER | FRIBIDI_MASK_RTL) == FRIBIDI_MASK_LETTER)

/* Is right to left letter: RTL, AL? */
#define FRIBIDI_IS_RTL_LETTER(p) \
    ((p) & (FRIBIDI_MASK_LETTER | FRIBIDI_MASK_RTL) \
    == (FRIBIDI_MASK_LETTER | FRIBIDI_MASK_RTL))

/* Is ES or CS: ES, CS? */
#define FRIBIDI_IS_ES_OR_CS(p) \
    ((p) & (FRIBIDI_MASK_ES | FRIBIDI_MASK_CS))

/* Is explicit or BN: LRE, RLE, LRO, RLO, PDF, BN? */
#define FRIBIDI_IS_EXPLICIT_OR_BN(p) \
    ((p) & (FRIBIDI_MASK_EXPLICIT | FRIBIDI_MASK_BN))

/* Is explicit or BN or NSM: LRE, RLE, LRO, RLO, PDF, BN, NSM? */
#define FRIBIDI_IS_EXPLICIT_OR_BN_OR_NSM(p) \
    ((p) & (FRIBIDI_MASK_EXPLICIT | FRIBIDI_MASK_BN | FRIBIDI_MASK_NSM))

/* Is explicit or BN or WS: LRE, RLE, LRO, RLO, PDF, BN, WS? */
#define FRIBIDI_IS_EXPLICIT_OR_BN_OR_WS(p) \
    ((p) & (FRIBIDI_MASK_EXPLICIT | FRIBIDI_MASK_BN | FRIBIDI_MASK_WS))

/* Is explicit or separator or BN or WS: LRE, RLE, LRO, RLO, PDF, BS, SS, BN, WS? */
#define FRIBIDI_IS_EXPLICIT_OR_SEPARATOR_OR_BN_OR_WS(p) \
    ((p) & (FRIBIDI_MASK_EXPLICIT | FRIBIDI_MASK_SEPARATOR \
        | FRIBIDI_MASK_BN | FRIBIDI_MASK_WS))

/* Is private-use type for application? */
#define FRIBIDI_IS_PRIVATE(p) ((p) & FRIBIDI_MASK_PRIVATE)

/* Define some conversions. */

/* Change numbers to RTL: EN,AN -> RTL. */
#define FRIBIDI_CHANGE_NUMBER_TO_RTL(p) \
    (FRIBIDI_IS_NUMBER(p) ? FRIBIDI_TYPE_RTL : (p))

/* Override status of an explicit mark:
 * LRO,LRE->LTR, RLO,RLE->RTL, otherwise->ON. */
#define FRIBIDI_EXPLICIT_TO_OVERRIDE_DIR(p) \
    (FRIBIDI_IS_OVERRIDE(p) ? FRIBIDI_LEVEL_TO_DIR(FRIBIDI_DIR_TO_LEVEL(p)) \
                : FRIBIDI_TYPE_ON)

/* Weaken type for paragraph fallback purposes:
 * LTR->WLTR, RTL->WRTL. */
#define FRIBIDI_WEAK_PARAGRAPH(p) (FRIBIDI_PAR_WLTR | ((p) & FRIBIDI_MASK_RTL))


/* Functions finally */


#define fribidi_get_bidi_type FRIBIDI_NAMESPACE(get_bidi_type)
/* fribidi_get_bidi_type - get character bidi type
 *
 * This function returns the bidi type of a character as defined in Table 3.7
 * Bidirectional Character Types of the Unicode Bidirectional Algorithm
 * available at
 * http://www.unicode.org/reports/tr9/#Bidirectional_Character_Types, using
 * data provided in file UnicodeData.txt of the Unicode Character Database
 * available at http://www.unicode.org/Public/UNIDATA/UnicodeData.txt.
 *
 * There are a few macros defined in fribidi-bidi-types.h for querying a bidi
 * type.
 */
FRIBIDI_ENTRY FriBidiCharType
fribidi_get_bidi_type (
  FriBidiChar ch        /* input character */
) FRIBIDI_GNUC_CONST;

#define fribidi_get_bidi_types FRIBIDI_NAMESPACE(get_bidi_types)
/* fribidi_get_bidi_types - get bidi types for an string of characters
 *
 * This function finds the bidi types of an string of characters.  See
 * fribidi_get_bidi_type() for more information about the bidi types returned
 * by this function.
 */
     FRIBIDI_ENTRY void fribidi_get_bidi_types (
  const FriBidiChar *str,    /* input string */
  const FriBidiStrIndex len,    /* input string length */
  FriBidiCharType *btypes    /* output bidi types */
);

#define fribidi_get_bidi_type_name FRIBIDI_NAMESPACE(get_bidi_type_name)
/* fribidi_get_bidi_type_name - get bidi type name
 *
 * This function returns the bidi type name of a character type.  The
 * returned string is a static string and should not be freed.
 *
 * The type names are the same as ones defined in Table 3.7 Bidirectional
 * Character Types of the Unicode Bidirectional Algorithm available at
 * http://www.unicode.org/reports/tr9/#Bidirectional_Character_Types, with a
 * few modifications: L->LTR, R->RTL, B->BS, S->SS.
 */
     FRIBIDI_ENTRY const char *fribidi_get_bidi_type_name (
  FriBidiCharType t        /* input bidi type */
) FRIBIDI_GNUC_CONST;

#include "fribidi-enddecls.h"

#endif /* !_FRIBIDI_BIDI_TYPES_H */
/* Editor directions:
 * vim:textwidth=78:tabstop=8:shiftwidth=2:autoindent:cindent
 */
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值