evil-qemacs/indic.c
Charlie Gordon 7e70e611b6 Use char32_t for all code point variables and arrays
- char32_t is defined in cutils.h but may conflict with <uchar.h>
- all qe_isxxx functions take a char32_t
- add etf8x encoding for full range of char32_t type
- add utf8_decode_strict()
- add ustr_match_keyword()
- utf8_encode() / utf8_decode() handle up to 32 bits
- improve detect_charset():
  - detect utf8 and utf8x
  - avoid failure on partial utf8 sequence at end of buffer
  - detect overlong utf8 sequences
- fix display bugs for code points beyond MAX_UNICODE_DISPLAY
- simplify do_compare_windows(), avoid magic char values.
- rename functions:
    eb_encode_uchar -> eb_encode_char32
    eb_insert_uchar -> eb_insert_char32
    eb_insert_uchars -> eb_insert_char32_n
    eb_match_uchar -> eb_match_char32
    eb_delete_uchar -> eb_delete_char32
    eb_replace_uchar -> eb_replace_char32
    utf8_to_unicode -> utf8_to_char32
- use char32_t for all variables and arrays holding code-points
- fix some language syntax parsers.
- fix detect_eol_type_32bit(), used uint16_t instead of uint32_t
- bump VERSION to 5.4.0
2022-10-29 19:43:38 +02:00

139 lines
3.9 KiB
C

/*
* Indic algorithms for QEmacs.
*
* Copyright (c) 2000 Fabrice Bellard.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "cutils.h"
#include "unicode_join.h"
#define VIRAMA 0x94d
#define RA 0x930
#define RRA 0x931
#define ZERO_WIDTH_JOINER 0x200d
/* private unicode extensions */
#define DEAD_CONSONANT_OFFSET 0x10000
#define HALF_OFFSET 0xe000
#define RA_SUP 0xe97e
#define RA_SUB 0xe97f
#define RRA_HALF 0xe97d
#define RA_DEAD (RA + DEAD_CONSONANT_OFFSET)
#if 0
static int is_vowel_sign(char32_t i) {
return (i >= 0x93E && i <= 0x94c) || (i >= 0x962 && i <= 0x963);
}
#endif
static int is_consonant(char32_t i) {
return (i >= 0x915 && i <= 0x939) || (i >= 0x958 && i <= 0x95f);
}
static int is_ind_vowel(char32_t i) {
return (i >= 0x905 && i <= 0x914);
}
static int is_dead_consonant(char32_t i) {
return (i >= DEAD_CONSONANT_OFFSET && i <= DEAD_CONSONANT_OFFSET + 0x7f);
}
/* always returns a smaller buffer */
int devanagari_log2vis(char32_t *str, unsigned int *ctog, int len) {
char32_t cc, c;
int i, len1, j, k;
/* CG: C99 variable-length arrays may be too large */
char32_t *q, buf[len];
/* Rule 1 : dead consonant rule */
q = buf;
len1 = len - 1;
for (i = 0; i < len; i++) {
cc = str[i];
if (is_consonant(cc) && i < len1 && str[i+1] == VIRAMA) {
*q++ = cc + DEAD_CONSONANT_OFFSET;
i++;
} else {
*q++ = cc;
}
}
/************ RA rules */
/* XXX: rule 3, 4, 7 should be handled as ligatures */
for (i = 0; i < len1; i++) {
/* Rule 2 */
if (buf[i] == RA_DEAD &&
(is_ind_vowel(buf[i+1]) || is_consonant(buf[i+1]))) {
buf[i] = buf[i+1];
buf[i+1] = RA_SUP;
} else
/* Rule 5 */
if (buf[i] == RRA &&
buf[i+1] == VIRAMA) {
buf[i] = RRA_HALF;
buf[i+1] = 0;
} else
/* Rule 5a */
if (buf[i] == RA_DEAD &&
buf[i+1] == ZERO_WIDTH_JOINER) {
buf[i] = RRA_HALF;
buf[i+1] = 0;
} else
/* Rule 6 */
if (is_dead_consonant(buf[i]) && buf[i+1] == RA) {
buf[i] -= DEAD_CONSONANT_OFFSET;
buf[i+1] = RA_SUB;
} else
/* Rule 8 */
if (is_dead_consonant(buf[i]) &&
buf[i+1] == RA_DEAD) {
buf[i] -= DEAD_CONSONANT_OFFSET;
buf[i+1] = RA_SUB;
buf[i+2] = VIRAMA;
}
}
/* convert dead consonant to half consonants */
for (i = 0; i < len1; i++) {
if (is_dead_consonant(buf[i]) &&
(i == (len1 - 1) ||
buf[i+1] == ZERO_WIDTH_JOINER ||
is_consonant(buf[i+1]) ||
is_dead_consonant(buf[i+1]))) {
buf[i] -= DEAD_CONSONANT_OFFSET + HALF_OFFSET;
}
}
/* output result and update ctog */
j = 0;
for (i = 0; i < len; i++) {
c = buf[i];
if (c != 0) {
ctog[i] = j;
str[j++] = c;
} else {
/* zero: associate it to previous char */
/* XXX: is it always a good guess ? */
k = j - 1;
if (k < 0)
k = 0;
ctog[i] = k;
}
}
return j;
}