summaryrefslogtreecommitdiffstats
path: root/unicode/courier-unicode.h.in
diff options
context:
space:
mode:
Diffstat (limited to 'unicode/courier-unicode.h.in')
-rw-r--r--unicode/courier-unicode.h.in498
1 files changed, 418 insertions, 80 deletions
diff --git a/unicode/courier-unicode.h.in b/unicode/courier-unicode.h.in
index 085f085..cc9dbbb 100644
--- a/unicode/courier-unicode.h.in
+++ b/unicode/courier-unicode.h.in
@@ -2,7 +2,7 @@
#define courier_unicode_h
/*
-** Copyright 2000-2018 Double Precision, Inc.
+** Copyright 2000-2020 Double Precision, Inc.
** See COPYING for distribution information.
**
*/
@@ -12,6 +12,7 @@
#include <string>
#include <vector>
#include <list>
+#include <functional>
extern "C" {
#endif
@@ -40,7 +41,7 @@ typedef uint32_t char32_t;
#endif
#endif
-#define COURIER_UNICODE_VERSION 210
+#define COURIER_UNICODE_VERSION 220
/*
** The system default character set, from the locale.
@@ -75,6 +76,24 @@ extern char32_t unicode_tc(char32_t);
char32_t unicode_html40ent_lookup(const char *n);
/*
+** East Asian Width lookup.
+**
+** unicode_eastasia looks up the EastAsianWidth property for the given
+** Unicode character.
+*/
+
+#define UNICODE_EASTASIA_A 'A' /* Ambiguous */
+#define UNICODE_EASTASIA_F 'F' /* Full width */
+#define UNICODE_EASTASIA_H 'H' /* Half width */
+#define UNICODE_EASTASIA_N '/' /* Unassigned */
+#define UNICODE_EASTASIA_Na 'N' /* Narrow */
+#define UNICODE_EASTASIA_W 'W' /* Wide */
+
+typedef char unicode_eastasia_t;
+
+unicode_eastasia_t unicode_eastasia(char32_t);
+
+/*
**
** Return "width" of unicode character.
**
@@ -181,15 +200,66 @@ extern int unicode_islower(char32_t ch);
extern int unicode_isupper(char32_t ch);
/*
+** Implementation of Unicode emoji classification, as per
+** http://www.unicode.org/reports/tr51/tr51-18.html
+**
+** Given a char32_t, returns the character's emoji value, which is a bitmask:
+**
+*/
+
+#define UNICODE_EMOJI_NONE 0
+#define UNICODE_EMOJI 1
+#define UNICODE_EMOJI_PRESENTATION 2
+#define UNICODE_EMOJI_MODIFIER 4
+#define UNICODE_EMOJI_MODIFIER_BASE 8
+#define UNICODE_EMOJI_COMPONENT 16
+#define UNICODE_EMOJI_EXTENDED_PICTOGRAPHIC 32
+
+typedef unsigned char unicode_emoji_t;
+
+extern unicode_emoji_t unicode_emoji_lookup(char32_t);
+
+/* Look up just one of the properties, returns non-0 if the char has it */
+
+extern int unicode_emoji(char32_t);
+extern int unicode_emoji_presentation(char32_t);
+extern int unicode_emoji_modifier(char32_t);
+extern int unicode_emoji_modifier_base(char32_t);
+extern int unicode_emoji_component(char32_t);
+extern int unicode_emoji_extended_pictographic(char32_t);
+
+/*
** Implementation of grapheme cluster boundary rules, as per
-** http://www.unicode.org/reports/tr29/tr29-27.html
+** http://www.unicode.org/reports/tr29/tr29-37.html
** including GB9a and GB9b.
**
-** Returns non-zero if there's a grapheme break between the two referenced
-** characters.
+** unicode_grapheme_break_init() allocates an opaque
+** unicode_grapheme_break_info_t handle, and
+** unicode_grapheme_break_destroy() destroys it.
+**
+** Passing the handle to unicode_grapheme_break_next() returns non-0 if
+** there's a grapheme break before the given character (and after the
+** character that got passed in the previous call).
+**
+** The first call to unicode_grapheme_break_next() returns 1, as per GB1.
+**
+** unicode_grapheme_break() is a simplified interface that returns non-0
+** if there is a grapheme break between the two characters. This simplified
+** interface is equivalent to calling unicode_grapheme_break_init(),
+** followed by two calls to unicode_grapheme_break_next(), and finally
+** unicode_grapheme_break_deinit(), and returns the result of the second
+** call to unicode_grapheme_break_next().
*/
-int unicode_grapheme_break(char32_t a, char32_t b);
+struct unicode_grapheme_break_info_s;
+
+typedef struct unicode_grapheme_break_info_s *unicode_grapheme_break_info_t;
+
+extern unicode_grapheme_break_info_t unicode_grapheme_break_init();
+extern int unicode_grapheme_break_next(unicode_grapheme_break_info_t, char32_t);
+extern void unicode_grapheme_break_deinit(unicode_grapheme_break_info_t);
+
+extern int unicode_grapheme_break(char32_t a, char32_t b);
typedef enum {
@@ -199,14 +269,14 @@ typedef enum {
/*
** Look up the unicode script property, as per
-** http://www.unicode.org/reports/tr24/tr24-24.html
+** http://www.unicode.org/reports/tr24/tr24-31.html
*/
unicode_script_t unicode_script(char32_t a);
/*
** Implementation of line break rules, as per
-** http://www.unicode.org/reports/tr14/tr14-35.html
+** http://www.unicode.org/reports/tr14/tr14-45.html
**
** Invoke unicode_lb_init() to initialize the linebreaking algorithm. The
** first parameter is a callback function that gets invoked with two
@@ -365,7 +435,7 @@ extern void unicode_lbc_set_opts(unicode_lbc_info_t i, int opts);
/*
** Implemention of word break rules, as per
-** http://www.unicode.org/reports/tr29/tr29-27.html
+** http://www.unicode.org/reports/tr29/tr29-37.html
**
** Invoke unicode_wb_init() to initialize the wordbreaking algorithm. The
** first parameter is a callback function that gets invoked with two
@@ -466,6 +536,154 @@ int unicode_wbscan_next(unicode_wbscan_info_t i, char32_t ch);
size_t unicode_wbscan_end(unicode_wbscan_info_t i);
+/* Unicode directional markers */
+
+#define UNICODE_LRM 0x200E /* Left-to-right marker */
+#define UNICODE_RLM 0x200F /* Right-to-left marker */
+#define UNICODE_ALM 0x061C /* Right-to-left Arabic marker */
+#define UNICODE_LRI 0x2066 /* Left-to-right isolate */
+#define UNICODE_RLI 0x2067 /* Right-to-left isolate */
+#define UNICODE_PDI 0x2069 /* Pop isolate */
+#define UNICODE_RLO 0x202e /* Right-to-left override */
+#define UNICODE_LRO 0x202d /* Left-to-right override */
+#define UNICODE_PDF 0x202c /* Pop directional override */
+
+
+typedef char unicode_bidi_bracket_type_t;
+
+#define UNICODE_BIDI_n 'n'
+#define UNICODE_BIDI_o 'o'
+#define UNICODE_BIDI_c 'c'
+
+extern char32_t unicode_bidi_mirror(char32_t c);
+
+extern char32_t unicode_bidi_bracket_type(char32_t c,
+ unicode_bidi_bracket_type_t *ret);
+
+
+typedef unsigned char unicode_bidi_level_t;
+
+#define UNICODE_BIDI_LR ((unicode_bidi_level_t)0)
+#define UNICODE_BIDI_RL ((unicode_bidi_level_t)1)
+#define UNICODE_BIDI_SKIP ((unicode_bidi_level_t)254)
+
+extern unicode_bidi_level_t unicode_bidi_calc(const char32_t *p, size_t n,
+ unicode_bidi_level_t *bufp,
+ const unicode_bidi_level_t *
+ initial_embedding_level);
+
+extern void unicode_bidi_reorder(char32_t *p,
+ unicode_bidi_level_t *levels,
+ size_t n,
+ void (*reorder_callback)(size_t, size_t,
+ void *),
+ void *arg);
+
+/* BIDI_TYPE_LIST */
+typedef enum {
+ UNICODE_BIDI_TYPE_AL,
+ UNICODE_BIDI_TYPE_AN,
+ UNICODE_BIDI_TYPE_B,
+ UNICODE_BIDI_TYPE_BN,
+ UNICODE_BIDI_TYPE_CS,
+ UNICODE_BIDI_TYPE_EN,
+ UNICODE_BIDI_TYPE_ES,
+ UNICODE_BIDI_TYPE_ET,
+ UNICODE_BIDI_TYPE_FSI,
+ UNICODE_BIDI_TYPE_L,
+ UNICODE_BIDI_TYPE_LRE,
+ UNICODE_BIDI_TYPE_LRI,
+ UNICODE_BIDI_TYPE_LRO,
+ UNICODE_BIDI_TYPE_NSM,
+ UNICODE_BIDI_TYPE_ON,
+ UNICODE_BIDI_TYPE_PDF,
+ UNICODE_BIDI_TYPE_PDI,
+ UNICODE_BIDI_TYPE_R,
+ UNICODE_BIDI_TYPE_RLE,
+ UNICODE_BIDI_TYPE_RLI,
+ UNICODE_BIDI_TYPE_RLO,
+ UNICODE_BIDI_TYPE_S,
+ UNICODE_BIDI_TYPE_WS,
+} enum_bidi_type_t;
+
+extern enum_bidi_type_t unicode_bidi_type(char32_t c);
+
+extern size_t unicode_bidi_cleanup(char32_t *string,
+ unicode_bidi_level_t *levels,
+ size_t n,
+ void (*removed_callback)(size_t, void *),
+ void *);
+
+extern size_t unicode_bidi_extra_cleanup(char32_t *string,
+ unicode_bidi_level_t *levels,
+ size_t n,
+ void (*removed_callback)(size_t,
+ void *),
+ void *);
+
+extern void unicode_bidi_logical_order(char32_t *string,
+ unicode_bidi_level_t *levels,
+ size_t n,
+ unicode_bidi_level_t paragraph_embedding,
+ void (*reorder_callback)(size_t, size_t,
+ void *),
+ void *arg);
+
+extern void unicode_bidi_embed(const char32_t *string,
+ const unicode_bidi_level_t *levels,
+ size_t n,
+ unicode_bidi_level_t paragraph_embedding,
+ void (*emit)(const char32_t *string,
+ size_t n,
+ void *arg),
+ void *arg);
+
+extern char32_t unicode_bidi_embed_paragraph_level(const char32_t *str,
+ size_t n,
+ unicode_bidi_level_t);
+
+/*
+** unicode_canonical() returns the canonical mapping of the given Unicode
+** character. The returned structure specifies:
+**
+** - A pointer to the canonical decomposition of the given character.
+** - Number of characters in the canonical decomposition.
+** - An optional formatting tag.
+**
+** A null pointer, and a 0 character count gets returned for characters
+** without a canonical decomposition.
+**
+*/
+
+typedef enum {
+ UNICODE_CANONICAL_FMT_NONE=0,
+
+ UNICODE_CANONICAL_FMT_CIRCLE,
+ UNICODE_CANONICAL_FMT_COMPAT,
+ UNICODE_CANONICAL_FMT_FINAL,
+ UNICODE_CANONICAL_FMT_FONT,
+ UNICODE_CANONICAL_FMT_FRACTION,
+ UNICODE_CANONICAL_FMT_INITIAL,
+ UNICODE_CANONICAL_FMT_ISOLATED,
+ UNICODE_CANONICAL_FMT_MEDIAL,
+ UNICODE_CANONICAL_FMT_NARROW,
+ UNICODE_CANONICAL_FMT_NOBREAK,
+ UNICODE_CANONICAL_FMT_SMALL,
+ UNICODE_CANONICAL_FMT_SQUARE,
+ UNICODE_CANONICAL_FMT_SUB,
+ UNICODE_CANONICAL_FMT_SUPER,
+ UNICODE_CANONICAL_FMT_VERTICAL,
+ UNICODE_CANONICAL_FMT_WIDE,
+} unicode_canonical_fmt_t;
+
+typedef struct {
+ const char32_t *canonical_chars;
+ size_t n_canonical_chars;
+ unicode_canonical_fmt_t format;
+} unicode_canonical_t;
+
+extern unicode_canonical_t unicode_canonical(char32_t);
+
/*
** A buffer that holds unicode characters, and dynamically grows as needed.
*/
@@ -1407,11 +1625,11 @@ class linebreak_callback_base {
int opts;
#if __cplusplus >= 201103L
- public:
+public:
linebreak_callback_base(const linebreak_callback_base &)=delete;
linebreak_callback_base &operator=(const
linebreak_callback_base &)=delete;
- private:
+private:
#else
linebreak_callback_base(const linebreak_callback_base &);
/* NOT IMPLEMENTED */
@@ -1420,7 +1638,7 @@ class linebreak_callback_base {
linebreak_callback_base &);
/* NOT IMPLEMENTED */
#endif
- public:
+public:
linebreak_callback_base();
virtual ~linebreak_callback_base();
@@ -1433,8 +1651,8 @@ class linebreak_callback_base {
linebreak_callback_base &operator<<(char32_t uc);
template<typename iter_type>
- linebreak_callback_base &operator()(iter_type beg_iter,
- iter_type end_iter)
+ linebreak_callback_base &operator()(iter_type beg_iter,
+ iter_type end_iter)
{
while (beg_iter != end_iter)
operator<<(*beg_iter++);
@@ -1442,17 +1660,17 @@ class linebreak_callback_base {
}
template<typename container_type>
- linebreak_callback_base &operator()(const container_type &vec)
+ linebreak_callback_base &operator()(const container_type &vec)
{
return operator()(vec.begin(), vec.end());
}
- private:
+private:
virtual int callback(int);
};
class linebreak_callback_save_buf : public linebreak_callback_base {
- public:
+public:
std::list<int> lb_buf;
linebreak_callback_save_buf();
@@ -1460,7 +1678,7 @@ class linebreak_callback_save_buf : public linebreak_callback_base {
using linebreak_callback_base::operator<<;
using linebreak_callback_base::operator();
- private:
+private:
int callback(int value);
};
@@ -1470,7 +1688,7 @@ class linebreak_callback_save_buf : public linebreak_callback_base {
*/
template<typename input_t> class linebreak_iter
-: public std::iterator<std::input_iterator_tag, int, void>
+ : public std::iterator<std::input_iterator_tag, int, void>
{
mutable input_t iter_value, end_iter_value;
@@ -1500,16 +1718,16 @@ template<typename input_t> class linebreak_iter
mutable value_type bufvalue;
- public:
- linebreak_iter(const input_t &iter_valueArg,
- const input_t &iter_endvalueArg)
- : iter_value(iter_valueArg),
- end_iter_value(iter_endvalueArg),
- buf(new linebreak_callback_save_buf)
- {
- }
+public:
+ linebreak_iter(const input_t &iter_valueArg,
+ const input_t &iter_endvalueArg)
+ : iter_value(iter_valueArg),
+ end_iter_value(iter_endvalueArg),
+ buf(new linebreak_callback_save_buf)
+ {
+ }
- linebreak_iter() : buf(NULL)
+ linebreak_iter() : buf(NULL)
{
}
@@ -1525,23 +1743,23 @@ template<typename input_t> class linebreak_iter
delete buf;
}
- linebreak_iter(const linebreak_iter<input_t> &v)
- : buf(NULL)
+ linebreak_iter(const linebreak_iter<input_t> &v)
+ : buf(NULL)
{
operator=(v);
}
linebreak_iter<input_t> &operator=(const
linebreak_iter<input_t> &v)
- {
- if (buf)
- delete buf;
- buf=v.buf;
- iter_value=v.iter_value;
- end_iter_value=v.end_iter_value;
- v.buf=NULL;
- return *this;
- }
+ {
+ if (buf)
+ delete buf;
+ buf=v.buf;
+ iter_value=v.iter_value;
+ end_iter_value=v.end_iter_value;
+ v.buf=NULL;
+ return *this;
+ }
bool operator==(const linebreak_iter<input_t> &v) const
{
@@ -1591,14 +1809,14 @@ class linebreakc_callback_base {
int opts;
#if __cplusplus >= 201103L
- public:
+public:
linebreakc_callback_base(const linebreakc_callback_base &)
- =delete;
+ =delete;
linebreakc_callback_base &operator=(const
linebreakc_callback_base
&)=delete;
- private:
+private:
#else
linebreakc_callback_base(const linebreakc_callback_base &);
/* NOT IMPLEMENTED */
@@ -1609,7 +1827,7 @@ class linebreakc_callback_base {
/* NOT IMPLEMENTED */
#endif
- public:
+public:
linebreakc_callback_base();
virtual ~linebreakc_callback_base();
@@ -1622,8 +1840,8 @@ class linebreakc_callback_base {
linebreakc_callback_base &operator<<(char32_t uc);
template<typename iter_type>
- linebreakc_callback_base &operator()(iter_type beg_iter,
- iter_type end_iter)
+ linebreakc_callback_base &operator()(iter_type beg_iter,
+ iter_type end_iter)
{
while (beg_iter != end_iter)
operator<<(*beg_iter++);
@@ -1636,13 +1854,13 @@ class linebreakc_callback_base {
{
return operator()(vec.begin(), vec.end());
}
- private:
+private:
virtual int callback(int, char32_t);
};
class linebreakc_callback_save_buf : public linebreakc_callback_base {
- public:
+public:
std::list<std::pair<int, char32_t> > lb_buf;
linebreakc_callback_save_buf();
@@ -1650,7 +1868,7 @@ class linebreakc_callback_save_buf : public linebreakc_callback_base {
using linebreakc_callback_base::operator<<;
using linebreakc_callback_base::operator();
- private:
+private:
int callback(int, char32_t);
};
@@ -1663,8 +1881,8 @@ class linebreakc_callback_save_buf : public linebreakc_callback_base {
*/
template<typename input_t> class linebreakc_iter
-: public std::iterator<std::input_iterator_tag,
- std::pair<int, char32_t>, void>
+ : public std::iterator<std::input_iterator_tag,
+ std::pair<int, char32_t>, void>
{
mutable input_t iter_value, end_iter_value;
@@ -1695,16 +1913,16 @@ template<typename input_t> class linebreakc_iter
mutable value_type bufvalue;
- public:
- linebreakc_iter(const input_t &iter_valueArg,
- const input_t &iter_endvalueArg)
- : iter_value(iter_valueArg),
- end_iter_value(iter_endvalueArg),
- buf(new linebreakc_callback_save_buf)
- {
- }
+public:
+ linebreakc_iter(const input_t &iter_valueArg,
+ const input_t &iter_endvalueArg)
+ : iter_value(iter_valueArg),
+ end_iter_value(iter_endvalueArg),
+ buf(new linebreakc_callback_save_buf)
+ {
+ }
- linebreakc_iter() : buf(NULL)
+ linebreakc_iter() : buf(NULL)
{
}
@@ -1714,23 +1932,23 @@ template<typename input_t> class linebreakc_iter
delete buf;
}
- linebreakc_iter(const linebreakc_iter<input_t> &v)
- : buf(NULL)
+ linebreakc_iter(const linebreakc_iter<input_t> &v)
+ : buf(NULL)
{
operator=(v);
}
linebreakc_iter<input_t> &operator=(const
linebreakc_iter<input_t> &v)
- {
- if (buf)
- delete buf;
- buf=v.buf;
- iter_value=v.iter_value;
- end_iter_value=v.end_iter_value;
- v.buf=NULL;
- return *this;
- }
+ {
+ if (buf)
+ delete buf;
+ buf=v.buf;
+ iter_value=v.iter_value;
+ end_iter_value=v.end_iter_value;
+ v.buf=NULL;
+ return *this;
+ }
bool operator==(const linebreakc_iter<input_t> &v) const
{
@@ -1786,13 +2004,13 @@ class wordbreak_callback_base {
unicode_wb_info_t handle;
#if __cplusplus >= 201103L
- public:
+public:
wordbreak_callback_base(const wordbreak_callback_base &)=delete;
wordbreak_callback_base &operator=(const
wordbreak_callback_base &)
- =delete;
- private:
+ =delete;
+private:
#else
wordbreak_callback_base(const wordbreak_callback_base &);
/* NOT IMPLEMENTED */
@@ -1801,7 +2019,7 @@ class wordbreak_callback_base {
wordbreak_callback_base &);
/* NOT IMPLEMENTED */
#endif
- public:
+public:
wordbreak_callback_base();
virtual ~wordbreak_callback_base();
@@ -1812,8 +2030,8 @@ class wordbreak_callback_base {
wordbreak_callback_base &operator<<(char32_t uc);
template<typename iter_type>
- wordbreak_callback_base &operator()(iter_type beg_iter,
- iter_type end_iter)
+ wordbreak_callback_base &operator()(iter_type beg_iter,
+ iter_type end_iter)
{
while (beg_iter != end_iter)
operator<<(*beg_iter++);
@@ -1826,7 +2044,7 @@ class wordbreak_callback_base {
{
return operator()(vec.begin(), vec.end());
}
- private:
+private:
virtual int callback(bool);
};
@@ -1839,10 +2057,10 @@ class wordbreakscan {
unicode_wbscan_info_t handle;
#if __cplusplus >= 201103L
- public:
+public:
wordbreakscan(const wordbreakscan &)=delete;
wordbreakscan &operator=(const wordbreakscan &)=delete;
- private:
+private:
#else
wordbreakscan(const wordbreakscan &);
/* NOT IMPLEMENTED */
@@ -1850,7 +2068,7 @@ class wordbreakscan {
wordbreakscan &operator=(const wordbreakscan &);
/* NOT IMPLEMENTED */
#endif
- public:
+public:
wordbreakscan();
~wordbreakscan();
@@ -1886,6 +2104,126 @@ std::u32string tolower(const std::u32string &u);
std::u32string toupper(const std::u32string &u);
+//! Calculate bidirectional embedding levels
+
+//! Returns the bidirectional embedding levels, and the paragraph
+//! embedding level.
+
+std::tuple<std::vector<unicode_bidi_level_t>,
+ unicode_bidi_level_t> bidi_calc(const std::u32string &s);
+
+//! Calculate bidirectional embedding levels
+
+//! Overload calculates the embedding levels using a predetermined
+//! paragraph embedding level.
+//!
+//! Returns the bidirectional embedding levels, and the same paragraph
+//! embedding level.
+
+std::tuple<std::vector<unicode_bidi_level_t>,
+ unicode_bidi_level_t> bidi_calc(const std::u32string &s,
+ unicode_bidi_level_t level);
+
+//! Reorder bidirectional text
+
+//! Reorders the string and levels in place.
+//!
+//! Non-0 return value indicates the string and levels' sizes do not match.
+
+int bidi_reorder(std::u32string &string,
+ std::vector<unicode_bidi_level_t> &levels,
+ const std::function<void (size_t, size_t)>
+ &reorder_callback=[](size_t, size_t){});
+
+//! Dry-run reorder bidirectional text
+void bidi_reorder(std::vector<unicode_bidi_level_t> &levels,
+ const std::function<void (size_t, size_t)>
+ &reorder_callback=[](size_t, size_t){});
+
+//! Remove directional markers
+
+//! Removes them from the string, in place. Optional lambda gets notified
+//! of the index (in the original string, of each removed marker.
+
+void bidi_cleanup(std::u32string &string,
+ const std::function<void (size_t)> &removed_callback=
+ [](size_t) {});
+
+//! Also remove them from the embedding direction level buffer.
+
+//! Returns non-0 in case of non-matching level buffer size.
+
+int bidi_cleanup(std::u32string &string,
+ std::vector<unicode_bidi_level_t> &levels,
+ const std::function<void (size_t)> &removed_callback=
+ [](size_t) {});
+
+
+//! Remove directional markers and isolation markers.
+
+//! Removes them from the string, in place. Optional lambda gets notified
+//! of the index (in the original string, of each removed marker.
+
+void bidi_extra_cleanup(std::u32string &string,
+ const std::function<void (size_t)>
+ &removed_callback=
+ [](size_t) {});
+
+//! Also remove them from the embedding direction level buffer.
+
+//! Returns non-0 in case of non-matching level buffer size.
+
+int bidi_extra_cleanup(std::u32string &string,
+ std::vector<unicode_bidi_level_t> &levels,
+ const std::function<void (size_t)>
+ &removed_callback=
+ [](size_t) {});
+
+//! Convert Unicode string from canonical rendering order to logical order.
+int bidi_logical_order(std::u32string &string,
+ std::vector<unicode_bidi_level_t> &levels,
+ unicode_bidi_level_t paragraph_embedding,
+ const std::function<void (size_t, size_t)>
+ &lambda=[](size_t,size_t){});
+
+//! Convert Unicode string from canonical rendering order to logical order.
+void bidi_logical_order(std::vector<unicode_bidi_level_t> &levels,
+ unicode_bidi_level_t paragraph_embedding,
+ const std::function<void (size_t, size_t)>
+ &lambda);
+
+//! Embed directional and isolation markers
+
+//! Non-0 return value indicates the string and levels' sizes do not match.
+//!
+//! The lambda gets called repeatedly, to specify the contents of the
+//! string with embedded direction markers.
+
+int bidi_embed(const std::u32string &string,
+ const std::vector<unicode_bidi_level_t> &levels,
+ unicode_bidi_level_t paragraph_embedding,
+ const std::function<void (const char32_t *string,
+ size_t n)> &lambda);
+
+//! Embed directional and isolation markers
+
+//! \overload
+//!
+//! Provides a lambda that collects the new string, and returns it. An
+//! empty string gets returned if the string and levels' sizes do not match.
+
+std::u32string bidi_embed(const std::u32string &string,
+ const std::vector<unicode_bidi_level_t> &levels,
+ unicode_bidi_level_t paragraph_embedding);
+
+//! Check if a directional marker needs to be inserted
+
+//! In order for the unicode string to have the specified default
+//! paragraph embedding level.
+
+extern char32_t bidi_embed_paragraph_level(const std::u32string &string,
+ unicode_bidi_level_t level);
+
#if 0
{
#endif