[Base-utils][Ubidi][ACR-808] Module implementation added. 70/87570/25
authorTomasz Bochenski <t.bochenski@partner.samsung.com>
Thu, 8 Sep 2016 14:08:10 +0000 (16:08 +0200)
committerTomasz Bochenski <t.bochenski@samsung.com>
Wed, 2 Nov 2016 08:54:10 +0000 (09:54 +0100)
Change-Id: I18bee9118b3dfb59b279d7e98449c52c4624cb12
Signed-off-by: Tomasz Bochenski <t.bochenski@partner.samsung.com>
Signed-off-by: Tomasz Bochenski <t.bochenski@samsung.com>
src/CMakeLists.txt
src/include/utils_i18n.h
src/include/utils_i18n_types.h
src/include/utils_i18n_ubidi.h [new file with mode: 0644]
src/utils_i18n_ubidi.c [new file with mode: 0644]

index 7374727733bec470d5798845b95cb27885085694..f0d33977ece1e1c47a7b73dc5b68edfa66ea34cc 100755 (executable)
@@ -37,6 +37,7 @@ SET(BASEUTILS_SRCS
     utils_i18n_parse_position.cpp
     utils_i18n_ushape.c
     utils_i18n_utmscale.c
+    utils_i18n_ubidi.c
 )
 
 ADD_LIBRARY(${target_name} SHARED ${BASEUTILS_SRCS}
@@ -84,5 +85,6 @@ INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${INC_DIR}/utils_i18n_field_position.h
 INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${INC_DIR}/utils_i18n_parse_position.h DESTINATION ${INCLUDE_INSTALL_DIR}/base)
 INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${INC_DIR}/utils_i18n_ushape.h DESTINATION ${INCLUDE_INSTALL_DIR}/base)
 INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${INC_DIR}/utils_i18n_utmscale.h DESTINATION ${INCLUDE_INSTALL_DIR}/base)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${INC_DIR}/utils_i18n_ubidi.h DESTINATION ${INCLUDE_INSTALL_DIR}/base)
 INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${INC_DIR}/utils_i18n.h DESTINATION ${INCLUDE_INSTALL_DIR}/base)
 INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${pc_name}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
index eb6d3802ea00bcaaf0be734de2397f9f2e2ef01d..037642325bd24104f47b2bebca79844e6208f06c 100644 (file)
@@ -42,6 +42,7 @@
 #include <utils_i18n_parse_position.h>
 #include <utils_i18n_ushape.h>
 #include <utils_i18n_utmscale.h>
+#include <utils_i18n_ubidi.h>
 
 /**
  * @file utils_i18n.h
@@ -56,7 +57,29 @@ extern "C" {
 /**
  * @ingroup CAPI_BASE_UTILS_MODULE
  * @defgroup CAPI_BASE_UTILS_I18N_MODULE i18n
- * @brief The i18n module contains uchar, ucollator, unormalization, usearch, ustring, ucalendar, udate, udatepg, ulocale, unumber, alpha_idx, formattable, measure unit, measure, format, measure format, field position, parse position, ushape and utmscale.
+ * @brief The i18n module contains:
+ *       - uchar
+ *       - ucollator
+ *       - unormalization
+ *       - usearch
+ *       - ustring
+ *       - ucalendar
+ *       - udate
+ *       - udatepg
+ *       - ulocale
+ *       - unumber
+ *       - alpha_idx
+ *       - formattable
+ *       - measure unit
+ *       - measure
+ *       - format
+ *       - measure format
+ *       - field position
+ *       - parse position
+ *       - ushape
+ *       - utmscale
+ *       - ubidi
+ *
  *        This module provides flexible generation of number or date format patterns and helps you format and parse dates/number for any locale.
  * The i18n module provides various features based on data from ICU. The following table shows the version of ICU used in each Tizen platform.
  * <table>
@@ -178,6 +201,10 @@ extern "C" {
  *    <td>@ref CAPI_BASE_UTILS_I18N_UTMSCALE_MODULE</td>
  *    <td>The Universal Time Scale</td>
  * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>Ubidi module provides implementation of the Unicode Bidirectional Algorithm.</td>
+ * </tr>
  * </table>
  *
  * @section CAPI_BASE_UTILS_I18N_MODULE_MAPPING_TABLE Mapping Table
@@ -2924,6 +2951,7 @@ extern "C" {
  *    <td>u_shapeArabic</td>
  * </tr>
  * <tr>
+ * <tr>
  *    <td>@ref CAPI_BASE_UTILS_I18N_UTMSCALE_MODULE</td>
  *    <td>#i18n_utmscale_get_time_scale_value</td>
  *    <td>utmscale_getTimeScaleValue</td>
@@ -2938,6 +2966,211 @@ extern "C" {
  *    <td>#i18n_utmscale_to_int64</td>
  *    <td>utmscale_toInt64</td>
  * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_destroy</td>
+ *    <td>ubidi_close</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_count_paragraphs</td>
+ *    <td>ubidi_countParagraphs</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_count_runs</td>
+ *    <td>ubidi_countRuns</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_get_base_direction</td>
+ *    <td>ubidi_getBaseDirection</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_get_class_cb</td>
+ *    <td>ubidi_getClassCallback</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_get_customized_class</td>
+ *    <td>ubidi_getCustomizedClass</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_get_direction</td>
+ *    <td>ubidi_getDirection</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_get_length</td>
+ *    <td>ubidi_getLength</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_get_level_at</td>
+ *    <td>ubidi_getLevelAt</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_get_levels</td>
+ *    <td>ubidi_getLevels</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_get_logical_index</td>
+ *    <td>ubidi_getLogicalIndex</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_get_logical_map</td>
+ *    <td>ubidi_getLogicalMap</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_get_logical_run</td>
+ *    <td>ubidi_getLogicalRun</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_get_paragraph</td>
+ *    <td>ubidi_getParagraph</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_get_paragraph_by_index</td>
+ *    <td>ubidi_getParagraphByIndex</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_get_para_level</td>
+ *    <td>ubidi_getParaLevel</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_get_processed_length</td>
+ *    <td>ubidi_getProcessedLength</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_get_reordering_mode</td>
+ *    <td>ubidi_getReorderingMode</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_get_reordering_options</td>
+ *    <td>ubidi_getReorderingOptions</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_get_result_length</td>
+ *    <td>ubidi_getResultLength</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_get_text</td>
+ *    <td>ubidi_getText</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_get_visual_index</td>
+ *    <td>ubidi_getVisualIndex</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_get_visual_map</td>
+ *    <td>ubidi_getVisualMap</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_get_visual_run</td>
+ *    <td>ubidi_getVisualRun</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_invert_map</td>
+ *    <td>ubidi_invertMap</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_is_inverse</td>
+ *    <td>ubidi_isInverse</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_is_order_paragraphs_ltr</td>
+ *    <td>ubidi_isOrderParagraphsLTR</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_create</td>
+ *    <td>ubidi_open</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_create_sized</td>
+ *    <td>ubidi_openSized</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_order_paragraphs_ltr</td>
+ *    <td>ubidi_orderParagraphsLTR</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_reorder_logical</td>
+ *    <td>ubidi_reorderLogical</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_reorder_visual</td>
+ *    <td>ubidi_reorderVisual</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_set_class_cb</td>
+ *    <td>ubidi_setClassCallback</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_set_context</td>
+ *    <td>ubidi_setContext</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_set_inverse</td>
+ *    <td>ubidi_setInverse</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_set_line</td>
+ *    <td>ubidi_setLine</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_set_para</td>
+ *    <td>ubidi_setPara</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_set_reordering_mode</td>
+ *    <td>ubidi_setReorderingMode</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_set_reordering_options</td>
+ *    <td>ubidi_setReorderingOptions</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_write_reordered</td>
+ *    <td>ubidi_writeReordered</td>
+ * </tr>
+ * <tr>
+ *    <td>@ref CAPI_BASE_UTILS_I18N_UBIDI_MODULE</td>
+ *    <td>#i18n_ubidi_write_reverse</td>
+ *    <td>ubidi_writeReverse</td>
+ * </tr>
  * </table>
  */
 
index bf016a13239b4800cd5697954381295c28871864..d571a6acf91d336806ee3f807bf08c0b2ff9632a 100644 (file)
@@ -3512,6 +3512,408 @@ typedef enum {
     I18N_UTMSCALE_VALUE_MAX                     /**< The number of time scale values, in other words limit of this enum.*/
 } i18n_utmscale_value_e;
 
