summaryrefslogtreecommitdiff
path: root/firmware/bidi.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/bidi.c')
-rw-r--r--firmware/bidi.c186
1 files changed, 140 insertions, 46 deletions
diff --git a/firmware/bidi.c b/firmware/bidi.c
index dcb44999ec..93c1dd0951 100644
--- a/firmware/bidi.c
+++ b/firmware/bidi.c
@@ -24,75 +24,168 @@
24#include <ctype.h> 24#include <ctype.h>
25#include "file.h" 25#include "file.h"
26#include "lcd.h" 26#include "lcd.h"
27#include "rbunicode.h"
28#include "arabjoin.h"
27 29
28#define _HEB_BUFFER_LENGTH MAX_PATH + LCD_WIDTH/2 + 3 + 2 + 2 30//#define _HEB_BUFFER_LENGTH (MAX_PATH + LCD_WIDTH/2 + 3 + 2 + 2) * 2
29#define _HEB_BLOCK_TYPE_ENG 1 31#define _HEB_BLOCK_TYPE_ENG 1
30#define _HEB_BLOCK_TYPE_HEB 0 32#define _HEB_BLOCK_TYPE_HEB 0
31#define _HEB_ORIENTATION_LTR 1 33#define _HEB_ORIENTATION_LTR 1
32#define _HEB_ORIENTATION_RTL 0 34#define _HEB_ORIENTATION_RTL 0
33 35
34#define ischar(c) (((((unsigned char) c)>=193) && (((unsigned char) c)<=250)) ? 1 : 0) 36#define ischar(c) ((c > 0x0589 && c < 0x0700) || (c >= 0xfb50 && c <= 0xfefc) ? 1 : 0)
35#define _isblank(c) (((((unsigned char) c)==' ' || ((unsigned char) c)=='\t')) ? 1 : 0) 37#define _isblank(c) ((c==' ' || c=='\t') ? 1 : 0)
36#define _isnewline(c) (((((unsigned char) c)=='\n' || ((unsigned char) c)=='\r')) ? 1 : 0) 38#define _isnewline(c) ((c=='\n' || c=='\r') ? 1 : 0)
37#define XOR(a,b) ((a||b) && !(a&&b)) 39#define XOR(a,b) ((a||b) && !(a&&b))
38 40
39bool bidi_support_enabled = false; 41arab_t * arab_lookup(unsigned short uchar)
42{
43 if (uchar >= 0x621 && uchar <= 0x63a)
44 return &(jointable[uchar - 0x621]);
45 if (uchar >= 0x640 && uchar <= 0x64a)
46 return &(jointable[uchar - 0x621 - 5]);
47 if (uchar >= 0x671 && uchar <= 0x6d5)
48 return &(jointable[uchar - 0x621 - 5 - 38]);
49 if (uchar == 0x200D) /* Support for the zero-width joiner */
50 return &zwj;
51 return 0;
52}
53
54void arabjoin(unsigned short * stringprt, int length){
55
56 bool connected = false;
57 unsigned short * writeprt = stringprt;
58
59 arab_t * prev = 0;
60 arab_t * cur;
61 arab_t * ligature = 0;
62 short uchar;
40 63
41unsigned char *bidi_l2v(const char *str, int orientation) 64 int i;
65 for (i = 0; i <= length; i++) {
66 cur = arab_lookup(uchar = *stringprt++);
67
68 /* Skip non-arabic chars */
69 if (cur == 0) {
70 if (prev) {
71 /* Finish the last char */
72 if (connected) {
73 *writeprt++ = prev->final;
74 connected = false;
75 } else
76 *writeprt++ = prev->isolated;
77 prev = 0;
78 *writeprt++ = uchar;
79 } else {
80 *writeprt++ = uchar;
81 }
82 continue;
83 }
84
85 /* nothing to do for arabic char if the previous was non-arabic */
86 if (prev == 0) {
87 prev = cur;
88 continue;
89 }
90
91 /* if it's LAM, check for LAM+ALEPH ligatures */
92 if (prev->isolated == 0xfedd) {
93 switch (cur->isolated) {
94 case 0xfe8d:
95 ligature = &(lamaleph[0]);
96 break;
97 case 0xfe87:
98 ligature = &(lamaleph[1]);
99 break;
100 case 0xfe83:
101 ligature = &(lamaleph[2]);
102 break;
103 case 0xfe81:
104 ligature = &(lamaleph[3]);
105 }
106 }
107
108 if (ligature) { /* replace the 2 glyphs by their ligature */
109 prev = ligature;
110 ligature = 0;
111 } else {
112 if (connected) { /* previous char has something connected to it */
113 if (prev->medial && cur->final) /* Can we connect to it? */
114 *writeprt++ = prev->medial;
115 else {
116 *writeprt++ = prev->final;
117 connected = false;
118 }
119 } else {
120 if (prev->initial && cur->final) { /* Can we connect to it? */
121 *writeprt++ = prev->initial;
122 connected = true;
123 } else
124 *writeprt++ = prev->isolated;
125 }
126 prev = cur;
127 }
128 }
129}
130
131unsigned short *bidi_l2v(const unsigned char *str, int orientation)
42{ 132{
43 static unsigned char buf_heb_str[_HEB_BUFFER_LENGTH]; 133 int length = utf8length(str);
44 static unsigned char buf_broken_str[_HEB_BUFFER_LENGTH]; 134 static unsigned short utf16_buf[MAX_PATH+1];
45 const unsigned char *tmp; 135 static unsigned short bidi_buf[MAX_PATH+1];
46 unsigned char *heb_str, *target, *opposite_target, *broken_str; 136 unsigned short *heb_str, *target, *tmp; // *broken_str
47 int block_start, block_end, block_type, block_length, i; 137 int block_start, block_end, block_type, block_length, i;
48 int block_ended; 138 //long max_chars=0;
49 long max_chars=0; 139 //int begin, end, char_count, orig_begin;
50 int begin, end, char_count, orig_begin;
51 140
52 if (!str || !*str) 141 if (!str || !*str)
53 return (unsigned char *)""; 142 return &(unsigned short){0};
143
144 //tmp = str;
145 target = tmp = utf16_buf;
146 while (*str)
147 str = utf8decode(str, target++);
148 *target = 0;
54 149
55 tmp = (unsigned char *)str; 150 /* properly join any arabic chars */
56 block_start=block_end=0; 151 arabjoin(utf16_buf, length);
57 block_ended=0;
58 152
59 heb_str = buf_heb_str; 153 block_start=block_end=block_length=0;
154
155 heb_str = bidi_buf;
60 if (orientation) { 156 if (orientation) {
61 target = heb_str; 157 target = heb_str;
62 opposite_target = heb_str + strlen(str);
63 } else { 158 } else {
64 target = heb_str + strlen(str); 159 target = heb_str + length;
65 opposite_target = heb_str;
66 *target = 0; 160 *target = 0;
67 target--; 161 target--;
68 } 162 }
69 163
70 block_length=0;
71 if (ischar(*tmp)) 164 if (ischar(*tmp))
72 block_type = _HEB_BLOCK_TYPE_HEB; 165 block_type = _HEB_BLOCK_TYPE_HEB;
73 else 166 else
74 block_type = _HEB_BLOCK_TYPE_ENG; 167 block_type = _HEB_BLOCK_TYPE_ENG;
75 168
76 do { 169 do {
77 while((XOR(ischar((int)*(tmp+1)),block_type) 170 while((XOR(ischar(*(tmp+1)),block_type)
78 || _isblank((int)*(tmp+1)) || ispunct((int)*(tmp+1)) 171 || _isblank(*(tmp+1)) || ispunct((int)*(tmp+1))
79 || (int)*(tmp+1)=='\n') 172 || *(tmp+1)=='\n')
80 && block_end<(int)strlen(str)-1) { 173 && block_end < length-1) {
81 tmp++; 174 tmp++;
82 block_end++; 175 block_end++;
83 block_length++; 176 block_length++;
84 } 177 }
85 178
86 if (block_type != orientation) { 179 if (block_type != orientation) {
87 while ((_isblank((int)*tmp) || ispunct((int)*tmp)) 180 while ((_isblank(*tmp) || ispunct((int)*tmp))
88 && *tmp!='/' && *tmp!='-' && block_end>block_start) { 181 && *tmp!='/' && *tmp!='-' && block_end>block_start) {
89 tmp--; 182 tmp--;
90 block_end--; 183 block_end--;
91 } 184 }
92 } 185 }
93 186
94 for (i=block_start; i<=block_end; i++) { 187 for (i=block_start; i<=block_end; i++) {
95 *target = (block_type == orientation) ? *(str+i) : *(str+block_end-i+block_start); 188 *target = (block_type == orientation) ? *(utf16_buf+i) : *(utf16_buf+block_end-i+block_start);
96 if (block_type!=orientation) { 189 if (block_type!=orientation) {
97 switch (*target) { 190 switch (*target) {
98 case '(': 191 case '(':
@@ -109,12 +202,15 @@ unsigned char *bidi_l2v(const char *str, int orientation)
109 } 202 }
110 block_type = !block_type; 203 block_type = !block_type;
111 block_start=block_end+1; 204 block_start=block_end+1;
112 } while(block_end<(int)strlen(str)-1); 205 } while(block_end<length-1);
113 206
114 broken_str = buf_broken_str; 207 *target = 0;
115 begin=end=strlen(str)-1; 208
209#if 0 /* Is this code really necessary? */
210 broken_str = utf16_buf;
211 begin=end=length-1;
116 target = broken_str; 212 target = broken_str;
117 213
118 while (1) { 214 while (1) {
119 char_count=0; 215 char_count=0;
120 while ((!max_chars || char_count<max_chars) && begin>0) { 216 while ((!max_chars || char_count<max_chars) && begin>0) {
@@ -147,9 +243,9 @@ unsigned char *bidi_l2v(const char *str, int orientation)
147 } 243 }
148 orig_begin=begin; 244 orig_begin=begin;
149 245
150 if (_isblank(heb_str[begin])) { 246 /* if (_isblank(heb_str[begin])) {
151 heb_str[begin]='\n'; 247 heb_str[begin]='\n';
152 } 248 } */
153 249
154 /* skip leading newlines */ 250 /* skip leading newlines */
155 while (begin<=end && _isnewline(heb_str[begin])) { 251 while (begin<=end && _isnewline(heb_str[begin])) {
@@ -176,9 +272,7 @@ unsigned char *bidi_l2v(const char *str, int orientation)
176 end=begin; 272 end=begin;
177 } 273 }
178 return broken_str; 274 return broken_str;
275#endif
276 return heb_str;
179} 277}
180 278
181void set_bidi_support(bool setting)
182{
183 bidi_support_enabled = setting;
184}