/* * Unicode joining 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 "qfribidi.h" #include "qe.h" #ifdef CONFIG_UNICODE_JOIN /* ligature tables */ static unsigned short *subst1; static unsigned short *ligature2; static unsigned short *ligature_long; static int subst1_count = 0; static int ligature2_count = 0; /* XXX: eof ? */ static int uni_get_be16(FILE *f) { int v; v = fgetc(f) << 8; v |= fgetc(f); return v; } static unsigned short *read_array_be16(FILE *f, int n) { unsigned short *tab; int i; tab = malloc(n * sizeof(unsigned short)); if (!tab) return NULL; for(i=0;i> 1; v1 = ligature2[3 * m]; v2 = ligature2[3 * m + 1]; if (v1 == l1 && v2 == l2) return ligature2[3 * m + 2]; else if (v1 > l1 || (v1 == l1 && v2 > l2)) { b = m - 1; } else { a = m + 1; } } return -1; } /* apply all the ligature rules in logical order. Always return a smaller buffer */ static int unicode_ligature(unsigned int *buf_out, unsigned int *pos_L_to_V, int len) { int l, l1, l2, len1, len2, i, j; unsigned int *q; const unsigned short *lig; unsigned int buf[len]; memcpy(buf, buf_out, len * sizeof(int)); q = buf_out; for(i=0;i= 0x202a && l1 <= 0x202e) { /* LRE, RLE, PDF, RLO, LRO */ pos_L_to_V[i] = q - buf_out; i++; goto found; } /* fast test to eliminate common cases */ if (i == (len - 1)) goto nolig; l2 = buf[i + 1]; if (l1 <= 0x7f && l2 <= 0x7f) goto nolig; l = find_ligature(l1, l2); if (l < 0) goto nolig; if (l > 0) { /* ligature of length 2 found */ pos_L_to_V[i] = q - buf_out; pos_L_to_V[i+1] = q - buf_out; *q++ = l; i += 2; } else { /* generic case : use ligature_long[] table */ lig = ligature_long; for(;;) { len1 = *lig++; if (len1 == 0) break; len2 = *lig++; if (i + len1 <= len) { for(j=0;j= 0x2000) /* fast test for non handled scripts */ continue; if (c >= 0x600 && c <= 0x6ff) mask |= UNICODE_ARABIC; else if (c >= 0x900 && c <= 0x97f) mask |= UNICODE_INDIC; } return mask; } static void compose_char_to_glyph(unsigned int *ctog, int len, unsigned *ctog1) { int i; for(i=0;i dst_size) len = dst_size; memcpy(dst, src, len * sizeof(unsigned int)); if (char_to_glyph_pos) { for(i=0;i dst_size) len = dst_size; memcpy(dst, buf, len * sizeof(unsigned int)); if (char_to_glyph_pos) { memcpy(char_to_glyph_pos, ctog, src_size * sizeof(unsigned int)); } } return len; } #else /* CONFIG_UNICODE_JOIN */ /* fallback unicode functions */ void load_ligatures(void) { } int unicode_to_glyphs(unsigned int *dst, unsigned int *char_to_glyph_pos, int dst_size, unsigned int *src, int src_size, int reverse) { int len, i; len = src_size; if (len > dst_size) len = dst_size; memcpy(dst, src, len * sizeof(unsigned int)); if (char_to_glyph_pos) { for(i=0;i