From da7c2175ddf25544f1fd184d5f01ece8985307b6 Mon Sep 17 00:00:00 2001 From: Vincent Wei Date: Tue, 12 Mar 2019 12:29:13 +0800 Subject: [PATCH] cleanup --- include/gdi.h | 125 ++- src/font/Makefile.am | 2 +- src/font/charset-unicode.c | 1576 ++++++++++++++++++++++++++++++ src/font/charset.c | 1540 +---------------------------- src/font/unicode-joining-types.c | 4 +- src/font/unicode-joining.c | 4 +- src/font/unicode-shape-arabic.c | 6 +- src/font/unicode-shape.c | 12 +- 8 files changed, 1680 insertions(+), 1589 deletions(-) create mode 100644 src/font/charset-unicode.c diff --git a/include/gdi.h b/include/gdi.h index c15f452d..ad4247e7 100644 --- a/include/gdi.h +++ b/include/gdi.h @@ -7853,25 +7853,29 @@ MG_EXPORT UCharBreakType GUIAPI UCharGetBreakType(Uchar32 uc); * \return The bidi type. * * \sa UStrGetBidiTypes, bidi_types + * + * Since: 3.4.0 */ MG_EXPORT BidiType GUIAPI UCharGetBidiType(Uchar32 uc); /** * \fn void GUIAPI UStrGetBidiTypes(const Uchar32* ucs, int nr_ucs, - * BidiType* bds); + * BidiType* bdts); * \brief Get bidi types for an string of Unicode characters. * * This function finds the bidi types of an string of Unicode characters. * * \param ucs The pointer to the Uchar32 string. * \param nr_ucs The number of Unicode characters in the string. - * \param bds The pointer to a buffer which will be used to store + * \param bdts The pointer to a buffer which will be used to store * the bidi types of the characters in \a ucs. * * \sa UCharGetBidiType + * + * Since: 3.4.0 */ MG_EXPORT void GUIAPI UStrGetBidiTypes(const Uchar32* ucs, int nr_ucs, - BidiType* bds); + BidiType* bdts); /* \fn BidiBracketType GUIAPI UCharGetBracketType(Uchar32 ch) * \brief Get bracketed character @@ -7888,21 +7892,24 @@ MG_EXPORT void GUIAPI UStrGetBidiTypes(const Uchar32* ucs, int nr_ucs, * \param ch input character * * \return The bracket type of the character. Use the - * BIDI_IS_BRACKET(BidiBracketType) to test if it is a valid - * property. Use BCHI_BRACKET_CHAR(BidiBracketType) to get - * the bracketed character value. + * BIDI_IS_BRACKET(BidiBracketType) to test if it is a valid + * property. Use BCHI_BRACKET_CHAR(BidiBracketType) to get + * the bracketed character value. * * \sa UStrGetBracketTypes + * + * Since: 3.4.0 */ MG_EXPORT BidiBracketType GUIAPI UCharGetBracketType(Uchar32 ch); -/* \fn void UStrGetBracketTypes(const Uchar32 *ucs, int nr_ucs, - * const BidiType *bidi_types, BidiBracketType *bracket_types) +/* \fn void UStrGetBracketTypes(const Uchar32 *ucs, + * const BidiType *bidi_types, int nr_ucs, + * BidiBracketType *bracket_types) * \brief Get bracketed characters of a Uchar32 string. * - * This function finds the bracketed characters of an string of characters. - * See UCharGetBracketType() for more information about the bracketed - * characters returned by this function. + * This function finds the bracketed characters of a string of Unicode + * characters. See UCharGetBracketType() for more information about the + * bracketed characters returned by this function. * * \param ucs The input Uchar32 string. * \param nr_ucs The length of string. @@ -7911,9 +7918,12 @@ MG_EXPORT BidiBracketType GUIAPI UCharGetBracketType(Uchar32 ch); * the bracketed characters. * * \sa UCharGetBracketType + * + * Since: 3.4.0 */ -MG_EXPORT void GUIAPI UStrGetBracketTypes(const Uchar32 *ucs, int len_ucs, - const BidiType *bidi_types, BidiBracketType *bracket_types); +MG_EXPORT void GUIAPI UStrGetBracketTypes(const Uchar32 *ucs, + const BidiType *bidi_types, int len_ucs, + BidiBracketType *bracket_types); /** * \fn BOOL GUIAPI UCharGetMirror(Uchar32 uc, Uchar32* mirrored) @@ -7934,6 +7944,8 @@ MG_EXPORT void GUIAPI UStrGetBracketTypes(const Uchar32 *ucs, int len_ucs, * * \return A BOOL value indicates if the character has a mirroring equivalent * or not. + * + * Since: 3.4.0 */ MG_EXPORT BOOL GUIAPI UCharGetMirror(Uchar32 uc, Uchar32* mirrored); @@ -7955,12 +7967,17 @@ MG_EXPORT BOOL GUIAPI UCharGetMirror(Uchar32 uc, Uchar32* mirrored); * * https://www.unicode.org/Public/UNIDATA/UnicodeData.txt. * + * \param uc The Uchar32 character. + * + * \return The joining type of the specified Uchar32 character. + * + * Since: 3.4.0 */ MG_EXPORT BidiJoiningType GUIAPI UCharGetJoiningType(Uchar32 uc); /** - * \fn void GUIAPI UStrGetJoiningTypes(const Uchar32 *ucs, - * BidiJoiningType *joing_types, int len) + * \fn void GUIAPI UStrGetJoiningTypes(const Uchar32 *ucs, int nr_ucs, + * BidiJoiningType *joing_types) * \brief Get joining types for a string of Unicode characters * * This function finds the joining types of an string of characters. @@ -7968,13 +7985,16 @@ MG_EXPORT BidiJoiningType GUIAPI UCharGetJoiningType(Uchar32 uc); * joining types returned by this function. * * \param ucs The input Uchar32 string. - * \param joining_types The output joining types. - * \param len The string length. + * \param nr_ucs The number of Uchar32 characters. + * \param joining_types The pointer to a BidiJoiningType array storing + * the joining types of the characters. * * \sa UCharGetJoiningType + * + * Since: 3.4.0 */ -MG_EXPORT void GUIAPI UStrGetJoiningTypes(const Uchar32 *ucs, - BidiJoiningType *joing_types, int len); +MG_EXPORT void GUIAPI UStrGetJoiningTypes(const Uchar32 *ucs, int nr_ucs, + BidiJoiningType *joing_types); /** * \fn BidiType GUIAPI UBidiGetParagraphDir(const BidiType *bidi_types, int len) @@ -8001,6 +8021,7 @@ MG_EXPORT void GUIAPI UStrGetJoiningTypes(const Uchar32 *ucs, * \return Base pargraph direction. No weak paragraph direction is returned, * only BIDI_PGDIR_LTR, BIDI_PGDIR_RTL, or BIDI_PGDIR_ON. * + * Since: 3.4.0 */ MG_EXPORT BidiType GUIAPI UBidiGetParagraphDir(const BidiType *bidi_types, int len); @@ -8041,6 +8062,8 @@ MG_EXPORT BidiType GUIAPI UBidiGetParagraphDir(const BidiType *bidi_types, int l * (memory allocation failure most probably). * * \sa UStrGetBidiTypes, UStrGetBracketTypes + * + * Since: 3.4.0 */ MG_EXPORT BidiLevel GUIAPI UBidiGetParagraphEmbeddingLevels( const BidiType *bidi_types, @@ -8116,6 +8139,8 @@ typedef void (*CB_REVERSE_EXTRA) (void* extra, int len, int pos); * * \sa UStrGetBidiTypes, UStrGetBracketTypes, * UBidiGetParagraphEmbeddingLevels + * + * Since: 3.4.0 */ MG_EXPORT BidiLevel GUIAPI UBidiReorderLine(Uint32 bidi_flags, const BidiType *bidi_types, int len, int off, @@ -8125,7 +8150,7 @@ MG_EXPORT BidiLevel GUIAPI UBidiReorderLine(Uint32 bidi_flags, /** * \fn void GUIAPI UBidiShapeMirroring(const BidiLevel *els, - * Uchar32 *ucs, int len) + * int len, Uchar32 *ucs) * \brief Do mirroring shaping * * This functions replaces mirroring characters on right-to-left embeddings in @@ -8138,19 +8163,21 @@ MG_EXPORT BidiLevel GUIAPI UBidiReorderLine(Uint32 bidi_flags, * * \param els input list of embedding levels, as returned by * UBidiGetParagraphEmbeddingLevels(). - * \param ucs The Uchar32 string to shape. * \param len The input string length. + * \param ucs The Uchar32 string to shape. * * \sa UBidiGetParagraphEmbeddingLevels + * + * Since: 3.4.0 */ MG_EXPORT void GUIAPI UBidiShapeMirroring(const BidiLevel *els, - Uchar32* ucs, int len); + int len, Uchar32* ucs); /** * \fn void GUIAPI UBidiJoinArabic(const BidiType *bidi_types, - * const BidiLevel *embedding_levels, BidiArabicProp *ar_props, - * int len); - * \brief Do Arabic joining + * const BidiLevel *embedding_levels, int len, + * BidiArabicProp *ar_props); + * \brief Do Arabic joining. * * This function does the Arabic joining algorithm. Means, given Arabic * joining types of the characters in ar_props (note that @@ -8161,7 +8188,7 @@ MG_EXPORT void GUIAPI UBidiShapeMirroring(const BidiLevel *els, * This function implements rules R1 to R7 inclusive (all rules) of the Arabic * Cursive Joining algorithm of the Unicode standard as available at * - * https://www.unicode.org/versions/Unicode4.0.0/ch08.pdf#G7462. + * https://www.unicode.org/versions/Unicode12.0.0/ch08.pdf#G7462. * * It also interacts correctly with the bidirection algorithm as defined in * Section 3.5 Shaping of the Unicode Bidirectional Algorithm available at @@ -8171,31 +8198,37 @@ MG_EXPORT void GUIAPI UBidiShapeMirroring(const BidiLevel *els, * \param bidi_types The list of bidi types as returned by UStrGetBidiTypes(). * \param embedding_levels input list of embedding levels, as returned by * UBidiGetParagraphEmbeddingLevels(). + * \param len The input string length. * \param ar_props Arabic properties to analyze, initialized by joining types, * as returned by UStrGetJoiningTypes(). * * \sa UBidiGetParagraphEmbeddingLevels, UStrGetJoiningTypes + * + * Since: 3.4.0 */ MG_EXPORT void GUIAPI UBidiJoinArabic(const BidiType *bidi_types, - const BidiLevel *embedding_levels, BidiArabicProp *ar_props, - int len); + const BidiLevel *embedding_levels, int len, + BidiArabicProp *ar_props); /** * \fn void GUIAPI UBidiShapeArabic(Uint32 bidi_flags, - * const BidiLevel *embedding_levels, - * BidiArabicProp *ar_props, Uchar32 *ucs, int len) + * const BidiLevel *embedding_levels, int len, + * BidiArabicProp *ar_props, Uchar32 *ucs) * \brief Do Arabic shaping. * * The actual shaping that is done depends on the flags set. The following * flags affect this function: * - * - BIDI_FLAG_SHAPE_MIRRORING: Do mirroring.\n - * - BIDI_FLAG_SHAPE_ARAB_PRES: Shape Arabic characters to - * their presentation form glyphs.\n - * - BIDI_FLAG_SHAPE_ARAB_LIGA: Form mandatory Arabic ligatures.\n - * - BIDI_FLAG_SHAPE_ARAB_CONSOLE: Perform additional Arabic shaping + * - BIDI_FLAG_SHAPE_MIRRORING\n + * Do mirroring. + * - BIDI_FLAG_SHAPE_ARAB_PRES\n + * Shape Arabic characters to their presentation form glyphs. + * - BIDI_FLAG_SHAPE_ARAB_LIGA\n + * Form mandatory Arabic ligatures. + * - BIDI_FLAG_SHAPE_ARAB_CONSOLE\n + * Perform additional Arabic shaping * suitable for text rendered on grid terminals with no mark - * rendering capabilities.\n + * rendering capabilities. * * Of the above, BIDI_FLAG_SHAPE_ARAB_CONSOLE is only used in special * cases, but the rest are recommended in any environment that doesn't have @@ -8205,21 +8238,23 @@ MG_EXPORT void GUIAPI UBidiJoinArabic(const BidiType *bidi_types, * \param shaping_flags shaping flags. * \param embedding_levels input list of embedding levels, as returned by * UBidiGetParagraphEmbeddingLevels(). + * \param len The length of the string. * \param arb_props The Arabic character properties as computed by * UBidiJoinArabic(). * \param ucs The Uchar32 string to shape. - * \param len The length of the string. * * \sa UBidiGetParagraphEmbeddingLevels, UBidiJoinArabic + * + * Since: 3.4.0 */ MG_EXPORT void GUIAPI UBidiShapeArabic(Uint32 shaping_flags, - const BidiLevel *embedding_levels, - BidiArabicProp *ar_props, Uchar32* ucs, int len); + const BidiLevel *embedding_levels, int len, + BidiArabicProp *ar_props, Uchar32* ucs); /** * \fn void GUIAPI UBidiShape(Uint32 shaping_flags, - const BidiLevel *embedding_levels, - BidiArabicProp *ar_props, Uchar32* ucs, int len) + const BidiLevel *embedding_levels, int len, + BidiArabicProp *ar_props, Uchar32* ucs) * \brief Do bidi-aware shaping. * * This function does all shaping work that depends on the resolved embedding @@ -8239,16 +8274,18 @@ MG_EXPORT void GUIAPI UBidiShapeArabic(Uint32 shaping_flags, * \param shaping_flags shaping flags * \param embedding_levels input list of embedding levels, as returned by * UBidiGetParagraphEmbeddingLevels(). + * \param len The length of the string. * \param arb_props The Arabic character properties as computed by * UBidiJoinArabic(). * \param ucs The Uchar32 string to shape. - * \param len The length of the string. * * \sa UBidiShapeArabic, UBidiShapeMirroring + * + * Since: 3.4.0 */ MG_EXPORT void GUIAPI UBidiShape(Uint32 shaping_flags, - const BidiLevel *embedding_levels, - BidiArabicProp *ar_props, Uchar32* ucs, int len); + const BidiLevel *embedding_levels, int len, + BidiArabicProp *ar_props, Uchar32* ucs); /** The function determines whether a character is alphanumeric. */ MG_EXPORT BOOL GUIAPI IsUCharAlnum(Uchar32 uc); diff --git a/src/font/Makefile.am b/src/font/Makefile.am index 1778ae05..f1e547d0 100644 --- a/src/font/Makefile.am +++ b/src/font/Makefile.am @@ -2,7 +2,7 @@ SUBDIRS = in-core noinst_LTLIBRARIES = libfont.la -SRC_FILES = charset.c charset-arabic.c legacy-bidi.c \ +SRC_FILES = charset.c charset-arabic.c legacy-bidi.c charset-unicode.c \ unicode-comp.c unicode-script.c language-code.c \ sysfont.c logfont.c devfont.c fontname.c \ rawbitmap.c varbitmap.c qpf.c upf.c \ diff --git a/src/font/charset-unicode.c b/src/font/charset-unicode.c new file mode 100644 index 00000000..62e207c3 --- /dev/null +++ b/src/font/charset-unicode.c @@ -0,0 +1,1576 @@ +/* + * This file is part of MiniGUI, a mature cross-platform windowing + * and Graphics User Interface (GUI) support system for embedded systems + * and smart IoT devices. + * + * Copyright (C) 2002~2018, Beijing FMSoft Technologies Co., Ltd. + * Copyright (C) 1998~2002, WEI Yongming + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Or, + * + * As this program is a library, any link to this program must follow + * GNU General Public License version 3 (GPLv3). If you cannot accept + * GPLv3, you need to be licensed from FMSoft. + * + * If you have got a commercial license of this program, please use it + * under the terms and conditions of the commercial license. + * + * For more information about the commercial license, please refer to + * . + */ +/* +** charset.c: The charset operation set. +** +** Create date: 2000/06/13 +*/ + +#include +#include +#include +#include +#include + +#include "common.h" +#include "minigui.h" +#include "gdi.h" +#include "devfont.h" +#include "charset.h" + +#ifdef _MGCHARSET_UNICODE + +/************************* UTF-8 Specific Operations ************************/ +static int utf8_len_first_char (const unsigned char* mstr, int len) +{ + int t, c = *((unsigned char *)(mstr++)); + + if (c & 0x80) { + int n = 1, ch_len = 0; + while (c & (0x80 >> n)) + n++; + + if (n > len) + return 0; + + ch_len = n; + while (--n > 0) { + t = *((unsigned char *)(mstr++)); + + if ((!(t & 0x80)) || (t & 0x40)) + return 0; + } + + return ch_len; + } + + /* for ascii character */ + return 1; +} + +static Achar32 utf8_get_char_value (const unsigned char* pre_mchar, int pre_len, + const unsigned char* cur_mchar, int cur_len) +{ + Uchar32 wc = *((unsigned char *)(cur_mchar++)); + int n, t; + + if (wc & 0x80) { + n = 1; + while (wc & (0x80 >> n)) + n++; + + wc &= (1 << (8-n)) - 1; + while (--n > 0) { + t = *((unsigned char *)(cur_mchar++)); + + wc = (wc << 6) | (t & 0x3F); + } + } + + return wc; +} + +#include "unicode-tables.h" +#include "unicode-break-tables.h" + +#define ATTR_TABLE(Page) (((Page) <= UCHAR_LAST_PAGE_PART1) \ + ? attr_table_part1[Page] \ + : attr_table_part2[(Page) - 0xe00]) + +#define ATTTABLE(Page, Char) \ + ((ATTR_TABLE(Page) == UCHAR_MAX_TABLE_INDEX) ? 0 : (attr_data[ATTR_TABLE(Page)][Char])) + +#define TTYPE_PART1(Page, Char) \ + ((type_table_part1[Page] >= UCHAR_MAX_TABLE_INDEX) \ + ? (type_table_part1[Page] - UCHAR_MAX_TABLE_INDEX) \ + : (type_data[type_table_part1[Page]][Char])) + +#define TTYPE_PART2(Page, Char) \ + ((type_table_part2[Page] >= UCHAR_MAX_TABLE_INDEX) \ + ? (type_table_part2[Page] - UCHAR_MAX_TABLE_INDEX) \ + : (type_data[type_table_part2[Page]][Char])) + +#define TYPE(Char) \ + (((Char) <= UCHAR_LAST_CHAR_PART1) \ + ? TTYPE_PART1 ((Char) >> 8, (Char) & 0xff) \ + : (((Char) >= 0xe0000 && (Char) <= UCHAR_LAST_CHAR) \ + ? TTYPE_PART2 (((Char) - 0xe0000) >> 8, (Char) & 0xff) \ + : UCHAR_CATEGORY_UNASSIGNED)) + +#define IS(Type, Class) (((unsigned int)1 << (Type)) & (Class)) +#define OR(Type, Rest) (((unsigned int)1 << (Type)) | (Rest)) + +#define ISALPHA(Type) IS ((Type), \ + OR (UCHAR_CATEGORY_LOWERCASE_LETTER, \ + OR (UCHAR_CATEGORY_UPPERCASE_LETTER, \ + OR (UCHAR_CATEGORY_TITLECASE_LETTER, \ + OR (UCHAR_CATEGORY_MODIFIER_LETTER, \ + OR (UCHAR_CATEGORY_OTHER_LETTER, 0)))))) + +#define ISALDIGIT(Type) IS ((Type), \ + OR (UCHAR_CATEGORY_DECIMAL_NUMBER, \ + OR (UCHAR_CATEGORY_LETTER_NUMBER, \ + OR (UCHAR_CATEGORY_OTHER_NUMBER, \ + OR (UCHAR_CATEGORY_LOWERCASE_LETTER, \ + OR (UCHAR_CATEGORY_UPPERCASE_LETTER, \ + OR (UCHAR_CATEGORY_TITLECASE_LETTER, \ + OR (UCHAR_CATEGORY_MODIFIER_LETTER, \ + OR (UCHAR_CATEGORY_OTHER_LETTER, 0))))))))) + +#define ISMARK(Type) IS ((Type), \ + OR (UCHAR_CATEGORY_NON_SPACING_MARK, \ + OR (UCHAR_CATEGORY_SPACING_MARK, \ + OR (UCHAR_CATEGORY_ENCLOSING_MARK, 0)))) + +#define ISZEROWIDTHTYPE(Type) IS ((Type), \ + OR (UCHAR_CATEGORY_NON_SPACING_MARK, \ + OR (UCHAR_CATEGORY_ENCLOSING_MARK, \ + OR (UCHAR_CATEGORY_FORMAT, 0)))) + +#define TPROP_PART1(Page, Char) \ + ((break_property_table_part1[Page] >= UCHAR_MAX_TABLE_INDEX) \ + ? (break_property_table_part1[Page] - UCHAR_MAX_TABLE_INDEX) \ + : (break_property_data[break_property_table_part1[Page]][Char])) + +#define TPROP_PART2(Page, Char) \ + ((break_property_table_part2[Page] >= UCHAR_MAX_TABLE_INDEX) \ + ? (break_property_table_part2[Page] - UCHAR_MAX_TABLE_INDEX) \ + : (break_property_data[break_property_table_part2[Page]][Char])) + +#define PROP(Char) \ + (((Char) <= UCHAR_LAST_CHAR_PART1) \ + ? TPROP_PART1 ((Char) >> 8, (Char) & 0xff) \ + : (((Char) >= 0xe0000 && (Char) <= UCHAR_LAST_CHAR) \ + ? TPROP_PART2 (((Char) - 0xe0000) >> 8, (Char) & 0xff) \ + : UCHAR_BREAK_UNKNOWN)) + +extern unsigned int __mg_sb_char_type(Achar32); + +static unsigned int unicode_char_type (Achar32 chv) +{ + unsigned int mchar_type = ACHAR_BASIC_UNKNOWN; + unsigned int basic_type = 0, break_type = 0; + + chv = REAL_ACHAR(chv); + basic_type = TYPE(chv); + break_type = PROP(chv); + + if (chv < 0x80) + mchar_type = __mg_sb_char_type(chv); + else if (break_type == UCHAR_BREAK_CARRIAGE_RETURN) + mchar_type = ACHAR_BASIC_CR; + else if (break_type == UCHAR_BREAK_LINE_FEED) + mchar_type = ACHAR_BASIC_LF; + else if (break_type == UCHAR_BREAK_NEXT_LINE) + mchar_type = ACHAR_BASIC_LF; + else if (break_type == UCHAR_BREAK_SPACE) + mchar_type = ACHAR_BASIC_SPACE; + else if (chv != 0x00AD && ISZEROWIDTHTYPE (basic_type)) + mchar_type = ACHAR_BASIC_ZEROWIDTH; + else if ((chv >= 0x1160 && chv < 0x1200) + || chv == 0x200B) + mchar_type = ACHAR_BASIC_ZEROWIDTH; + + return (break_type << 24) | (basic_type << 16) | mchar_type; +} + +#define _USE_UNIBIDI + +#ifdef _USE_UNIBIDI + +enum _BidiCharTypeLinearEnum { +#define _UNIBIDI_ADD_TYPE(TYPE,SYMBOL) TYPE, +#include "unicode-bidi-types-list.inc" +#undef _UNIBIDI_ADD_TYPE + _UNIBIDI_NUM_TYPES +}; + +#include "unicode-bidi-type-table.inc" + +/* Map _BidiCharTypeLinearEnum to BidiType. */ +static const BidiType linear_enum_to_bidi_type[] = { +#define _UNIBIDI_ADD_TYPE(TYPE,SYMBOL) BIDI_TYPE_##TYPE, +#include "unicode-bidi-types-list.inc" +#undef _UNIBIDI_ADD_TYPE +}; + +static BidiType unicode_bidi_char_type(Achar32 ch) +{ + ch = REAL_ACHAR(ch); + return linear_enum_to_bidi_type[UNIBIDI_GET_BIDI_TYPE(ch)]; +} + +BidiType GUIAPI UCharGetBidiType(Uchar32 uc) +{ + return linear_enum_to_bidi_type[UNIBIDI_GET_BIDI_TYPE(uc)]; +} + +void GUIAPI UStrGetBidiTypes(const Uchar32 *str, int len, BidiType *btypes) +{ + register int i = len; + for (; i; i--) { + *btypes++ = linear_enum_to_bidi_type[UNIBIDI_GET_BIDI_TYPE(*str)]; + str++; + } +} + +#include "unicode-bidi-brackets-table.inc" +#include "unicode-bidi-brackets-type-table.inc" + +#define UNIBIDI_TYPE_BRACKET_OPEN 2 + +BidiBracketType UCharGetBracketType(Uchar32 ch) +{ + BidiBracketType bracket_type; + register Uint8 char_type = UNIBIDI_GET_BRACKET_TYPE (ch); + + /* The bracket type from the table may be: + 0 - Not a bracket + 1 - a bracket + 2 - closing. + + This will be recodeded into the BidiBracketType as having a + bracket_id = 0 if the character is not a bracket. + */ + BOOL is_open = FALSE; + + if (char_type == 0) + bracket_type = BIDI_BRACKET_NONE; + else { + is_open = (char_type & UNIBIDI_TYPE_BRACKET_OPEN) != 0; + bracket_type = UNIBIDI_GET_BRACKETS (ch) & BIDI_BRACKET_CHAR_MASK; + } + + if (is_open) + bracket_type |= BIDI_BRACKET_OPEN_MASK; + + return bracket_type; +} + +#include "unicode-bidi-mirroring-table.inc" + +static BOOL unicode_bidi_mirror_char(Achar32 ch, Achar32* mirrored_ch) +{ + register Achar32 result; + register Uint32 mbc_mask; + + mbc_mask = ch & ACHAR_MBC_FLAG; + ch = REAL_ACHAR(ch); + result = UNIBIDI_GET_MIRRORING(ch); + if (mirrored_ch) + *mirrored_ch = result; + result |= mbc_mask; + + return ch != result ? TRUE : FALSE; +} + +BOOL GUIAPI UCharGetMirror(Uchar32 ch, Uchar32* mirrored_ch) +{ + register Achar32 result; + + result = UNIBIDI_GET_MIRRORING(ch); + if (mirrored_ch) + *mirrored_ch = result; + return ch != result ? TRUE : FALSE; +} + +#else + +#include "unicode-bidi-tables.h" + +static BidiType unicode_bidi_char_type (Achar32 chv) +{ + Achar32 chv_first = 0; + Achar32 chv_last = (Achar32)TABLESIZE (__mg___mg_unicode_bidi_char_type_map); + Achar32 chv_mid; + + chv = REAL_ACHAR(chv); + while (chv_last >= chv_first) { + chv_mid = (chv_first + chv_last)/2; + + if ((__mg___mg_unicode_bidi_char_type_map[chv_mid].chv <= chv) + && ((__mg___mg_unicode_bidi_char_type_map[chv_mid].chv + __mg___mg_unicode_bidi_char_type_map[chv_mid].count) > chv)) { + return __mg___mg_unicode_bidi_char_type_map[chv_mid].type; + } + + if (chv >= (__mg___mg_unicode_bidi_char_type_map[chv_mid].chv + __mg___mg_unicode_bidi_char_type_map[chv_mid].count)) { + chv_first = chv_mid + 1; + } + else { + if (chv < __mg___mg_unicode_bidi_char_type_map[chv_mid].chv) + chv_last = chv_mid - 1; + else + chv_last = chv_mid; + } + } + + return BIDI_TYPE_LTR; +} + +static BOOL unicode_bidi_mirror_char (Achar32 chv, Achar32* mirrored) +{ + return get_mirror_char (__mg_unicode_mirror_table, + TABLESIZE (__mg_unicode_mirror_table), chv, mirrored); +} + +BidiType GUIAPI UCharGetBidiType(Uchar32 uc) +{ + return unicode_bidi_char_type(uc); +} + +BidiBracketType GUIAPI UCharGetBracketType(Uchar32 uc) +{ + BidiBracketType bracket_type; + unsigned int lower = 0; + unsigned int upper = TABLESIZE (__mg_unicode_bracket_table) - 1; + int mid = TABLESIZE (__mg_unicode_bracket_table) / 2; + + if (uc < __mg_unicode_bracket_table[lower].chv || + uc > __mg_unicode_bracket_table[upper].chv) + return BIDI_BRACKET_NONE; + + do { + if (uc < __mg_unicode_bracket_table[mid].chv) + upper = mid - 1; + else if (uc > __mg_unicode_bracket_table[mid].chv) + lower = mid + 1; + else + goto found; + + mid = (lower + upper) / 2; + + } while (lower <= upper); + + return BIDI_BRACKET_NONE; + +found: + bracket_type = __mg_unicode_bracket_table[mid].chv + + __mg_unicode_bracket_table[mid].bracket_off; + bracket_type &= BIDI_BRACKET_CHAR_MASK; + if (__mg_unicode_bracket_table[mid].type == UNIBIDI_BRACKET_OPEN) + bracket_type |= BIDI_BRACKET_OPEN_MASK; + + return bracket_type; +} + +void GUIAPI UStrGetBidiTypes(const Uchar32 *str, int len, BidiType *btypes) +{ + register int i = len; + for (; i; i--) { + *btypes++ = UCharGetBracketType(*str); + str++; + } +} + +/** The function returns the mirror character of a UNICODE character. */ +BOOL GUIAPI UCharGetMirror(Uchar32 uc, Uchar32* mirrored) +{ + return unicode_bidi_mirror_char (uc, mirrored); +} + +#endif /* !_USE_UNIBIDI */ + +void UStrGetBracketTypes(const Uchar32 *str, + const BidiType *types, int len, BidiBracketType *btypes) +{ + int i; + for (i = 0; i < len; i++) { + /* Optimization that bracket must be of types ON */ + if (*types == BIDI_TYPE_ON) + *btypes = UCharGetBracketType (*str); + else + *btypes = BIDI_BRACKET_NONE; + + btypes++; + types++; + str++; + } +} + +static int utf8_nr_chars_in_str (const unsigned char* mstr, int mstrlen) +{ + int charlen; + int n = 0; + int left = mstrlen; + + while (left >= 0) { + charlen = utf8_len_first_char (mstr, left); + if (charlen > 0) + n ++; + + left -= charlen; + mstr += charlen; + } + + return n; +} + +static int utf8_is_this_charset (const unsigned char* charset) +{ + int i; + char name [LEN_LOGFONT_NAME_FIELD + 1]; + + for (i = 0; i < LEN_LOGFONT_NAME_FIELD + 1; i++) { + if (charset [i] == '\0') + break; + name [i] = toupper (charset [i]); + } + name [i] = '\0'; + + if (strstr (name, "UTF") && strstr (name, "8")) + return 0; + + return 1; +} + +static int utf8_len_first_substr (const unsigned char* mstr, int mstrlen) +{ + int ch_len; + int sub_len = 0; + + while (mstrlen > 0) { + ch_len = utf8_len_first_char (mstr, mstrlen); + + if (ch_len == 0) + break; + + sub_len += ch_len; + mstrlen -= ch_len; + mstr += ch_len; + } + + return sub_len; +} + +static const unsigned char* utf8_get_next_word (const unsigned char* mstr, + int mstrlen, WORDINFO* word_info) +{ + const unsigned char* mchar = mstr; + int ch_len; + Uchar32 wc; + + word_info->len = 0; + word_info->delimiter = '\0'; + word_info->nr_delimiters = 0; + + if (mstrlen == 0) return NULL; + + while (mstrlen > 0) { + ch_len = utf8_len_first_char (mchar, mstrlen); + + if (ch_len == 0) + break; + + wc = utf8_get_char_value (NULL, 0, mchar, 0); + if (wc > 0x0FFF) { + if (word_info->len) + return mstr + word_info->len + word_info->nr_delimiters; + else { /* Treate the first char as a word */ + word_info->len = ch_len; + return mstr + word_info->len + word_info->nr_delimiters; + } + } + + switch (mchar[0]) { + case ' ': + case '\t': + case '\n': + case '\r': + if (word_info->delimiter == '\0') { + word_info->delimiter = mchar[0]; + word_info->nr_delimiters ++; + } + else if (word_info->delimiter == mchar[0]) + word_info->nr_delimiters ++; + else + return mstr + word_info->len + word_info->nr_delimiters; + + break; + + default: + if (word_info->delimiter != '\0') + return mstr + word_info->len + word_info->nr_delimiters; + + word_info->len += ch_len; + break; + } + + mchar += ch_len; + mstrlen -= ch_len; + } + + return mstr + word_info->len + word_info->nr_delimiters; +} + +static int utf8_pos_first_char (const unsigned char* mstr, int mstrlen) +{ + int ch_len; + int pos = 0; + + while (mstrlen > 0) { + ch_len = utf8_len_first_char (mstr, mstrlen); + + /*charset encoding mismatch*/ + if (ch_len == 0) + return -1; + + if (ch_len > 0) + return pos; + + pos += ch_len; + mstrlen -= ch_len; + mstr += ch_len; + } + + return -1; +} + +static int utf8_conv_from_uc32 (Uchar32 wc, unsigned char* mchar) +{ + int first, len; + + if (wc < 0x80) { + first = 0; + len = 1; + } + else if (wc < 0x800) { + first = 0xC0; + len = 2; + } + else if (wc < 0x10000) { + first = 0xE0; + len = 3; + } + else if (wc < 0x200000) { + first = 0xF0; + len = 4; + } + else if (wc < 0x400000) { + first = 0xF8; + len = 5; + } + else { + first = 0xFC; + len = 6; + } + + switch (len) { + case 6: + mchar [5] = (wc & 0x3f) | 0x80; wc >>= 6; /* Fall through */ + case 5: + mchar [4] = (wc & 0x3f) | 0x80; wc >>= 6; /* Fall through */ + case 4: + mchar [3] = (wc & 0x3f) | 0x80; wc >>= 6; /* Fall through */ + case 3: + mchar [2] = (wc & 0x3f) | 0x80; wc >>= 6; /* Fall through */ + case 2: + mchar [1] = (wc & 0x3f) | 0x80; wc >>= 6; /* Fall through */ + case 1: + mchar [0] = wc | first; + } + + return len; +} + +CHARSETOPS __mg_CharsetOps_utf8 = { + 0x7FFFFFFF, + 6, + FONT_CHARSET_UTF8, + 0, + utf8_len_first_char, + utf8_get_char_value, + NULL, + unicode_char_type, + utf8_nr_chars_in_str, + utf8_is_this_charset, + utf8_len_first_substr, + utf8_get_next_word, + utf8_pos_first_char, + unicode_bidi_char_type, + unicode_bidi_mirror_char, + NULL, + utf8_conv_from_uc32, +}; + +/************************* UTF-16LE Specific Operations ***********************/ +static int utf16le_len_first_char (const unsigned char* mstr, int len) +{ + Uchar16 w1, w2; + + if (len < 2) + return 0; + + w1 = MAKEWORD16 (mstr[0], mstr[1]); + + if (w1 < 0xD800 || w1 > 0xDFFF) + return 2; + + if (w1 >= 0xD800 && w1 <= 0xDBFF) { + if (len < 4) + return 0; + w2 = MAKEWORD16 (mstr[2], mstr[3]); + if (w2 < 0xDC00 || w2 > 0xDFFF) + return 0; + } + + return 4; +} + +static Achar32 utf16le_get_char_value (const unsigned char* pre_mchar, + int pre_len, const unsigned char* cur_mchar, int cur_len) +{ + Uchar16 w1, w2; + Uchar32 wc; + + w1 = MAKEWORD16 (cur_mchar[0], cur_mchar[1]); + + if (w1 < 0xD800 || w1 > 0xDFFF) + return w1; + + w2 = MAKEWORD16 (cur_mchar[2], cur_mchar[3]); + + wc = w1; + wc <<= 10; + wc |= (w2 & 0x03FF); + wc += 0x10000; + + return wc; +} + +static int utf16le_nr_chars_in_str (const unsigned char* mstr, int mstrlen) +{ + int charlen; + int n = 0; + int left = mstrlen; + + while (left >= 0) { + charlen = utf16le_len_first_char (mstr, left); + if (charlen > 0) + n ++; + + left -= charlen; + mstr += charlen; + } + + return n; +} + +static int utf16le_is_this_charset (const unsigned char* charset) +{ + int i; + char name [LEN_LOGFONT_NAME_FIELD + 1]; + + for (i = 0; i < LEN_LOGFONT_NAME_FIELD + 1; i++) { + if (charset [i] == '\0') + break; + name [i] = toupper (charset [i]); + } + name [i] = '\0'; + + if (strstr (name, "UTF") && strstr (name, "16LE")) + return 0; + + return 1; +} + +static int utf16le_len_first_substr (const unsigned char* mstr, int mstrlen) +{ + int ch_len; + int sub_len = 0; + + while (mstrlen > 0) { + ch_len = utf16le_len_first_char (mstr, mstrlen); + + if (ch_len == 0) + break; + + sub_len += ch_len; + mstrlen -= ch_len; + mstr += ch_len; + } + + return sub_len; +} + +static const unsigned char* utf16le_get_next_word (const unsigned char* mstr, + int mstrlen, WORDINFO* word_info) +{ + const unsigned char* mchar = mstr; + Uchar32 wc; + int ch_len; + + word_info->len = 0; + word_info->delimiter = '\0'; + word_info->nr_delimiters = 0; + + if (mstrlen == 0) return NULL; + + while (mstrlen > 0) { + ch_len = utf16le_len_first_char (mchar, mstrlen); + + if (ch_len == 0) + break; + + wc = utf16le_get_char_value (NULL, 0, mchar, 0); + if (wc > 0x0FFF) { + if (word_info->len) + return mstr + word_info->len + word_info->nr_delimiters; + else { /* Treate the first char as a word */ + word_info->len = ch_len; + return mstr + word_info->len + word_info->nr_delimiters; + } + } + + switch (wc) { + case ' ': + case '\t': + case '\n': + case '\r': + if (word_info->delimiter == '\0') { + word_info->delimiter = (unsigned char)wc; + word_info->nr_delimiters += ch_len; + } + else if (word_info->delimiter == (unsigned char)wc) + word_info->nr_delimiters += ch_len; + else + return mstr + word_info->len + word_info->nr_delimiters; + break; + + default: + if (word_info->delimiter != '\0') + return mstr + word_info->len + word_info->nr_delimiters; + + word_info->len += ch_len; + break; + } + + mstrlen -= ch_len; + mchar += ch_len; + } + + return mstr + word_info->len + word_info->nr_delimiters; +} + +static int utf16le_pos_first_char (const unsigned char* mstr, int mstrlen) +{ + int ch_len; + int pos = 0; + + while (mstrlen > 0) { + ch_len = utf16le_len_first_char (mstr, mstrlen); + + if (ch_len > 0) + return pos; + + pos += ch_len; + mstrlen -= ch_len; + mstr += ch_len; + } + + return -1; +} + +static int utf16le_conv_from_uc32 (Uchar32 wc, unsigned char* mchar) +{ + Uchar16 w1, w2; + + if (wc > 0x10FFFF) { + return 0; + } + + if (wc < 0x10000) { + mchar [0] = LOBYTE (wc); + mchar [1] = HIBYTE (wc); + return 2; + } + + wc -= 0x10000; + w1 = 0xD800; + w2 = 0xDC00; + + w1 |= (wc >> 10); + w2 |= (wc & 0x03FF); + + mchar [0] = LOBYTE (w1); + mchar [1] = HIBYTE (w1); + mchar [2] = LOBYTE (w2); + mchar [3] = HIBYTE (w2); + return 4; +} + +CHARSETOPS __mg_CharsetOps_utf16le = { + 0x7FFFFFFF, + 4, + FONT_CHARSET_UTF16LE, + 0, + utf16le_len_first_char, + utf16le_get_char_value, + NULL, + unicode_char_type, + utf16le_nr_chars_in_str, + utf16le_is_this_charset, + utf16le_len_first_substr, + utf16le_get_next_word, + utf16le_pos_first_char, + unicode_bidi_char_type, + unicode_bidi_mirror_char, + NULL, + utf16le_conv_from_uc32 +}; + +/************************* UTF-16BE Specific Operations ***********************/ +static int utf16be_len_first_char (const unsigned char* mstr, int len) +{ + Uchar16 w1, w2; + + if (len < 2) + return 0; + + w1 = MAKEWORD16 (mstr[1], mstr[0]); + + if (w1 < 0xD800 || w1 > 0xDFFF) + return 2; + + if (w1 >= 0xD800 && w1 <= 0xDBFF) { + if (len < 4) + return 0; + w2 = MAKEWORD16 (mstr[3], mstr[2]); + if (w2 < 0xDC00 || w2 > 0xDFFF) + return 0; + } + + return 4; +} + +static Achar32 utf16be_get_char_value (const unsigned char* pre_mchar, + int pre_len, const unsigned char* cur_mchar, int cur_len) +{ + Uchar16 w1, w2; + Uchar32 wc; + + w1 = MAKEWORD16 (cur_mchar[1], cur_mchar[0]); + + if (w1 < 0xD800 || w1 > 0xDFFF) + return w1; + + w2 = MAKEWORD16 (cur_mchar[3], cur_mchar[2]); + + wc = w1; + wc <<= 10; + wc |= (w2 & 0x03FF); + wc += 0x10000; + + return wc; +} + +static int utf16be_nr_chars_in_str (const unsigned char* mstr, int mstrlen) +{ + int charlen; + int n = 0; + int left = mstrlen; + + while (left >= 0) { + charlen = utf16be_len_first_char (mstr, left); + if (charlen > 0) + n ++; + + left -= charlen; + mstr += charlen; + } + + return n; +} + +static int utf16be_is_this_charset (const unsigned char* charset) +{ + int i; + char name [LEN_LOGFONT_NAME_FIELD + 1]; + + for (i = 0; i < LEN_LOGFONT_NAME_FIELD + 1; i++) { + if (charset [i] == '\0') + break; + name [i] = toupper (charset [i]); + } + name [i] = '\0'; + + if (strstr (name, "UTF") && strstr (name, "16BE")) + return 0; + + return 1; +} + +static int utf16be_len_first_substr (const unsigned char* mstr, int mstrlen) +{ + int ch_len; + int sub_len = 0; + + while (mstrlen > 0) { + ch_len = utf16be_len_first_char (mstr, mstrlen); + + if (ch_len == 0) + break; + + sub_len += ch_len; + mstrlen -= ch_len; + mstr += ch_len; + } + + return sub_len; +} + +static const unsigned char* utf16be_get_next_word (const unsigned char* mstr, + int mstrlen, WORDINFO* word_info) +{ + const unsigned char* mchar = mstr; + Uchar32 wc; + int ch_len; + + word_info->len = 0; + word_info->delimiter = '\0'; + word_info->nr_delimiters = 0; + + if (mstrlen == 0) return NULL; + + while (mstrlen > 0) { + ch_len = utf16be_len_first_char (mchar, mstrlen); + + if (ch_len == 0) + break; + + wc = utf16be_get_char_value (NULL, 0, mchar, 0); + if (wc > 0x0FFF) { + if (word_info->len) + return mstr + word_info->len + word_info->nr_delimiters; + else { /* Treate the first char as a word */ + word_info->len = ch_len; + return mstr + word_info->len + word_info->nr_delimiters; + } + } + + switch (wc) { + case ' ': + case '\t': + case '\n': + case '\r': + if (word_info->delimiter == '\0') { + word_info->delimiter = (unsigned char)wc; + word_info->nr_delimiters += ch_len; + } + else if (word_info->delimiter == (unsigned char)wc) + word_info->nr_delimiters += ch_len; + else + return mstr + word_info->len + word_info->nr_delimiters; + break; + + default: + if (word_info->delimiter != '\0') + return mstr + word_info->len + word_info->nr_delimiters; + + word_info->len += ch_len; + break; + } + + mstrlen -= ch_len; + mchar += ch_len; + } + + return mstr + word_info->len + word_info->nr_delimiters; +} + +static int utf16be_pos_first_char (const unsigned char* mstr, int mstrlen) +{ + int ch_len; + int pos = 0; + + while (mstrlen > 0) { + ch_len = utf16be_len_first_char (mstr, mstrlen); + + if (ch_len > 0) + return pos; + + pos += ch_len; + mstrlen -= ch_len; + mstr += ch_len; + } + + return -1; +} + +static int utf16be_conv_from_uc32 (Uchar32 wc, unsigned char* mchar) +{ + Uchar16 w1, w2; + + if (wc > 0x10FFFF) { + return 0; + } + + if (wc < 0x10000) { + mchar [1] = LOBYTE (wc); + mchar [0] = HIBYTE (wc); + return 2; + } + + wc -= 0x10000; + w1 = 0xD800; + w2 = 0xDC00; + + w1 |= (wc >> 10); + w2 |= (wc & 0x03FF); + + mchar [1] = LOBYTE (w1); + mchar [0] = HIBYTE (w1); + mchar [3] = LOBYTE (w2); + mchar [2] = HIBYTE (w2); + return 4; +} + +CHARSETOPS __mg_CharsetOps_utf16be = { + 0x7FFFFFFF, + 4, + FONT_CHARSET_UTF16BE, + 0, + utf16be_len_first_char, + utf16be_get_char_value, + NULL, + unicode_char_type, + utf16be_nr_chars_in_str, + utf16be_is_this_charset, + utf16be_len_first_substr, + utf16be_get_next_word, + utf16be_pos_first_char, + unicode_bidi_char_type, + unicode_bidi_mirror_char, + NULL, + utf16be_conv_from_uc32 +}; + +UCharGeneralCategory GUIAPI UCharGetCategory(Uchar32 uc) +{ + return (UCharGeneralCategory)TYPE(uc); +} + +/** The function determines the break type of a UNICODE character. */ +UCharBreakType GUIAPI UCharGetBreakType(Uchar32 uc) +{ + return (UCharBreakType)PROP(uc); +} + +BOOL GUIAPI IsUCharAlnum(Uchar32 uc) +{ + return ISALDIGIT(TYPE(uc)); +} + +BOOL GUIAPI IsUCharAlpha(Uchar32 uc) +{ + return ISALPHA (TYPE(uc)); +} + +BOOL GUIAPI IsUCharControl(Uchar32 uc) +{ + return TYPE(uc) == UCHAR_CATEGORY_CONTROL; +} + +BOOL GUIAPI IsUCharDigit(Uchar32 uc) +{ + return TYPE(uc) == UCHAR_CATEGORY_DECIMAL_NUMBER; +} + +BOOL GUIAPI IsUCharGraph(Uchar32 uc) +{ + return !IS (TYPE(uc), + OR (UCHAR_CATEGORY_CONTROL, + OR (UCHAR_CATEGORY_FORMAT, + OR (UCHAR_CATEGORY_UNASSIGNED, + OR (UCHAR_CATEGORY_SURROGATE, + OR (UCHAR_CATEGORY_SPACE_SEPARATOR, + 0)))))); +} + +BOOL GUIAPI IsUCharLowercase(Uchar32 uc) +{ + return TYPE(uc) == UCHAR_CATEGORY_LOWERCASE_LETTER; +} + +BOOL GUIAPI IsUCharPrint(Uchar32 uc) +{ + return !IS (TYPE(uc), + OR (UCHAR_CATEGORY_CONTROL, + OR (UCHAR_CATEGORY_FORMAT, + OR (UCHAR_CATEGORY_UNASSIGNED, + OR (UCHAR_CATEGORY_SURROGATE, + 0))))); +} + +BOOL GUIAPI IsUCharUppercase(Uchar32 uc) +{ + return TYPE(uc) == UCHAR_CATEGORY_UPPERCASE_LETTER; +} + +BOOL GUIAPI IsUCharPunct(Uchar32 uc) +{ + return IS (TYPE(uc), + OR (UCHAR_CATEGORY_CONNECT_PUNCTUATION, + OR (UCHAR_CATEGORY_DASH_PUNCTUATION, + OR (UCHAR_CATEGORY_CLOSE_PUNCTUATION, + OR (UCHAR_CATEGORY_FINAL_PUNCTUATION, + OR (UCHAR_CATEGORY_INITIAL_PUNCTUATION, + OR (UCHAR_CATEGORY_OTHER_PUNCTUATION, + OR (UCHAR_CATEGORY_OPEN_PUNCTUATION, + OR (UCHAR_CATEGORY_CURRENCY_SYMBOL, + OR (UCHAR_CATEGORY_MODIFIER_SYMBOL, + OR (UCHAR_CATEGORY_MATH_SYMBOL, + OR (UCHAR_CATEGORY_OTHER_SYMBOL, + 0)))))))))))); +} + +BOOL GUIAPI IsUCharSpace(Uchar32 uc) +{ + switch (uc) { + /* special-case these since Unicode thinks they are not spaces */ + case '\t': + case '\n': + case '\r': + case '\f': + return TRUE; + + default: { + if (IS (TYPE(uc), + OR (UCHAR_CATEGORY_SPACE_SEPARATOR, + OR (UCHAR_CATEGORY_LINE_SEPARATOR, + OR (UCHAR_CATEGORY_PARAGRAPH_SEPARATOR, + 0))))) + return TRUE; + } + break; + } + + return FALSE; +} + +BOOL GUIAPI IsUCharMark(Uchar32 uc) +{ + return ISMARK (TYPE(uc)); +} + +BOOL GUIAPI IsUCharTitle(Uchar32 uc) +{ + unsigned int i; + + for (i = 0; i < TABLESIZE (title_table); ++i) { + if (title_table[i][0] == uc) { + return TRUE; + } + } + + return FALSE; +} + +BOOL GUIAPI IsUCharXDigit(Uchar32 uc) +{ + return ((uc >= 'a' && uc <= 'f') + || (uc >= 'A' && uc <= 'F') + || (TYPE(uc) == UCHAR_CATEGORY_DECIMAL_NUMBER)); +} + +BOOL GUIAPI IsUCharDefined(Uchar32 uc) +{ + return !IS (TYPE(uc), + OR (UCHAR_CATEGORY_UNASSIGNED, + OR (UCHAR_CATEGORY_SURROGATE, + 0))); +} + +BOOL GUIAPI IsUCharZeroWidth(Uchar32 uc) +{ + if (uc != 0x00AD && ISZEROWIDTHTYPE (TYPE(uc))) + return TRUE; + else if ((uc >= 0x1160 && uc < 0x1200) + || uc == 0x200B) + return TRUE; + + return FALSE; +} + +static inline BOOL g_unichar_iswide_bsearch (Uchar32 ch) +{ + unsigned int lower = 0; + unsigned int upper = TABLESIZE (unicode_width_table_wide) - 1; + int mid = TABLESIZE (unicode_width_table_wide) / 2; + + do { + if (ch < unicode_width_table_wide[mid].start) + upper = mid - 1; + else if (ch > unicode_width_table_wide[mid].end) + lower = mid + 1; + else + return TRUE; + + mid = (lower + upper) / 2; + } + while (lower <= upper); + + return FALSE; +} + +BOOL GUIAPI IsUCharWide(Uchar32 uc) +{ + if (uc < unicode_width_table_wide[0].start) + return FALSE; + else + return g_unichar_iswide_bsearch (uc); +} + +static int interval_compare (const void *key, const void *elt) +{ + Uchar32 uc = (Uchar32)((intptr_t)key); + struct Interval *interval = (struct Interval *)elt; + + if (uc < interval->start) + return -1; + if (uc > interval->end) + return +1; + + return 0; +} + +BOOL GUIAPI IsUCharWideCJK (Uchar32 uc) +{ + if (IsUCharWide(uc)) + return TRUE; + + /* bsearch() is declared attribute(nonnull(1)) so we can't validly search + * for a NULL key */ + if (uc == 0) + return FALSE; + + if (bsearch((void*)((intptr_t)uc), + unicode_width_table_ambiguous, + TABLESIZE (unicode_width_table_ambiguous), + sizeof unicode_width_table_ambiguous[0], + interval_compare)) + return TRUE; + + return FALSE; +} + +/** + * Converts a character to uppercase. + */ +Uchar32 UCharToUpper (Uchar32 uc) +{ + int t = TYPE (uc); + if (t == UCHAR_CATEGORY_LOWERCASE_LETTER) { + Uchar32 val = ATTTABLE (uc >> 8, uc & 0xff); + if (val >= 0x1000000) { + const unsigned char *p = special_case_table + val - 0x1000000; + val = utf8_get_char_value (NULL, 0, p, -1); + } + /* Some lowercase letters, e.uc., U+000AA, FEMININE ORDINAL INDICATOR, + * do not have an uppercase equivalent, in which case val will be + * zero. + */ + return val ? val : uc; + } + else if (t == UCHAR_CATEGORY_TITLECASE_LETTER) { + unsigned int i; + for (i = 0; i < TABLESIZE (title_table); ++i) { + if (title_table[i][0] == uc) + return title_table[i][1] ? title_table[i][1] : uc; + } + } + + return uc; +} + +/** + * Converts a character to lower case. + */ +Uchar32 GUIAPI UCharToLower (Uchar32 uc) +{ + int t = TYPE (uc); + if (t == UCHAR_CATEGORY_UPPERCASE_LETTER) { + Uchar32 val = ATTTABLE (uc >> 8, uc & 0xff); + if (val >= 0x1000000) { + const unsigned char *p = special_case_table + val - 0x1000000; + return utf8_get_char_value (NULL, 0, p, -1); + } + else { + /* Not all uppercase letters are guaranteed to have a lowercase + * equivalent. If this is the case, val will be zero. */ + return val ? val : uc; + } + } + else if (t == UCHAR_CATEGORY_TITLECASE_LETTER) { + unsigned int i; + for (i = 0; i < TABLESIZE (title_table); ++i) { + if (title_table[i][0] == uc) + return title_table[i][2]; + } + } + return uc; +} + +/** + * Converts a chv to the titlecase. + */ +Uchar32 GUIAPI UCharToTitle (Uchar32 uc) +{ + unsigned int i; + for (i = 0; i < TABLESIZE (title_table); ++i) { + if (title_table[i][0] == uc || title_table[i][1] == uc + || title_table[i][2] == uc) + return title_table[i][0]; + } + + if (TYPE (uc) == UCHAR_CATEGORY_LOWERCASE_LETTER) + return UCharToUpper (uc); + + return uc; +} + +/** Converts a chv to full-width. */ +Uchar32 GUIAPI UCharToFullWidth (Uchar32 uc) +{ + if (uc == 0x20) + return 0x3000; + + if (uc >= 0x21 && uc <= 0x7E) { + return uc + (0xFF01 - 0x21); + } + + return uc; +} + +/** Converts a chv to single-width. */ +Uchar32 GUIAPI UCharToSingleWidth (Uchar32 uc) +{ + if (uc == 0x3000) + return 0x20; + + if (uc >= 0xFF01 && uc <= 0xFF5E) { + return uc - (0xFF01 - 0x21); + } + + return uc; +} + +struct UCharMap { + Uchar32 one, other; +}; + +static const struct UCharMap kana_small_to_full_size_table [] = { + { /*ぁ*/ 0x3041, /*あ*/ 0x3042}, + { /*ぃ*/ 0x3043, /*い*/ 0x3044}, + { /*ぅ*/ 0x3045, /*う*/ 0x3046}, + { /*ぇ*/ 0x3047, /*え*/ 0x3048}, + { /*ぉ*/ 0x3049, /*お*/ 0x304A}, + { /*ゕ*/ 0x3095, /*か*/ 0x304B}, + { /*ゖ*/ 0x3096, /*け*/ 0x3051}, + { /*っ*/ 0x3063, /*つ*/ 0x3064}, + { /*ゃ*/ 0x3083, /*や*/ 0x3084}, + { /*ゅ*/ 0x3085, /*ゆ*/ 0x3086}, + { /*ょ*/ 0x3087, /*よ*/ 0x3088}, + { /*ゎ*/ 0x308E, /*わ*/ 0x308F}, + { /*ァ*/ 0x30A1, /*ア*/ 0x30A2}, + { /*ィ*/ 0x30A3, /*イ*/ 0x30A4}, + { /*ゥ*/ 0x30A5, /*ウ*/ 0x30A6}, + { /*ェ*/ 0x30A7, /*エ*/ 0x30A8}, + { /*ォ*/ 0x30A9, /*オ*/ 0x30AA}, + { /*ヵ*/ 0x30F5, /*カ*/ 0x30AB}, + { /*ㇰ*/ 0x31F0, /*ク*/ 0x30AF}, + { /*ヶ*/ 0x30F6, /*ケ*/ 0x30B1}, + { /*ㇱ*/ 0x31F1, /*シ*/ 0x30B7}, + { /*ㇲ*/ 0x31F2, /*ス*/ 0x30B9}, + { /*ッ*/ 0x30C3, /*ツ*/ 0x30C4}, + { /*ㇳ*/ 0x31F3, /*ト*/ 0x30C8}, + { /*ㇴ*/ 0x31F4, /*ヌ*/ 0x30CC}, + { /*ㇵ*/ 0x31F5, /*ハ*/ 0x30CF}, + { /*ㇶ*/ 0x31F6, /*ヒ*/ 0x30D2}, + { /*ㇷ*/ 0x31F7, /*フ*/ 0x30D5}, + { /*ㇸ*/ 0x31F8, /*ヘ*/ 0x30D8}, + { /*ㇹ*/ 0x31F9, /*ホ*/ 0x30DB}, + { /*ㇺ*/ 0x31FA, /*ム*/ 0x30E0}, + { /*ャ*/ 0x30E3, /*ヤ*/ 0x30E4}, + { /*ュ*/ 0x30E5, /*ユ*/ 0x30E6}, + { /*ョ*/ 0x30E7, /*ヨ*/ 0x30E8}, + { /*ㇻ*/ 0x31FB, /*ラ*/ 0x30E9}, + { /*ㇼ*/ 0x31FC, /*リ*/ 0x30EA}, + { /*ㇽ*/ 0x31FD, /*ル*/ 0x30EB}, + { /*ㇾ*/ 0x31FE, /*レ*/ 0x30EC}, + { /*ㇿ*/ 0x31FF, /*ロ*/ 0x30ED}, + { /*ヮ*/ 0x30EE, /*ワ*/ 0x30EF}, + { /*ァ*/ 0xFF67, /*ア*/ 0xFF71}, + { /*ィ*/ 0xFF68, /*イ*/ 0xFF72}, + { /*ゥ*/ 0xFF69, /*ウ*/ 0xFF73}, + { /*ェ*/ 0xFF6A, /*エ*/ 0xFF74}, + { /*ォ*/ 0xFF6B, /*オ*/ 0xFF75}, + { /*ッ*/ 0xFF6F, /*ツ*/ 0xFF82}, + { /*ャ*/ 0xFF6C, /*ヤ*/ 0xFF94}, + { /*ュ*/ 0xFF6D, /*ユ*/ 0xFF95}, + { /*ョ*/ 0xFF6E, /*ヨ*/ 0xFF96}, +}; + +/** Converts a chv to full-size Kana. */ +Uchar32 GUIAPI UCharToFullSizeKana (Uchar32 uc) +{ + unsigned int lower = 0; + unsigned int upper = TABLESIZE (kana_small_to_full_size_table) - 1; + int mid = TABLESIZE (kana_small_to_full_size_table) / 2; + + if (uc < kana_small_to_full_size_table[lower].one + || uc > kana_small_to_full_size_table[upper].one) + return uc; + + do { + if (uc < kana_small_to_full_size_table[mid].one) + upper = mid - 1; + else if (uc > kana_small_to_full_size_table[mid].one) + lower = mid + 1; + else + return kana_small_to_full_size_table[mid].other; + + mid = (lower + upper) / 2; + + } while (lower <= upper); + + return uc; +} + +#if 0 // VincentWei: use kana_small_to_full_size_table instead +static const struct UCharMap kana_full_size_to_small_table [] = { + { /*あ*/ 0x3041, /*ぁ*/ 0x3041}, + { /*い*/ 0x3043, /*ぃ*/ 0x3043}, + { /*う*/ 0x3045, /*ぅ*/ 0x3045}, + { /*え*/ 0x3047, /*ぇ*/ 0x3047}, + { /*お*/ 0x3049, /*ぉ*/ 0x3049}, + { /*か*/ 0x304A, /*ゕ*/ 0x3095}, + { /*け*/ 0x3050, /*ゖ*/ 0x3096}, + { /*つ*/ 0x3063, /*っ*/ 0x3063}, + { /*や*/ 0x3083, /*ゃ*/ 0x3083}, + { /*ゆ*/ 0x3085, /*ゅ*/ 0x3085}, + { /*よ*/ 0x3087, /*ょ*/ 0x3087}, + { /*わ*/ 0x308E, /*ゎ*/ 0x308E}, + { /*ア*/ 0x30A1, /*ァ*/ 0x30A1}, + { /*イ*/ 0x30A3, /*ィ*/ 0x30A3}, + { /*ウ*/ 0x30A5, /*ゥ*/ 0x30A5}, + { /*エ*/ 0x30A7, /*ェ*/ 0x30A7}, + { /*オ*/ 0x30A9, /*ォ*/ 0x30A9}, + { /*カ*/ 0x30AA, /*ヵ*/ 0x30F5}, + { /*ク*/ 0x30AE, /*ㇰ*/ 0x31F0}, + { /*ケ*/ 0x30B0, /*ヶ*/ 0x30F6}, + { /*シ*/ 0x30B6, /*ㇱ*/ 0x31F1}, + { /*ス*/ 0x30B8, /*ㇲ*/ 0x31F2}, + { /*ツ*/ 0x30C3, /*ッ*/ 0x30C3}, + { /*ト*/ 0x30C7, /*ㇳ*/ 0x31F3}, + { /*ヌ*/ 0x30CB, /*ㇴ*/ 0x31F4}, + { /*ハ*/ 0x30CE, /*ㇵ*/ 0x31F5}, + { /*ヒ*/ 0x30D1, /*ㇶ*/ 0x31F6}, + { /*フ*/ 0x30D4, /*ㇷ*/ 0x31F7}, + { /*ヘ*/ 0x30D7, /*ㇸ*/ 0x31F8}, + { /*ホ*/ 0x30DA, /*ㇹ*/ 0x31F9}, + { /*ム*/ 0x30DF, /*ㇺ*/ 0x31FA}, + { /*ヤ*/ 0x30E3, /*ャ*/ 0x30E3}, + { /*ユ*/ 0x30E5, /*ュ*/ 0x30E5}, + { /*ヨ*/ 0x30E7, /*ョ*/ 0x30E7}, + { /*ラ*/ 0x30E8, /*ㇻ*/ 0x31FB}, + { /*リ*/ 0x30E9, /*ㇼ*/ 0x31FC}, + { /*ル*/ 0x30EA, /*ㇽ*/ 0x31FD}, + { /*レ*/ 0x30EB, /*ㇾ*/ 0x31FE}, + { /*ロ*/ 0x30EC, /*ㇿ*/ 0x31FF}, + { /*ワ*/ 0x30EE, /*ヮ*/ 0x30EE}, + { /*ア*/ 0xFF70, /*ァ*/ 0xFF67}, + { /*イ*/ 0xFF71, /*ィ*/ 0xFF68}, + { /*ウ*/ 0xFF72, /*ゥ*/ 0xFF69}, + { /*エ*/ 0xFF73, /*ェ*/ 0xFF6A}, + { /*オ*/ 0xFF74, /*ォ*/ 0xFF6B}, + { /*ツ*/ 0xFF81, /*ッ*/ 0xFF6F}, + { /*ヤ*/ 0xFF93, /*ャ*/ 0xFF6C}, + { /*ユ*/ 0xFF94, /*ュ*/ 0xFF6D}, + { /*ヨ*/ 0xFF95, /*ョ*/ 0xFF6E}, +}; + +/** Converts a chv to small Kana. */ +Uchar32 GUIAPI UCharToSmallKana (Uchar32 uc) +{ + unsigned int lower = 0; + unsigned int upper = TABLESIZE (kana_full_size_to_small_table) - 1; + int mid = TABLESIZE (kana_full_size_to_small_table) / 2; + + if (uc < kana_full_size_to_small_table[lower].one + || uc < kana_full_size_to_small_table[upper].one) + return uc; + + do { + if (uc < kana_full_size_to_small_table[mid].one) + upper = mid - 1; + else if (uc > kana_full_size_to_small_table[mid].one) + lower = mid + 1; + else + return kana_full_size_to_small_table[mid].other; + + mid = (lower + upper) / 2; + + } while (lower <= upper); + + return uc; +} +#endif // VincentWei: use kana_small_to_full_size_table instead + +/** Converts a chv to small Kana. */ +Uchar32 GUIAPI UCharToSmallKana (Uchar32 uc) +{ + unsigned int lower = 0; + unsigned int upper = TABLESIZE (kana_small_to_full_size_table) - 1; + int mid = TABLESIZE (kana_small_to_full_size_table) / 2; + + if (uc < kana_small_to_full_size_table[lower].other + || uc > kana_small_to_full_size_table[upper].other) + return uc; + + do { + if (uc < kana_small_to_full_size_table[mid].other) + upper = mid - 1; + else if (uc > kana_small_to_full_size_table[mid].other) + lower = mid + 1; + else + return kana_small_to_full_size_table[mid].one; + + mid = (lower + upper) / 2; + + } while (lower <= upper); + + return uc; +} + +#endif /* _MGCHARSET_UNICODE */ diff --git a/src/font/charset.c b/src/font/charset.c index 5bb00177..26971559 100644 --- a/src/font/charset.c +++ b/src/font/charset.c @@ -63,7 +63,9 @@ static Achar32 sb_get_char_value (const unsigned char* pre_mchar, int pre_len, return (Achar32)(*cur_mchar); } -static unsigned int sb_char_type (Achar32 chv) +#define sb_char_type __mg_sb_char_type + +unsigned int __mg_sb_char_type (Achar32 chv) { unsigned int ch_type = ACHAR_BASIC_UNKNOWN; @@ -3424,1031 +3426,10 @@ static CHARSETOPS CharsetOps_jisx0208_1 = { #endif /* _SHIFTJIS */ #ifdef _MGCHARSET_UNICODE - -/************************* UTF-8 Specific Operations ************************/ -static int utf8_len_first_char (const unsigned char* mstr, int len) -{ - int t, c = *((unsigned char *)(mstr++)); - - if (c & 0x80) { - int n = 1, ch_len = 0; - while (c & (0x80 >> n)) - n++; - - if (n > len) - return 0; - - ch_len = n; - while (--n > 0) { - t = *((unsigned char *)(mstr++)); - - if ((!(t & 0x80)) || (t & 0x40)) - return 0; - } - - return ch_len; - } - - /* for ascii character */ - return 1; -} - -static Achar32 utf8_get_char_value (const unsigned char* pre_mchar, int pre_len, - const unsigned char* cur_mchar, int cur_len) -{ - Uchar32 wc = *((unsigned char *)(cur_mchar++)); - int n, t; - - if (wc & 0x80) { - n = 1; - while (wc & (0x80 >> n)) - n++; - - wc &= (1 << (8-n)) - 1; - while (--n > 0) { - t = *((unsigned char *)(cur_mchar++)); - - wc = (wc << 6) | (t & 0x3F); - } - } - - return wc; -} - -#include "unicode-tables.h" -#include "unicode-break-tables.h" - -#define ATTR_TABLE(Page) (((Page) <= UCHAR_LAST_PAGE_PART1) \ - ? attr_table_part1[Page] \ - : attr_table_part2[(Page) - 0xe00]) - -#define ATTTABLE(Page, Char) \ - ((ATTR_TABLE(Page) == UCHAR_MAX_TABLE_INDEX) ? 0 : (attr_data[ATTR_TABLE(Page)][Char])) - -#define TTYPE_PART1(Page, Char) \ - ((type_table_part1[Page] >= UCHAR_MAX_TABLE_INDEX) \ - ? (type_table_part1[Page] - UCHAR_MAX_TABLE_INDEX) \ - : (type_data[type_table_part1[Page]][Char])) - -#define TTYPE_PART2(Page, Char) \ - ((type_table_part2[Page] >= UCHAR_MAX_TABLE_INDEX) \ - ? (type_table_part2[Page] - UCHAR_MAX_TABLE_INDEX) \ - : (type_data[type_table_part2[Page]][Char])) - -#define TYPE(Char) \ - (((Char) <= UCHAR_LAST_CHAR_PART1) \ - ? TTYPE_PART1 ((Char) >> 8, (Char) & 0xff) \ - : (((Char) >= 0xe0000 && (Char) <= UCHAR_LAST_CHAR) \ - ? TTYPE_PART2 (((Char) - 0xe0000) >> 8, (Char) & 0xff) \ - : UCHAR_CATEGORY_UNASSIGNED)) - -#define IS(Type, Class) (((unsigned int)1 << (Type)) & (Class)) -#define OR(Type, Rest) (((unsigned int)1 << (Type)) | (Rest)) - -#define ISALPHA(Type) IS ((Type), \ - OR (UCHAR_CATEGORY_LOWERCASE_LETTER, \ - OR (UCHAR_CATEGORY_UPPERCASE_LETTER, \ - OR (UCHAR_CATEGORY_TITLECASE_LETTER, \ - OR (UCHAR_CATEGORY_MODIFIER_LETTER, \ - OR (UCHAR_CATEGORY_OTHER_LETTER, 0)))))) - -#define ISALDIGIT(Type) IS ((Type), \ - OR (UCHAR_CATEGORY_DECIMAL_NUMBER, \ - OR (UCHAR_CATEGORY_LETTER_NUMBER, \ - OR (UCHAR_CATEGORY_OTHER_NUMBER, \ - OR (UCHAR_CATEGORY_LOWERCASE_LETTER, \ - OR (UCHAR_CATEGORY_UPPERCASE_LETTER, \ - OR (UCHAR_CATEGORY_TITLECASE_LETTER, \ - OR (UCHAR_CATEGORY_MODIFIER_LETTER, \ - OR (UCHAR_CATEGORY_OTHER_LETTER, 0))))))))) - -#define ISMARK(Type) IS ((Type), \ - OR (UCHAR_CATEGORY_NON_SPACING_MARK, \ - OR (UCHAR_CATEGORY_SPACING_MARK, \ - OR (UCHAR_CATEGORY_ENCLOSING_MARK, 0)))) - -#define ISZEROWIDTHTYPE(Type) IS ((Type), \ - OR (UCHAR_CATEGORY_NON_SPACING_MARK, \ - OR (UCHAR_CATEGORY_ENCLOSING_MARK, \ - OR (UCHAR_CATEGORY_FORMAT, 0)))) - -#define TPROP_PART1(Page, Char) \ - ((break_property_table_part1[Page] >= UCHAR_MAX_TABLE_INDEX) \ - ? (break_property_table_part1[Page] - UCHAR_MAX_TABLE_INDEX) \ - : (break_property_data[break_property_table_part1[Page]][Char])) - -#define TPROP_PART2(Page, Char) \ - ((break_property_table_part2[Page] >= UCHAR_MAX_TABLE_INDEX) \ - ? (break_property_table_part2[Page] - UCHAR_MAX_TABLE_INDEX) \ - : (break_property_data[break_property_table_part2[Page]][Char])) - -#define PROP(Char) \ - (((Char) <= UCHAR_LAST_CHAR_PART1) \ - ? TPROP_PART1 ((Char) >> 8, (Char) & 0xff) \ - : (((Char) >= 0xe0000 && (Char) <= UCHAR_LAST_CHAR) \ - ? TPROP_PART2 (((Char) - 0xe0000) >> 8, (Char) & 0xff) \ - : UCHAR_BREAK_UNKNOWN)) - -static unsigned int unicode_char_type (Achar32 chv) -{ - unsigned int mchar_type = ACHAR_BASIC_UNKNOWN; - unsigned int basic_type = 0, break_type = 0; - - chv = REAL_ACHAR(chv); - basic_type = TYPE(chv); - break_type = PROP(chv); - - if (chv < 0x80) - mchar_type = sb_char_type(chv); - else if (break_type == UCHAR_BREAK_CARRIAGE_RETURN) - mchar_type = ACHAR_BASIC_CR; - else if (break_type == UCHAR_BREAK_LINE_FEED) - mchar_type = ACHAR_BASIC_LF; - else if (break_type == UCHAR_BREAK_NEXT_LINE) - mchar_type = ACHAR_BASIC_LF; - else if (break_type == UCHAR_BREAK_SPACE) - mchar_type = ACHAR_BASIC_SPACE; - else if (chv != 0x00AD && ISZEROWIDTHTYPE (basic_type)) - mchar_type = ACHAR_BASIC_ZEROWIDTH; - else if ((chv >= 0x1160 && chv < 0x1200) - || chv == 0x200B) - mchar_type = ACHAR_BASIC_ZEROWIDTH; - - return (break_type << 24) | (basic_type << 16) | mchar_type; -} - -#define _USE_UNIBIDI - -#ifdef _USE_UNIBIDI - -enum _BidiCharTypeLinearEnum { -#define _UNIBIDI_ADD_TYPE(TYPE,SYMBOL) TYPE, -#include "unicode-bidi-types-list.inc" -#undef _UNIBIDI_ADD_TYPE - _UNIBIDI_NUM_TYPES -}; - -#include "unicode-bidi-type-table.inc" - -/* Map _BidiCharTypeLinearEnum to BidiType. */ -static const BidiType linear_enum_to_bidi_type[] = { -#define _UNIBIDI_ADD_TYPE(TYPE,SYMBOL) BIDI_TYPE_##TYPE, -#include "unicode-bidi-types-list.inc" -#undef _UNIBIDI_ADD_TYPE -}; - -static BidiType __mg_unicode_bidi_char_type(Achar32 ch) -{ - ch = REAL_ACHAR(ch); - return linear_enum_to_bidi_type[UNIBIDI_GET_BIDI_TYPE(ch)]; -} - -BidiType GUIAPI UCharGetBidiType(Uchar32 uc) -{ - return linear_enum_to_bidi_type[UNIBIDI_GET_BIDI_TYPE(uc)]; -} - -void GUIAPI UStrGetBidiTypes(const Uchar32 *str, int len, BidiType *btypes) -{ - register int i = len; - for (; i; i--) { - *btypes++ = linear_enum_to_bidi_type[UNIBIDI_GET_BIDI_TYPE(*str)]; - str++; - } -} - -#include "unicode-bidi-brackets-table.inc" -#include "unicode-bidi-brackets-type-table.inc" - -#define UNIBIDI_TYPE_BRACKET_OPEN 2 - -BidiBracketType UCharGetBracketType(Uchar32 ch) -{ - BidiBracketType bracket_type; - register Uint8 char_type = UNIBIDI_GET_BRACKET_TYPE (ch); - - /* The bracket type from the table may be: - 0 - Not a bracket - 1 - a bracket - 2 - closing. - - This will be recodeded into the BidiBracketType as having a - bracket_id = 0 if the character is not a bracket. - */ - BOOL is_open = FALSE; - - if (char_type == 0) - bracket_type = BIDI_BRACKET_NONE; - else { - is_open = (char_type & UNIBIDI_TYPE_BRACKET_OPEN) != 0; - bracket_type = UNIBIDI_GET_BRACKETS (ch) & BIDI_BRACKET_CHAR_MASK; - } - - if (is_open) - bracket_type |= BIDI_BRACKET_OPEN_MASK; - - return bracket_type; -} - -void UStrGetBracketTypes(const Uchar32 *str, int len, - const BidiType *types, BidiBracketType *btypes) -{ - int i; - for (i = 0; i < len; i++) { - /* Optimization that bracket must be of types ON */ - if (*types == BIDI_TYPE_ON) - *btypes = UCharGetBracketType (*str); - else - *btypes = BIDI_BRACKET_NONE; - - btypes++; - types++; - str++; - } -} - -#include "unicode-bidi-mirroring-table.inc" - -static BOOL __mg_unicode_bidi_mirror_char(Achar32 ch, Achar32* mirrored_ch) -{ - register Achar32 result; - register Uint32 mbc_mask; - - mbc_mask = ch & ACHAR_MBC_FLAG; - ch = REAL_ACHAR(ch); - result = UNIBIDI_GET_MIRRORING(ch); - if (mirrored_ch) - *mirrored_ch = result; - result |= mbc_mask; - - return ch != result ? TRUE : FALSE; -} - -BOOL GUIAPI UCharGetMirror(Uchar32 ch, Uchar32* mirrored_ch) -{ - register Achar32 result; - - result = UNIBIDI_GET_MIRRORING(ch); - if (mirrored_ch) - *mirrored_ch = result; - return ch != result ? TRUE : FALSE; -} - -#else - -#include "unicode-bidi-tables.h" - -static BidiType __mg_unicode_bidi_char_type (Achar32 chv) -{ - Achar32 chv_first = 0; - Achar32 chv_last = (Achar32)TABLESIZE (__mg___mg_unicode_bidi_char_type_map); - Achar32 chv_mid; - - chv = REAL_ACHAR(chv); - while (chv_last >= chv_first) { - chv_mid = (chv_first + chv_last)/2; - - if ((__mg___mg_unicode_bidi_char_type_map[chv_mid].chv <= chv) - && ((__mg___mg_unicode_bidi_char_type_map[chv_mid].chv + __mg___mg_unicode_bidi_char_type_map[chv_mid].count) > chv)) { - return __mg___mg_unicode_bidi_char_type_map[chv_mid].type; - } - - if (chv >= (__mg___mg_unicode_bidi_char_type_map[chv_mid].chv + __mg___mg_unicode_bidi_char_type_map[chv_mid].count)) { - chv_first = chv_mid + 1; - } - else { - if (chv < __mg___mg_unicode_bidi_char_type_map[chv_mid].chv) - chv_last = chv_mid - 1; - else - chv_last = chv_mid; - } - } - - return BIDI_TYPE_LTR; -} - -static BOOL __mg_unicode_bidi_mirror_char (Achar32 chv, Achar32* mirrored) -{ - return get_mirror_char (__mg_unicode_mirror_table, - TABLESIZE (__mg_unicode_mirror_table), chv, mirrored); -} - -BidiType GUIAPI UCharGetBidiType(Uchar32 uc) -{ - return __mg_unicode_bidi_char_type(uc); -} - -BidiBracketType GUIAPI UCharGetBracketType(Uchar32 uc) -{ - BidiBracketType bracket_type; - unsigned int lower = 0; - unsigned int upper = TABLESIZE (__mg_unicode_bracket_table) - 1; - int mid = TABLESIZE (__mg_unicode_bracket_table) / 2; - - if (uc < __mg_unicode_bracket_table[lower].chv || - uc > __mg_unicode_bracket_table[upper].chv) - return BIDI_BRACKET_NONE; - - do { - if (uc < __mg_unicode_bracket_table[mid].chv) - upper = mid - 1; - else if (uc > __mg_unicode_bracket_table[mid].chv) - lower = mid + 1; - else - goto found; - - mid = (lower + upper) / 2; - - } while (lower <= upper); - - return BIDI_BRACKET_NONE; - -found: - bracket_type = __mg_unicode_bracket_table[mid].chv + - __mg_unicode_bracket_table[mid].bracket_off; - bracket_type &= BIDI_BRACKET_CHAR_MASK; - if (__mg_unicode_bracket_table[mid].type == UNIBIDI_BRACKET_OPEN) - bracket_type |= BIDI_BRACKET_OPEN_MASK; - - return bracket_type; -} - -void GUIAPI UStrGetBidiTypes(const Uchar32 *str, int len, BidiType *btypes) -{ - register int i = len; - for (; i; i--) { - *btypes++ = UCharGetBracketType(*str); - str++; - } -} - -/** The function returns the mirror character of a UNICODE character. */ -BOOL GUIAPI UCharGetMirror(Uchar32 uc, Uchar32* mirrored) -{ - return __mg_unicode_bidi_mirror_char (uc, mirrored); -} - -#endif /* !_USE_UNIBIDI */ - -static int utf8_nr_chars_in_str (const unsigned char* mstr, int mstrlen) -{ - int charlen; - int n = 0; - int left = mstrlen; - - while (left >= 0) { - charlen = utf8_len_first_char (mstr, left); - if (charlen > 0) - n ++; - - left -= charlen; - mstr += charlen; - } - - return n; -} - -static int utf8_is_this_charset (const unsigned char* charset) -{ - int i; - char name [LEN_LOGFONT_NAME_FIELD + 1]; - - for (i = 0; i < LEN_LOGFONT_NAME_FIELD + 1; i++) { - if (charset [i] == '\0') - break; - name [i] = toupper (charset [i]); - } - name [i] = '\0'; - - if (strstr (name, "UTF") && strstr (name, "8")) - return 0; - - return 1; -} - -static int utf8_len_first_substr (const unsigned char* mstr, int mstrlen) -{ - int ch_len; - int sub_len = 0; - - while (mstrlen > 0) { - ch_len = utf8_len_first_char (mstr, mstrlen); - - if (ch_len == 0) - break; - - sub_len += ch_len; - mstrlen -= ch_len; - mstr += ch_len; - } - - return sub_len; -} - -static const unsigned char* utf8_get_next_word (const unsigned char* mstr, - int mstrlen, WORDINFO* word_info) -{ - const unsigned char* mchar = mstr; - int ch_len; - Uchar32 wc; - - word_info->len = 0; - word_info->delimiter = '\0'; - word_info->nr_delimiters = 0; - - if (mstrlen == 0) return NULL; - - while (mstrlen > 0) { - ch_len = utf8_len_first_char (mchar, mstrlen); - - if (ch_len == 0) - break; - - wc = utf8_get_char_value (NULL, 0, mchar, 0); - if (wc > 0x0FFF) { - if (word_info->len) - return mstr + word_info->len + word_info->nr_delimiters; - else { /* Treate the first char as a word */ - word_info->len = ch_len; - return mstr + word_info->len + word_info->nr_delimiters; - } - } - - switch (mchar[0]) { - case ' ': - case '\t': - case '\n': - case '\r': - if (word_info->delimiter == '\0') { - word_info->delimiter = mchar[0]; - word_info->nr_delimiters ++; - } - else if (word_info->delimiter == mchar[0]) - word_info->nr_delimiters ++; - else - return mstr + word_info->len + word_info->nr_delimiters; - - break; - - default: - if (word_info->delimiter != '\0') - return mstr + word_info->len + word_info->nr_delimiters; - - word_info->len += ch_len; - break; - } - - mchar += ch_len; - mstrlen -= ch_len; - } - - return mstr + word_info->len + word_info->nr_delimiters; -} - -static int utf8_pos_first_char (const unsigned char* mstr, int mstrlen) -{ - int ch_len; - int pos = 0; - - while (mstrlen > 0) { - ch_len = utf8_len_first_char (mstr, mstrlen); - - /*charset encoding mismatch*/ - if (ch_len == 0) - return -1; - - if (ch_len > 0) - return pos; - - pos += ch_len; - mstrlen -= ch_len; - mstr += ch_len; - } - - return -1; -} - -static int utf8_conv_from_uc32 (Uchar32 wc, unsigned char* mchar) -{ - int first, len; - - if (wc < 0x80) { - first = 0; - len = 1; - } - else if (wc < 0x800) { - first = 0xC0; - len = 2; - } - else if (wc < 0x10000) { - first = 0xE0; - len = 3; - } - else if (wc < 0x200000) { - first = 0xF0; - len = 4; - } - else if (wc < 0x400000) { - first = 0xF8; - len = 5; - } - else { - first = 0xFC; - len = 6; - } - - switch (len) { - case 6: - mchar [5] = (wc & 0x3f) | 0x80; wc >>= 6; /* Fall through */ - case 5: - mchar [4] = (wc & 0x3f) | 0x80; wc >>= 6; /* Fall through */ - case 4: - mchar [3] = (wc & 0x3f) | 0x80; wc >>= 6; /* Fall through */ - case 3: - mchar [2] = (wc & 0x3f) | 0x80; wc >>= 6; /* Fall through */ - case 2: - mchar [1] = (wc & 0x3f) | 0x80; wc >>= 6; /* Fall through */ - case 1: - mchar [0] = wc | first; - } - - return len; -} - -static CHARSETOPS CharsetOps_utf8 = { - 0x7FFFFFFF, - 6, - FONT_CHARSET_UTF8, - 0, - utf8_len_first_char, - utf8_get_char_value, - NULL, - unicode_char_type, - utf8_nr_chars_in_str, - utf8_is_this_charset, - utf8_len_first_substr, - utf8_get_next_word, - utf8_pos_first_char, - __mg_unicode_bidi_char_type, - __mg_unicode_bidi_mirror_char, - NULL, - utf8_conv_from_uc32, -}; - -/************************* UTF-16LE Specific Operations ***********************/ -static int utf16le_len_first_char (const unsigned char* mstr, int len) -{ - Uchar16 w1, w2; - - if (len < 2) - return 0; - - w1 = MAKEWORD16 (mstr[0], mstr[1]); - - if (w1 < 0xD800 || w1 > 0xDFFF) - return 2; - - if (w1 >= 0xD800 && w1 <= 0xDBFF) { - if (len < 4) - return 0; - w2 = MAKEWORD16 (mstr[2], mstr[3]); - if (w2 < 0xDC00 || w2 > 0xDFFF) - return 0; - } - - return 4; -} - -static Achar32 utf16le_get_char_value (const unsigned char* pre_mchar, - int pre_len, const unsigned char* cur_mchar, int cur_len) -{ - Uchar16 w1, w2; - Uchar32 wc; - - w1 = MAKEWORD16 (cur_mchar[0], cur_mchar[1]); - - if (w1 < 0xD800 || w1 > 0xDFFF) - return w1; - - w2 = MAKEWORD16 (cur_mchar[2], cur_mchar[3]); - - wc = w1; - wc <<= 10; - wc |= (w2 & 0x03FF); - wc += 0x10000; - - return wc; -} - -static int utf16le_nr_chars_in_str (const unsigned char* mstr, int mstrlen) -{ - int charlen; - int n = 0; - int left = mstrlen; - - while (left >= 0) { - charlen = utf16le_len_first_char (mstr, left); - if (charlen > 0) - n ++; - - left -= charlen; - mstr += charlen; - } - - return n; -} - -static int utf16le_is_this_charset (const unsigned char* charset) -{ - int i; - char name [LEN_LOGFONT_NAME_FIELD + 1]; - - for (i = 0; i < LEN_LOGFONT_NAME_FIELD + 1; i++) { - if (charset [i] == '\0') - break; - name [i] = toupper (charset [i]); - } - name [i] = '\0'; - - if (strstr (name, "UTF") && strstr (name, "16LE")) - return 0; - - return 1; -} - -static int utf16le_len_first_substr (const unsigned char* mstr, int mstrlen) -{ - int ch_len; - int sub_len = 0; - - while (mstrlen > 0) { - ch_len = utf16le_len_first_char (mstr, mstrlen); - - if (ch_len == 0) - break; - - sub_len += ch_len; - mstrlen -= ch_len; - mstr += ch_len; - } - - return sub_len; -} - -static const unsigned char* utf16le_get_next_word (const unsigned char* mstr, - int mstrlen, WORDINFO* word_info) -{ - const unsigned char* mchar = mstr; - Uchar32 wc; - int ch_len; - - word_info->len = 0; - word_info->delimiter = '\0'; - word_info->nr_delimiters = 0; - - if (mstrlen == 0) return NULL; - - while (mstrlen > 0) { - ch_len = utf16le_len_first_char (mchar, mstrlen); - - if (ch_len == 0) - break; - - wc = utf16le_get_char_value (NULL, 0, mchar, 0); - if (wc > 0x0FFF) { - if (word_info->len) - return mstr + word_info->len + word_info->nr_delimiters; - else { /* Treate the first char as a word */ - word_info->len = ch_len; - return mstr + word_info->len + word_info->nr_delimiters; - } - } - - switch (wc) { - case ' ': - case '\t': - case '\n': - case '\r': - if (word_info->delimiter == '\0') { - word_info->delimiter = (unsigned char)wc; - word_info->nr_delimiters += ch_len; - } - else if (word_info->delimiter == (unsigned char)wc) - word_info->nr_delimiters += ch_len; - else - return mstr + word_info->len + word_info->nr_delimiters; - break; - - default: - if (word_info->delimiter != '\0') - return mstr + word_info->len + word_info->nr_delimiters; - - word_info->len += ch_len; - break; - } - - mstrlen -= ch_len; - mchar += ch_len; - } - - return mstr + word_info->len + word_info->nr_delimiters; -} - -static int utf16le_pos_first_char (const unsigned char* mstr, int mstrlen) -{ - int ch_len; - int pos = 0; - - while (mstrlen > 0) { - ch_len = utf16le_len_first_char (mstr, mstrlen); - - if (ch_len > 0) - return pos; - - pos += ch_len; - mstrlen -= ch_len; - mstr += ch_len; - } - - return -1; -} - -static int utf16le_conv_from_uc32 (Uchar32 wc, unsigned char* mchar) -{ - Uchar16 w1, w2; - - if (wc > 0x10FFFF) { - return 0; - } - - if (wc < 0x10000) { - mchar [0] = LOBYTE (wc); - mchar [1] = HIBYTE (wc); - return 2; - } - - wc -= 0x10000; - w1 = 0xD800; - w2 = 0xDC00; - - w1 |= (wc >> 10); - w2 |= (wc & 0x03FF); - - mchar [0] = LOBYTE (w1); - mchar [1] = HIBYTE (w1); - mchar [2] = LOBYTE (w2); - mchar [3] = HIBYTE (w2); - return 4; -} - -static CHARSETOPS CharsetOps_utf16le = { - 0x7FFFFFFF, - 4, - FONT_CHARSET_UTF16LE, - 0, - utf16le_len_first_char, - utf16le_get_char_value, - NULL, - unicode_char_type, - utf16le_nr_chars_in_str, - utf16le_is_this_charset, - utf16le_len_first_substr, - utf16le_get_next_word, - utf16le_pos_first_char, - __mg_unicode_bidi_char_type, - __mg_unicode_bidi_mirror_char, - NULL, - utf16le_conv_from_uc32 -}; - -/************************* UTF-16BE Specific Operations ***********************/ -static int utf16be_len_first_char (const unsigned char* mstr, int len) -{ - Uchar16 w1, w2; - - if (len < 2) - return 0; - - w1 = MAKEWORD16 (mstr[1], mstr[0]); - - if (w1 < 0xD800 || w1 > 0xDFFF) - return 2; - - if (w1 >= 0xD800 && w1 <= 0xDBFF) { - if (len < 4) - return 0; - w2 = MAKEWORD16 (mstr[3], mstr[2]); - if (w2 < 0xDC00 || w2 > 0xDFFF) - return 0; - } - - return 4; -} - -static Achar32 utf16be_get_char_value (const unsigned char* pre_mchar, - int pre_len, const unsigned char* cur_mchar, int cur_len) -{ - Uchar16 w1, w2; - Uchar32 wc; - - w1 = MAKEWORD16 (cur_mchar[1], cur_mchar[0]); - - if (w1 < 0xD800 || w1 > 0xDFFF) - return w1; - - w2 = MAKEWORD16 (cur_mchar[3], cur_mchar[2]); - - wc = w1; - wc <<= 10; - wc |= (w2 & 0x03FF); - wc += 0x10000; - - return wc; -} - -static int utf16be_nr_chars_in_str (const unsigned char* mstr, int mstrlen) -{ - int charlen; - int n = 0; - int left = mstrlen; - - while (left >= 0) { - charlen = utf16be_len_first_char (mstr, left); - if (charlen > 0) - n ++; - - left -= charlen; - mstr += charlen; - } - - return n; -} - -static int utf16be_is_this_charset (const unsigned char* charset) -{ - int i; - char name [LEN_LOGFONT_NAME_FIELD + 1]; - - for (i = 0; i < LEN_LOGFONT_NAME_FIELD + 1; i++) { - if (charset [i] == '\0') - break; - name [i] = toupper (charset [i]); - } - name [i] = '\0'; - - if (strstr (name, "UTF") && strstr (name, "16BE")) - return 0; - - return 1; -} - -static int utf16be_len_first_substr (const unsigned char* mstr, int mstrlen) -{ - int ch_len; - int sub_len = 0; - - while (mstrlen > 0) { - ch_len = utf16be_len_first_char (mstr, mstrlen); - - if (ch_len == 0) - break; - - sub_len += ch_len; - mstrlen -= ch_len; - mstr += ch_len; - } - - return sub_len; -} - -static const unsigned char* utf16be_get_next_word (const unsigned char* mstr, - int mstrlen, WORDINFO* word_info) -{ - const unsigned char* mchar = mstr; - Uchar32 wc; - int ch_len; - - word_info->len = 0; - word_info->delimiter = '\0'; - word_info->nr_delimiters = 0; - - if (mstrlen == 0) return NULL; - - while (mstrlen > 0) { - ch_len = utf16be_len_first_char (mchar, mstrlen); - - if (ch_len == 0) - break; - - wc = utf16be_get_char_value (NULL, 0, mchar, 0); - if (wc > 0x0FFF) { - if (word_info->len) - return mstr + word_info->len + word_info->nr_delimiters; - else { /* Treate the first char as a word */ - word_info->len = ch_len; - return mstr + word_info->len + word_info->nr_delimiters; - } - } - - switch (wc) { - case ' ': - case '\t': - case '\n': - case '\r': - if (word_info->delimiter == '\0') { - word_info->delimiter = (unsigned char)wc; - word_info->nr_delimiters += ch_len; - } - else if (word_info->delimiter == (unsigned char)wc) - word_info->nr_delimiters += ch_len; - else - return mstr + word_info->len + word_info->nr_delimiters; - break; - - default: - if (word_info->delimiter != '\0') - return mstr + word_info->len + word_info->nr_delimiters; - - word_info->len += ch_len; - break; - } - - mstrlen -= ch_len; - mchar += ch_len; - } - - return mstr + word_info->len + word_info->nr_delimiters; -} - -static int utf16be_pos_first_char (const unsigned char* mstr, int mstrlen) -{ - int ch_len; - int pos = 0; - - while (mstrlen > 0) { - ch_len = utf16be_len_first_char (mstr, mstrlen); - - if (ch_len > 0) - return pos; - - pos += ch_len; - mstrlen -= ch_len; - mstr += ch_len; - } - - return -1; -} - -static int utf16be_conv_from_uc32 (Uchar32 wc, unsigned char* mchar) -{ - Uchar16 w1, w2; - - if (wc > 0x10FFFF) { - return 0; - } - - if (wc < 0x10000) { - mchar [1] = LOBYTE (wc); - mchar [0] = HIBYTE (wc); - return 2; - } - - wc -= 0x10000; - w1 = 0xD800; - w2 = 0xDC00; - - w1 |= (wc >> 10); - w2 |= (wc & 0x03FF); - - mchar [1] = LOBYTE (w1); - mchar [0] = HIBYTE (w1); - mchar [3] = LOBYTE (w2); - mchar [2] = HIBYTE (w2); - return 4; -} - -static CHARSETOPS CharsetOps_utf16be = { - 0x7FFFFFFF, - 4, - FONT_CHARSET_UTF16BE, - 0, - utf16be_len_first_char, - utf16be_get_char_value, - NULL, - unicode_char_type, - utf16be_nr_chars_in_str, - utf16be_is_this_charset, - utf16be_len_first_substr, - utf16be_get_next_word, - utf16be_pos_first_char, - __mg_unicode_bidi_char_type, - __mg_unicode_bidi_mirror_char, - NULL, - utf16be_conv_from_uc32 -}; - -/************************* End of UNICODE *************************************/ -#endif /* _UNICODE */ +extern CHARSETOPS __mg_CharsetOps_utf8; +extern CHARSETOPS __mg_CharsetOps_utf16le; +extern CHARSETOPS __mg_CharsetOps_utf16be; +#endif /*_MGCHARSET_UNICODE */ static CHARSETOPS* Charsets [] = { @@ -4520,9 +3501,9 @@ static CHARSETOPS* Charsets [] = &CharsetOps_jisx0208_1, #endif #ifdef _MGCHARSET_UNICODE - &CharsetOps_utf8, - &CharsetOps_utf16le, - &CharsetOps_utf16be, + &__mg_CharsetOps_utf8, + &__mg_CharsetOps_utf16le, + &__mg_CharsetOps_utf16be, #endif }; @@ -4575,504 +3556,3 @@ BOOL IsCompatibleCharset (const char* charset, CHARSETOPS* ops) return FALSE; } -#ifdef _MGCHARSET_UNICODE - -UCharGeneralCategory GUIAPI UCharGetCategory(Uchar32 uc) -{ - return (UCharGeneralCategory)TYPE(uc); -} - -/** The function determines the break type of a UNICODE character. */ -UCharBreakType GUIAPI UCharGetBreakType(Uchar32 uc) -{ - return (UCharBreakType)PROP(uc); -} - -BOOL GUIAPI IsUCharAlnum(Uchar32 uc) -{ - return ISALDIGIT(TYPE(uc)); -} - -BOOL GUIAPI IsUCharAlpha(Uchar32 uc) -{ - return ISALPHA (TYPE(uc)); -} - -BOOL GUIAPI IsUCharControl(Uchar32 uc) -{ - return TYPE(uc) == UCHAR_CATEGORY_CONTROL; -} - -BOOL GUIAPI IsUCharDigit(Uchar32 uc) -{ - return TYPE(uc) == UCHAR_CATEGORY_DECIMAL_NUMBER; -} - -BOOL GUIAPI IsUCharGraph(Uchar32 uc) -{ - return !IS (TYPE(uc), - OR (UCHAR_CATEGORY_CONTROL, - OR (UCHAR_CATEGORY_FORMAT, - OR (UCHAR_CATEGORY_UNASSIGNED, - OR (UCHAR_CATEGORY_SURROGATE, - OR (UCHAR_CATEGORY_SPACE_SEPARATOR, - 0)))))); -} - -BOOL GUIAPI IsUCharLowercase(Uchar32 uc) -{ - return TYPE(uc) == UCHAR_CATEGORY_LOWERCASE_LETTER; -} - -BOOL GUIAPI IsUCharPrint(Uchar32 uc) -{ - return !IS (TYPE(uc), - OR (UCHAR_CATEGORY_CONTROL, - OR (UCHAR_CATEGORY_FORMAT, - OR (UCHAR_CATEGORY_UNASSIGNED, - OR (UCHAR_CATEGORY_SURROGATE, - 0))))); -} - -BOOL GUIAPI IsUCharUppercase(Uchar32 uc) -{ - return TYPE(uc) == UCHAR_CATEGORY_UPPERCASE_LETTER; -} - -BOOL GUIAPI IsUCharPunct(Uchar32 uc) -{ - return IS (TYPE(uc), - OR (UCHAR_CATEGORY_CONNECT_PUNCTUATION, - OR (UCHAR_CATEGORY_DASH_PUNCTUATION, - OR (UCHAR_CATEGORY_CLOSE_PUNCTUATION, - OR (UCHAR_CATEGORY_FINAL_PUNCTUATION, - OR (UCHAR_CATEGORY_INITIAL_PUNCTUATION, - OR (UCHAR_CATEGORY_OTHER_PUNCTUATION, - OR (UCHAR_CATEGORY_OPEN_PUNCTUATION, - OR (UCHAR_CATEGORY_CURRENCY_SYMBOL, - OR (UCHAR_CATEGORY_MODIFIER_SYMBOL, - OR (UCHAR_CATEGORY_MATH_SYMBOL, - OR (UCHAR_CATEGORY_OTHER_SYMBOL, - 0)))))))))))); -} - -BOOL GUIAPI IsUCharSpace(Uchar32 uc) -{ - switch (uc) { - /* special-case these since Unicode thinks they are not spaces */ - case '\t': - case '\n': - case '\r': - case '\f': - return TRUE; - - default: { - if (IS (TYPE(uc), - OR (UCHAR_CATEGORY_SPACE_SEPARATOR, - OR (UCHAR_CATEGORY_LINE_SEPARATOR, - OR (UCHAR_CATEGORY_PARAGRAPH_SEPARATOR, - 0))))) - return TRUE; - } - break; - } - - return FALSE; -} - -BOOL GUIAPI IsUCharMark(Uchar32 uc) -{ - return ISMARK (TYPE(uc)); -} - -BOOL GUIAPI IsUCharTitle(Uchar32 uc) -{ - unsigned int i; - - for (i = 0; i < TABLESIZE (title_table); ++i) { - if (title_table[i][0] == uc) { - return TRUE; - } - } - - return FALSE; -} - -BOOL GUIAPI IsUCharXDigit(Uchar32 uc) -{ - return ((uc >= 'a' && uc <= 'f') - || (uc >= 'A' && uc <= 'F') - || (TYPE(uc) == UCHAR_CATEGORY_DECIMAL_NUMBER)); -} - -BOOL GUIAPI IsUCharDefined(Uchar32 uc) -{ - return !IS (TYPE(uc), - OR (UCHAR_CATEGORY_UNASSIGNED, - OR (UCHAR_CATEGORY_SURROGATE, - 0))); -} - -BOOL GUIAPI IsUCharZeroWidth(Uchar32 uc) -{ - if (uc != 0x00AD && ISZEROWIDTHTYPE (TYPE(uc))) - return TRUE; - else if ((uc >= 0x1160 && uc < 0x1200) - || uc == 0x200B) - return TRUE; - - return FALSE; -} - -static inline BOOL g_unichar_iswide_bsearch (Uchar32 ch) -{ - unsigned int lower = 0; - unsigned int upper = TABLESIZE (unicode_width_table_wide) - 1; - int mid = TABLESIZE (unicode_width_table_wide) / 2; - - do { - if (ch < unicode_width_table_wide[mid].start) - upper = mid - 1; - else if (ch > unicode_width_table_wide[mid].end) - lower = mid + 1; - else - return TRUE; - - mid = (lower + upper) / 2; - } - while (lower <= upper); - - return FALSE; -} - -BOOL GUIAPI IsUCharWide(Uchar32 uc) -{ - if (uc < unicode_width_table_wide[0].start) - return FALSE; - else - return g_unichar_iswide_bsearch (uc); -} - -static int interval_compare (const void *key, const void *elt) -{ - Uchar32 uc = (Uchar32)((intptr_t)key); - struct Interval *interval = (struct Interval *)elt; - - if (uc < interval->start) - return -1; - if (uc > interval->end) - return +1; - - return 0; -} - -BOOL GUIAPI IsUCharWideCJK (Uchar32 uc) -{ - if (IsUCharWide(uc)) - return TRUE; - - /* bsearch() is declared attribute(nonnull(1)) so we can't validly search - * for a NULL key */ - if (uc == 0) - return FALSE; - - if (bsearch((void*)((intptr_t)uc), - unicode_width_table_ambiguous, - TABLESIZE (unicode_width_table_ambiguous), - sizeof unicode_width_table_ambiguous[0], - interval_compare)) - return TRUE; - - return FALSE; -} - -/** - * Converts a character to uppercase. - */ -Uchar32 UCharToUpper (Uchar32 uc) -{ - int t = TYPE (uc); - if (t == UCHAR_CATEGORY_LOWERCASE_LETTER) { - Uchar32 val = ATTTABLE (uc >> 8, uc & 0xff); - if (val >= 0x1000000) { - const unsigned char *p = special_case_table + val - 0x1000000; - val = utf8_get_char_value (NULL, 0, p, -1); - } - /* Some lowercase letters, e.uc., U+000AA, FEMININE ORDINAL INDICATOR, - * do not have an uppercase equivalent, in which case val will be - * zero. - */ - return val ? val : uc; - } - else if (t == UCHAR_CATEGORY_TITLECASE_LETTER) { - unsigned int i; - for (i = 0; i < TABLESIZE (title_table); ++i) { - if (title_table[i][0] == uc) - return title_table[i][1] ? title_table[i][1] : uc; - } - } - - return uc; -} - -/** - * Converts a character to lower case. - */ -Uchar32 GUIAPI UCharToLower (Uchar32 uc) -{ - int t = TYPE (uc); - if (t == UCHAR_CATEGORY_UPPERCASE_LETTER) { - Uchar32 val = ATTTABLE (uc >> 8, uc & 0xff); - if (val >= 0x1000000) { - const unsigned char *p = special_case_table + val - 0x1000000; - return utf8_get_char_value (NULL, 0, p, -1); - } - else { - /* Not all uppercase letters are guaranteed to have a lowercase - * equivalent. If this is the case, val will be zero. */ - return val ? val : uc; - } - } - else if (t == UCHAR_CATEGORY_TITLECASE_LETTER) { - unsigned int i; - for (i = 0; i < TABLESIZE (title_table); ++i) { - if (title_table[i][0] == uc) - return title_table[i][2]; - } - } - return uc; -} - -/** - * Converts a chv to the titlecase. - */ -Uchar32 GUIAPI UCharToTitle (Uchar32 uc) -{ - unsigned int i; - for (i = 0; i < TABLESIZE (title_table); ++i) { - if (title_table[i][0] == uc || title_table[i][1] == uc - || title_table[i][2] == uc) - return title_table[i][0]; - } - - if (TYPE (uc) == UCHAR_CATEGORY_LOWERCASE_LETTER) - return UCharToUpper (uc); - - return uc; -} - -/** Converts a chv to full-width. */ -Uchar32 GUIAPI UCharToFullWidth (Uchar32 uc) -{ - if (uc == 0x20) - return 0x3000; - - if (uc >= 0x21 && uc <= 0x7E) { - return uc + (0xFF01 - 0x21); - } - - return uc; -} - -/** Converts a chv to single-width. */ -Uchar32 GUIAPI UCharToSingleWidth (Uchar32 uc) -{ - if (uc == 0x3000) - return 0x20; - - if (uc >= 0xFF01 && uc <= 0xFF5E) { - return uc - (0xFF01 - 0x21); - } - - return uc; -} - -struct UCharMap { - Uchar32 one, other; -}; - -static const struct UCharMap kana_small_to_full_size_table [] = { - { /*ぁ*/ 0x3041, /*あ*/ 0x3042}, - { /*ぃ*/ 0x3043, /*い*/ 0x3044}, - { /*ぅ*/ 0x3045, /*う*/ 0x3046}, - { /*ぇ*/ 0x3047, /*え*/ 0x3048}, - { /*ぉ*/ 0x3049, /*お*/ 0x304A}, - { /*ゕ*/ 0x3095, /*か*/ 0x304B}, - { /*ゖ*/ 0x3096, /*け*/ 0x3051}, - { /*っ*/ 0x3063, /*つ*/ 0x3064}, - { /*ゃ*/ 0x3083, /*や*/ 0x3084}, - { /*ゅ*/ 0x3085, /*ゆ*/ 0x3086}, - { /*ょ*/ 0x3087, /*よ*/ 0x3088}, - { /*ゎ*/ 0x308E, /*わ*/ 0x308F}, - { /*ァ*/ 0x30A1, /*ア*/ 0x30A2}, - { /*ィ*/ 0x30A3, /*イ*/ 0x30A4}, - { /*ゥ*/ 0x30A5, /*ウ*/ 0x30A6}, - { /*ェ*/ 0x30A7, /*エ*/ 0x30A8}, - { /*ォ*/ 0x30A9, /*オ*/ 0x30AA}, - { /*ヵ*/ 0x30F5, /*カ*/ 0x30AB}, - { /*ㇰ*/ 0x31F0, /*ク*/ 0x30AF}, - { /*ヶ*/ 0x30F6, /*ケ*/ 0x30B1}, - { /*ㇱ*/ 0x31F1, /*シ*/ 0x30B7}, - { /*ㇲ*/ 0x31F2, /*ス*/ 0x30B9}, - { /*ッ*/ 0x30C3, /*ツ*/ 0x30C4}, - { /*ㇳ*/ 0x31F3, /*ト*/ 0x30C8}, - { /*ㇴ*/ 0x31F4, /*ヌ*/ 0x30CC}, - { /*ㇵ*/ 0x31F5, /*ハ*/ 0x30CF}, - { /*ㇶ*/ 0x31F6, /*ヒ*/ 0x30D2}, - { /*ㇷ*/ 0x31F7, /*フ*/ 0x30D5}, - { /*ㇸ*/ 0x31F8, /*ヘ*/ 0x30D8}, - { /*ㇹ*/ 0x31F9, /*ホ*/ 0x30DB}, - { /*ㇺ*/ 0x31FA, /*ム*/ 0x30E0}, - { /*ャ*/ 0x30E3, /*ヤ*/ 0x30E4}, - { /*ュ*/ 0x30E5, /*ユ*/ 0x30E6}, - { /*ョ*/ 0x30E7, /*ヨ*/ 0x30E8}, - { /*ㇻ*/ 0x31FB, /*ラ*/ 0x30E9}, - { /*ㇼ*/ 0x31FC, /*リ*/ 0x30EA}, - { /*ㇽ*/ 0x31FD, /*ル*/ 0x30EB}, - { /*ㇾ*/ 0x31FE, /*レ*/ 0x30EC}, - { /*ㇿ*/ 0x31FF, /*ロ*/ 0x30ED}, - { /*ヮ*/ 0x30EE, /*ワ*/ 0x30EF}, - { /*ァ*/ 0xFF67, /*ア*/ 0xFF71}, - { /*ィ*/ 0xFF68, /*イ*/ 0xFF72}, - { /*ゥ*/ 0xFF69, /*ウ*/ 0xFF73}, - { /*ェ*/ 0xFF6A, /*エ*/ 0xFF74}, - { /*ォ*/ 0xFF6B, /*オ*/ 0xFF75}, - { /*ッ*/ 0xFF6F, /*ツ*/ 0xFF82}, - { /*ャ*/ 0xFF6C, /*ヤ*/ 0xFF94}, - { /*ュ*/ 0xFF6D, /*ユ*/ 0xFF95}, - { /*ョ*/ 0xFF6E, /*ヨ*/ 0xFF96}, -}; - -/** Converts a chv to full-size Kana. */ -Uchar32 GUIAPI UCharToFullSizeKana (Uchar32 uc) -{ - unsigned int lower = 0; - unsigned int upper = TABLESIZE (kana_small_to_full_size_table) - 1; - int mid = TABLESIZE (kana_small_to_full_size_table) / 2; - - if (uc < kana_small_to_full_size_table[lower].one - || uc > kana_small_to_full_size_table[upper].one) - return uc; - - do { - if (uc < kana_small_to_full_size_table[mid].one) - upper = mid - 1; - else if (uc > kana_small_to_full_size_table[mid].one) - lower = mid + 1; - else - return kana_small_to_full_size_table[mid].other; - - mid = (lower + upper) / 2; - - } while (lower <= upper); - - return uc; -} - -#if 0 // VincentWei: use kana_small_to_full_size_table instead -static const struct UCharMap kana_full_size_to_small_table [] = { - { /*あ*/ 0x3041, /*ぁ*/ 0x3041}, - { /*い*/ 0x3043, /*ぃ*/ 0x3043}, - { /*う*/ 0x3045, /*ぅ*/ 0x3045}, - { /*え*/ 0x3047, /*ぇ*/ 0x3047}, - { /*お*/ 0x3049, /*ぉ*/ 0x3049}, - { /*か*/ 0x304A, /*ゕ*/ 0x3095}, - { /*け*/ 0x3050, /*ゖ*/ 0x3096}, - { /*つ*/ 0x3063, /*っ*/ 0x3063}, - { /*や*/ 0x3083, /*ゃ*/ 0x3083}, - { /*ゆ*/ 0x3085, /*ゅ*/ 0x3085}, - { /*よ*/ 0x3087, /*ょ*/ 0x3087}, - { /*わ*/ 0x308E, /*ゎ*/ 0x308E}, - { /*ア*/ 0x30A1, /*ァ*/ 0x30A1}, - { /*イ*/ 0x30A3, /*ィ*/ 0x30A3}, - { /*ウ*/ 0x30A5, /*ゥ*/ 0x30A5}, - { /*エ*/ 0x30A7, /*ェ*/ 0x30A7}, - { /*オ*/ 0x30A9, /*ォ*/ 0x30A9}, - { /*カ*/ 0x30AA, /*ヵ*/ 0x30F5}, - { /*ク*/ 0x30AE, /*ㇰ*/ 0x31F0}, - { /*ケ*/ 0x30B0, /*ヶ*/ 0x30F6}, - { /*シ*/ 0x30B6, /*ㇱ*/ 0x31F1}, - { /*ス*/ 0x30B8, /*ㇲ*/ 0x31F2}, - { /*ツ*/ 0x30C3, /*ッ*/ 0x30C3}, - { /*ト*/ 0x30C7, /*ㇳ*/ 0x31F3}, - { /*ヌ*/ 0x30CB, /*ㇴ*/ 0x31F4}, - { /*ハ*/ 0x30CE, /*ㇵ*/ 0x31F5}, - { /*ヒ*/ 0x30D1, /*ㇶ*/ 0x31F6}, - { /*フ*/ 0x30D4, /*ㇷ*/ 0x31F7}, - { /*ヘ*/ 0x30D7, /*ㇸ*/ 0x31F8}, - { /*ホ*/ 0x30DA, /*ㇹ*/ 0x31F9}, - { /*ム*/ 0x30DF, /*ㇺ*/ 0x31FA}, - { /*ヤ*/ 0x30E3, /*ャ*/ 0x30E3}, - { /*ユ*/ 0x30E5, /*ュ*/ 0x30E5}, - { /*ヨ*/ 0x30E7, /*ョ*/ 0x30E7}, - { /*ラ*/ 0x30E8, /*ㇻ*/ 0x31FB}, - { /*リ*/ 0x30E9, /*ㇼ*/ 0x31FC}, - { /*ル*/ 0x30EA, /*ㇽ*/ 0x31FD}, - { /*レ*/ 0x30EB, /*ㇾ*/ 0x31FE}, - { /*ロ*/ 0x30EC, /*ㇿ*/ 0x31FF}, - { /*ワ*/ 0x30EE, /*ヮ*/ 0x30EE}, - { /*ア*/ 0xFF70, /*ァ*/ 0xFF67}, - { /*イ*/ 0xFF71, /*ィ*/ 0xFF68}, - { /*ウ*/ 0xFF72, /*ゥ*/ 0xFF69}, - { /*エ*/ 0xFF73, /*ェ*/ 0xFF6A}, - { /*オ*/ 0xFF74, /*ォ*/ 0xFF6B}, - { /*ツ*/ 0xFF81, /*ッ*/ 0xFF6F}, - { /*ヤ*/ 0xFF93, /*ャ*/ 0xFF6C}, - { /*ユ*/ 0xFF94, /*ュ*/ 0xFF6D}, - { /*ヨ*/ 0xFF95, /*ョ*/ 0xFF6E}, -}; - -/** Converts a chv to small Kana. */ -Uchar32 GUIAPI UCharToSmallKana (Uchar32 uc) -{ - unsigned int lower = 0; - unsigned int upper = TABLESIZE (kana_full_size_to_small_table) - 1; - int mid = TABLESIZE (kana_full_size_to_small_table) / 2; - - if (uc < kana_full_size_to_small_table[lower].one - || uc < kana_full_size_to_small_table[upper].one) - return uc; - - do { - if (uc < kana_full_size_to_small_table[mid].one) - upper = mid - 1; - else if (uc > kana_full_size_to_small_table[mid].one) - lower = mid + 1; - else - return kana_full_size_to_small_table[mid].other; - - mid = (lower + upper) / 2; - - } while (lower <= upper); - - return uc; -} -#endif // VincentWei: use kana_small_to_full_size_table instead - -/** Converts a chv to small Kana. */ -Uchar32 GUIAPI UCharToSmallKana (Uchar32 uc) -{ - unsigned int lower = 0; - unsigned int upper = TABLESIZE (kana_small_to_full_size_table) - 1; - int mid = TABLESIZE (kana_small_to_full_size_table) / 2; - - if (uc < kana_small_to_full_size_table[lower].other - || uc > kana_small_to_full_size_table[upper].other) - return uc; - - do { - if (uc < kana_small_to_full_size_table[mid].other) - upper = mid - 1; - else if (uc > kana_small_to_full_size_table[mid].other) - lower = mid + 1; - else - return kana_small_to_full_size_table[mid].one; - - mid = (lower + upper) / 2; - - } while (lower <= upper); - - return uc; -} - -#endif /* _MGCHARSET_UNICODE */ diff --git a/src/font/unicode-joining-types.c b/src/font/unicode-joining-types.c index d269504a..70a96dea 100644 --- a/src/font/unicode-joining-types.c +++ b/src/font/unicode-joining-types.c @@ -71,8 +71,8 @@ BidiJoiningType GUIAPI UCharGetJoiningType(Uchar32 ch) return UNIBIDI_GET_JOINING_TYPE (ch); } -void GUIAPI UStrGetJoiningTypes (const Uchar32 *ucs, - BidiJoiningType *joining_types, int len) +void GUIAPI UStrGetJoiningTypes (const Uchar32 *ucs, int len, + BidiJoiningType *joining_types) { register int i = len; for (; i; i--) { diff --git a/src/font/unicode-joining.c b/src/font/unicode-joining.c index f3415433..cb5875c0 100644 --- a/src/font/unicode-joining.c +++ b/src/font/unicode-joining.c @@ -102,8 +102,8 @@ static void print_joining_types(const BidiLevel *embedding_levels, ((i) == (j) || (i) == BIDI_SENTINEL || (j) == BIDI_SENTINEL) void GUIAPI UBidiJoinArabic(const BidiType *bidi_types, - const BidiLevel *embedding_levels, - BidiArabicProp *ar_props, int len) + const BidiLevel *embedding_levels, int len, + BidiArabicProp *ar_props) { if (len == 0) return; diff --git a/src/font/unicode-shape-arabic.c b/src/font/unicode-shape-arabic.c index 440e4b67..5b561700 100644 --- a/src/font/unicode-shape-arabic.c +++ b/src/font/unicode-shape-arabic.c @@ -142,10 +142,8 @@ static void unibidi_shape_arabic_ligature(const PairMap *table, #define DO_SHAPING(tablemacro, len, ar_props, str) \ unibidi_shape_arabic_joining (tablemacro(,), len, ar_props, str) -void UBidiShapeArabic(Uint32 flags, - const BidiLevel *embedding_levels, - BidiArabicProp *ar_props, - Uchar32 *str, int len) +void UBidiShapeArabic(Uint32 flags, const BidiLevel *embedding_levels, int len, + BidiArabicProp *ar_props, Uchar32 *str) { _DBG_PRINTF ("in UBidiShapeArabic"); diff --git a/src/font/unicode-shape.c b/src/font/unicode-shape.c index 38727462..f2b2fa79 100644 --- a/src/font/unicode-shape.c +++ b/src/font/unicode-shape.c @@ -58,8 +58,8 @@ #include "unicode-bidi.h" -void GUIAPI UBidiShapeMirroring(const BidiLevel *embedding_levels, - Uchar32* str, int len) +void GUIAPI UBidiShapeMirroring(const BidiLevel *embedding_levels, int len, + Uchar32* str) { register int i; @@ -77,17 +77,17 @@ void GUIAPI UBidiShapeMirroring(const BidiLevel *embedding_levels, } void GUIAPI UBidiShape(Uint32 flags, - const BidiLevel *embedding_levels, - BidiArabicProp *ar_props, Uchar32 *str, int len) + const BidiLevel *embedding_levels, int len, + BidiArabicProp *ar_props, Uchar32 *str) { if (len == 0 || !str) return; if (ar_props) - UBidiShapeArabic(flags, embedding_levels, ar_props, str, len); + UBidiShapeArabic(flags, embedding_levels, len, ar_props, str); if (BIDI_TEST_BITS (flags, BIDI_FLAG_SHAPE_MIRRORING)) - UBidiShapeMirroring (embedding_levels, str, len); + UBidiShapeMirroring (embedding_levels, len, str); } #endif /* _MGCHARSET_UNICODE */