2004-05-29 10:17:37 +00:00
|
|
|
/*
|
2008-01-03 09:51:29 +00:00
|
|
|
* Indic algorithms for QEmacs.
|
2004-05-29 10:17:37 +00:00
|
|
|
*
|
|
|
|
|
* 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
|
|
|
|
|
*/
|
2007-12-03 16:12:40 +00:00
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
#include "qe.h"
|
|
|
|
|
#include "qfribidi.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 (unsigned int i)
|
|
|
|
|
{
|
|
|
|
|
return (i >= 0x93E && i <= 0x94c) || (i >= 0x962 && i <= 0x963);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static int is_consonant (unsigned int i)
|
|
|
|
|
{
|
|
|
|
|
return (i >= 0x915 && i <= 0x939) || (i >= 0x958 && i <= 0x95f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int is_ind_vowel (unsigned int i)
|
|
|
|
|
{
|
|
|
|
|
return (i >= 0x905 && i <= 0x914);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int is_dead_consonant(unsigned int i)
|
|
|
|
|
{
|
|
|
|
|
return (i >= DEAD_CONSONANT_OFFSET && i <= DEAD_CONSONANT_OFFSET + 0x7f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* always returns a smaller buffer */
|
|
|
|
|
int devanagari_log2vis(unsigned int *str, unsigned int *ctog, int len)
|
|
|
|
|
{
|
|
|
|
|
int i, len1, cc, j, k, c;
|
|
|
|
|
unsigned int *q, buf[len];
|
2008-01-03 09:51:29 +00:00
|
|
|
|
2004-05-29 10:17:37 +00:00
|
|
|
/* Rule 1 : dead consonant rule */
|
|
|
|
|
q = buf;
|
|
|
|
|
len1 = len - 1;
|
2005-05-11 15:12:14 +00:00
|
|
|
for (i = 0; i < len; i++) {
|
2004-05-29 10:17:37 +00:00
|
|
|
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 */
|
2005-05-11 15:12:14 +00:00
|
|
|
for (i = 0; i < len1; i++) {
|
2004-05-29 10:17:37 +00:00
|
|
|
/* Rule 2 */
|
2008-01-03 09:51:29 +00:00
|
|
|
if (buf[i] == RA_DEAD &&
|
2004-05-29 10:17:37 +00:00
|
|
|
(is_ind_vowel(buf[i+1]) || is_consonant(buf[i+1]))) {
|
|
|
|
|
buf[i] = buf[i+1];
|
|
|
|
|
buf[i+1] = RA_SUP;
|
2008-01-03 09:51:29 +00:00
|
|
|
} else
|
2004-05-29 10:17:37 +00:00
|
|
|
/* Rule 5 */
|
2008-01-03 09:51:29 +00:00
|
|
|
if (buf[i] == RRA &&
|
2004-05-29 10:17:37 +00:00
|
|
|
buf[i+1] == VIRAMA) {
|
|
|
|
|
buf[i] = RRA_HALF;
|
|
|
|
|
buf[i+1] = 0;
|
|
|
|
|
} else
|
|
|
|
|
/* Rule 5a */
|
2008-01-03 09:51:29 +00:00
|
|
|
if (buf[i] == RA_DEAD &&
|
2004-05-29 10:17:37 +00:00
|
|
|
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 */
|
2008-01-03 09:51:29 +00:00
|
|
|
if (is_dead_consonant(buf[i]) &&
|
2004-05-29 10:17:37 +00:00
|
|
|
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 */
|
2005-05-11 15:12:14 +00:00
|
|
|
for (i = 0; i < len1; i++) {
|
2008-01-03 09:51:29 +00:00
|
|
|
if (is_dead_consonant(buf[i]) &&
|
2004-05-29 10:17:37 +00:00
|
|
|
(i == (len1 - 1) ||
|
2008-01-03 09:51:29 +00:00
|
|
|
buf[i+1] == ZERO_WIDTH_JOINER ||
|
2004-05-29 10:17:37 +00:00
|
|
|
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;
|
2005-05-11 15:12:14 +00:00
|
|
|
for (i = 0; i < len; i++) {
|
2004-05-29 10:17:37 +00:00
|
|
|
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;
|
|
|
|
|
}
|