+/**
+ * @}
+ */
+
+
+/**
+ * @addtogroup CAPI_BASE_UTILS_I18N_UBIDI_MODULE
+ * @{
+ */
+
+/**
+ * @brief Value returned by i18n_ubidi_class_cb() callbacks when there is no need to override the standard ubidi class for a given code point.
+ * @since_tizen 3.0
+ */
+#define I18N_UBIDI_CLASS_DEFAULT            I18N_UCHAR_U_CHAR_DIRECTION_COUNT
+
+/**
+ * @brief Paragraph level setting: Constant indicating that the base direction depends on the first
+ *        strong directional character in the text according to the Unicode Bidirectional Algorithm.
+ *        If no strong directional character is present, then set the paragraph level to 0
+ *        (left-to-right).
+ * @details If this value is used in conjunction with reordering modes
+ *          #I18N_UBIDI_REORDER_INVERSE_LIKE_DIRECT or #I18N_UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL,
+ *          the text to reorder is assumed to be visual LTR, and the text after reordering is
+ *          required to be the corresponding logical string with appropriate contextual direction.
+ *          The direction of the result string will be RTL if either the rightmost or leftmost
+ *          strong character of the source text is RTL or Arabic Letter, the direction will be LTR
+ *          otherwise.
+ *
+ *          If reordering option #I18N_UBIDI_OPTION_INSERT_MARKS is set, an RLM may be
+ *          added at the beginning of the result string to ensure round trip (that the result
+ *          string, when reordered back to visual, will produce the original source text).
+ * @since_tizen 3.0
+ * @see I18N_UBIDI_REORDER_INVERSE_LIKE_DIRECT
+ * @see I18N_UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL
+ */
+#define I18N_UBIDI_DEFAULT_LTR              0xfe
+
+/**
+ * @brief Paragraph level setting:
+ *
+ *        Constant indicating that the base direction depends on the first
+ *        strong directional character in the text according to the Unicode Bidirectional Algorithm.
+ *        If no strong directional character is present, then set the paragraph level to 1
+ *        (right-to-left).
+ * @details If this value is used in conjunction with reordering modes
+ *          #I18N_UBIDI_REORDER_INVERSE_LIKE_DIRECT or #I18N_UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL,
+ *          the text to reorder is assumed to be visual LTR, and the text after reordering is
+ *          required to be the corresponding logical string with appropriate contextual direction.
+ *          The direction of the result string will be RTL if either the rightmost or leftmost
+ *          strong character of the source text is RTL or Arabic Letter, or if the text contains no
+ *          strong character; the direction will be LTR otherwise.
+ *
+ *          If reordering option
+ *          #I18N_UBIDI_OPTION_INSERT_MARKS is set, an RLM may be added at the beginning of the
+ *          result string to ensure round trip (that the result string, when reordered back to
+ *          visual, will produce the original source text).
+ * @since_tizen 3.0
+ * @see I18N_UBIDI_REORDER_INVERSE_LIKE_DIRECT
+ * @see I18N_UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL
+ */
+ #define I18N_UBIDI_DEFAULT_RTL             0xff
+
+/**
+ * @brief Option bit for i18n_ubidi_write_reordered(): replace characters with the "mirrored"
+ *        property in RTL runs by their mirror-image mappings.
+ * @since_tizen 3.0
+ * @see i18n_ubidi_write_reordered()
+ */
+#define I18N_UBIDI_DO_MIRRORING             2
+
+/**
+ * @brief Option bit for i18n_ubidi_write_reordered(): surround the run with LRMs if necessary;
+ *        this is part of the approximate "inverse ubidi" algorithm.
+ * @details This option does not imply corresponding adjustment of the index mappings.
+ * @since_tizen 3.0
+ * @see i18n_ubidi_set_inverse()
+ * @see i18n_ubidi_write_reordered()
+ */
+#define I18N_UBIDI_INSERT_LRM_FOR_NUMERIC   4
+
+/**
+ * @brief Option bit for i18n_ubidi_write_reordered(): keep combining characters after their base
+ *        characters in RTL runs.
+ * @since_tizen 3.0
+ * @see i18n_ubidi_write_reordered()
+ */
+#define I18N_UBIDI_KEEP_BASE_COMBINING      1
+
+/**
+ * @brief Bit flag for level input.
+ * @details Overrides directional properties.
+ * @since_tizen 3.0
+ */
+#define I18N_UBIDI_LEVEL_OVERRIDE           0x80
+
+/**
+ * @brief Special value which can be returned by the mapping functions when a logical index has no
+ *        corresponding visual index or vice-versa.
+ * @details This may happen for the logical-to-visual mapping of a ubidi control when option
+ *          #I18N_UBIDI_OPTION_REMOVE_CONTROLS is specified. This can also happen for the
+ *          visual-to-logical mapping of a ubidi mark (LRM or RLM) inserted by option
+ *          #I18N_UBIDI_OPTION_INSERT_MARKS.
+ * @since_tizen 3.0
+ * @see i18n_ubidi_get_visual_index()
+ * @see i18n_ubidi_get_visual_map()
+ * @see i18n_ubidi_get_logical_index()
+ * @see i18n_ubidi_get_logical_map()
+ */
+#define I18N_UBIDI_MAP_NOWHERE              (-1)
+
+/**
+ * @brief Maximum explicit embedding level.
+ * @details The maximum resolved level can be up to #I18N_UBIDI_MAX_EXPLICIT_LEVEL + 1.
+ * @since_tizen 3.0
+ */
+#define I18N_UBIDI_MAX_EXPLICIT_LEVEL       125
+
+/**
+ * @brief Option bit for i18n_ubidi_write_reordered(): write the output in reverse order.
+ * @details This has the same effect as calling i18n_ubidi_write_reordered() first without this
+ *          option, and then calling i18n_ubidi_write_reordered() without mirroring. Doing this
+ *          in the same step is faster and avoids a temporary buffer. An example for using this
+ *          option is output to a character terminal that is designed for RTL scripts and stores
+ *          text in reverse order.
+ * @since_tizen 3.0
+ * @see i18n_ubidi_write_reordered()
+ */
+#define I18N_UBIDI_OUTPUT_REVERSE           16
+
+/**
+ * @brief Option bit for i18n_ubidi_write_reordered(): remove ubidi control characters (this does
+ *        not affect #I18N_UBIDI_INSERT_LRM_FOR_NUMERIC).
+ * @details This option does not imply corresponding adjustment of the index mappings.
+ * @since_tizen 3.0
+ * @see i18n_ubidi_write_reordered()
+ */
+#define I18N_UBIDI_REMOVE_BIDI_CONTROLS     8
+
+/**
+ * @brief An #i18n_ubidi_h handle.
+ * @details Use i18n_ubidi_* functions to operate on Ubidi objects.
+ * @since_tizen 3.0
+ */
+typedef void* i18n_ubidi_h;
+
+/**
+ * @brief Callback type declaration for overriding default ubidi class values with custom ones.
+ * @details Usually, the function pointer will be propagated to an #i18n_ubidi_h handle by calling
+ *          the i18n_ubidi_set_class_cb() function; then the callback will be invoked by the UBA
+ *          implementation any time the class of a character is to be determined.
+ * @since_tizen 3.0
+ *
+ * @param[in]  context   A pointer to the callback private data
+ * @param[in]  c         The code point to get a ubidi class for
+ *
+ * @retval direction     The directional property / ubidi class for the given code point @a c if
+ *                       the default class has been overridden, or #I18N_UBIDI_CLASS_DEFAULT if
+ *                       the standard ubidi class value for code point @a c is to be used.
+ *
+ * @see i18n_ubidi_set_class_cb()
+ * @see i18n_ubidi_get_class_cb()
+ */
+typedef i18n_uchar_direction_e (*i18n_ubidi_class_cb)(const void *context, i18n_uchar32 c);
+
+/**
+ * @brief The type of the level values in this ubidi implementation.
+ * @details It holds an embedding level and indicates the visual direction by its bit 0
+ *          (even/odd value).
+ *
+ *          It can also hold non-level values for the @c para_level and @c embedding_levels
+ *          arguments of i18n_ubidi_set_para(); there:
+ *          - bit 7 of an @c embedding_levels[] value indicates whether the using application is
+ *          specifying the level of a character to override whatever the ubidi implementation would
+ *          resolve it to.
+ *          - @c para_level can be set to the pseudo-level values #I18N_UBIDI_DEFAULT_LTR and
+ *          #I18N_UBIDI_DEFAULT_RTL.
+ *
+ *          The related constants are not real, valid level values. I18N_UBIDI_DEFAULT_XXX can be
+ *          used to specify a default for the paragraph level for when the i18n_ubidi_set_para()
+ *          function shall determine it but there is no strongly typed character in the input.
+ *
+ *          Note that the value for #I18N_UBIDI_DEFAULT_LTR is even and the one for
+ *          #I18N_UBIDI_DEFAULT_RTL is odd, just like with normal LTR and RTL level values - these
+ *          special values are designed that way. Also, the implementation assumes that
+ *          #I18N_UBIDI_MAX_EXPLICIT_LEVEL is odd.
+ *
+ * @see i18n_ubidi_set_para()
+ * @see I18N_UBIDI_DEFAULT_LTR
+ * @see I18N_UBIDI_DEFAULT_RTL
+ * @see I18N_UBIDI_LEVEL_OVERRIDE
+ * @see I18N_UBIDI_MAX_EXPLICIT_LEVEL
+ */
+typedef uint8_t i18n_ubidi_level_t;
+
+
+/**
+ * @brief Enumeration for text direction.
+ * @since_tizen 3.0
+ */
+typedef enum {
+    /**
+     * Left-to-right text. This is a 0 value.
+     * - As return value for i18n_ubidi_get_direction(), it means that the source string contains
+     * no right-to-left characters, or that the source string is empty and the paragraph level is
+     * even.
+     * - As return value for i18n_ubidi_get_base_direction(), it means that the first strong
+     * character of the source string has a left-to-right direction.
+     */
+    I18N_UBIDI_LTR,
+
+    /**
+     * Right-to-left text. This is a 1 value.
+     * - As return value for i18n_ubidi_get_direction(), it means that the source string contains
+     * no left-to-right characters, or that the source string is empty and the paragraph level is odd.
+     * - As return value for i18n_ubidi_get_base_direction(), it means that the first strong character
+     * of the source string has a right-to-left direction.
+     */
+    I18N_UBIDI_RTL,
+
+    /**
+     * Mixed-directional text.
+     *
+     * As return value for i18n_ubidi_get_direction(), it means that the
+     * source string contains both left-to-right and right-to-left characters.
+     */
+    I18N_UBIDI_MIXED,
+
+    /**
+     * No strongly directional text.
+     *
+     * As return value for i18n_ubidi_get_direction(), it means that
+     * the source string is missing or empty, or contains neither left-to-right nor right-to-left
+     * characters.
+     */
+    I18N_UBIDI_NEUTRAL
+} i18n_ubidi_direction_e;
+
+
+/**
+ * @brief Enumeration for reordering mode.
+ * @details These values indicate which variant of the ubidi algorithm to use.
+ * @since_tizen 3.0
+ * @see i18n_ubidi_set_reordering_mode()
+ * @see i18n_ubidi_set_inverse()
+ */
+typedef enum {
+    /**
+     * Regular Logical to Visual ubidi algorithm according to Unicode. This is a 0 value.
+     */
+    I18N_UBIDI_REORDER_DEFAULT = 0,
+
+    /**
+     * Logical to Visual algorithm which handles numbers in a way which mimicks the behavior of
+     * Windows XP.
+     */
+    I18N_UBIDI_REORDER_NUMBERS_SPECIAL,
+
+    /**
+     * Logical to Visual algorithm grouping numbers with adjacent R characters (reversible
+     * algorithm).
+     */
+    I18N_UBIDI_REORDER_GROUP_NUMBERS_WITH_R,
+
+    /**
+     * Reorder runs only to transform a Logical LTR string to the Logical RTL string with the same
+     * display, or vice-versa.
+     *
+     * If this mode is set together with option #I18N_UBIDI_OPTION_INSERT_MARKS, some ubidi
+     * controls in the source text may be removed and other controls may be added to produce the
+     * minimum combination which has the required display.
+     */
+    I18N_UBIDI_REORDER_RUNS_ONLY,
+
+    /**
+     * Visual to Logical algorithm which handles numbers like L (same algorithm as selected by
+     * i18n_ubidi_set_inverse(true).
+     */
+    I18N_UBIDI_REORDER_INVERSE_NUMBERS_AS_L,
+
+    /**
+     * Visual to Logical algorithm equivalent to the regular Logical to Visual algorithm.
+     */
+    I18N_UBIDI_REORDER_INVERSE_LIKE_DIRECT,
+
+    /**
+     * Inverse ubidi (Visual to Logical) algorithm for the #I18N_UBIDI_REORDER_NUMBERS_SPECIAL
+     * ubidi algorithm.
+     */
+    I18N_UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL,
+
+    /**
+     * Number of values for reordering mode.
+     */
+    I18N_UBIDI_REORDER_COUNT
+} i18n_ubidi_reordering_mode_e;
+
+
+/**
+ * @brief Enumeration for reordering options.
+ * @details These values indicate which options are specified to affect the ubidi algorithm.
+ * @since_tizen 3.0
+ * @see i18n_ubidi_set_reordering_options()
+ * @see i18n_ubidi_set_inverse()
+ */
+typedef enum {
+    /**
+     * Option value for i18n_ubidi_set_reordering_options(): disable all the options which can be set
+     * with this function.
+     */
+    I18N_UBIDI_OPTION_DEFAULT = 0,
+
+    /**
+     * Option bit for i18n_ubidi_set_reordering_options(): insert ubidi marks (LRM or RLM) when
+     * needed to ensure correct result of a reordering to a Logical order. This option must be set
+     * or reset before calling i18n_ubidi_set_para().
+     *
+     * This option is significant only with reordering modes which generate a result with Logical
+     * order, specifically:
+     *     - #I18N_UBIDI_REORDER_RUNS_ONLY
+     *     - #I18N_UBIDI_REORDER_INVERSE_NUMBERS_AS_L
+     *     - #I18N_UBIDI_REORDER_INVERSE_LIKE_DIRECT
+     *     - #I18N_UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL
+     *
+     * If this option is set in conjunction with reordering mode
+     * #I18N_UBIDI_REORDER_INVERSE_NUMBERS_AS_L or with calling i18n_ubidi_set_inverse(true), it
+     * implies option #I18N_UBIDI_INSERT_LRM_FOR_NUMERIC in calls to function
+     * i18n_ubidi_write_reordered().
+     *
+     * For other reordering modes, a minimum number of LRM or RLM characters will be added to the
+     * source text after reordering it so as to ensure round trip, i.e. when applying the inverse
+     * reordering mode on the resulting logical text with removal of ubidi marks (option
+     * #I18N_UBIDI_OPTION_REMOVE_CONTROLS set before calling i18n_ubidi_set_para() or option
+     * #I18N_UBIDI_REMOVE_BIDI_CONTROLS in i18n_ubidi_write_reordered(), the result will be identical
+     * to the source text in the first transformation.
+     *
+     * This option will be ignored if specified together with option
+     * #I18N_UBIDI_OPTION_REMOVE_CONTROLS. It inhibits option #I18N_UBIDI_REMOVE_BIDI_CONTROLS in
+     * calls to function i18n_ubidi_write_reordered() and it implies option
+     * #I18N_UBIDI_INSERT_LRM_FOR_NUMERIC in calls to function i18n_ubidi_write_reordered() if the
+     * reordering mode is #I18N_UBIDI_REORDER_INVERSE_NUMBERS_AS_L.
+     *
+     * @see i18n_ubidi_set_reordering_mode()
+     * @see i18n_ubidi_set_reordering_options()
+     */
+    I18N_UBIDI_OPTION_INSERT_MARKS = 1,
+
+    /**
+     * Option bit for i18n_ubidi_set_reordering_options(): remove ubidi control characters.
+     *
+     * This option must be set or reset before calling i18n_ubidi_set_para().
+     *
+     * This option nullifies option #I18N_UBIDI_OPTION_INSERT_MARKS. It inhibits option
+     * #I18N_UBIDI_INSERT_LRM_FOR_NUMERIC in calls to function i18n_write_reordered() and it implies
+     * option #I18N_UBIDI_REMOVE_BIDI_CONTROLS in calls to that function.
+     *
+     * @see i18n_ubidi_set_reordering_mode()
+     * @see i18n_ubidi_set_reordering_options()
+     */
+    I18N_UBIDI_OPTION_REMOVE_CONTROLS = 2,
+
+    /**
+     * Option bit for i18n_ubidi_set_reordering_options(): process the output as part of a stream
+     * to be continued.
+     *
+     * This option must be set or reset before calling i18n_ubidi_set_para().
+     *
+     * This option specifies that the caller is interested in processing large text object in parts.
+     * The results of the successive calls are expected to be concatenated by the caller. Only the
+     * call for the last part will have this option bit off.
+     *
+     * When this option bit is on, i18n_ubidi_set_para() may process less than the full source text
+     * in order to truncate the text at a meaningful boundary. The caller should call
+     * i18n_ubidi_get_processed_length() immediately after calling i18n_ubidi_set_para()
+     * in order to determine how much of the source text has been processed.
+     * Source text beyond that length should be resubmitted in following calls to
+     * i18n_ubidi_set_para().
+     * The processed length may be less than the length of the source text if a character preceding
+     * the last character of the source text constitutes a reasonable boundary (like a block
+     * separator) for text to be continued. If the last character of the source text constitutes a
+     * reasonable boundary, the whole text will be processed at once.
+     * If nowhere in the source text there exists such a reasonable boundary, the processed length
+     * will be zero.
+     * The caller should check for such an occurrence and do one of the following:
+     *     - submit a larger amount of text with a better chance to include a reasonable boundary.
+     *     - resubmit the same text after turning off option #I18N_UBIDI_OPTION_STREAMING.
+     *
+     * In all cases, this option should be turned off before processing the last part of the text.
+     *
+     * When the #I18N_UBIDI_OPTION_STREAMING option is used, it is recommended to call
+     * i18n_ubidi_order_paragraphs_ltr() with argument order_paragraphs_ltr set to true before
+     * calling i18n_ubidi_set_para() so that later paragraphs may be concatenated to previous
+     * paragraphs on the right.
+     *
+     * @see i18n_ubidi_set_reordering_mode()
+     * @see i18n_ubidi_set_reordering_options()
+     * @see i18n_ubidi_get_processed_length()
+     * @see i18n_ubidi_order_paragraphs_ltr()
+     */
+    I18N_UBIDI_OPTION_STREAMING = 4
+} i18n_ubidi_reordering_option_e;
+
 /**
  * @}
  */
diff --git a/src/include/utils_i18n_ubidi.h b/src/include/utils_i18n_ubidi.h
new file mode 100644 (file)
index 0000000..3c635db
--- /dev/null
@@ -0,0 +1,1317 @@
+/*
+* Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+*
+*    Licensed under the Apache License, Version 2.0 (the "License");
+*    you may not use this file except in compliance with the License.
+*    You may obtain a copy of the License at
+*
+*        http://www.apache.org/licenses/LICENSE-2.0
+*
+*    Unless required by applicable law or agreed to in writing, software
+*    distributed under the License is distributed on an "AS IS" BASIS,
+*    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*    See the License for the specific language governing permissions and
+*    limitations under the License.
+*
+* Copyright (C) 1999-2013, International Business Machines Corporation
+* and others. All Rights Reserved.
+*/
+
+#ifndef __UTILS_I18N_UBIDI_H__
+#define __UTILS_I18N_UBIDI_H__
+
+#include <utils_i18n_types.h>
+
+/**
+ * @file utils_i18n_ubidi.h
+ * @version 0.1
+ * @brief utils_i18n_ubidi
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @ingroup CAPI_BASE_UTILS_I18N_MODULE
+ * @defgroup CAPI_BASE_UTILS_I18N_UBIDI_MODULE Ubidi
+ * @brief Ubidi module provides an implementation of the Unicode Bidirectional Algorithm.
+ *
+ * @section CAPI_BASE_UTILS_I18N_UBIDI_MODULE_HEADER Required Header
+ * \#include <utils_i18n.h>
+ *
+ * @section CAPI_BASE_UTILS_I18N_UBIDI_MODULE_OVERVIEW Overview
+ * @details Ubidi module provides an implementation of the Unicode Bidirectional Algorithm. The
+ *          algorithm is defined in the Unicode Standard Annex #9.
+ *          Note: Libraries that perform a bidirectional algorithm and reorder strings accordingly
+ *          are sometimes called "Storage Layout Engines".
+ *          ubidi and shaping APIs can be used at the core of such "Storage Layout Engines".
+ */
+
+/**
+ * @addtogroup CAPI_BASE_UTILS_I18N_UBIDI_MODULE
+ * @{
+ */
+
+/**
+ * @brief This function must be called to free the memory associated with an #i18n_ubidi_h handle.
+ * @details Important: A parent #i18n_ubidi_h handle must not be destroyed or reused if it still has
+ *          children. If an #i18n_ubidi_h handle has become the child of
+ *          another one (its parent) by calling i18n_ubidi_set_line(), then the child object must be
+ *          destroyed or reused (by calling i18n_ubidi_set_para() or i18n_ubidi_set_line()) before
+ *          the parent object.
+ * @since_tizen 3.0
+ *
+ * @param[in]       ubidi       #i18n_ubidi_h handle to be destroyed
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see i18n_ubidi_set_para()
+ * @see i18n_ubidi_set_line()
+ */
+int i18n_ubidi_destroy(i18n_ubidi_h ubidi);
+
+/**
+ * @brief Gets the number of paragraphs.
+ * @since_tizen 3.0
+ *
+ * @param[in]      ubidi        The paragraph or line #i18n_ubidi_h object
+ * @param[out]     count        The number of paragraphs
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ */
+int i18n_ubidi_count_paragraphs(i18n_ubidi_h ubidi, int32_t *count);
+
+/**
+ * @brief Gets the number of runs.
+ * @details This function may invoke the actual reordering on the #i18n_ubidi_h handle, after
+ *          i18n_ubidi_set_para() may have resolved only the levels of the text. Therefore,
+ *          i18n_ubidi_count_runs() may have to allocate memory, and may fail doing so.
+ * @since_tizen 3.0
+ *
+ * @param[in]       ubidi       The paragraph or line #i18n_ubidi_h object
+ * @param[out]      count       The number of runs
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @retval #I18N_ERROR_OUT_OF_MEMORY Out of memory
+ */
+int i18n_ubidi_count_runs(i18n_ubidi_h ubidi, int32_t *count);
+
+/**
+ * @brief Gets the base direction of the text provided according to the Unicode Bidirectional
+ *          Algorithm.
+ * @details The base direction is derived from the first character in the string with bidirectional
+ *          character type L, R, or AL. If the first such character has type L, #I18N_UBIDI_LTR is
+ *          returned. If the first such character has type R or AL, #I18N_UBIDI_RTL is returned.
+ *          If the string does not contain any character of these types, then #I18N_UBIDI_NEUTRAL
+ *          is returned.
+ *
+ *          This is a lightweight function for use when only the base direction is needed and no
+ *          further bidi processing of the text is needed.
+ * @since_tizen 3.0
+ *
+ * @param[in]      text       A pointer to the @a text whose base direction is needed. Note: the @a text
+ *                            must be (at least) @a length long.
+ * @param[in]      length     The length of the @a text; if @a length == -1 then the text must be
+ *                            zero-terminated
+ * @param[out]     direction  Base direction of the @a text
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ */
+int i18n_ubidi_get_base_direction(const i18n_uchar *text, int32_t length,
+                                  i18n_ubidi_direction_e *direction);
+
+/**
+ * @brief Gets the current callback function used for ubidi class determination.
+ * @since_tizen 3.0
+ *
+ * @param[in]       ubidi       The paragraph #i18n_ubidi_h object
+ * @param[out]      fn          The callback function pointer. This can be @c NULL.
+ * @param[out]      context     The callback's private context. This can be @c NULL.
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see i18n_ubidi_set_class_cb()
+ */
+int i18n_ubidi_get_class_cb(i18n_ubidi_h ubidi, i18n_ubidi_class_cb *fn,
+                            const void **context);
+
+/**
+ * @brief Retrieves the ubidi class for a given code point.
+ * @details If an #i18n_ubidi_class_cb callback is defined and returns a value other than
+ *          #I18N_UBIDI_CLASS_DEFAULT, that value is used; otherwise the default class
+ *          determination mechanism is invoked.
+ * @since_tizen 3.0
+ *
+ * @param[in]       ubidi        The paragraph #i18n_ubidi_h object
+ * @param[in]       c            The code point whose ubidi class must be retrieved
+ * @param[out]      direction    The ubidi class for character @a c based on the given @a ubidi instance
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see i18n_ubidi_class_cb()
+ */
+int i18n_ubidi_get_customized_class(i18n_ubidi_h ubidi, i18n_uchar32 c,
+                                    i18n_uchar_direction_e *direction);
+
+/**
+ * @brief Gets the directionality of the text.
+ * @since_tizen 3.0
+ *
+ * @param[in]        ubidi       The paragraph or line #i18n_ubidi_h object
+ * @param[out]       direction   A value of #I18N_UBIDI_LTR, #I18N_UBIDI_RTL or #I18N_UBIDI_MIXED
+ *                               that indicates if the entire text represented by this object is
+ *                               unidirectional, and which direction, or if it is mixed-directional.
+ *                               Note - The value #I18N_UBIDI_NEUTRAL is never returned from this
+ *                               method.
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see i18n_ubidi_direction_e
+ */
+int i18n_ubidi_get_direction(const i18n_ubidi_h ubidi, i18n_ubidi_direction_e *direction);
+
+/**
+ * @brief Gets the length of the text.
+ * @since_tizen 3.0
+ *
+ * @param[in]       ubidi        The paragraph or line #i18n_ubidi_h object
+ * @param[out]      length       The length of the text that the #i18n_ubidi_h object was created for
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ */
+int i18n_ubidi_get_length(const i18n_ubidi_h ubidi, int32_t *length);
+
+/**
+ * @brief Gets the level for one character.
+ * @since_tizen 3.0
+ *
+ * @param[in]       ubidi       The paragraph or line #i18n_ubidi_h object
+ * @param[in]       char_index  The index of a character. It must be in the range
+ *                              [0..i18n_ubidi_get_processed_length(@a ubidi)-1]
+ * @param[out]      level       The level for the character at @a char_index (0 if @a char_index is not in
+ *                              the valid range)
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see i18n_ubidi_level_t
+ * @see i18n_ubidi_get_processed_length()
+ */
+int i18n_ubidi_get_level_at(const i18n_ubidi_h ubidi, int32_t char_index,
+                            i18n_ubidi_level_t *level);
+
+/**
+ * @brief Gets an array of levels for each character.
+ * @details Note that this function may allocate memory under some circumstances, unlike
+ *          i18n_ubidi_get_level_at().
+ * @since_tizen 3.0
+ * @remarks @a levels should not be freed.
+ *
+ * @param[in]      ubidi     The paragraph or line #i18n_ubidi_h object, whose text length must be
+ *                           strictly positive
+ * @param[out]     levels     The levels array for the text, or @c NULL if an error occurs
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @retval #I18N_ERROR_OUT_OF_MEMORY Out of memory
+ * @see i18n_ubidi_level_t
+ * @see i18n_ubidi_get_processed_length()
+ */
+int i18n_ubidi_get_levels(i18n_ubidi_h ubidi, const i18n_ubidi_level_t **levels);
+
+/**
+ * @brief Gets the logical text position from a visual position.
+ * @details If such a mapping is used many times on the same #i18n_ubidi_h object, then calling
+ *          i18n_ubidi_get_visual_map() is more efficient.
+ *
+ *          The value returned may be #I18N_UBIDI_MAP_NOWHERE if there is no logical position
+ *          because the corresponding text character is a ubidi mark inserted in the output by
+ *          option #I18N_UBIDI_OPTION_INSERT_MARKS.
+ *
+ *          This is the inverse function to i18n_ubidi_get_visual_index().
+ *
+ *          When the visual output is altered by using options of i18n_ubidi_write_reordered() such
+ *          as #I18N_UBIDI_INSERT_LRM_FOR_NUMERIC, #I18N_UBIDI_KEEP_BASE_COMBINING,
+ *          #I18N_UBIDI_OUTPUT_REVERSE, #I18N_UBIDI_REMOVE_BIDI_CONTROLS, the logical position
+ *          returned may not be correct.
+ *          It is advised to use, when possible, reordering options such as
+ *          #I18N_UBIDI_OPTION_INSERT_MARKS and #I18N_UBIDI_OPTION_REMOVE_CONTROLS.
+ * @since_tizen 3.0
+ *
+ * @param[in]      ubidi           The paragraph or line #i18n_ubidi_h object
+ * @param[in]      visual_index    The visual position of a character
+ * @param[out]     logical_index   The index of this character in the text
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see i18n_ubidi_get_visual_map()
+ * @see i18n_ubidi_get_visual_index()
+ * @see i18n_ubidi_get_result_length()
+ */
+int i18n_ubidi_get_logical_index(i18n_ubidi_h ubidi, int32_t visual_index, int32_t *logical_index);
+
+/**
+ * @brief Gets a logical-to-visual index map (array) for the characters in the #i18n_ubidi_h (paragraph or
+ *          line) object.
+ * @details Some values in the map may be #I18N_UBIDI_MAP_NOWHERE if the corresponding text
+ *          characters are ubidi controls removed from the visual output by the option
+ *          #I18N_UBIDI_OPTION_REMOVE_CONTROLS.
+ *
+ *          When the visual output is altered by using options of i18n_ubidi_write_reordered()
+ *          such as #I18N_UBIDI_INSERT_LRM_FOR_NUMERIC, #I18N_UBIDI_KEEP_BASE_COMBINING,
+ *          #I18N_UBIDI_OUTPUT_REVERSE, #I18N_UBIDI_REMOVE_BIDI_CONTROLS, the visual positions
+ *          returned may not be correct. It is advised to use, when possible, reordering options
+ *          such as #I18N_UBIDI_OPTION_INSERT_MARKS and #I18N_UBIDI_OPTION_REMOVE_CONTROLS.
+ *
+ *          Note that in right-to-left runs, this mapping places second surrogates before first
+ *          ones (which is generally a bad idea) and combining characters before base characters.
+ *          Use of i18n_ubidi_write_reordered(), optionally with the #I18N_UBIDI_KEEP_BASE_COMBINING
+ *          option can be considered instead of using the mapping, in order to avoid these issues.
+ * @since_tizen 3.0
+ *
+ * @param[in]       ubidi         The paragraph or line #i18n_ubidi_h object
+ * @param[out]      index_map     A pointer to an array of i18n_ubidi_get_processed_length()
+ *                                indexes which will reflect the reordering of the characters.
+ *                                If option #I18N_UBIDI_OPTION_INSERT_MARKS is set, the number of
+ *                                elements allocated in the @a index_map must be no less than
+ *                                i18n_ubidi_get_result_length().
+ *
+ *                                The array does not need to be initialized.
+ *
+ *                                The index map will result in
+ *                                index_map[logical_index] == visual_index.
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see i18n_ubidi_get_visual_map()
+ * @see i18n_ubidi_get_visual_index()
+ * @see i18n_ubidi_get_processed_length()
+ * @see i18n_ubidi_get_result_length()
+ */
+int i18n_ubidi_get_logical_map(i18n_ubidi_h ubidi, int32_t *index_map);
+
+/**
+ * @brief Gets a logical run.
+ * @details This function returns information about a run and is used to retrieve runs in logical
+ *          order.
+ *
+ *          This is especially useful for line-breaking on a paragraph.
+ * @since_tizen 3.0
+ *
+ * @param[in]      ubidi                The paragraph or line #i18n_ubidi_h object
+ * @param[in]      logical_position     A logical position within the source text
+ * @param[out]     logical_limit        The limit of the corresponding run. The l-value that you
+ *                                      point to here may be the same expression (variable) as
+ *                                      the one for @a logical_position.
+ *                                      This pointer can be @c NULL if this value is not necessary.
+ * @param[out]     level                The level of the corresponding run. This pointer can be
+ *                                      @c NULL if this value is not necessary.
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see i18n_ubidi_get_processed_length()
+ */
+int i18n_ubidi_get_logical_run(const i18n_ubidi_h ubidi,
+                               int32_t logical_position,
+                               int32_t *logical_limit,
+                               i18n_ubidi_level_t *level);
+
+/**
+ * @brief Gets a paragraph, given a position within the text.
+ * @details This function returns information about a paragraph.
+ *
+ *          Note: if the paragraph index is known, it is more efficient to retrieve the paragraph
+ *          information using i18n_ubidi_get_paragraph_by_index().
+ * @since_tizen 3.0
+ *
+ * @param[in]       ubidi            The paragraph or line #i18n_ubidi_h object
+ * @param[in]       char_index       The index of a character within the text, in the range
+ *                                   [0..i18n_ubidi_get_processed_length(@a ubidi)-1]
+ * @param[out]      para_start       The index of the first character of the paragraph in the text.
+ *                                   This pointer can be @c NULL if this value is not necessary.
+ * @param[out]      para_limit       The limit of the paragraph. The l-value that you point to here
+ *                                   may be the same expression (variable) as the one for
+ *                                   @a char_index. This pointer can be @c NULL if this value is not
+ *                                   necessary.
+ * @param[out]      para_level       The level of the paragraph. This pointer can be @c NULL if this
+ *                                   value is not necessary.
+ * @param[out]      index            The index of the paragraph containing the specified position
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see i18n_ubidi_get_processed_length()
+ */
+int i18n_ubidi_get_paragraph(const i18n_ubidi_h ubidi,
+                             int32_t char_index,
+                             int32_t *para_start,
+                             int32_t *para_limit,
+                             i18n_ubidi_level_t *para_level,
+                             int32_t *index);
+
+/**
+ * @brief Gets a paragraph, given the index of this paragraph.
+ * @details This function returns information about paragraphs.
+ * @since_tizen 3.0
+ *
+ * @param[in]       ubidi            The paragraph #i18n_ubidi_h object
+ * @param[in]       para_index       The number of the paragraph, in the range
+ *                                   [0..i18n_ubidi_count_paragraphs(@a ubidi)-1]
+ * @param[out]      para_start       The index of the first character of the paragraph in the text.
+ *                                   This pointer can be @c NULL if this value is not necessary.
+ * @param[out]      para_limit       The limit of the paragraph. This pointer can be @c NULL if this
+ *                                   value is not necessary.
+ * @param[out]      para_level       The level of the paragraph. This pointer can be @c NULL if this
+ *                                   value is not necessary.
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ */
+int i18n_ubidi_get_paragraph_by_index(const i18n_ubidi_h ubidi,
+                                      int32_t para_index,
+                                      int32_t *para_start,
+                                      int32_t *para_limit,
+                                      i18n_ubidi_level_t *para_level);
+
+/**
+ * @brief Gets the paragraph level of the text.
+ * @since_tizen 3.0
+ *
+ * @param[in]       ubidi         The paragraph or line #i18n_ubidi_h object
+ * @param[out]      level         The paragraph level. If there are multiple paragraphs, their
+ *                                level may vary if the required para_level is
+ *                                #I18N_UBIDI_DEFAULT_LTR or #I18N_UBIDI_DEFAULT_RTL. In that case,
+ *                                the level of the first paragraph is returned.
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see i18n_ubidi_level_t
+ * @see i18n_ubidi_get_paragraph()
+ * @see i18n_ubidi_get_paragraph_by_index()
+ */
+int i18n_ubidi_get_para_level(const i18n_ubidi_h ubidi, i18n_ubidi_level_t *level);
+
+/**
+ * @brief Gets the length of the source text processed by the last call to i18n_ubidi_set_para().
+ * @details This length may be different from the length of the source text if option
+ *          #I18N_UBIDI_OPTION_STREAMING has been set.
+ *
+ *          Note that whenever the length of the text affects the execution or the result of a
+ *          function, it is the processed length which must be considered, except for
+ *          i18n_ubidi_set_para() (which receives unprocessed source text) and i18n_ubidi_get_length()
+ *          (which returns the original length of the source text).
+ *
+ *          In particular, the processed @a length is the one to consider in the following cases:
+ *              - maximum value of the limit argument of i18n_ubidi_set_line()
+ *              - maximum value of the char_index argument of i18n_ubidi_get_paragraph()
+ *              - maximum value of the char_index argument of i18n_ubidi_get_level_at()
+ *              - number of elements in the array returned by i18n_ubidi_get_levels()
+ *              - maximum value of the logical_start argument of i18n_ubidi_get_logical_run()
+ *              - maximum value of the logical_index argument of i18n_ubidi_get_visual_index()
+ *              - number of elements filled in the @a index_map argument of i18n_ubidi_get_logical_map()
+ *              - length of text processed by i18n_ubidi_write_reordered()
+ *
+ * @since_tizen 3.0
+ *
+ * @param[in]       ubidi          The paragraph #i18n_ubidi_h object
+ * @param[out]      length         The length of the part of the source text processed by the last
+ *                                 call to i18n_ubidi_set_para()
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see i18n_ubidi_set_para()
+ * @see I18N_UBIDI_OPTION_STREAMING
+ */
+int i18n_ubidi_get_processed_length(const i18n_ubidi_h ubidi, int32_t *length);
+
+/**
+ * @brief Gets the requested reordering mode for a given #i18n_ubidi_h object.
+ * @since_tizen 3.0
+ *
+ * @param[in]       ubidi       An #i18n_ubidi_h object
+ * @param[out]      mode        The current reordering mode of the @a ubidi object
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see i18n_ubidi_set_reordering_mode()
+ */
+int i18n_ubidi_get_reordering_mode(i18n_ubidi_h ubidi, i18n_ubidi_reordering_mode_e *mode);
+
+/**
+ * @brief Gets the reordering options applied to a given #i18n_ubidi_h object.
+ * @since_tizen 3.0
+ *
+ * @param[in]       ubidi       An #i18n_ubidi_h object
+ * @param[out]      options     The current reordering options of the @a ubidi object;
+ *                              #i18n_ubidi_reordering_option_e values combined with bitwise 'or'
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see i18n_ubidi_set_reordering_options()
+ */
+int i18n_ubidi_get_reordering_options(i18n_ubidi_h ubidi, uint32_t *options);
+
+/**
+ * @brief Gets the length of the reordered text resulting from the last call to
+ *          i18n_ubidi_set_para().
+ * @details This length may be different from the length of the source text if option
+ *          #I18N_UBIDI_OPTION_INSERT_MARKS or option #I18N_UBIDI_OPTION_REMOVE_CONTROLS has been set.
+ *
+ *          This resulting @a length is the one to consider in the following cases:
+ *              - maximum value of the visual_index argument of i18n_ubidi_get_logical_index()
+ *              - number of elements of the a index_map argument of i18n_ubidi_get_visual_map()
+ *
+ *          Note that this @a length stays identical to the source text length if ubidi marks are
+ *          inserted or removed using option bits of i18n_ubidi_write_reordered(), or if option
+ *          #I18N_UBIDI_REORDER_INVERSE_NUMBERS_AS_L has been set.
+ * @since_tizen 3.0
+ *
+ * @param[in]        ubidi        The paragraph #i18n_ubidi_h object
+ * @param[out]       length       The length of the reordered text resulting from the last call to
+ *                                i18n_ubidi_set_para()
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see i18n_ubidi_set_para()
+ * @see I18N_UBIDI_OPTION_INSERT_MARKS
+ * @see I18N_UBIDI_OPTION_REMOVE_CONTROLS
+ */
+int i18n_ubidi_get_result_length(const i18n_ubidi_h ubidi, int32_t *length);
+
+/**
+ * @brief Gets the pointer to the given #i18n_ubidi_h object's text.
+ * @since_tizen 3.0
+ * @remarks @a text should be freed with free().
+ *
+ * @param[in]       ubidi      The paragraph or line #i18n_ubidi_h object
+ * @param[out]      text       The pointer to the text that the @a ubidi object was created for
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @retval #I18N_ERROR_OUT_OF_MEMORY Out of memory
+ * @see i18n_ubidi_set_para()
+ * @see i18n_ubidi_set_line()
+ */
+int i18n_ubidi_get_text(const i18n_ubidi_h ubidi, char **text);
+
+/**
+ * @brief Gets the visual position from a logical text position.
+ * @details If such a mapping is used many times on the same #i18n_ubidi_h object, then calling
+ *          i18n_ubidi_get_logical_map() is more efficient.
+ *
+ *          The value returned may be #I18N_UBIDI_MAP_NOWHERE if there is no visual position because
+ *          the corresponding text character is an ubidi control removed from output by the option
+ *          #I18N_UBIDI_OPTION_REMOVE_CONTROLS.
+ *
+ *          When the visual output is altered by using options of i18n_ubidi_write_reordered()
+ *          such as #I18N_UBIDI_INSERT_LRM_FOR_NUMERIC, #I18N_UBIDI_KEEP_BASE_COMBINING,
+ *          #I18N_UBIDI_OUTPUT_REVERSE, #I18N_UBIDI_REMOVE_BIDI_CONTROLS, the visual position
+ *          returned may not be correct.
+ *          It is advised to use, when possible, reordering options such as
+ *          #I18N_UBIDI_OPTION_INSERT_MARKS and #I18N_UBIDI_OPTION_REMOVE_CONTROLS.
+ *
+ *          Note that in right-to-left runs, this mapping places second surrogates before first ones
+ *          (which is generally a bad idea) and combining characters before base characters. Use of
+ *          i18n_ubidi_write_reordered(), optionally with the #I18N_UBIDI_KEEP_BASE_COMBINING
+ *          option can be considered instead of using the mapping, in order to avoid these issues.
+ * @since_tizen 3.0
+ * @param[in]       ubidi             The paragraph or line #i18n_ubidi_h object
+ * @param[in]       logical_index     The index of a character in the text
+ * @param[out]      visual_index      The visual position of this character
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see i18n_ubidi_get_logical_map()
+ * @see i18n_ubidi_get_logical_index()
+ * @see i18n_ubidi_get_processed_length()
+ */
+int i18n_ubidi_get_visual_index(i18n_ubidi_h ubidi, int32_t logical_index, int32_t *visual_index);
+
+/**
+ * @brief Gets a visual-to-logical index map (array) for the characters in the #i18n_ubidi_h
+ *          (paragraph or line) object.
+ * @details Some values in the map may be #I18N_UBIDI_MAP_NOWHERE if the corresponding text
+ *          characters are ubidi marks inserted in the visual output by the option
+ *          #I18N_UBIDI_OPTION_INSERT_MARKS.
+ *
+ *          When the visual output is altered by using options of i18n_ubidi_write_reordered()
+ *          such as #I18N_UBIDI_INSERT_LRM_FOR_NUMERIC, #I18N_UBIDI_KEEP_BASE_COMBINING,
+ *          #I18N_UBIDI_OUTPUT_REVERSE, #I18N_UBIDI_REMOVE_BIDI_CONTROLS, the logical positions
+ *          returned may not be correct. It is advised to use, when possible, reordering options
+ *          such as #I18N_UBIDI_OPTION_INSERT_MARKS and #I18N_UBIDI_OPTION_REMOVE_CONTROLS.
+ * @since_tizen 3.0
+ *
+ * @param[in]        ubidi           The paragraph or line #i18n_ubidi_h object
+ * @param[out]       index_map       Pointer to an array of i18n_ubidi_get_result_length() indexes
+ *                                   which will reflect the reordering of the characters. If option
+ *                                   #I18N_UBIDI_OPTION_REMOVE_CONTROLS is set, the number of
+ *                                   elements allocated in @a index_map must be no less than
+ *                                   i18n_ubidi_get_processed_length(). The array does not need to
+ *                                   be initialized.
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see i18n_ubidi_get_logical_map()
+ * @see i18n_ubidi_get_logical_index()
+ * @see i18n_ubidi_get_processed_length()
+ * @see i18n_ubidi_get_result_length()
+ */
+int i18n_ubidi_get_visual_map(i18n_ubidi_h ubidi, int32_t *index_map);
+
+/**
+ * @brief Gets one run's logical start, length, and directionality, which can be 0 for LTR or 1 for
+ *        RTL.
+ * @details In an RTL run, the character at the logical start is visually on the right of the
+ *          displayed run.
+ *          The @a length is the number of characters in the run.
+ *          i18n_ubidi_count_runs() should be called before the runs are retrieved.
+ *
+ *          Note that in right-to-left runs, code like this places second surrogates before first
+ *          ones (which is generally a bad idea) and combining characters before base characters.
+ *
+ *          Use of i18n_ubidi_write_reordered(), optionally with the #I18N_UBIDI_KEEP_BASE_COMBINING
+ *          option, can be considered in order to avoid these issues.
+ * @since_tizen 3.0
+ *
+ * @param[in]       ubidi             The paragraph or line #i18n_ubidi_h object
+ * @param[in]       run_index         The number of the run in visual order, in the range
+ *                                    [0..i18n_ubidi_count_runs(@a ubidi)-1]
+ * @param[out]      logical_index     The first logical character index in the text. The pointer
+ *                                    may be @c NULL if this index is not needed
+ * @param[out]      length            The number of characters (at least one) in the run.
+ *                                    The pointer may be @c NULL if this is not needed.
+ * @param[out]      direction         The directionality of the run, #I18N_UBIDI_LTR == 0 or
+ *                                    #I18N_UBIDI_RTL == 1, never #I18N_UBIDI_MIXED, never
+ *                                    #I18N_UBIDI_NEUTRAL.
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see i18n_ubidi_count_runs()
+ */
+int i18n_ubidi_get_visual_run(i18n_ubidi_h ubidi,
+                              int32_t run_index,
+                              int32_t *logical_index,
+                              int32_t *length,
+                              i18n_ubidi_direction_e *direction);
+
+/**
+ * @brief Inverts an index map.
+ * @details The index mapping of the first map is inverted and written to the second one.
+ * @since_tizen 3.0
+ * @remarks The @a dest_map array should be provided by the user.
+ *
+ * @param[in]       src_map       An array with @a length elements which defines the original mapping
+ *                                from a source array containing @a length elements to a destination
+ *                                array. Some elements of the source array may have no mapping in
+ *                                the destination array. In that case, their value will be the
+ *                                special value #I18N_UBIDI_MAP_NOWHERE.
+ *                                All elements must be >=0 or equal to #I18N_UBIDI_MAP_NOWHERE.
+ *                                Some elements may have a value >= length, if the destination array
+ *                                has more elements than the source array. There must be no
+ *                                duplicate indexes (two or more elements with the same value
+ *                                except #I18N_UBIDI_MAP_NOWHERE).
+ * @param[in]       length        The length of each array
+ * @param[out]      dest_map      An array with a number of elements equal to 1 + the highest
+ *                                value in @a src_map. @a dest_map will be filled with the inverse
+ *                                mapping. If element with index i in @a src_map has a value k
+ *                                different from #I18N_UBIDI_MAP_NOWHERE, this means that element i
+ *                                of the source array maps to element k in the destination array.
+ *                                The inverse map will have value i in its k-th element.
+ *                                For all elements of the destination array which do not map to an
+ *                                element in the source array, the corresponding element in the
+ *                                inverse map will have a value equal to #I18N_UBIDI_MAP_NOWHERE.
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see I18N_UBIDI_MAP_NOWHERE
+ */
+int i18n_ubidi_invert_map(const int32_t *src_map, int32_t length, int32_t *dest_map);
+
+/**
+ * @brief Gets whether the given #i18n_ubidi_h object is set to perform the inverse ubidi algorithm.
+ * @details Note: calling this function after setting the reordering mode with
+ *          i18n_ubidi_set_reordering_mode() will return @c true if the reordering mode was set
+ *          to #I18N_UBIDI_REORDER_INVERSE_NUMBERS_AS_L, @c false for all other values.
+ * @since_tizen 3.0
+ *
+ * @param[in]        ubidi         An #i18n_ubidi_h object
+ * @param[out]       is_inverse    @c true if the @a ubidi object is set to perform the inverse ubidi
+ *                                 algorithm by handling numbers as L
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see i18n_ubidi_set_inverse()
+ * @see i18n_ubidi_set_reordering_mode()
+ */
+int i18n_ubidi_is_inverse(i18n_ubidi_h ubidi, i18n_ubool *is_inverse);
+
+/**
+ * @brief Gets whether the given #i18n_ubidi_h object is set to allocate level 0 to block separators.
+ * @details This function gets the information whether the given #i18n_ubidi_h object is set to allocate level 0 to block separators.
+ * so that successive paragraphs progress from left to right.
+ * @since_tizen 3.0
+ *
+ * @param[in]        ubidi         An #i18n_ubidi_h object
+ * @param[out]       is_order      @c true if the @a ubidi object is set to allocate level 0 to block
+ *                                 separators
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see i18n_ubidi_order_paragraphs_ltr()
+ */
+int i18n_ubidi_is_order_paragraphs_ltr(i18n_ubidi_h ubidi, i18n_ubool *is_order);
+
+/**
+ * @brief Creates an ubidi object.
+ * @details Such an object is initially empty. It is assigned the ubidi properties of a piece of text
+ *          containing one or more paragraphs by i18n_ubidi_set_para() or the ubidi properties of
+ *          a line within a paragraph by i18n_ubidi_set_line().
+ *
+ *          This object can be reused for as long as it is not deallocated by calling
+ *          i18n_ubidi_destroy().
+ *
+ *          i18n_ubidi_set_para() and i18n_ubidi_set_line() will allocate additional memory for
+ *          internal structures as necessary.
+ * @since_tizen 3.0
+ * @remarks @a ubidi should be destroyed with i18n_ubidi_destroy().
+ *
+ * @param[out]       ubidi         An empty #i18n_ubidi_h object
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ */
+int i18n_ubidi_create(i18n_ubidi_h *ubidi);
+
+/**
+ * @brief Creates an ubidi structure with preallocated memory for internal structures.
+ * @details This function provides an ubidi object like i18n_ubidi_create() with no arguments,
+ *          but it also preallocates memory for internal structures according to the sizings
+ *          supplied by the caller.
+ *
+ *          Subsequent functions will not allocate any more memory, and are thus guaranteed not
+ *          to fail because of lack of memory.
+ *
+ *          The preallocation can be limited to some of the
+ *          internal memory by setting some values to 0 here. That means that if, e.g.,
+ *          @a max_run_count cannot be reasonably predetermined and should not be set to @a max_length
+ *          (the only failproof value) to avoid wasting memory, then @a max_run_count could be set to
+ *          0 here and the internal structures that are associated with it will be allocated on
+ *          demand, just like with i18n_ubidi_create().
+ * @since_tizen 3.0
+ * @remarks @a ubidi should be destroyed with i18n_ubidi_destroy().
+ *
+ * @param[in]       max_length       The maximum text or line length that internal memory will be
+ *                                   preallocated for. An attempt to associate this object with a
+ *                                   longer text will fail, unless this value is 0, which
+ *                                   leaves the allocation up to the implementation.
+ * @param[in]       max_run_count    The maximum anticipated number of same-level runs that internal
+ *                                   memory will be preallocated for. An attempt to access visual
+ *                                   runs on an object that was not preallocated for as many runs
+ *                                   as the text was actually resolved to will fail, unless this
+ *                                   value is 0, which leaves the allocation up to the
+ *                                   implementation.
+ *                                   The number of runs depends on the actual text and maybe
+ *                                   anywhere between 1 and @a max_length. It is typically small
+ * @param[out]      ubidi            An empty #i18n_ubidi_h handle with preallocated memory
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ */
+int i18n_ubidi_create_sized(int32_t max_length, int32_t max_run_count, i18n_ubidi_h *ubidi);
+
+/**
+ * @brief Sets whether block separators must be allocated level zero, so that successive
+ *          paragraphs will progress from left to right.
+ * @details This function must be called before i18n_ubidi_set_para(). Paragraph separators (B) may
+ *          appear in the text. Setting them to level zero means that all paragraph separators
+ *          (including one possibly appearing in the last text position) are kept in the reordered
+ *          text after the text that they follow in the source text. When this feature is not
+ *          enabled, a paragraph separator at the last position of the text before reordering will
+ *          go to the first position of the reordered text when the paragraph level is odd.
+ * @since_tizen 3.0
+ * @param[in]       ubidi                 An #i18n_ubidi_h object
+ * @param[in]       order_paragraphs_ltr  Specifies whether paragraph separators (B) must receive
+ *                                        level 0, so that successive paragraphs progress from left
+ *                                        to right
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see i18n_ubidi_set_para()
+ */
+int i18n_ubidi_order_paragraphs_ltr(i18n_ubidi_h ubidi, i18n_ubool order_paragraphs_ltr);
+
+/**
+ * @brief Performs logical reordering.
+ * @details This is a convenience function that does not use an #i18n_ubidi_h object.
+ *          It is intended to be used for when an application has determined the levels of objects
+ *          (character sequences) and just needs to have them reordered (L2). This is equivalent to
+ *          using i18n_ubidi_get_logical_map() on an #i18n_ubidi_h object.
+ *
+ *          The index map will result in index_map[logical_index] == visual_index.
+ * @since_tizen 3.0
+ *
+ * @param[in]       levels        An array with @a length levels that have been determined by the
+ *                                application
+ * @param[in]       length        The number of levels in the array, or, semantically, the number
+ *                                of objects to be reordered. @a length must be > 0.
+ * @param[out]      index_map     Pointer to an array of @a length indexes which will reflect the
+ *                                reordering of the characters. The array does not need to be
+ *                                initialized.
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ */
+int i18n_ubidi_reorder_logical(const i18n_ubidi_level_t *levels, int32_t length,
+                               int32_t *index_map);
+
+/**
+ * @brief Performs visual reordering.
+ * @details This is a convenience function that does not use an #i18n_ubidi_h object.
+ *          It is intended to be used for when an application has determined the levels of objects
+ *          (character sequences) and just needs to have them reordered (L2). This is equivalent
+ *          to using i18n_ubidi_get_visual_map() on an #i18n_ubidi_h handle.
+ *          The index map will result in @a index_map[visual_index] == logical_index.
+ * @since_tizen 3.0
+ *
+ * @param[in]       levels        An array with @a length levels that have been determined by the
+ *                                application
+ * @param[in]       length        The number of levels in the array, or, semantically, the number
+ *                                of objects to be reordered. @a length must be > 0.
+ * @param[out]      index_map     Pointer to an array of @a length indexes which will reflect the
+ *                                reordering of the characters. The array does not need to be
+ *                                initialized.
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ */
+int i18n_ubidi_reorder_visual(const i18n_ubidi_level_t *levels, int32_t length, int32_t *index_map);
+
+/**
+ * @brief Sets the callback function and callback data used by the UBA implementation for ubidi class
+ *          determination.
+ * @details This may be useful for assigning ubidi classes to PUA characters, or for special
+ *          application needs. For instance, an application may want to handle all spaces like L
+ *          or R characters (according to the base direction) when creating the visual ordering of
+ *          logical lines which are part of a report organized in columns: there should not be
+ *          interaction between adjacent cells.
+ * @since_tizen 3.0
+ *
+ * @param[in]       ubidi            The paragraph #i18n_ubidi_h object
+ * @param[in]       new_fn           The new callback function pointer
+ * @param[in]       new_context      The new callback context pointer. This can be @c NULL.
+ * @param[out]      old_fn           The old callback function pointer. This can be @c NULL.
+ * @param[out]      old_context      The old callback's context. This can be @c NULL.
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see i18n_ubidi_get_class_cb()
+ */
+int i18n_ubidi_set_class_cb(i18n_ubidi_h ubidi,
+                            i18n_ubidi_class_cb new_fn,
+                            const void *new_context,
+                            i18n_ubidi_class_cb *old_fn,
+                            const void **old_context);
+/**
+ * @brief Sets the context before a call to i18n_ubidi_set_para().
+ * @details i18n_ubidi_set_para() computes the left-right directionality for a given piece of text
+ *          which is supplied as one of its arguments. Sometimes this piece of text (the "main
+ *          text") should be considered in context, because text appearing before ("prologue")
+ *          and/or after ("epilogue") the main text may affect the result of this computation.
+ *
+ *          This function specifies the prologue and/or the epilogue for the next call to
+ *          i18n_ubidi_set_para(). The characters specified as prologue and epilogue should not
+ *          be modified by the calling program until the call to i18n_ubidi_set_para() has returned.
+ *          If successive calls to i18n_ubidi_set_para() all need specification of a context,
+ *          i18n_ubidi_set_context() must be called before each call to i18n_ubidi_set_para().
+ *          In other words, a context is not "remembered" after the following successful call to
+ *          i18n_ubidi_set_para().
+ *
+ *          If a call to i18n_ubidi_set_para() specifies #I18N_UBIDI_DEFAULT_LTR or
+ *          #I18N_UBIDI_DEFAULT_RTL as para_level and is preceded by a call to
+ *          i18n_ubidi_set_context() which specifies a prologue, the paragraph level will be
+ *          computed taking into consideration the text in the prologue.
+ *
+ *          When i18n_ubidi_set_para() is called without a previous call to i18n_ubidi_set_context(),
+ *          the main text is handled as if preceded and followed by strong directional characters
+ *          at the current paragraph level. Calling i18n_ubidi_set_context() with specification of
+ *          a prologue will change this behavior by handling the main text as if preceded by the
+ *          last strong character appearing in the prologue, if any. Calling
+ *          i18n_ubidi_set_context() with specification of an epilogue will change the behavior of
+ *          i18n_ubidi_set_para() by handling the main text as if followed by the first strong
+ *          character or digit appearing in the epilogue, if any.
+ *
+ *          Note 1: if i18n_ubidi_set_context() is called repeatedly without calling
+ *          i18n_ubidi_set_para(), the earlier calls have no effect, only the last call will be
+ *          remembered for the next call to i18n_ubidi_set_para().
+ *
+ *          Note 2: calling i18n_ubidi_set_context(ubidi, NULL, 0, NULL, 0) cancels any previous
+ *          setting of non-empty prologue or epilogue. The next call to i18n_ubidi_set_para() will
+ *          process no prologue or epilogue.
+ *
+ *          Note 3: users must be aware that even after setting the context before a call to
+ *          i18n_ubidi_set_para() to perform e.g. a logical to visual transformation, the resulting
+ *          string may not be identical to what it would have been if all the text, including
+ *          prologue and epilogue, had been processed together.
+ *          Example (upper case letters represent RTL characters):
+ *
+ *            prologue = <code>"abc DE"</code>\n
+ *            epilogue = none\n
+ *            main text = <code>"FGH xyz"</code>\n
+ *            para_level = I18N_UBIDI_LTR\n
+ *            display without prologue = <code>"HGF xyz"</code> ("HGF" is adjacent to "xyz")\n
+ *            display with prologue = <code>"abc HGFED xyz"</code> ("HGF" is not adjacent to "xyz")\n
+ * @since_tizen 3.0
+ *
+ * @param[in]       ubidi        A paragraph #i18n_ubidi_h object
+ * @param[in]       prologue     Pointer to the text which precedes the text that will be specified
+ *                               in a coming call to i18n_ubidi_set_para(). If there is no prologue
+ *                               to consider, then @a pro_length must be zero and this pointer can be
+ *                               @c NULL.
+ * @param[in]       pro_length   The length of the @a prologue; if @a pro_length == -1 then the prologue
+ *                               must be zero-terminated. Otherwise @a pro_length must be >= 0.
+ *                               If @a pro_length == 0, it means that there is no prologue to consider.
+ * @param[in]       epilogue     A pointer to the text which follows the text that will be specified
+ *                               in a coming call to i18n_ubidi_set_para(). If there is no epilogue
+ *                               to consider, then @a epi_length must be zero and this pointer can be
+ *                               @c NULL.
+ * @param[in]       epi_length   The length of the @a epilogue; if @a epi_length == -1 then the epilogue
+ *                               must be zero-terminated. Otherwise @a epi_length must be >= 0.
+ *                               If @a epi_length == 0, it means that there is no epilogue to consider.
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see i18n_ubidi_set_para()
+ */
+int i18n_ubidi_set_context(i18n_ubidi_h ubidi,
+                           const i18n_uchar *prologue,
+                           int32_t pro_length,
+                           const i18n_uchar *epilogue,
+                           int32_t epi_length);
+
+/**
+ * @brief Modifies the operation of the ubidi algorithm such that it approximates an "inverse ubidi"
+ *          algorithm.
+ * @details This function must be called before i18n_ubidi_set_para().
+ *
+ *          The normal operation of the ubidi algorithm as described in the Unicode Technical Report
+ *          is to take text stored in logical (keyboard, typing) order and to determine the
+ *          reordering of it for visual rendering. Some legacy systems store text in visual order,
+ *          and for operations with standard, Unicode-based algorithms, the text needs to be
+ *          transformed to logical order. This is effectively the inverse algorithm of the
+ *          described ubidi algorithm.
+ *          Note that there is no standard algorithm for this "inverse ubidi" and that the current
+ *          implementation provides only an approximation of "inverse ubidi".
+ *
+ *          With @a is_inverse set to @c true, this function changes the behavior of some of the
+ *          subsequent functions in a way that they can be used for the inverse ubidi algorithm.
+ *          Specifically, runs of text with numeric characters will be treated in a special way and
+ *          may need to be surrounded with LRM characters when they are written in reordered
+ *          sequence.
+ *
+ *          Output runs should be retrieved using i18n_ubidi_get_visual_run(). Since the actual
+ *          input for "inverse ubidi" is visually ordered text and i18n_ubidi_get_visual_run() gets
+ *          the reordered runs, these are actually the runs of the logically ordered output.
+ *          Calling this function with argument @a is_inverse set to @c true is equivalent to calling
+ *          i18n_ubidi_set_reordering_mode() with argument reordering_mode set to
+ *          #I18N_UBIDI_REORDER_INVERSE_NUMBERS_AS_L.
+ *
+ *          Calling this function with argument @a is_inverse set to @c false is equivalent to calling
+ *          i18n_ubidi_set_reordering_mode() with argument reordering_mode set to
+ *          #I18N_UBIDI_REORDER_DEFAULT.
+ * @since_tizen 3.0
+ *
+ * @param[in]      ubidi          An #i18n_ubidi_h object
+ * @param[in]      is_inverse     Specifies "forward" or "inverse" ubidi operation
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see i18n_ubidi_set_para()
+ * @see i18n_ubidi_write_reordered()
+ * @see i18n_ubidi_set_reordering_mode()
+ */
+int i18n_ubidi_set_inverse(i18n_ubidi_h ubidi, i18n_ubool is_inverse);
+
+/**
+ * @brief Sets an #i18n_ubidi_h object to contain the reordering information, especially the resolved levels,
+ *          for all the characters in a line of text.
+ * @details This line of text is specified by referring to an #i18n_ubidi_h object representing this
+ *          information for a piece of text containing one or more paragraphs, and by specifying
+ *          a range of indexes in this text.
+ *
+ *          In the new line object, the indexes will range from 0 to @a limit - @a start - 1.
+ *
+ *          This is used after calling i18n_ubidi_set_para() for a piece of text, and after
+ *          line-breaking on that text. It is not necessary if each paragraph is treated as a
+ *          single line.
+ *
+ *          After line-breaking, rules (L1) and (L2) for the treatment of trailing WS and for
+ *          reordering are performed on an #i18n_ubidi_h object that represents a line.
+ *
+ *          Important: @a line_bidi shares data with @a para_bidi. You must destroy or reuse
+ *          @a line_bidi before @a para_bidi. In other words, you must destroy or reuse the
+ *          #i18n_ubidi_h object for a line before the object for its parent paragraph.
+ *
+ *          The text pointer that was stored in @a para_bidi is also copied, and @a start is added to
+ *          it so that it points to the beginning of the line for this object.
+ * @since_tizen 3.0
+ *
+ * @param[in]       para_bidi         The parent paragraph object. It must have been set by a
+ *                                    successful call to i18n_ubidi_set_para()
+ * @param[in]       start             The line's first index into the text
+ * @param[in]       limit             The index after the last line's index (its last index + 1)
+ * @param[in]       line_bidi         The object that will now represent a line of the text
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see i18n_ubidi_set_para()
+ * @see i18n_ubidi_get_processed_length()
+ */
+int i18n_ubidi_set_line(const i18n_ubidi_h para_bidi, int32_t start, int32_t limit,
+                        i18n_ubidi_h line_bidi);
+
+/**
+ * @brief Performs the Unicode bidi algorithm.
+ * @details It is defined in the Unicode Standard Anned #9, version 13, also described in The
+ *          Unicode Standard, Version 4.0 .
+ *
+ *          This function takes a piece of plain text containing one or more paragraphs, with or
+ *          without externally specified embedding levels from styled text and computes the
+ *          left-right-directionality of each character.
+ *
+ *          If the entire text is all of the same directionality, then the function may not perform
+ *          all the steps described by the algorithm, i.e., some levels may not be the same as if
+ *          all steps were performed. This is not relevant for unidirectional text.
+ *          For example, in pure LTR text with numbers the numbers would get a resolved level of 2
+ *          higher than the surrounding text according to the algorithm. This implementation may
+ *          set all resolved levels to the same value in such a case.
+ *
+ *          The text can be composed of multiple paragraphs. Occurrence of a block separator in
+ *          the text terminates a paragraph, and whatever comes next starts a new paragraph.
+ *          The exception to this rule is when a Carriage Return (CR) is followed by a Line Feed
+ *          (LF). Both CR and LF are block separators, but in that case, the pair of characters is
+ *          considered as terminating the preceding paragraph, and a new paragraph will be started
+ *          by a character coming after the LF.
+ * @since_tizen 3.0
+ *
+ * @param[in]      ubidi            An #i18n_ubidi_h object allocated with i18n_ubidi_create() which
+ *                                  will be set to contain the reordering information, especially
+ *                                  the resolved levels for all the characters in the @a text
+ * @param[in]      text             A pointer to the text that the ubidi algorithm will be performed
+ *                                  on. This pointer is stored in the #i18n_ubidi_h handle and can
+ *                                  be retrieved with i18n_ubidi_get_text().
+ *                                  Note: The @a text must be (at least) @a length long.
+ * @param[in]      length           The length of the @a text; if @a length == -1 then the text must be
+ *                                  zero-terminated
+ * @param[in]      para_level       Specifies the default level for the @a text; it is typically 0
+ *                                  (LTR) or 1 (RTL). If the function shall determine the paragraph
+ *                                  level from the text, then @a para_level can be set to either
+ *                                  #I18N_UBIDI_DEFAULT_LTR or #I18N_UBIDI_DEFAULT_RTL; if the text
+ *                                  contains multiple paragraphs, the paragraph level shall be
+ *                                  determined separately for each paragraph; if a paragraph does
+ *                                  not include any strongly typed character, then the desired
+ *                                  default is used (0 for LTR or 1 for RTL). Any other value
+ *                                  between 0 and #I18N_UBIDI_MAX_EXPLICIT_LEVEL is also valid, with
+ *                                  odd levels indicating RTL.
+ * @param[in]      embedding_levels May be used to preset the embedding and override levels,
+ *                                  ignoring characters like LRE and PDF in the text.
+ *                                  A level overrides the directional property of its corresponding
+ *                                  (same index) character if the level has the
+ *                                  #I18N_UBIDI_LEVEL_OVERRIDE bit set.
+ *                                  Caution: A copy of this pointer, not of the levels, will be stored in the
+ *                                  #i18n_ubidi_h object; the @a embedding_levels array must not be
+ *                                  deallocated before the #i18n_ubidi_h structure is destroyed or reused,
+ *                                  and the @a embedding_levels should not be modified to avoid unexpected
+ *                                  results on subsequent ubidi operations. However, the i18n_ubidi_set_para()
+ *                                  and i18n_ubidi_set_line() functions may modify some or all of the levels.
+ *
+ *                                  After the #i18n_ubidi_h object is reused or destroyed, the caller must
+ *                                  take care of the deallocation of the @a embedding_levels array.
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ */
+int i18n_ubidi_set_para(i18n_ubidi_h ubidi,
+                        const i18n_uchar *text,
+                        int32_t length,
+                        i18n_ubidi_level_t para_level,
+                        i18n_ubidi_level_t *embedding_levels);
+
+/**
+ * @brief Modifies the operation of the ubidi algorithm such that it implements some variant to the
+ *          basic ubidi algorithm or approximates an "inverse ubidi" algorithm, depending on different
+ *          values of the "reordering mode".
+ * @details This function must be called before i18n_ubidi_set_para(), and stays in effect until
+ *          called again with a different argument.
+ *
+ *          The normal operation of the ubidi algorithm as described in the Unicode Standard Annex
+ *          #9 is to take text stored in logical (keyboard, typing) order and to determine how to
+ *          reorder it for visual rendering.
+ *
+ *          With the @a reordering_mode set to a value other than #I18N_UBIDI_REORDER_DEFAULT, this
+ *          function changes the behavior of some of the subsequent functions in a way such that
+ *          they implement an inverse ubidi algorithm or some other algorithm variants.
+ *
+ *          Some legacy systems store text in visual order, and for operations with standard,
+ *          Unicode-based algorithms, the text needs to be transformed into logical order. This is
+ *          effectively the inverse algorithm of the described ubidi algorithm.
+ *          Note that there is no standard algorithm for this "inverse ubidi", so a number of
+ *          variants are implemented here.
+ *
+ *          In other cases, it may be desirable to emulate some variant of the Logical to Visual
+ *          algorithm (e.g. one used in MS Windows), or perform a Logical to Logical transformation.
+ *              - When the @a reordering_mode is set to #I18N_UBIDI_REORDER_DEFAULT, the standard ubidi
+ *              Logical to Visual algorithm is applied.
+ *              - When the @a reordering_mode is set to #I18N_UBIDI_REORDER_NUMBERS_SPECIAL, the
+ *              algorithm used to perform ubidi transformations when calling i18n_ubidi_set_para()
+ *              should approximate the algorithm used in Microsoft Windows XP rather than strictly
+ *              conform to the Unicode bidi algorithm. The differences between the basic algorithm
+ *              and the algorithm addressed by this option are as follows:
+ *                  - Within text at an even embedding level, the sequence "123AB" (where AB
+ *                  represent R or AL letters) is transformed to "123BA" by the Unicode algorithm
+ *                  and to "BA123" by the Windows algorithm.
+ *                  - Arabic-Indic numbers (AN) are handled by the Windows algorithm just like
+ *                  regular numbers (EN).
+ *              - When the @a reordering_mode is set to #I18N_UBIDI_REORDER_GROUP_NUMBERS_WITH_R,
+ *              numbers located between LTR text and RTL text are associated with the RTL text.
+ *              For instance, an LTR paragraph with content "abc 123 DEF" (where upper case letters
+ *              represent RTL characters) will be transformed to "abc FED 123" (and not "abc 123
+ *              FED"), "DEF 123 abc" will be transformed to "123 FED abc" and "123 FED abc"
+ *              will be transformed to "DEF 123 abc". This makes the algorithm reversible and makes
+ *              it useful when round trip (from visual to logical and back to visual) must be
+ *              achieved without adding LRM characters. However, this is a variation from the
+ *              standard Unicode bidi algorithm. The source text should not contain ubidi control
+ *              characters other than LRM or RLM.
+ *              - When the @a reordering_mode is set to #I18N_UBIDI_REORDER_RUNS_ONLY, a "Logical to
+ *              Logical" transformation must be performed:
+ *                  - If the default text level of the source text (argument para_level in
+ *                  i18n_ubidi_set_para() ) is even, the source text will be handled as LTR logical
+ *                  text and will be transformed to the RTL logical text which has the same LTR
+ *                  visual display.
+ *                  - If the default level of the source text is odd, the source text will be
+ *                  handled as RTL logical text and will be transformed to the LTR logical text
+ *                  which has the same LTR visual display.
+ *              This mode may be needed when logical text which is basically Arabic or Hebrew, with
+ *              possible included numbers or phrases in English, has to be displayed as if it had
+ *              an even embedding level (this can happen if the displaying application treats all
+ *              text as if it was basically LTR).
+ *              This mode may also be needed in the reverse case, when logical text which is
+ *              basically English, with possible included phrases in Arabic or Hebrew, has to be
+ *              displayed as if it had an odd embedding level. Both cases could be handled by
+ *              adding LRE or RLE at the head of the text, if the display subsystem supports these
+ *              formatting controls. If it does not, the problem may be handled by transforming
+ *              the source text in this mode before displaying it, so that it will be displayed
+ *              properly.
+ *
+ *              The source text should not contain ubidi control characters other than
+ *              LRM or RLM.
+ *              - When the @a reordering_mode is set to #I18N_UBIDI_REORDER_INVERSE_NUMBERS_AS_L, an
+ *              "inverse ubidi" algorithm is applied. Runs of text with numeric characters will be
+ *              treated like LTR letters and may need to be surrounded with LRM characters when
+ *              they are written in reordered sequence (the option #I18N_UBIDI_INSERT_LRM_FOR_NUMERIC
+ *              can be used with function i18n_ubidi_write_reordered() to this end. This mode is
+ *              equivalent to calling i18n_ubidi_set_inverse() with argument is_inverse set to @c true.
+ *              - When the @a reordering_mode is set to #I18N_UBIDI_REORDER_INVERSE_LIKE_DIRECT, the
+ *              "direct" Logical to Visual Ubidi algorithm is used as an approximation of an
+ *              "inverse ubidi" algorithm. This mode is similar to mode
+ *              #I18N_UBIDI_REORDER_INVERSE_NUMBERS_AS_L but is closer to the regular ubidi algorithm.
+ *              For example, an LTR paragraph with the content "FED 123 456 CBA" (where upper case
+ *              represents RTL characters) will be transformed to "ABC 456 123 DEF", as opposed to
+ *              "DEF 123 456 ABC" with mode #I18N_UBIDI_REORDER_INVERSE_NUMBERS_AS_L.
+ *              When used in conjunction with option #I18N_UBIDI_OPTION_INSERT_MARKS, this mode
+ *              generally adds ubidi marks to the output significantly more sparingly than mode
+ *              #I18N_UBIDI_REORDER_INVERSE_NUMBERS_AS_L with option
+ *              #I18N_UBIDI_INSERT_LRM_FOR_NUMERIC in calls to i18n_ubidi_write_reordered().
+ *              - When the reordering mode is set to #I18N_UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL,
+ *              the Logical to Visual ubidi algorithm used in Windows XP is used as an approximation
+ *              of an "inverse ubidi" algorithm.
+ *              For example, an LTR paragraph with the content "abc FED123" (where upper case
+ *              represents RTL characters) will be transformed to "abc 123DEF."
+ *
+ *          In all the reordering modes specifying an "inverse ubidi" algorithm (i.e. those with
+ *          a name starting with I18N_UBIDI_REORDER_INVERSE), output runs should be retrieved
+ *          using i18n_ubidi_get_visual_run(), and the output text with
+ *          i18n_ubidi_write_reordered(). The caller should keep in mind that in
+ *          "inverse ubidi" modes the input is actually visually ordered text and reordered
+ *          output returned by i18n_ubidi_get_visual_run() or i18n_ubidi_write_reordered() are
+ *          actually runs or character string of logically ordered output.
+ *          For all the "inverse ubidi" modes, the source text should not contain ubidi control
+ *          characters other than LRM or RLM.
+ *
+ *          Note that option #I18N_UBIDI_OUTPUT_REVERSE of i18n_ubidi_write_reordered() has no useful
+ *          meaning and should not be used in conjunction with any value of the @a reordering_mode
+ *          specifying "inverse ubidi" or with value #I18N_UBIDI_REORDER_RUNS_ONLY.
+ * @since_tizen 3.0
+ *
+ * @param[in]         ubidi               An #i18n_ubidi_h object
+ * @param[in]         reordering_mode     Specifies the required variant of the ubidi algorithm
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see i18n_ubidi_reordering_mode_e
+ * @see i18n_ubidi_set_inverse()
+ * @see i18n_ubidi_set_para()
+ * @see i18n_ubidi_write_reordered()
+ */
+int i18n_ubidi_set_reordering_mode(i18n_ubidi_h ubidi,
+                                   i18n_ubidi_reordering_mode_e reordering_mode);
+
+/**
+ * @brief Specifies which of the reordering options should be applied during ubidi transformations.
+ * @since_tizen 3.0
+ *
+ * @param[in]       ubidi                 An #i18n_ubidi_h object
+ * @param[in]       reordering_options    A bitwise 'or' combination of zero or more of:
+ *                                        #I18N_UBIDI_OPTION_DEFAULT, #I18N_UBIDI_OPTION_INSERT_MARKS,
+ *                                        #I18N_UBIDI_OPTION_REMOVE_CONTROLS,
+ *                                        #I18N_UBIDI_OPTION_STREAMING.
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see i18n_ubidi_get_reordering_options()
+ */
+int i18n_ubidi_set_reordering_options(i18n_ubidi_h ubidi, uint32_t reordering_options);
+
+/**
+ * @brief Takes an #i18n_ubidi_h object containing the reordering information for a piece of text (one
+ *        or more paragraphs) set by i18n_ubidi_set_para() or for a line of text set by
+ *        i18n_ubidi_set_line() and write a reordered string to the destination buffer.
+ * @details This function preserves the integrity of characters with multiple code units and
+ *          (optionally) combining characters. Characters in RTL runs can be replaced by
+ *          mirror-image characters in the destination buffer. Note that "real" mirroring has to be
+ *          done in a rendering engine by glyph selection and that for many "mirrored" characters
+ *          there are no Unicode characters as mirror-image equivalents. There are also options to
+ *          insert or remove ubidi control characters; see the description of the @a dest_size and
+ *          @a options parameters and of the option bit flags.
+ * @since_tizen 3.0
+ * @remarks The @a dest array should be provided by the user.
+ *
+ * @param[in]     ubidi           An #i18n_ubidi_h object that is set by
+ *                                i18n_ubidi_set_para() or i18n_ubidi_set_line() and contains
+ *                                the reordering information for the text that it was defined for,
+ *                                as well as a pointer to that text.
+ * @param[in]     options         A bit set of options for the reordering that control how the
+ *                                reordered text is written. The options include mirroring the
+ *                                characters on a code point basis and inserting LRM characters,
+ *                                which is used especially for transforming visually stored text to
+ *                                logically stored text (although this is still an imperfect
+ *                                implementation of an "inverse ubidi" algorithm because it uses the
+ *                                "forward ubidi" algorithm at its core). The available options
+ *                                are: #I18N_UBIDI_DO_MIRRORING, #I18N_UBIDI_INSERT_LRM_FOR_NUMERIC,
+ *                                #I18N_UBIDI_KEEP_BASE_COMBINING, #I18N_UBIDI_OUTPUT_REVERSE,
+ *                                #I18N_UBIDI_REMOVE_BIDI_CONTROLS.
+ * @param[in]     dest_size       The size of the @a dest buffer, in number of i18n_uchars. If the
+ *                                #I18N_UBIDI_INSERT_LRM_FOR_NUMERIC option is set, then the
+ *                                destination length could be as large as
+ *                                i18n_ubidi_get_length(@a ubidi)+2*i18n_ubidi_count_runs(@a ubidi).
+ *                                If the #I18N_UBIDI_REMOVE_BIDI_CONTROLS option is set, then the
+ *                                destination length may be less than i18n_ubidi_get_length(@a ubidi).
+ *                                If none of these options is set, then the destination length
+ *                                will be exactly i18n_ubidi_get_processed_length(@a ubidi).
+ * @param[out]    dest            A pointer to where the reordered text is to be copied. The
+ *                                source text and the destination buffer @a dest must not overlap.
+ * @param[out]    output_length   The length of the output string
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ * @see i18n_ubidi_get_processed_length()
+ */
+int i18n_ubidi_write_reordered(i18n_ubidi_h ubidi,
+                               uint16_t options,
+                               int32_t dest_size,
+                               i18n_uchar *dest,
+                               int32_t *output_length);
+
+/**
+ * @brief Reverses a Right-To-Left run of Unicode text.
+ * @details This function preserves the integrity of characters with multiple code units and
+ *          (optionally) combining characters. Characters can be replaced by mirror-image
+ *          characters in the destination buffer. Note that "real" mirroring has to be done in a
+ *          rendering engine by glyph selection and that for many "mirrored" characters there are
+ *          no Unicode characters as mirror-image equivalents. There are also options to insert
+ *          or remove ubidi control characters.
+ *
+ *          This function is the implementation for reversing RTL runs as part of
+ *          i18n_ubidi_write_reordered(). For detailed descriptions of the parameters, see there.
+ *          Since no ubidi controls are inserted here, the output string length will never exceed
+ *          @a src_length.
+ * @since_tizen 3.0
+ *
+ * @param[in]       src                A pointer to the RTL run text
+ * @param[in]       src_length         The length of the RTL run
+ * @param[in]       options            A bit set of options for the reordering that control how the
+ *                                     reordered text is written. See the options parameter
+ *                                     in i18n_ubidi_write_reordered().
+ * @param[in]       dest_size          The size of the @a dest buffer, in number of i18n_uchars. If the
+ *                                     #I18N_UBIDI_REMOVE_BIDI_CONTROLS option is set, then the
+ *                                     destination length may be less than @a src_length. If this
+ *                                     option is not set, then the destination length will be
+ *                                     exactly @a src_length.
+ * @param[out]      dest               A pointer to where the reordered text is to be copied.
+ *                                     @a src and @a dest arrays (of length @a src_length and @a dest_size,
+ *                                     respectively) must not overlap.
+ * @param[out]      output_length      The length of the output string
+ *
+ * @remarks do not free @a dest with free() function
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #I18N_ERROR_NONE Successful
+ * @retval #I18N_ERROR_INVALID_PARAMETER Invalid function parameter
+ */
+int i18n_ubidi_write_reverse(const i18n_uchar *src,
+                             int32_t src_length,
+                             uint16_t options,
+                             int32_t dest_size,
+                             i18n_uchar *dest,
+                             int32_t *output_length);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif
diff --git a/src/utils_i18n_ubidi.c b/src/utils_i18n_ubidi.c
new file mode 100644 (file)
index 0000000..ff38fa9
--- /dev/null
@@ -0,0 +1,535 @@
+/*
+* Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+*
+*    Licensed under the Apache License, Version 2.0 (the "License");
+*    you may not use this file except in compliance with the License.
+*    You may obtain a copy of the License at
+*
+*        http://www.apache.org/licenses/LICENSE-2.0
+*
+*    Unless required by applicable law or agreed to in writing, software
+*    distributed under the License is distributed on an "AS IS" BASIS,
+*    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*    See the License for the specific language governing permissions and
+*    limitations under the License.
+*/
+
+
+#include <unicode/ubidi.h>
+#include <unicode/uchar.h>
+#include <unicode/ustring.h>
+
+#include <utils_i18n_ubidi.h>
+#include <utils_i18n_private.h>
+#include <malloc.h>
+
+int i18n_ubidi_destroy(i18n_ubidi_h ubidi)
+{
+    retv_if(ubidi == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    ubidi_close(ubidi);
+
+    return I18N_ERROR_NONE;
+}
+
+int i18n_ubidi_count_paragraphs(i18n_ubidi_h ubidi, int32_t *count)
+{
+    retv_if(ubidi == NULL || count == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    *count = ubidi_countParagraphs(ubidi);
+
+    return I18N_ERROR_NONE;
+}
+
+int i18n_ubidi_count_runs(i18n_ubidi_h ubidi, int32_t *count)
+{
+    retv_if(ubidi == NULL || count == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    i18n_error_code_e i18n_error;
+    UErrorCode icu_error = U_ZERO_ERROR;
+    *count = ubidi_countRuns(ubidi, &icu_error);
+    ERR_MAPPING(icu_error, i18n_error);
+    I18N_ERR(i18n_error);
+
+    return i18n_error;
+}
+
+int i18n_ubidi_get_base_direction(const i18n_uchar *text, int32_t length,
+                                  i18n_ubidi_direction_e *direction)
+{
+    retv_if(text == NULL || direction == NULL || length < -1, I18N_ERROR_INVALID_PARAMETER);
+
+    *direction = ubidi_getBaseDirection(text, length);
+
+    return I18N_ERROR_NONE;
+}
+
+int i18n_ubidi_get_class_cb(i18n_ubidi_h ubidi, i18n_ubidi_class_cb *fn, const void **context)
+{
+    retv_if(ubidi == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    enum UCharDirection (*_fn)(const void *, UChar32);
+    ubidi_getClassCallback(ubidi, &_fn, context);
+    if (fn)
+        *fn = (i18n_uchar_direction_e (*)(const void *, i18n_uchar32)) _fn;
+
+    return I18N_ERROR_NONE;
+}
+
+int i18n_ubidi_get_customized_class(i18n_ubidi_h ubidi, i18n_uchar32 c,
+                                    i18n_uchar_direction_e *direction)
+{
+    retv_if(ubidi == NULL || direction == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    *direction = ubidi_getCustomizedClass(ubidi, c);
+
+    return I18N_ERROR_NONE;
+}
+
+int i18n_ubidi_get_direction(const i18n_ubidi_h ubidi, i18n_ubidi_direction_e *direction)
+{
+    retv_if(ubidi == NULL || direction == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    *direction = ubidi_getDirection(ubidi);
+
+    return I18N_ERROR_NONE;
+}
+
+int i18n_ubidi_get_length(const i18n_ubidi_h ubidi, int32_t *length)
+{
+    retv_if(ubidi == NULL || length == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    *length = ubidi_getLength(ubidi);
+
+    return I18N_ERROR_NONE;
+}
+
+int i18n_ubidi_get_level_at(const i18n_ubidi_h ubidi, int32_t char_index, i18n_ubidi_level_t *level)
+{
+    retv_if(ubidi == NULL || level == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    *level = ubidi_getLevelAt(ubidi, char_index);
+
+    return I18N_ERROR_NONE;
+}
+
+int i18n_ubidi_get_levels(i18n_ubidi_h ubidi, const i18n_ubidi_level_t **levels)
+{
+    retv_if(ubidi == NULL || levels == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    i18n_error_code_e i18n_error;
+    UErrorCode icu_error = U_ZERO_ERROR;
+    *levels = ubidi_getLevels(ubidi, &icu_error);
+    ERR_MAPPING(icu_error, i18n_error);
+    I18N_ERR(i18n_error);
+
+    return i18n_error;
+}
+
+int i18n_ubidi_get_logical_index(i18n_ubidi_h ubidi, int32_t visual_index, int32_t *logical_index)
+{
+    retv_if(ubidi == NULL || logical_index == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    i18n_error_code_e i18n_error;
+    UErrorCode icu_error = U_ZERO_ERROR;
+    *logical_index = ubidi_getLogicalIndex(ubidi, visual_index, &icu_error);
+    ERR_MAPPING(icu_error, i18n_error);
+    I18N_ERR(i18n_error);
+
+    return i18n_error;
+}
+
+int i18n_ubidi_get_logical_map(i18n_ubidi_h ubidi, int32_t *index_map)
+{
+    retv_if(ubidi == NULL || index_map == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    i18n_error_code_e i18n_error;
+    UErrorCode icu_error = U_ZERO_ERROR;
+    ubidi_getLogicalMap(ubidi, index_map, &icu_error);
+    ERR_MAPPING(icu_error, i18n_error);
+    I18N_ERR(i18n_error);
+
+    return i18n_error;
+}
+
+int i18n_ubidi_get_logical_run(const i18n_ubidi_h ubidi,
+                         int32_t logical_position,
+                         int32_t *logical_limit,
+                         i18n_ubidi_level_t *level)
+{
+    retv_if(ubidi == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    ubidi_getLogicalRun(ubidi, logical_position, logical_limit, level);
+
+    return I18N_ERROR_NONE;
+}
+
+int i18n_ubidi_get_paragraph(const i18n_ubidi_h ubidi,
+                             int32_t char_index,
+                             int32_t *para_start,
+                             int32_t *para_limit,
+                             i18n_ubidi_level_t *para_level,
+                             int32_t *index)
+{
+    retv_if(ubidi == NULL || index == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    i18n_error_code_e i18n_error;
+    UErrorCode icu_error = U_ZERO_ERROR;
+    *index = ubidi_getParagraph(ubidi, char_index, para_start, para_limit, para_level,
+                                &icu_error);
+    ERR_MAPPING(icu_error, i18n_error);
+    I18N_ERR(i18n_error);
+
+    return i18n_error;
+}
+
+int i18n_ubidi_get_paragraph_by_index(const i18n_ubidi_h ubidi,
+                                      int32_t para_index,
+                                      int32_t *para_start,
+                                      int32_t *para_limit,
+                                      i18n_ubidi_level_t *para_level)
+{
+    retv_if(ubidi == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    i18n_error_code_e i18n_error;
+    UErrorCode icu_error = U_ZERO_ERROR;
+    ubidi_getParagraphByIndex(ubidi, para_index, para_start, para_limit, para_level,
+                              &icu_error);
+    ERR_MAPPING(icu_error, i18n_error);
+    I18N_ERR(i18n_error);
+
+    return i18n_error;
+}
+
+int i18n_ubidi_get_para_level(const i18n_ubidi_h ubidi, i18n_ubidi_level_t *level)
+{
+    retv_if(ubidi == NULL || level == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    *level = ubidi_getParaLevel(ubidi);
+
+    return I18N_ERROR_NONE;
+}
+
+int i18n_ubidi_get_processed_length(const i18n_ubidi_h ubidi, int32_t *length)
+{
+    retv_if(ubidi == NULL || length == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    *length = ubidi_getProcessedLength(ubidi);
+
+    return I18N_ERROR_NONE;
+}
+
+int i18n_ubidi_get_reordering_mode(i18n_ubidi_h ubidi, i18n_ubidi_reordering_mode_e *mode)
+{
+    retv_if(ubidi == NULL || mode == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    *mode = ubidi_getReorderingMode(ubidi);
+
+    return I18N_ERROR_NONE;
+}
+
+int i18n_ubidi_get_reordering_options(i18n_ubidi_h ubidi, uint32_t *options)
+{
+    retv_if(ubidi == NULL || options == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    *options = ubidi_getReorderingOptions(ubidi);
+
+    return I18N_ERROR_NONE;
+}
+
+int i18n_ubidi_get_result_length(const i18n_ubidi_h ubidi, int32_t *length)
+{
+    retv_if(ubidi == NULL || length == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    *length = ubidi_getResultLength(ubidi);
+
+    return I18N_ERROR_NONE;
+}
+
+
+int i18n_ubidi_get_text(const i18n_ubidi_h ubidi, char **text)
+{
+    retv_if(ubidi == NULL || text == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    *text = NULL;
+
+    const UChar *_ubidi_text = ubidi_getText(ubidi);
+    retv_if(_ubidi_text == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    int32_t ulen = u_strlen(_ubidi_text);
+    retv_if(ulen <= 0, I18N_ERROR_INVALID_PARAMETER);
+
+    /*
+     * UTF-16 uses at least two bytes, growing up to four bytes as necessary,
+     * that is why we multiply UChar by 4.
+     */
+    char _text[4*ulen+1];
+    u_austrcpy(_text, _ubidi_text);
+
+    int32_t len = strlen(_text);
+
+    *text = (char *)malloc(len + 1);
+    retv_if(*text == NULL, I18N_ERROR_OUT_OF_MEMORY);
+
+    strcpy(*text, _text);
+
+    return I18N_ERROR_NONE;
+}
+
+int i18n_ubidi_get_visual_index(i18n_ubidi_h ubidi, int32_t logical_index, int32_t *visual_index)
+{
+    retv_if(ubidi == NULL || visual_index == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    i18n_error_code_e i18n_error;
+    UErrorCode icu_error = U_ZERO_ERROR;
+    *visual_index = ubidi_getVisualIndex(ubidi, logical_index, &icu_error);
+    ERR_MAPPING(icu_error, i18n_error);
+    I18N_ERR(i18n_error);
+
+    return i18n_error;
+}
+
+int i18n_ubidi_get_visual_map(i18n_ubidi_h ubidi, int32_t *index_map)
+{
+    retv_if(ubidi == NULL || index_map == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    i18n_error_code_e i18n_error;
+    UErrorCode icu_error = U_ZERO_ERROR;
+    ubidi_getVisualMap(ubidi, index_map, &icu_error);
+    ERR_MAPPING(icu_error, i18n_error);
+    I18N_ERR(i18n_error);
+
+    return i18n_error;
+}
+
+int i18n_ubidi_get_visual_run(i18n_ubidi_h ubidi,
+                              int32_t run_index,
+                              int32_t *logical_index,
+                              int32_t *length,
+                              i18n_ubidi_direction_e *direction)
+{
+    retv_if(ubidi == NULL || direction == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    int32_t count_runs;
+    i18n_error_code_e i18n_error = i18n_ubidi_count_runs(ubidi, &count_runs);
+    if(i18n_error != I18N_ERROR_NONE)
+        return i18n_error;
+
+    retv_if(run_index < 0 || run_index > count_runs-1, I18N_ERROR_INVALID_PARAMETER);
+
+    *direction = ubidi_getVisualRun(ubidi, run_index, logical_index, length);
+
+    return I18N_ERROR_NONE;
+}
+
+int i18n_ubidi_invert_map(const int32_t *scr_map, int32_t length, int32_t *dest_map)
+{
+    retv_if(scr_map == NULL || dest_map == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    ubidi_invertMap(scr_map, dest_map, length);
+
+    return I18N_ERROR_NONE;
+}
+
+int i18n_ubidi_is_inverse(i18n_ubidi_h ubidi, i18n_ubool *is_inverse)
+{
+    retv_if(ubidi == NULL || is_inverse == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    *is_inverse = ubidi_isInverse(ubidi);
+
+    return I18N_ERROR_NONE;
+}
+
+int i18n_ubidi_is_order_paragraphs_ltr(i18n_ubidi_h ubidi, i18n_ubool *is_order)
+{
+    retv_if(ubidi == NULL || is_order == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    *is_order = ubidi_isOrderParagraphsLTR(ubidi);
+
+    return I18N_ERROR_NONE;
+}
+
+int i18n_ubidi_create(i18n_ubidi_h *ubidi)
+{
+    retv_if(ubidi == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    *ubidi = ubidi_open();
+
+    return I18N_ERROR_NONE;
+}
+
+int i18n_ubidi_create_sized(int32_t max_length, int32_t max_run_count, i18n_ubidi_h *ubidi)
+{
+    retv_if(ubidi == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    i18n_error_code_e i18n_error;
+    UErrorCode icu_error = U_ZERO_ERROR;
+    *ubidi = ubidi_openSized(max_length, max_run_count, &icu_error);
+    ERR_MAPPING(icu_error, i18n_error);
+    I18N_ERR(i18n_error);
+
+    return i18n_error;
+}
+
+int i18n_ubidi_order_paragraphs_ltr(i18n_ubidi_h ubidi, i18n_ubool order_paragraphs_ltr)
+{
+    retv_if(ubidi == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    ubidi_orderParagraphsLTR(ubidi, order_paragraphs_ltr);
+
+    return I18N_ERROR_NONE;
+}
+
+int i18n_ubidi_reorder_logical(const i18n_ubidi_level_t *levels, int32_t length, int32_t *index_map)
+{
+    retv_if(levels == NULL || index_map == NULL || length <= 0, I18N_ERROR_INVALID_PARAMETER);
+
+    ubidi_reorderLogical(levels, length, index_map);
+
+    return I18N_ERROR_NONE;
+}
+
+int i18n_ubidi_reorder_visual(const i18n_ubidi_level_t *levels, int32_t length, int32_t *index_map)
+{
+    retv_if(levels == NULL || index_map == NULL || length <= 0, I18N_ERROR_INVALID_PARAMETER);
+
+    ubidi_reorderVisual(levels, length, index_map);
+
+    return I18N_ERROR_NONE;
+}
+
+int i18n_ubidi_set_class_cb(i18n_ubidi_h ubidi,
+                                  i18n_ubidi_class_cb new_fn,
+                                  const void *new_context,
+                                  i18n_ubidi_class_cb *old_fn,
+                                  const void **old_context)
+{
+    retv_if(ubidi == NULL || new_fn == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    enum UCharDirection (*_old_fn)(const void *, UChar32);
+    const void *_old_context;
+    i18n_error_code_e i18n_error;
+    UErrorCode icu_error = U_ZERO_ERROR;
+    ubidi_setClassCallback(ubidi, (enum UCharDirection (*)(const void*, UChar32)) new_fn, new_context,
+                           &_old_fn, &_old_context, &icu_error);
+    if (old_fn)
+        *old_fn = (i18n_uchar_direction_e (*)(const void *, i18n_uchar32)) _old_fn;
+    if (old_context)
+       *old_context = _old_context;
+    ERR_MAPPING(icu_error, i18n_error);
+    I18N_ERR(i18n_error);
+
+    return i18n_error;
+}
+
+int i18n_ubidi_set_context(i18n_ubidi_h ubidi,
+                           const i18n_uchar *prologue,
+                           int32_t pro_length,
+                           const i18n_uchar *epilogue,
+                           int32_t epi_length)
+{
+    retv_if(ubidi == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    i18n_error_code_e i18n_error;
+    UErrorCode icu_error = U_ZERO_ERROR;
+    ubidi_setContext(ubidi, prologue, pro_length, epilogue, epi_length, &icu_error);
+    ERR_MAPPING(icu_error, i18n_error);
+    I18N_ERR(i18n_error);
+
+    return i18n_error;
+}
+
+int i18n_ubidi_set_inverse(i18n_ubidi_h ubidi, i18n_ubool is_inverse)
+{
+    retv_if(ubidi == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    ubidi_setInverse(ubidi, is_inverse);
+
+    return I18N_ERROR_NONE;
+}
+
+int i18n_ubidi_set_line(const i18n_ubidi_h para_bidi,
+                        int32_t start,
+                        int32_t limit,
+                        i18n_ubidi_h line_bidi)
+{
+    retv_if(para_bidi == NULL || line_bidi == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    i18n_error_code_e i18n_error;
+    UErrorCode icu_error = U_ZERO_ERROR;
+    ubidi_setLine(para_bidi, start, limit, line_bidi, &icu_error);
+    ERR_MAPPING(icu_error, i18n_error);
+    I18N_ERR(i18n_error);
+
+    return i18n_error;
+}
+
+int i18n_ubidi_set_para(i18n_ubidi_h ubidi,
+                        const i18n_uchar *text,
+                        int32_t length,
+                        i18n_ubidi_level_t para_level,
+                        i18n_ubidi_level_t *embedding_levels)
+{
+    retv_if(ubidi == NULL || text == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    i18n_error_code_e i18n_error;
+    UErrorCode icu_error = U_ZERO_ERROR;
+    ubidi_setPara(ubidi, text, length, para_level, embedding_levels, &icu_error);
+    ERR_MAPPING(icu_error, i18n_error);
+    I18N_ERR(i18n_error);
+
+    return i18n_error;
+}
+
+int i18n_ubidi_set_reordering_mode(i18n_ubidi_h ubidi, i18n_ubidi_reordering_mode_e reordering_mode)
+{
+    retv_if(ubidi == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    ubidi_setReorderingMode(ubidi, reordering_mode);
+
+    return I18N_ERROR_NONE;
+}
+
+int i18n_ubidi_set_reordering_options(i18n_ubidi_h ubidi, uint32_t reordering_options)
+{
+    retv_if(ubidi == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    ubidi_setReorderingOptions(ubidi, reordering_options);
+
+    return I18N_ERROR_NONE;
+}
+
+int i18n_ubidi_write_reordered(i18n_ubidi_h ubidi,
+                               uint16_t options,
+                               int32_t dest_size,
+                               i18n_uchar *dest,
+                               int32_t *output_length)
+{
+    retv_if(ubidi == NULL || dest == NULL || output_length == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    i18n_error_code_e i18n_error;
+    UErrorCode icu_error = U_ZERO_ERROR;
+    *output_length = ubidi_writeReordered(ubidi, dest, dest_size, options, &icu_error);
+    ERR_MAPPING(icu_error, i18n_error);
+    I18N_ERR(i18n_error);
+
+    return i18n_error;
+}
+
+int i18n_ubidi_write_reverse(const i18n_uchar *src,
+                             int32_t src_length,
+                             uint16_t options,
+                             int32_t dest_size,
+                             i18n_uchar *dest,
+                             int32_t *output_length)
+{
+    retv_if(src == NULL || dest == NULL || output_length == NULL, I18N_ERROR_INVALID_PARAMETER);
+
+    i18n_error_code_e i18n_error;
+    UErrorCode icu_error = U_ZERO_ERROR;
+    *output_length = ubidi_writeReverse(src, src_length, dest, dest_size, options, &icu_error);
+    ERR_MAPPING(icu_error, i18n_error);
+    I18N_ERR(i18n_error);
+
+    return i18n_error;
+}