1 /* Low-level bidirectional buffer-scanning functions for GNU Emacs.
2 Copyright (C) 2000, 2001, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* A sequential implementation of the Unicode Bidirectional algorithm,
23 as per UAX#9, a part of the Unicode Standard.
25 Unlike the reference and most other implementations, this one is
26 designed to be called once for every character in the buffer.
28 The main entry point is bidi_get_next_char_visually. Each time it
29 is called, it finds the next character in the visual order, and
30 returns its information in a special structure. The caller is then
31 expected to process this character for display or any other
32 purposes, and call bidi_get_next_char_visually for the next
33 character. See the comments in bidi_get_next_char_visually for
34 more details about its algorithm that finds the next visual-order
35 character by resolving their levels on the fly.
37 A note about references to UAX#9 rules: if the reference says
38 something like "X9/Retaining", it means that you need to refer to
39 rule X9 and to its modifications decribed in the "Implementation
40 Notes" section of UAX#9, under "Retaining Format Codes". */
54 #include "character.h"
55 #include "dispextern.h"
57 static int bidi_initialized
= 0;
59 static Lisp_Object bidi_type_table
;
61 #define LRM_CHAR 0x200E
62 #define RLM_CHAR 0x200F
63 #define LRE_CHAR 0x202A
64 #define RLE_CHAR 0x202B
65 #define PDF_CHAR 0x202C
66 #define LRO_CHAR 0x202D
67 #define RLO_CHAR 0x202E
69 #define CHARSET_HEBREW 0x88
70 #define CHARSET_ARABIC 0x87
71 #define CHARSET_SYRIAC -1 /* these are undefined yet, -1 is invalid */
72 #define CHARSET_THAANA -1
74 /* FIXME: need to define wrappers for FETCH_CHAR etc. that return
75 BIDI_EOB when they hit ZV. */
79 #ifdef TEST_STANDALONE
82 static unsigned char *input_buf
;
83 static size_t input_buf_size
;
85 int _fetch_multibyte_char_len
, _c_c_
;
87 #undef FETCH_CHAR_ADVANCE
88 #define FETCH_CHAR_ADVANCE(ch, cp, bp) \
98 #define FETCH_CHAR(n) ((_c_c_ = input_buf[n]) ? _c_c_ : BIDI_EOB)
101 #define CHAR_CHARSET(c) \
102 (((c) >= 128 || ((c) < 8 && (c)) || ((c) >= 'A' && (c) < 'X')) \
104 : ((((c) >= 'X' && (c) <= 'Z') || ((c) >= '6' && (c) <= '9')) \
109 #define CHAR_TO_BYTE(pos) (pos)
111 #define char_bytes(ch) 1
129 static const char *bidi_name
[] =
131 "[???]", "[LRE]", "[LRO]", "[RLE]", "[RLO]", "[PDF]", "[RLM]", "[LRM]"
134 #endif /* TEST_STANDALONE */
136 /* Local data structures. (Look in dispextern.h for the rest.) */
138 /* What we need to know about the current paragraph. */
139 struct bidi_paragraph_info
{
140 int start_bytepos
; /* byte position where it begins */
141 int end_bytepos
; /* byte position where it ends */
142 int embedding_level
; /* its basic embedding level */
143 bidi_dir_t base_dir
; /* its base direction */
146 /* Data type for describing the bidirectional character categories. */
154 int bidi_ignore_explicit_marks_for_paragraph_level
= 1;
156 bidi_dir_t bidi_overriding_paragraph_direction
= NEUTRAL_DIR
;
159 #define ASCII_BIDI_TYPE_SET(STR, TYPE) \
162 for (p = (STR); *p; p++) \
163 CHAR_TABLE_SET (bidi_type_table, *p, (TYPE)); \
169 /* FIXME: This should come from the Unicode Database. */
174 { { 0x0000, 0x0008, WEAK_BN
},
175 { 0x0009, 0x0000, NEUTRAL_S
},
176 { 0x000A, 0x0000, NEUTRAL_B
},
177 { 0x000B, 0x0000, NEUTRAL_S
},
178 { 0x000C, 0x0000, NEUTRAL_WS
},
179 { 0x000D, 0x0000, NEUTRAL_B
},
180 { 0x000E, 0x001B, WEAK_BN
},
181 { 0x001C, 0x001E, NEUTRAL_B
},
182 { 0x001F, 0x0000, NEUTRAL_S
},
183 { 0x0020, 0x0000, NEUTRAL_WS
},
184 { 0x0021, 0x0022, NEUTRAL_ON
},
185 { 0x0023, 0x0025, WEAK_ET
},
186 { 0x0026, 0x002A, NEUTRAL_ON
},
187 { 0x002B, 0x0000, WEAK_ET
},
188 { 0x002C, 0x0000, WEAK_CS
},
189 { 0x002D, 0x0000, WEAK_ET
},
190 { 0x002E, 0x0000, WEAK_CS
},
191 { 0x002F, 0x0000, WEAK_ES
},
192 { 0x0030, 0x0039, WEAK_EN
},
193 { 0x003A, 0x0000, WEAK_CS
},
194 { 0x003B, 0x0040, NEUTRAL_ON
},
195 { 0x005B, 0x0060, NEUTRAL_ON
},
196 { 0x007B, 0x007E, NEUTRAL_ON
},
197 { 0x007F, 0x0084, WEAK_BN
},
198 { 0x0085, 0x0000, NEUTRAL_B
},
199 { 0x0086, 0x009F, WEAK_BN
},
200 { 0x00A0, 0x0000, WEAK_CS
},
201 { 0x00A1, 0x0000, NEUTRAL_ON
},
202 { 0x00A2, 0x00A5, WEAK_ET
},
203 { 0x00A6, 0x00A9, NEUTRAL_ON
},
204 { 0x00AB, 0x00AF, NEUTRAL_ON
},
205 { 0x00B0, 0x00B1, WEAK_ET
},
206 { 0x00B2, 0x00B3, WEAK_EN
},
207 { 0x00B4, 0x0000, NEUTRAL_ON
},
208 { 0x00B6, 0x00B8, NEUTRAL_ON
},
209 { 0x00B9, 0x0000, WEAK_EN
},
210 { 0x00BB, 0x00BF, NEUTRAL_ON
},
211 { 0x00D7, 0x0000, NEUTRAL_ON
},
212 { 0x00F7, 0x0000, NEUTRAL_ON
},
213 { 0x02B9, 0x02BA, NEUTRAL_ON
},
214 { 0x02C2, 0x02CF, NEUTRAL_ON
},
215 { 0x02D2, 0x02DF, NEUTRAL_ON
},
216 { 0x02E5, 0x02ED, NEUTRAL_ON
},
217 { 0x0300, 0x036F, WEAK_NSM
},
218 { 0x0374, 0x0375, NEUTRAL_ON
},
219 { 0x037E, 0x0385, NEUTRAL_ON
},
220 { 0x0387, 0x0000, NEUTRAL_ON
},
221 { 0x03F6, 0x0000, NEUTRAL_ON
},
222 { 0x0483, 0x0489, WEAK_NSM
},
223 { 0x058A, 0x0000, NEUTRAL_ON
},
224 { 0x0591, 0x05BD, WEAK_NSM
},
225 { 0x05BE, 0x0000, STRONG_R
},
226 { 0x05BF, 0x0000, WEAK_NSM
},
227 { 0x05C0, 0x0000, STRONG_R
},
228 { 0x05C1, 0x05C2, WEAK_NSM
},
229 { 0x05C3, 0x0000, STRONG_R
},
230 { 0x05C4, 0x0000, WEAK_NSM
},
231 { 0x05D0, 0x05F4, STRONG_R
},
232 { 0x060C, 0x0000, WEAK_CS
},
233 { 0x061B, 0x064A, STRONG_AL
},
234 { 0x064B, 0x0655, WEAK_NSM
},
235 { 0x0660, 0x0669, WEAK_AN
},
236 { 0x066A, 0x0000, WEAK_ET
},
237 { 0x066B, 0x066C, WEAK_AN
},
238 { 0x066D, 0x066F, STRONG_AL
},
239 { 0x0670, 0x0000, WEAK_NSM
},
240 { 0x0671, 0x06D5, STRONG_AL
},
241 { 0x06D6, 0x06DC, WEAK_NSM
},
242 { 0x06DD, 0x0000, STRONG_AL
},
243 { 0x06DE, 0x06E4, WEAK_NSM
},
244 { 0x06E5, 0x06E6, STRONG_AL
},
245 { 0x06E7, 0x06E8, WEAK_NSM
},
246 { 0x06E9, 0x0000, NEUTRAL_ON
},
247 { 0x06EA, 0x06ED, WEAK_NSM
},
248 { 0x06F0, 0x06F9, WEAK_EN
},
249 { 0x06FA, 0x070D, STRONG_AL
},
250 { 0x070F, 0x0000, WEAK_BN
},
251 { 0x0710, 0x0000, STRONG_AL
},
252 { 0x0711, 0x0000, WEAK_NSM
},
253 { 0x0712, 0x072C, STRONG_AL
},
254 { 0x0730, 0x074A, WEAK_NSM
},
255 { 0x0780, 0x07A5, STRONG_AL
},
256 { 0x07A6, 0x07B0, WEAK_NSM
},
257 { 0x07B1, 0x0000, STRONG_AL
},
258 { 0x0901, 0x0902, WEAK_NSM
},
259 { 0x093C, 0x0000, WEAK_NSM
},
260 { 0x0941, 0x0948, WEAK_NSM
},
261 { 0x094D, 0x0000, WEAK_NSM
},
262 { 0x0951, 0x0954, WEAK_NSM
},
263 { 0x0962, 0x0963, WEAK_NSM
},
264 { 0x0981, 0x0000, WEAK_NSM
},
265 { 0x09BC, 0x0000, WEAK_NSM
},
266 { 0x09C1, 0x09C4, WEAK_NSM
},
267 { 0x09CD, 0x0000, WEAK_NSM
},
268 { 0x09E2, 0x09E3, WEAK_NSM
},
269 { 0x09F2, 0x09F3, WEAK_ET
},
270 { 0x0A02, 0x0000, WEAK_NSM
},
271 { 0x0A3C, 0x0000, WEAK_NSM
},
272 { 0x0A41, 0x0A4D, WEAK_NSM
},
273 { 0x0A70, 0x0A71, WEAK_NSM
},
274 { 0x0A81, 0x0A82, WEAK_NSM
},
275 { 0x0ABC, 0x0000, WEAK_NSM
},
276 { 0x0AC1, 0x0AC8, WEAK_NSM
},
277 { 0x0ACD, 0x0000, WEAK_NSM
},
278 { 0x0B01, 0x0000, WEAK_NSM
},
279 { 0x0B3C, 0x0000, WEAK_NSM
},
280 { 0x0B3F, 0x0000, WEAK_NSM
},
281 { 0x0B41, 0x0B43, WEAK_NSM
},
282 { 0x0B4D, 0x0B56, WEAK_NSM
},
283 { 0x0B82, 0x0000, WEAK_NSM
},
284 { 0x0BC0, 0x0000, WEAK_NSM
},
285 { 0x0BCD, 0x0000, WEAK_NSM
},
286 { 0x0C3E, 0x0C40, WEAK_NSM
},
287 { 0x0C46, 0x0C56, WEAK_NSM
},
288 { 0x0CBF, 0x0000, WEAK_NSM
},
289 { 0x0CC6, 0x0000, WEAK_NSM
},
290 { 0x0CCC, 0x0CCD, WEAK_NSM
},
291 { 0x0D41, 0x0D43, WEAK_NSM
},
292 { 0x0D4D, 0x0000, WEAK_NSM
},
293 { 0x0DCA, 0x0000, WEAK_NSM
},
294 { 0x0DD2, 0x0DD6, WEAK_NSM
},
295 { 0x0E31, 0x0000, WEAK_NSM
},
296 { 0x0E34, 0x0E3A, WEAK_NSM
},
297 { 0x0E3F, 0x0000, WEAK_ET
},
298 { 0x0E47, 0x0E4E, WEAK_NSM
},
299 { 0x0EB1, 0x0000, WEAK_NSM
},
300 { 0x0EB4, 0x0EBC, WEAK_NSM
},
301 { 0x0EC8, 0x0ECD, WEAK_NSM
},
302 { 0x0F18, 0x0F19, WEAK_NSM
},
303 { 0x0F35, 0x0000, WEAK_NSM
},
304 { 0x0F37, 0x0000, WEAK_NSM
},
305 { 0x0F39, 0x0000, WEAK_NSM
},
306 { 0x0F3A, 0x0F3D, NEUTRAL_ON
},
307 { 0x0F71, 0x0F7E, WEAK_NSM
},
308 { 0x0F80, 0x0F84, WEAK_NSM
},
309 { 0x0F86, 0x0F87, WEAK_NSM
},
310 { 0x0F90, 0x0FBC, WEAK_NSM
},
311 { 0x0FC6, 0x0000, WEAK_NSM
},
312 { 0x102D, 0x1030, WEAK_NSM
},
313 { 0x1032, 0x1037, WEAK_NSM
},
314 { 0x1039, 0x0000, WEAK_NSM
},
315 { 0x1058, 0x1059, WEAK_NSM
},
316 { 0x1680, 0x0000, NEUTRAL_WS
},
317 { 0x169B, 0x169C, NEUTRAL_ON
},
318 { 0x1712, 0x1714, WEAK_NSM
},
319 { 0x1732, 0x1734, WEAK_NSM
},
320 { 0x1752, 0x1753, WEAK_NSM
},
321 { 0x1772, 0x1773, WEAK_NSM
},
322 { 0x17B7, 0x17BD, WEAK_NSM
},
323 { 0x17C6, 0x0000, WEAK_NSM
},
324 { 0x17C9, 0x17D3, WEAK_NSM
},
325 { 0x17DB, 0x0000, WEAK_ET
},
326 { 0x1800, 0x180A, NEUTRAL_ON
},
327 { 0x180B, 0x180D, WEAK_NSM
},
328 { 0x180E, 0x0000, WEAK_BN
},
329 { 0x18A9, 0x0000, WEAK_NSM
},
330 { 0x1FBD, 0x0000, NEUTRAL_ON
},
331 { 0x1FBF, 0x1FC1, NEUTRAL_ON
},
332 { 0x1FCD, 0x1FCF, NEUTRAL_ON
},
333 { 0x1FDD, 0x1FDF, NEUTRAL_ON
},
334 { 0x1FED, 0x1FEF, NEUTRAL_ON
},
335 { 0x1FFD, 0x1FFE, NEUTRAL_ON
},
336 { 0x2000, 0x200A, NEUTRAL_WS
},
337 { 0x200B, 0x200D, WEAK_BN
},
338 { 0x200F, 0x0000, STRONG_R
},
339 { 0x2010, 0x2027, NEUTRAL_ON
},
340 { 0x2028, 0x0000, NEUTRAL_WS
},
341 { 0x2029, 0x0000, NEUTRAL_B
},
342 { 0x202A, 0x0000, LRE
},
343 { 0x202B, 0x0000, RLE
},
344 { 0x202C, 0x0000, PDF
},
345 { 0x202D, 0x0000, LRO
},
346 { 0x202E, 0x0000, RLO
},
347 { 0x202F, 0x0000, NEUTRAL_WS
},
348 { 0x2030, 0x2034, WEAK_ET
},
349 { 0x2035, 0x2057, NEUTRAL_ON
},
350 { 0x205F, 0x0000, NEUTRAL_WS
},
351 { 0x2060, 0x206F, WEAK_BN
},
352 { 0x2070, 0x0000, WEAK_EN
},
353 { 0x2074, 0x2079, WEAK_EN
},
354 { 0x207A, 0x207B, WEAK_ET
},
355 { 0x207C, 0x207E, NEUTRAL_ON
},
356 { 0x2080, 0x2089, WEAK_EN
},
357 { 0x208A, 0x208B, WEAK_ET
},
358 { 0x208C, 0x208E, NEUTRAL_ON
},
359 { 0x20A0, 0x20B1, WEAK_ET
},
360 { 0x20D0, 0x20EA, WEAK_NSM
},
361 { 0x2100, 0x2101, NEUTRAL_ON
},
362 { 0x2103, 0x2106, NEUTRAL_ON
},
363 { 0x2108, 0x2109, NEUTRAL_ON
},
364 { 0x2114, 0x0000, NEUTRAL_ON
},
365 { 0x2116, 0x2118, NEUTRAL_ON
},
366 { 0x211E, 0x2123, NEUTRAL_ON
},
367 { 0x2125, 0x0000, NEUTRAL_ON
},
368 { 0x2127, 0x0000, NEUTRAL_ON
},
369 { 0x2129, 0x0000, NEUTRAL_ON
},
370 { 0x212E, 0x0000, WEAK_ET
},
371 { 0x2132, 0x0000, NEUTRAL_ON
},
372 { 0x213A, 0x0000, NEUTRAL_ON
},
373 { 0x2140, 0x2144, NEUTRAL_ON
},
374 { 0x214A, 0x215F, NEUTRAL_ON
},
375 { 0x2190, 0x2211, NEUTRAL_ON
},
376 { 0x2212, 0x2213, WEAK_ET
},
377 { 0x2214, 0x2335, NEUTRAL_ON
},
378 { 0x237B, 0x2394, NEUTRAL_ON
},
379 { 0x2396, 0x244A, NEUTRAL_ON
},
380 { 0x2460, 0x249B, WEAK_EN
},
381 { 0x24EA, 0x0000, WEAK_EN
},
382 { 0x24EB, 0x2FFB, NEUTRAL_ON
},
383 { 0x3000, 0x0000, NEUTRAL_WS
},
384 { 0x3001, 0x3004, NEUTRAL_ON
},
385 { 0x3008, 0x3020, NEUTRAL_ON
},
386 { 0x302A, 0x302F, WEAK_NSM
},
387 { 0x3030, 0x0000, NEUTRAL_ON
},
388 { 0x3036, 0x3037, NEUTRAL_ON
},
389 { 0x303D, 0x303F, NEUTRAL_ON
},
390 { 0x3099, 0x309A, WEAK_NSM
},
391 { 0x309B, 0x309C, NEUTRAL_ON
},
392 { 0x30A0, 0x0000, NEUTRAL_ON
},
393 { 0x30FB, 0x0000, NEUTRAL_ON
},
394 { 0x3251, 0x325F, NEUTRAL_ON
},
395 { 0x32B1, 0x32BF, NEUTRAL_ON
},
396 { 0xA490, 0xA4C6, NEUTRAL_ON
},
397 { 0xFB1D, 0x0000, STRONG_R
},
398 { 0xFB1E, 0x0000, WEAK_NSM
},
399 { 0xFB1F, 0xFB28, STRONG_R
},
400 { 0xFB29, 0x0000, WEAK_ET
},
401 { 0xFB2A, 0xFB4F, STRONG_R
},
402 { 0xFB50, 0xFD3D, STRONG_AL
},
403 { 0xFD3E, 0xFD3F, NEUTRAL_ON
},
404 { 0xFD50, 0xFDFC, STRONG_AL
},
405 { 0xFE00, 0xFE23, WEAK_NSM
},
406 { 0xFE30, 0xFE4F, NEUTRAL_ON
},
407 { 0xFE50, 0x0000, WEAK_CS
},
408 { 0xFE51, 0x0000, NEUTRAL_ON
},
409 { 0xFE52, 0x0000, WEAK_CS
},
410 { 0xFE54, 0x0000, NEUTRAL_ON
},
411 { 0xFE55, 0x0000, WEAK_CS
},
412 { 0xFE56, 0xFE5E, NEUTRAL_ON
},
413 { 0xFE5F, 0x0000, WEAK_ET
},
414 { 0xFE60, 0xFE61, NEUTRAL_ON
},
415 { 0xFE62, 0xFE63, WEAK_ET
},
416 { 0xFE64, 0xFE68, NEUTRAL_ON
},
417 { 0xFE69, 0xFE6A, WEAK_ET
},
418 { 0xFE6B, 0x0000, NEUTRAL_ON
},
419 { 0xFE70, 0xFEFC, STRONG_AL
},
420 { 0xFEFF, 0x0000, WEAK_BN
},
421 { 0xFF01, 0xFF02, NEUTRAL_ON
},
422 { 0xFF03, 0xFF05, WEAK_ET
},
423 { 0xFF06, 0xFF0A, NEUTRAL_ON
},
424 { 0xFF0B, 0x0000, WEAK_ET
},
425 { 0xFF0C, 0x0000, WEAK_CS
},
426 { 0xFF0D, 0x0000, WEAK_ET
},
427 { 0xFF0E, 0x0000, WEAK_CS
},
428 { 0xFF0F, 0x0000, WEAK_ES
},
429 { 0xFF10, 0xFF19, WEAK_EN
},
430 { 0xFF1A, 0x0000, WEAK_CS
},
431 { 0xFF1B, 0xFF20, NEUTRAL_ON
},
432 { 0xFF3B, 0xFF40, NEUTRAL_ON
},
433 { 0xFF5B, 0xFF65, NEUTRAL_ON
},
434 { 0xFFE0, 0xFFE1, WEAK_ET
},
435 { 0xFFE2, 0xFFE4, NEUTRAL_ON
},
436 { 0xFFE5, 0xFFE6, WEAK_ET
},
437 { 0xFFE8, 0xFFEE, NEUTRAL_ON
},
438 { 0xFFF9, 0xFFFB, WEAK_BN
},
439 { 0xFFFC, 0xFFFD, NEUTRAL_ON
},
440 { 0x1D167, 0x1D169, WEAK_NSM
},
441 { 0x1D173, 0x1D17A, WEAK_BN
},
442 { 0x1D17B, 0x1D182, WEAK_NSM
},
443 { 0x1D185, 0x1D18B, WEAK_NSM
},
444 { 0x1D1AA, 0x1D1AD, WEAK_NSM
},
445 { 0x1D7CE, 0x1D7FF, WEAK_EN
},
446 { 0xE0001, 0xE007F, WEAK_BN
} };
449 bidi_type_table
= Fmake_char_table (Qnil
, make_number (STRONG_L
));
451 for (i
= 0; i
< sizeof bidi_type
/ sizeof bidi_type
[0]; i
++)
452 char_table_set_range (bidi_type_table
, bidi_type
[i
].from
,
453 bidi_type
[i
].to
? bidi_type
[i
].to
: bidi_type
[i
].from
,
454 make_number (bidi_type
[i
].type
));
455 bidi_initialized
= 1;
459 bidi_is_arabic_number (int ch
)
461 #ifdef TEST_STANDALONE
462 return ch
>= '6' && ch
<= '9';
464 return 0; /* FIXME! */
468 /* Return the bidi type of a character CH. */
470 bidi_get_type (int ch
)
472 return (bidi_type_t
) XINT (CHAR_TABLE_REF (bidi_type_table
, ch
));
475 /* Given a bidi TYPE of a character, return its category. */
477 bidi_get_category (bidi_type_t type
)
491 case PDF
: /* ??? really?? */
510 /* FIXME: exceedingly temporary! Should consult the Unicode database
511 of character properties. */
513 bidi_mirror_char (int c
)
515 static const char mirrored_pairs
[] = "()<>[]{}";
516 const char *p
= strchr (mirrored_pairs
, c
);
520 size_t i
= p
- mirrored_pairs
;
523 return mirrored_pairs
[i
+ 1];
525 return mirrored_pairs
[i
- 1];
530 /* Copy the bidi iterator from FROM to TO. To save cycles, this only
531 copies the part of the level stack that is actually in use. */
533 bidi_copy_it (struct bidi_it
*to
, struct bidi_it
*from
)
537 /* Copy everything except the level stack. */
538 memcpy (to
, from
, ((int)&((struct bidi_it
*)0)->level_stack
[0]));
540 /* Copy the active part of the level stack. */
541 to
->level_stack
[0] = from
->level_stack
[0]; /* level zero is always in use */
542 for (i
= 1; i
<= from
->stack_idx
; i
++)
543 to
->level_stack
[i
] = from
->level_stack
[i
];
546 /* Caching the bidi iterator states. */
548 static struct bidi_it bidi_cache
[1000]; /* FIXME: make this dynamically allocated! */
549 static int bidi_cache_idx
;
550 static int bidi_cache_last_idx
;
553 bidi_cache_reset (void)
556 bidi_cache_last_idx
= -1;
560 bidi_cache_fetch_state (int idx
, struct bidi_it
*bidi_it
)
562 int current_scan_dir
= bidi_it
->scan_dir
;
564 if (idx
< 0 || idx
>= bidi_cache_idx
)
567 bidi_copy_it (bidi_it
, &bidi_cache
[idx
]);
568 bidi_it
->scan_dir
= current_scan_dir
;
569 bidi_cache_last_idx
= idx
;
572 /* Find a cached state with a given CHARPOS and resolved embedding
573 level less or equal to LEVEL. if LEVEL is -1, disregard the
574 resolved levels in cached states. DIR, if non-zero, means search
575 in that direction from the last cache hit. */
577 bidi_cache_search (int charpos
, int level
, int dir
)
583 if (charpos
< bidi_cache
[bidi_cache_last_idx
].charpos
)
585 else if (charpos
> bidi_cache
[bidi_cache_last_idx
].charpos
)
588 i_start
= bidi_cache_last_idx
;
592 i_start
= bidi_cache_idx
- 1;
597 /* Linear search for now; FIXME! */
598 for (i
= i_start
; i
>= 0; i
--)
599 if (bidi_cache
[i
].charpos
== charpos
600 && (level
== -1 || bidi_cache
[i
].resolved_level
<= level
))
605 for (i
= i_start
; i
< bidi_cache_idx
; i
++)
606 if (bidi_cache
[i
].charpos
== charpos
607 && (level
== -1 || bidi_cache
[i
].resolved_level
<= level
))
615 /* Find a cached state where the resolved level changes to a value
616 that is lower than LEVEL, and return its cache slot index. DIR is
617 the direction to search, starting with the last used cache slot.
618 BEFORE, if non-zero, means return the index of the slot that is
619 ``before'' the level change in the search direction. That is,
620 given the cached levels like this:
625 and assuming we are at the position cached at the slot marked with
626 C, searching backwards (DIR = -1) for LEVEL = 2 will return the
627 index of slot B or A, depending whether BEFORE is, respectively,
630 bidi_cache_find_level_change (int level
, int dir
, int before
)
634 int i
= dir
? bidi_cache_last_idx
: bidi_cache_idx
- 1;
635 int incr
= before
? 1 : 0;
646 if (bidi_cache
[i
- incr
].resolved_level
>= 0
647 && bidi_cache
[i
- incr
].resolved_level
< level
)
654 while (i
< bidi_cache_idx
- incr
)
656 if (bidi_cache
[i
+ incr
].resolved_level
>= 0
657 && bidi_cache
[i
+ incr
].resolved_level
< level
)
668 bidi_cache_iterator_state (struct bidi_it
*bidi_it
, int resolved
)
672 /* We should never cache on backward scans. */
673 if (bidi_it
->scan_dir
== -1)
675 idx
= bidi_cache_search (bidi_it
->charpos
, -1, 1);
679 idx
= bidi_cache_idx
;
680 if (idx
> sizeof (bidi_cache
) / sizeof (bidi_cache
[0]) - 1)
682 bidi_copy_it (&bidi_cache
[idx
], bidi_it
);
684 bidi_cache
[idx
].resolved_level
= -1;
688 /* Copy only the members which could have changed, to avoid
689 costly copying of the entire struct. */
690 bidi_cache
[idx
].type
= bidi_it
->type
;
691 bidi_cache
[idx
].orig_type
= bidi_it
->orig_type
;
693 bidi_cache
[idx
].resolved_level
= bidi_it
->resolved_level
;
695 bidi_cache
[idx
].resolved_level
= -1;
696 bidi_cache
[idx
].invalid_levels
= bidi_it
->invalid_levels
;
697 bidi_cache
[idx
].invalid_rl_levels
= bidi_it
->invalid_rl_levels
;
698 bidi_cache
[idx
].next_for_neutral
= bidi_it
->next_for_neutral
;
699 bidi_cache
[idx
].next_for_ws
= bidi_it
->next_for_ws
;
700 bidi_cache
[idx
].ignore_bn_limit
= bidi_it
->ignore_bn_limit
;
703 bidi_cache_last_idx
= idx
;
704 if (idx
>= bidi_cache_idx
)
705 bidi_cache_idx
= idx
+ 1;
708 static inline bidi_type_t
709 bidi_cache_find (int charpos
, int level
, struct bidi_it
*bidi_it
)
711 int i
= bidi_cache_search (charpos
, level
, bidi_it
->scan_dir
);
715 bidi_dir_t current_scan_dir
= bidi_it
->scan_dir
;
717 *bidi_it
= bidi_cache
[i
];
718 bidi_cache_last_idx
= i
;
719 /* Don't let scan direction from from the cached state override
720 the current scan direction. */
721 bidi_it
->scan_dir
= current_scan_dir
;
722 return bidi_it
->type
;
729 bidi_peek_at_next_level (struct bidi_it
*bidi_it
)
731 if (bidi_cache_idx
== 0 || bidi_cache_last_idx
== -1)
733 return bidi_cache
[bidi_cache_last_idx
+ bidi_it
->scan_dir
].resolved_level
;
736 /* Return non-zero if buffer's byte position POS is the last character
737 of a paragraph. THIS_CH is the character preceding the one at POS in
740 bidi_at_paragraph_end (int this_ch
, int pos
)
742 int next_ch
= FETCH_CHAR (pos
);
744 /* FIXME: This should support all Unicode characters that can end a
746 return (this_ch
== '\n' && next_ch
== '\n') || this_ch
== BIDI_EOB
;
749 /* Determine the start-of-run (sor) directional type given the two
750 embedding levels on either side of the run boundary. Also, update
751 the saved info about previously seen characters, since that info is
752 generally valid for a single level run. */
754 bidi_set_sor_type (struct bidi_it
*bidi_it
, int level_before
, int level_after
)
756 int higher_level
= level_before
> level_after
? level_before
: level_after
;
758 /* The prev_was_pdf gork is required for when we have several PDFs
759 in a row. In that case, we want to compute the sor type for the
760 next level run only once: when we see the first PDF. That's
761 because the sor type depends only on the higher of the two levels
762 that we find on the two sides of the level boundary (see UAX#9,
763 clause X10), and so we don't need to know the final embedding
764 level to which we descend after processing all the PDFs. */
765 if (level_before
< level_after
|| !bidi_it
->prev_was_pdf
)
766 /* FIXME: should the default sor direction be user selectable? */
767 bidi_it
->sor
= (higher_level
& 1) != 0 ? R2L
: L2R
;
768 if (level_before
> level_after
)
769 bidi_it
->prev_was_pdf
= 1;
771 bidi_it
->prev
.type
= UNKNOWN_BT
;
772 bidi_it
->last_strong
.type
= bidi_it
->last_strong
.orig_type
=
773 bidi_it
->last_strong
.pristine_type
= UNKNOWN_BT
;
774 bidi_it
->prev_for_neutral
.type
= bidi_it
->sor
== R2L
? STRONG_R
: STRONG_L
;
775 bidi_it
->prev_for_neutral
.charpos
= bidi_it
->charpos
;
776 bidi_it
->prev_for_neutral
.bytepos
= bidi_it
->bytepos
;
777 bidi_it
->next_for_neutral
.type
= bidi_it
->next_for_neutral
.orig_type
=
778 bidi_it
->next_for_neutral
.pristine_type
= UNKNOWN_BT
;
779 bidi_it
->ignore_bn_limit
= 0; /* meaning it's unknown */
783 bidi_paragraph_init (bidi_dir_t dir
, struct bidi_it
*bidi_it
)
785 bidi_it
->level_stack
[0].level
= 0;
787 bidi_it
->level_stack
[0].level
= 1;
788 else if (dir
== NEUTRAL_DIR
) /* P2 */
791 int pos
= bidi_it
->charpos
, bytepos
= bidi_it
->bytepos
;
796 else if (bidi_it
->ch
!= BIDI_EOB
)
799 bytepos
+= bidi_it
->ch_len
;
802 ch
= FETCH_CHAR (bytepos
);
804 bytepos
+= CHAR_BYTES (ch
);
806 /* FIXME: should actually go to where the paragraph begins and
807 start the loop below from there, since UAX#9 says to find the
808 first strong directional character in the paragraph. */
810 for (type
= bidi_get_type (ch
);
811 /* NOTE: UAX#9 says to search only for L, AL, or R types of
812 characters, and ignore RLE, RLO, LRE, and LRO. However,
813 I'm not sure it makes sense to omit those 4; should try
814 with and without that to see the effect. */
815 (bidi_get_category (type
) != STRONG
)
816 || (bidi_ignore_explicit_marks_for_paragraph_level
817 && (type
== RLE
|| type
== RLO
818 || type
== LRE
|| type
== LRO
));
819 type
= bidi_get_type (ch
))
821 if (type
== NEUTRAL_B
|| bidi_at_paragraph_end (ch
, bytepos
))
823 FETCH_CHAR_ADVANCE (ch
, pos
, bytepos
);
825 if (type
== STRONG_R
|| type
== STRONG_AL
) /* P3 */
826 bidi_it
->level_stack
[0].level
= 1;
828 bidi_it
->scan_dir
= 1; /* FIXME: do we need to have control on this? */
829 bidi_it
->resolved_level
= bidi_it
->level_stack
[0].level
;
830 bidi_it
->level_stack
[0].override
= NEUTRAL_DIR
; /* X1 */
831 bidi_it
->invalid_levels
= 0;
832 bidi_it
->invalid_rl_levels
= -1;
833 bidi_it
->new_paragraph
= 0;
834 bidi_it
->next_en_pos
= -1;
835 bidi_it
->next_for_ws
.type
= UNKNOWN_BT
;
836 bidi_set_sor_type (bidi_it
, bidi_it
->level_stack
[0].level
, 0); /* X10 */
841 /* Do whatever UAX#9 clause X8 says should be done at paragraph's end,
842 and set the new paragraph flag in the iterator. */
844 bidi_set_paragraph_end (struct bidi_it
*bidi_it
)
846 bidi_it
->invalid_levels
= 0;
847 bidi_it
->invalid_rl_levels
= -1;
848 bidi_it
->stack_idx
= 0;
849 bidi_it
->resolved_level
= bidi_it
->level_stack
[0].level
;
850 bidi_it
->new_paragraph
= 1;
853 /* Initialize the bidi iterator from buffer position POS for paragraph
854 direction DIR. Return the embedding level at POS. */
856 bidi_init_it (int pos
, bidi_dir_t dir
, struct bidi_it
*bidi_it
)
858 if (! bidi_initialized
)
860 bidi_set_paragraph_end (bidi_it
);
861 bidi_it
->charpos
= pos
;
864 bidi_it
->bytepos
= bidi_it
->charpos
;
865 bidi_it
->ch_len
= 1; /* so that incrementing bytepos works */
869 bidi_it
->bytepos
= CHAR_TO_BYTE (pos
);
871 = MULTIBYTE_FORM_LENGTH (BYTE_POS_ADDR (bidi_it
->bytepos
),
872 MAX_MULTIBYTE_LENGTH
);
874 bidi_it
->ch
= '\x1d'; /* FIXME: should be U+2029 */
875 bidi_it
->type
= NEUTRAL_B
;
876 bidi_it
->orig_type
= UNKNOWN_BT
;
877 bidi_it
->pristine_type
= UNKNOWN_BT
;
878 bidi_it
->prev_was_pdf
= 0;
879 bidi_it
->prev
.type
= bidi_it
->prev
.orig_type
= UNKNOWN_BT
;
880 bidi_it
->last_strong
.type
= bidi_it
->last_strong
.orig_type
=
881 bidi_it
->last_strong
.pristine_type
= UNKNOWN_BT
;
882 bidi_it
->next_for_neutral
.charpos
= -1;
883 bidi_it
->next_for_neutral
.type
=
884 bidi_it
->next_for_neutral
.orig_type
=
885 bidi_it
->next_for_neutral
.pristine_type
= UNKNOWN_BT
;
886 bidi_it
->prev_for_neutral
.charpos
= -1;
887 bidi_it
->prev_for_neutral
.type
=
888 bidi_it
->prev_for_neutral
.orig_type
=
889 bidi_it
->prev_for_neutral
.pristine_type
= UNKNOWN_BT
;
890 bidi_it
->sor
= L2R
; /* FIXME: should it be user-selectable? */
891 bidi_paragraph_init (dir
, bidi_it
);
894 /* Push the current embedding level and override status; reset the
895 current level to LEVEL and the current override status to OVERRIDE. */
897 bidi_push_embedding_level (struct bidi_it
*bidi_it
,
898 int level
, bidi_dir_t override
)
900 bidi_it
->stack_idx
++;
901 if (bidi_it
->stack_idx
>= BIDI_MAXLEVEL
)
903 bidi_it
->level_stack
[bidi_it
->stack_idx
].level
= level
;
904 bidi_it
->level_stack
[bidi_it
->stack_idx
].override
= override
;
907 /* Pop the embedding level and directional override status from the
908 stack, and return the new level. */
910 bidi_pop_embedding_level (struct bidi_it
*bidi_it
)
912 /* UAX#9 says to ignore invalid PDFs. */
913 if (bidi_it
->stack_idx
> 0)
914 bidi_it
->stack_idx
--;
915 return bidi_it
->level_stack
[bidi_it
->stack_idx
].level
;
918 /* Record in SAVED_INFO the information about the current character. */
920 bidi_remember_char (struct bidi_saved_info
*saved_info
,
921 struct bidi_it
*bidi_it
)
923 saved_info
->charpos
= bidi_it
->charpos
;
924 saved_info
->bytepos
= bidi_it
->bytepos
;
925 saved_info
->type
= bidi_it
->type
;
926 saved_info
->orig_type
= bidi_it
->orig_type
;
927 saved_info
->pristine_type
= bidi_it
->pristine_type
;
930 /* Resolve the type of a neutral character according to the type of
931 surrounding strong text and the current embedding level. */
932 static inline bidi_type_t
933 bidi_resolve_neutral_1 (bidi_type_t prev_type
, bidi_type_t next_type
, int lev
)
935 /* N1: European and Arabic numbers are treated as though they were R. */
936 if (next_type
== WEAK_EN
|| next_type
== WEAK_AN
)
937 next_type
= STRONG_R
;
938 if (prev_type
== WEAK_EN
|| prev_type
== WEAK_AN
)
939 prev_type
= STRONG_R
;
941 if (next_type
== prev_type
) /* N1 */
943 else if ((lev
& 1) == 0) /* N2 */
950 bidi_explicit_dir_char (int c
)
952 /* FIXME: this should be replaced with a lookup table with suitable
953 bits set, like standard C ctype macros do. */
954 return (c
== LRE_CHAR
|| c
== LRO_CHAR
955 || c
== RLE_CHAR
|| c
== RLO_CHAR
|| c
== PDF_CHAR
);
958 /* A helper function for bidi_resolve_explicit. It advances to the
959 next character in logical order and determines the new embedding
960 level and directional override, but does not take into account
963 bidi_resolve_explicit_1 (struct bidi_it
*bidi_it
)
971 if (bidi_it
->charpos
< 0)
972 bidi_it
->charpos
= bidi_it
->bytepos
= 0;
976 bidi_it
->bytepos
+= bidi_it
->ch_len
;
979 current_level
= bidi_it
->level_stack
[bidi_it
->stack_idx
].level
; /* X1 */
980 override
= bidi_it
->level_stack
[bidi_it
->stack_idx
].override
;
981 new_level
= current_level
;
983 /* in case it is a unibyte character (not yet implemented) */
984 /* _fetch_multibyte_char_len = 1; */
985 curchar
= FETCH_CHAR (bidi_it
->bytepos
);
986 bidi_it
->ch
= curchar
;
987 bidi_it
->ch_len
= CHAR_BYTES (curchar
);
989 type
= bidi_get_type (curchar
);
990 bidi_it
->pristine_type
= type
;
993 bidi_it
->prev_was_pdf
= 0;
995 bidi_it
->orig_type
= UNKNOWN_BT
;
1001 bidi_it
->orig_type
= type
;
1002 type
= WEAK_BN
; /* X9/Retaining */
1003 if (bidi_it
->ignore_bn_limit
<= 0)
1005 if (current_level
<= BIDI_MAXLEVEL
- 4)
1007 /* Compute the least odd embedding level greater than
1008 the current level. */
1009 new_level
= ((current_level
+ 1) & ~1) + 1;
1010 if (bidi_it
->orig_type
== RLE
)
1011 override
= NEUTRAL_DIR
;
1014 if (current_level
== BIDI_MAXLEVEL
- 4)
1015 bidi_it
->invalid_rl_levels
= 0;
1016 bidi_push_embedding_level (bidi_it
, new_level
, override
);
1020 bidi_it
->invalid_levels
++;
1021 /* See the commentary about invalid_rl_levels below. */
1022 if (bidi_it
->invalid_rl_levels
< 0)
1023 bidi_it
->invalid_rl_levels
= 0;
1024 bidi_it
->invalid_rl_levels
++;
1027 else if (bidi_it
->prev
.orig_type
== WEAK_EN
/* W5/Retaining */
1028 || bidi_it
->next_en_pos
> bidi_it
->charpos
)
1033 bidi_it
->orig_type
= type
;
1034 type
= WEAK_BN
; /* X9/Retaining */
1035 if (bidi_it
->ignore_bn_limit
<= 0)
1037 if (current_level
<= BIDI_MAXLEVEL
- 5)
1039 /* Compute the least even embedding level greater than
1040 the current level. */
1041 new_level
= ((current_level
+ 2) & ~1);
1042 if (bidi_it
->orig_type
== LRE
)
1043 override
= NEUTRAL_DIR
;
1046 bidi_push_embedding_level (bidi_it
, new_level
, override
);
1050 bidi_it
->invalid_levels
++;
1051 /* invalid_rl_levels counts invalid levels encountered
1052 while the embedding level was already too high for
1053 LRE/LRO, but not for RLE/RLO. That is because
1054 there may be exactly one PDF which we should not
1055 ignore even though invalid_levels is non-zero.
1056 invalid_rl_levels helps to know what PDF is
1058 if (bidi_it
->invalid_rl_levels
>= 0)
1059 bidi_it
->invalid_rl_levels
++;
1062 else if (bidi_it
->prev
.orig_type
== WEAK_EN
/* W5/Retaining */
1063 || bidi_it
->next_en_pos
> bidi_it
->charpos
)
1067 bidi_it
->orig_type
= type
;
1068 type
= WEAK_BN
; /* X9/Retaining */
1069 if (bidi_it
->ignore_bn_limit
<= 0)
1071 if (!bidi_it
->invalid_rl_levels
)
1073 new_level
= bidi_pop_embedding_level (bidi_it
);
1074 bidi_it
->invalid_rl_levels
= -1;
1075 if (bidi_it
->invalid_levels
)
1076 bidi_it
->invalid_levels
--;
1077 /* else nothing: UAX#9 says to ignore invalid PDFs */
1079 if (!bidi_it
->invalid_levels
)
1080 new_level
= bidi_pop_embedding_level (bidi_it
);
1083 bidi_it
->invalid_levels
--;
1084 bidi_it
->invalid_rl_levels
--;
1087 else if (bidi_it
->prev
.orig_type
== WEAK_EN
/* W5/Retaining */
1088 || bidi_it
->next_en_pos
> bidi_it
->charpos
)
1096 bidi_it
->type
= type
;
1101 /* Given an iterator state in BIDI_IT, advance one character position
1102 in the buffer to the next character (in the logical order), resolve
1103 any explicit embeddings and directional overrides, and return the
1104 embedding level of the character after resolving explicit
1105 directives and ignoring empty embeddings. */
1107 bidi_resolve_explicit (struct bidi_it
*bidi_it
)
1109 int prev_level
= bidi_it
->level_stack
[bidi_it
->stack_idx
].level
;
1110 int new_level
= bidi_resolve_explicit_1 (bidi_it
);
1112 if (prev_level
< new_level
1113 && bidi_it
->type
== WEAK_BN
1114 && bidi_it
->ignore_bn_limit
== 0 /* only if not already known */
1115 && bidi_explicit_dir_char (FETCH_CHAR (bidi_it
->bytepos
1116 + bidi_it
->ch_len
)))
1118 /* Avoid pushing and popping embedding levels if the level run
1119 is empty, as this breaks level runs where it shouldn't.
1120 UAX#9 removes all the explicit embedding and override codes,
1121 so empty embeddings disappear without a trace. We need to
1122 behave as if we did the same. */
1123 struct bidi_it saved_it
;
1124 int level
= prev_level
;
1126 bidi_copy_it (&saved_it
, bidi_it
);
1128 while (bidi_explicit_dir_char (FETCH_CHAR (bidi_it
->bytepos
1129 + bidi_it
->ch_len
)))
1131 level
= bidi_resolve_explicit_1 (bidi_it
);
1134 if (level
== prev_level
) /* empty embedding */
1135 saved_it
.ignore_bn_limit
= bidi_it
->charpos
+ 1;
1136 else /* this embedding is non-empty */
1137 saved_it
.ignore_bn_limit
= -1;
1139 bidi_copy_it (bidi_it
, &saved_it
);
1140 if (bidi_it
->ignore_bn_limit
> 0)
1142 /* We pushed a level, but we shouldn't have. Undo that. */
1143 if (!bidi_it
->invalid_rl_levels
)
1145 new_level
= bidi_pop_embedding_level (bidi_it
);
1146 bidi_it
->invalid_rl_levels
= -1;
1147 if (bidi_it
->invalid_levels
)
1148 bidi_it
->invalid_levels
--;
1150 if (!bidi_it
->invalid_levels
)
1151 new_level
= bidi_pop_embedding_level (bidi_it
);
1154 bidi_it
->invalid_levels
--;
1155 bidi_it
->invalid_rl_levels
--;
1160 /* For when the paragraph end is defined by anything other than a
1161 special Unicode character (a.k.a. ``higher protocols''). */
1162 if (bidi_it
->type
!= NEUTRAL_B
)
1163 if (bidi_at_paragraph_end (bidi_it
->ch
,
1164 bidi_it
->bytepos
+ bidi_it
->ch_len
))
1165 bidi_it
->type
= NEUTRAL_B
;
1167 if (bidi_it
->type
== NEUTRAL_B
) /* X8 */
1169 bidi_set_paragraph_end (bidi_it
);
1170 bidi_it
->orig_type
= bidi_it
->type
; /* needed below and in L1 */
1176 /* Advance in the buffer, resolve weak types and return the type of
1177 the next character after weak type resolution. */
1179 bidi_resolve_weak (struct bidi_it
*bidi_it
)
1182 bidi_dir_t override
;
1183 int prev_level
= bidi_it
->level_stack
[bidi_it
->stack_idx
].level
;
1184 int new_level
= bidi_resolve_explicit (bidi_it
);
1186 bidi_type_t type_of_next
;
1187 struct bidi_it saved_it
;
1189 type
= bidi_it
->type
;
1190 override
= bidi_it
->level_stack
[bidi_it
->stack_idx
].override
;
1192 if (type
== UNKNOWN_BT
1200 if (new_level
!= prev_level
1201 || bidi_it
->type
== NEUTRAL_B
)
1203 /* We've got a new embedding level run, compute the directional
1204 type of sor and initialize per-run variables (UAX#9, clause
1206 bidi_set_sor_type (bidi_it
, prev_level
, new_level
);
1208 else if (type
== NEUTRAL_S
|| type
== NEUTRAL_WS
1209 || type
== WEAK_BN
|| type
== STRONG_AL
)
1210 bidi_it
->orig_type
= type
; /* needed in L1 */
1212 /* Level and directional override status are already recorded in
1213 bidi_it, and do not need any change; see X6. */
1214 if (override
== R2L
) /* X6 */
1216 else if (override
== L2R
)
1218 else if (type
== STRONG_AL
)
1219 type
= STRONG_R
; /* W3 */
1220 else if (type
== WEAK_NSM
) /* W1 */
1222 /* Note that we don't need to consider the case where the prev
1223 character has its type overridden by an RLO or LRO: such
1224 characters are outside the current level run, and thus not
1225 relevant to this NSM. Thus, NSM gets the pristine_type of
1226 the previous character. */
1227 if (bidi_it
->prev
.type
!= UNKNOWN_BT
)
1228 type
= bidi_it
->prev
.pristine_type
;
1229 else if (bidi_it
->sor
== R2L
)
1231 else if (bidi_it
->sor
== L2R
)
1233 else /* shouldn't happen! */
1235 if (type
== WEAK_EN
/* W2 after W1 */
1236 && bidi_it
->last_strong
.orig_type
== STRONG_AL
)
1239 else if (type
== WEAK_EN
/* W2 */
1240 && bidi_it
->last_strong
.orig_type
== STRONG_AL
)
1242 else if ((type
== WEAK_ES
1243 && (bidi_it
->prev
.orig_type
== WEAK_EN
/* W4 */
1244 && (bidi_it
->prev
.pristine_type
== WEAK_EN
1245 || bidi_it
->prev
.pristine_type
== WEAK_NSM
))) /* aft W1 */
1247 && ((bidi_it
->prev
.orig_type
== WEAK_EN
1248 && (bidi_it
->prev
.pristine_type
== WEAK_EN
/* W4 */
1249 || bidi_it
->prev
.pristine_type
== WEAK_NSM
)) /* a/W1 */
1250 || bidi_it
->prev
.orig_type
== WEAK_AN
))) /* W4 */
1252 next_char
= FETCH_CHAR (bidi_it
->bytepos
+ bidi_it
->ch_len
);
1253 type_of_next
= bidi_get_type (next_char
);
1255 if (type_of_next
== WEAK_BN
1256 || bidi_explicit_dir_char (next_char
))
1258 bidi_copy_it (&saved_it
, bidi_it
);
1259 while (bidi_resolve_explicit (bidi_it
) == new_level
1260 && bidi_it
->type
== WEAK_BN
)
1262 type_of_next
= bidi_it
->type
;
1263 bidi_copy_it (bidi_it
, &saved_it
);
1266 /* If the next character is EN, but the last strong-type
1267 character is AL, that next EN will be changed to AN when we
1268 process it in W2 above. So in that case, this ES should not
1269 be changed into EN. */
1271 && type_of_next
== WEAK_EN
1272 && bidi_it
->last_strong
.orig_type
!= STRONG_AL
)
1274 else if (type
== WEAK_CS
)
1276 if (bidi_it
->prev
.orig_type
== WEAK_AN
1277 && (type_of_next
== WEAK_AN
1278 /* If the next character is EN, but the last
1279 strong-type character is AL, EN will be later
1280 changed to AN when we process it in W2 above. So
1281 in that case, this ES should not be changed into
1283 || (type_of_next
== WEAK_EN
1284 && bidi_it
->last_strong
.orig_type
== STRONG_AL
)))
1286 else if (bidi_it
->prev
.orig_type
== WEAK_EN
1287 && type_of_next
== WEAK_EN
1288 && bidi_it
->last_strong
.orig_type
!= STRONG_AL
)
1292 else if (type
== WEAK_ET
/* W5: ET with EN before or after it */
1293 || type
== WEAK_BN
) /* W5/Retaining */
1295 if (bidi_it
->prev
.orig_type
== WEAK_EN
/* ET/BN with EN before it */
1296 || bidi_it
->next_en_pos
> bidi_it
->charpos
)
1298 /* W5: ET with EN after it. */
1301 int en_pos
= bidi_it
->charpos
+ 1;
1303 next_char
= FETCH_CHAR (bidi_it
->bytepos
+ bidi_it
->ch_len
);
1304 type_of_next
= bidi_get_type (next_char
);
1306 if (type_of_next
== WEAK_ET
1307 || type_of_next
== WEAK_BN
1308 || bidi_explicit_dir_char (next_char
))
1310 bidi_copy_it (&saved_it
, bidi_it
);
1311 while (bidi_resolve_explicit (bidi_it
) == new_level
1312 && (bidi_it
->type
== WEAK_BN
|| bidi_it
->type
== WEAK_ET
))
1314 type_of_next
= bidi_it
->type
;
1315 en_pos
= bidi_it
->charpos
;
1316 bidi_copy_it (bidi_it
, &saved_it
);
1318 if (type_of_next
== WEAK_EN
)
1320 /* If the last strong character is AL, the EN we've
1321 found will become AN when we get to it (W2). */
1322 if (bidi_it
->last_strong
.orig_type
!= STRONG_AL
)
1325 /* Remember this EN position, to speed up processing
1327 bidi_it
->next_en_pos
= en_pos
;
1329 else if (type
== WEAK_BN
)
1330 type
= NEUTRAL_ON
; /* W6/Retaining */
1335 if (type
== WEAK_ES
|| type
== WEAK_ET
|| type
== WEAK_CS
/* W6 */
1336 || (type
== WEAK_BN
&& (bidi_it
->prev
.orig_type
== WEAK_CS
/* W6/Ret. */
1337 || bidi_it
->prev
.orig_type
== WEAK_ES
1338 || bidi_it
->prev
.orig_type
== WEAK_ET
)))
1341 /* Store the type we've got so far, before we clobber it with strong
1342 types in W7 and while resolving neutral types. But leave alone
1343 the original types that were recorded above, because we will need
1344 them for the L1 clause. */
1345 if (bidi_it
->orig_type
== UNKNOWN_BT
)
1346 bidi_it
->orig_type
= type
;
1348 if (type
== WEAK_EN
) /* W7 */
1350 if ((bidi_it
->last_strong
.orig_type
== STRONG_L
)
1351 || (bidi_it
->last_strong
.type
== UNKNOWN_BT
&& bidi_it
->sor
== L2R
))
1355 bidi_it
->type
= type
;
1360 bidi_resolve_neutral (struct bidi_it
*bidi_it
)
1362 int prev_level
= bidi_it
->level_stack
[bidi_it
->stack_idx
].level
;
1363 bidi_type_t type
= bidi_resolve_weak (bidi_it
);
1364 int current_level
= bidi_it
->level_stack
[bidi_it
->stack_idx
].level
;
1366 if (!(type
== STRONG_R
1371 || type
== NEUTRAL_B
1372 || type
== NEUTRAL_S
1373 || type
== NEUTRAL_WS
1374 || type
== NEUTRAL_ON
))
1377 if (bidi_get_category (type
) == NEUTRAL
1378 || (type
== WEAK_BN
&& prev_level
== current_level
))
1380 if (bidi_it
->next_for_neutral
.type
!= UNKNOWN_BT
)
1381 type
= bidi_resolve_neutral_1 (bidi_it
->prev_for_neutral
.type
,
1382 bidi_it
->next_for_neutral
.type
,
1386 /* Arrrgh!! The UAX#9 algorithm is too deeply entrenched in
1387 the assumption of batch-style processing; see clauses W4,
1388 W5, and especially N1, which require to look far forward
1389 (as well as back) in the buffer. May the fleas of a
1390 thousand camels infest the armpits of those who design
1391 supposedly general-purpose algorithms by looking at their
1392 own implementations, and fail to consider other possible
1394 struct bidi_it saved_it
;
1395 bidi_type_t next_type
;
1397 if (bidi_it
->scan_dir
== -1)
1400 bidi_copy_it (&saved_it
, bidi_it
);
1401 /* Scan the text forward until we find the first non-neutral
1402 character, and then use that to resolve the neutral we
1403 are dealing with now. We also cache the scanned iterator
1404 states, to salvage some of the effort later. */
1405 bidi_cache_iterator_state (bidi_it
, 0);
1407 /* Record the info about the previous character, so that
1408 it will be cached below with this state. */
1409 if (bidi_it
->orig_type
!= WEAK_BN
/* W1/Retaining */
1410 && bidi_it
->type
!= WEAK_BN
)
1411 bidi_remember_char (&bidi_it
->prev
, bidi_it
);
1412 type
= bidi_resolve_weak (bidi_it
);
1413 /* Paragraph separators have their levels fully resolved
1414 at this point, so cache them as resolved. */
1415 bidi_cache_iterator_state (bidi_it
, type
== NEUTRAL_B
);
1416 /* FIXME: implement L1 here, by testing for a newline and
1417 resetting the level for any sequence of whitespace
1418 characters adjacent to it. */
1419 } while (!(type
== NEUTRAL_B
1421 && bidi_get_category (type
) != NEUTRAL
)
1422 /* This is all per level run, so stop when we
1423 reach the end of this level run. */
1424 || bidi_it
->level_stack
[bidi_it
->stack_idx
].level
!=
1427 bidi_remember_char (&saved_it
.next_for_neutral
, bidi_it
);
1438 /* N1: ``European and Arabic numbers are treated as
1439 though they were R.'' */
1440 next_type
= STRONG_R
;
1441 saved_it
.next_for_neutral
.type
= STRONG_R
;
1444 if (!bidi_explicit_dir_char (bidi_it
->ch
))
1445 abort (); /* can't happen: BNs are skipped */
1448 /* Marched all the way to the end of this level run.
1449 We need to use the eor type, whose information is
1450 stored by bidi_set_sor_type in the prev_for_neutral
1452 if (saved_it
.type
!= WEAK_BN
1453 || bidi_get_category (bidi_it
->prev
.orig_type
) == NEUTRAL
)
1455 next_type
= bidi_it
->prev_for_neutral
.type
;
1456 saved_it
.next_for_neutral
.type
= next_type
;
1460 /* This is a BN which does not adjoin neutrals.
1461 Leave its type alone. */
1462 bidi_copy_it (bidi_it
, &saved_it
);
1463 return bidi_it
->type
;
1469 type
= bidi_resolve_neutral_1 (saved_it
.prev_for_neutral
.type
,
1470 next_type
, current_level
);
1471 saved_it
.type
= type
;
1472 bidi_copy_it (bidi_it
, &saved_it
);
1478 /* Given an iterator state in BIDI_IT, advance one character position
1479 in the buffer to the next character (in the logical order), resolve
1480 the bidi type of that next character, and return that type. */
1482 bidi_type_of_next_char (struct bidi_it
*bidi_it
)
1486 /* This should always be called during a forward scan. */
1487 if (bidi_it
->scan_dir
!= 1)
1490 /* Reset the limit until which to ignore BNs if we step out of the
1491 area where we found only empty levels. */
1492 if ((bidi_it
->ignore_bn_limit
> 0
1493 && bidi_it
->ignore_bn_limit
<= bidi_it
->charpos
)
1494 || (bidi_it
->ignore_bn_limit
== -1
1495 && !bidi_explicit_dir_char (bidi_it
->ch
)))
1496 bidi_it
->ignore_bn_limit
= 0;
1498 type
= bidi_resolve_neutral (bidi_it
);
1503 /* Given an iterator state BIDI_IT, advance one character position in
1504 the buffer to the next character (in the logical order), resolve
1505 the embedding and implicit levels of that next character, and
1506 return the resulting level. */
1508 bidi_level_of_next_char (struct bidi_it
*bidi_it
)
1511 int level
, prev_level
= -1;
1512 struct bidi_saved_info next_for_neutral
;
1514 if (bidi_it
->scan_dir
== 1)
1516 /* There's no sense in trying to advance if we hit end of text. */
1517 if (bidi_it
->ch
== BIDI_EOB
)
1518 return bidi_it
->resolved_level
;
1520 /* Record the info about the previous character. */
1521 if (bidi_it
->orig_type
!= WEAK_BN
/* W1/Retaining */
1522 && bidi_it
->type
!= WEAK_BN
)
1523 bidi_remember_char (&bidi_it
->prev
, bidi_it
);
1524 if (bidi_it
->orig_type
== STRONG_R
|| bidi_it
->orig_type
== STRONG_L
1525 || bidi_it
->orig_type
== STRONG_AL
)
1526 bidi_remember_char (&bidi_it
->last_strong
, bidi_it
);
1527 /* FIXME: it sounds like we don't need both prev and
1528 prev_for_neutral members, but I'm leaving them both for now. */
1529 if (bidi_it
->type
== STRONG_R
|| bidi_it
->type
== STRONG_L
1530 || bidi_it
->type
== WEAK_EN
|| bidi_it
->type
== WEAK_AN
)
1531 bidi_remember_char (&bidi_it
->prev_for_neutral
, bidi_it
);
1533 /* If we overstepped the characters used for resolving neutrals
1534 and whitespace, invalidate their info in the iterator. */
1535 if (bidi_it
->charpos
>= bidi_it
->next_for_neutral
.charpos
)
1536 bidi_it
->next_for_neutral
.type
= UNKNOWN_BT
;
1537 if (bidi_it
->next_en_pos
>= 0
1538 && bidi_it
->charpos
>= bidi_it
->next_en_pos
)
1539 bidi_it
->next_en_pos
= -1;
1540 if (bidi_it
->next_for_ws
.type
!= UNKNOWN_BT
1541 && bidi_it
->charpos
>= bidi_it
->next_for_ws
.charpos
)
1542 bidi_it
->next_for_ws
.type
= UNKNOWN_BT
;
1544 /* This must be taken before we fill the iterator with the info
1545 about the next char. If we scan backwards, the iterator
1546 state must be already cached, so there's no need to know the
1547 embedding level of the previous character, since we will be
1548 returning to our caller shortly. */
1549 prev_level
= bidi_it
->level_stack
[bidi_it
->stack_idx
].level
;
1551 next_for_neutral
= bidi_it
->next_for_neutral
;
1553 /* Perhaps it is already cached. */
1554 type
= bidi_cache_find (bidi_it
->charpos
+ bidi_it
->scan_dir
, -1, bidi_it
);
1555 if (type
!= UNKNOWN_BT
)
1557 /* Don't lose the information for resolving neutrals! The
1558 cached states could have been cached before their
1559 next_for_neutral member was computed. If we are on our way
1560 forward, we can simply take the info from the previous
1562 if (bidi_it
->scan_dir
== 1
1563 && bidi_it
->next_for_neutral
.type
== UNKNOWN_BT
)
1564 bidi_it
->next_for_neutral
= next_for_neutral
;
1566 /* If resolved_level is -1, it means this state was cached
1567 before it was completely resolved, so we cannot return
1569 if (bidi_it
->resolved_level
!= -1)
1570 return bidi_it
->resolved_level
;
1572 if (bidi_it
->scan_dir
== -1)
1573 /* If we are going backwards, the iterator state is already cached
1574 from previous scans, and should be fully resolved. */
1577 if (type
== UNKNOWN_BT
)
1578 type
= bidi_type_of_next_char (bidi_it
);
1580 if (type
== NEUTRAL_B
)
1581 return bidi_it
->resolved_level
;
1583 level
= bidi_it
->level_stack
[bidi_it
->stack_idx
].level
;
1584 if ((bidi_get_category (type
) == NEUTRAL
/* && type != NEUTRAL_B */)
1585 || (type
== WEAK_BN
&& prev_level
== level
))
1587 if (bidi_it
->next_for_neutral
.type
== UNKNOWN_BT
)
1590 /* If the cached state shows a neutral character, it was not
1591 resolved by bidi_resolve_neutral, so do it now. */
1592 type
= bidi_resolve_neutral_1 (bidi_it
->prev_for_neutral
.type
,
1593 bidi_it
->next_for_neutral
.type
,
1597 if (!(type
== STRONG_R
1601 || type
== WEAK_AN
))
1603 bidi_it
->type
= type
;
1605 /* For L1 below, we need to know, for each WS character, whether
1606 it belongs to a sequence of WS characters preceeding a newline
1607 or a TAB or a paragraph separator. */
1608 if (bidi_it
->pristine_type
== NEUTRAL_WS
1609 && bidi_it
->next_for_ws
.type
== UNKNOWN_BT
)
1612 int clen
= bidi_it
->ch_len
;
1613 int bpos
= bidi_it
->bytepos
;
1614 int cpos
= bidi_it
->charpos
;
1618 /*_fetch_multibyte_char_len = 1;*/
1619 ch
= FETCH_CHAR (bpos
+ clen
);
1622 clen
= CHAR_BYTES (ch
);
1623 if (ch
== '\n' /* || ch == LINESEP_CHAR */)
1626 chtype
= bidi_get_type (ch
);
1627 } while (chtype
== NEUTRAL_WS
|| chtype
== WEAK_BN
1628 || bidi_explicit_dir_char (ch
)); /* L1/Retaining */
1629 bidi_it
->next_for_ws
.type
= chtype
;
1630 bidi_it
->next_for_ws
.charpos
= cpos
;
1631 bidi_it
->next_for_ws
.bytepos
= bpos
;
1634 /* Resolve implicit levels, with a twist: PDFs get the embedding
1635 level of the enbedding they terminate. See below for the
1637 if (bidi_it
->pristine_type
== PDF
1638 /* Don't do this if this formatting code didn't change the
1639 embedding level due to invalid or empty embeddings. */
1640 && prev_level
!= level
)
1642 /* Don't look in UAX#9 for the reason for this: it's our own
1643 private quirk. The reason is that we want the formatting
1644 codes to be delivered so that they bracket the text of their
1645 embedding. For example, given the text
1649 we want it to be displayed as
1657 which will result because we bump up the embedding level as
1658 soon as we see the RLO and pop it as soon as we see the PDF,
1659 so RLO itself has the same embedding level as "teST", and
1660 thus would be normally delivered last, just before the PDF.
1661 The switch below fiddles with the level of PDF so that this
1662 ugly side effect does not happen.
1664 (This is, of course, only important if the formatting codes
1665 are actually displayed, but Emacs does display them if the
1669 else if (bidi_it
->pristine_type
== NEUTRAL_B
/* L1 */
1670 || bidi_it
->pristine_type
== NEUTRAL_S
1671 || bidi_it
->ch
== '\n' /* || bidi_it->ch == LINESEP_CHAR */
1672 || (bidi_it
->pristine_type
== NEUTRAL_WS
1673 && (bidi_it
->next_for_ws
.type
== NEUTRAL_B
1674 || bidi_it
->next_for_ws
.type
== NEUTRAL_S
)))
1675 level
= bidi_it
->level_stack
[0].level
;
1676 else if ((level
& 1) == 0) /* I1 */
1678 if (type
== STRONG_R
)
1680 else if (type
== WEAK_EN
|| type
== WEAK_AN
)
1685 if (type
== STRONG_L
|| type
== WEAK_EN
|| type
== WEAK_AN
)
1689 bidi_it
->resolved_level
= level
;
1693 /* Move to the other edge of a level given by LEVEL. If END_FLAG is
1694 non-zero, we are at the end of a level, and we need to prepare to
1695 resume the scan of the lower level.
1697 If this level's other edge is cached, we simply jump to it, filling
1698 the iterator structure with the iterator state on the other edge.
1699 Otherwise, we walk the buffer until we come back to the same level
1702 Note: we are not talking here about a ``level run'' in the UAX#9
1703 sense of the term, but rather about a ``level'' which includes
1704 all the levels higher than it. In other words, given the levels
1707 11111112222222333333334443343222222111111112223322111
1710 and assuming we are at point A scanning left to right, this
1711 function moves to point C, whereas the UAX#9 ``level 2 run'' ends
1714 bidi_find_other_level_edge (struct bidi_it
*bidi_it
, int level
, int end_flag
)
1716 int dir
= end_flag
? -bidi_it
->scan_dir
: bidi_it
->scan_dir
;
1719 /* Try the cache first. */
1720 if ((idx
= bidi_cache_find_level_change (level
, dir
, end_flag
)) >= 0)
1721 bidi_cache_fetch_state (idx
, bidi_it
);
1727 abort (); /* if we are at end of level, its edges must be cached */
1729 bidi_cache_iterator_state (bidi_it
, 1);
1731 new_level
= bidi_level_of_next_char (bidi_it
);
1732 bidi_cache_iterator_state (bidi_it
, 1);
1733 } while (new_level
>= level
);
1738 bidi_get_next_char_visually (struct bidi_it
*bidi_it
)
1740 int old_level
, new_level
, next_level
;
1741 struct bidi_it prev_bidi_it
;
1743 if (bidi_it
->scan_dir
== 0)
1745 bidi_it
->scan_dir
= 1; /* default to logical order */
1748 if (bidi_it
->new_paragraph
)
1749 bidi_paragraph_init (bidi_overriding_paragraph_direction
, bidi_it
);
1750 if (bidi_cache_idx
== 0)
1751 bidi_copy_it (&prev_bidi_it
, bidi_it
);
1753 old_level
= bidi_it
->resolved_level
;
1754 new_level
= bidi_level_of_next_char (bidi_it
);
1755 if (bidi_it
->ch
== BIDI_EOB
)
1758 /* Reordering of resolved levels (clause L2) is implemented by
1759 jumping to the other edge of the level and flipping direction of
1760 scanning the buffer whenever we find a level change. */
1761 if (new_level
!= old_level
)
1763 int ascending
= new_level
> old_level
;
1764 int level_to_search
= ascending
? old_level
+ 1 : old_level
;
1765 int incr
= ascending
? 1 : -1;
1766 int expected_next_level
= old_level
+ incr
;
1768 /* If we don't have anything cached yet, we need to cache the
1769 previous character we've seen, since we'll need it to record
1770 where to jump when the last non-base level is exhausted. */
1771 if (bidi_cache_idx
== 0)
1772 bidi_cache_iterator_state (&prev_bidi_it
, 1);
1773 /* Jump (or walk) to the other edge of this level. */
1774 bidi_find_other_level_edge (bidi_it
, level_to_search
, !ascending
);
1775 /* Switch scan direction and peek at the next character in the
1777 bidi_it
->scan_dir
= -bidi_it
->scan_dir
;
1779 /* The following loop handles the case where the resolved level
1780 jumps by more than one. This is typical for numbers inside a
1781 run of text with left-to-right embedding direction, but can
1782 also happen in other situations. In those cases the decision
1783 where to continue after a level change, and in what direction,
1784 is tricky. For example, given a text like below:
1789 (where the numbers below the text show the resolved levels),
1790 the result of reordering according to UAX#9 should be this:
1794 This is implemented by the loop below which flips direction
1795 and jumps to the other edge of the level each time it finds
1796 the new level not to be the expected one. The expected level
1797 is always one more or one less than the previous one. */
1798 next_level
= bidi_peek_at_next_level (bidi_it
);
1799 while (next_level
!= expected_next_level
)
1801 expected_next_level
+= incr
;
1802 level_to_search
+= incr
;
1803 bidi_find_other_level_edge (bidi_it
, level_to_search
, !ascending
);
1804 bidi_it
->scan_dir
= -bidi_it
->scan_dir
;
1805 next_level
= bidi_peek_at_next_level (bidi_it
);
1808 /* Finally, deliver the next character in the new direction. */
1809 next_level
= bidi_level_of_next_char (bidi_it
);
1812 if (bidi_it
->scan_dir
== 1 && bidi_cache_idx
)
1814 /* If we are at paragraph's base embedding level and beyond the
1815 last cached position, the cache's job is done and we can
1817 if (bidi_it
->resolved_level
== bidi_it
->level_stack
[0].level
1818 && bidi_it
->charpos
> bidi_cache
[bidi_cache_idx
- 1].charpos
)
1819 bidi_cache_reset ();
1820 /* But as long as we are caching during forward scan, we must
1821 cache each state, or else the cache integrity will be
1822 compromised: it assumes cached states correspond to buffer
1825 bidi_cache_iterator_state (bidi_it
, 1);
1829 /* This is meant to be called from within the debugger, whenever you
1830 wish to examine the cache contents. */
1832 bidi_dump_cached_states (void)
1837 if (bidi_cache_idx
== 0)
1839 fprintf (stderr
, "The cache is empty.\n");
1842 fprintf (stderr
, "Total of %d state%s in cache:\n",
1843 bidi_cache_idx
, bidi_cache_idx
== 1 ? "" : "s");
1845 for (i
= bidi_cache
[bidi_cache_idx
- 1].charpos
; i
> 0; i
/= 10)
1847 fputs ("ch ", stderr
);
1848 for (i
= 0; i
< bidi_cache_idx
; i
++)
1849 fprintf (stderr
, "%*c", ndigits
, bidi_cache
[i
].ch
);
1850 fputs ("\n", stderr
);
1851 fputs ("lvl ", stderr
);
1852 for (i
= 0; i
< bidi_cache_idx
; i
++)
1853 fprintf (stderr
, "%*d", ndigits
, bidi_cache
[i
].resolved_level
);
1854 fputs ("\n", stderr
);
1855 fputs ("pos ", stderr
);
1856 for (i
= 0; i
< bidi_cache_idx
; i
++)
1857 fprintf (stderr
, "%*d", ndigits
, bidi_cache
[i
].charpos
);
1858 fputs ("\n", stderr
);
1861 #ifdef TEST_STANDALONE
1863 #include <sys/stat.h>
1866 static char display_line
[80];
1867 static int simulate_display
;
1868 static int incr
= 1;
1871 signal_catcher (int sig
)
1873 if (simulate_display
)
1874 puts (display_line
);
1880 signal (sig
, SIG_DFL
);
1887 if (simulate_display
)
1891 if (p
>= display_line
)
1892 memset (display_line
, ' ', p
- display_line
+ 1);
1896 fputs (display_line
, stdout
);
1902 init_display_direction (bidi_dir_t default_dir
, int base_level
)
1906 /* To which display margin should we flush the lines? */
1907 switch (default_dir
)
1910 if ((base_level
& 1) == 0)
1917 p
= display_line
+ sizeof (display_line
) - 1;
1927 p
= display_line
+ sizeof (display_line
) - 1;
1939 continuation_line (char *p
, int need
)
1943 if (p
< display_line
+ need
)
1947 putc ('\n', stdout
);
1948 memset (display_line
, '>', sizeof(display_line
) - 1);
1949 p
= display_line
+ sizeof (display_line
) - 1;
1955 if (p
> display_line
+ sizeof(display_line
) - need
- 2)
1959 putc ('\n', stdout
);
1960 memset (display_line
, '<', sizeof(display_line
) - 1);
1968 int main (int argc
, char *argv
[])
1970 bidi_dir_t default_dir
= NEUTRAL_DIR
;
1971 char lots_of_equals
[] = "\n===============================================================================\n";
1974 if (argc
> 1 && argv
[1][0] == '-')
1980 simulate_display
= 1;
1985 simulate_display
= 1;
1989 simulate_display
= 1;
1995 bidi_overriding_paragraph_direction
= default_dir
;
1998 for (argv
++; *argv
; argv
++)
2000 FILE *in
= fopen (*argv
, "rb");
2001 struct stat stat_buf
;
2002 struct bidi_it iterator
;
2004 char *p
= display_line
;
2006 unsigned char *s
, *d
, *s_end
;
2008 if (!in
|| stat (*argv
, &stat_buf
))
2014 if (stat_buf
.st_size
> input_buf_size
)
2016 input_buf
= realloc (input_buf
, stat_buf
.st_size
+ 1);
2019 perror ("realloc input buffer");
2022 input_buf_size
= stat_buf
.st_size
;
2024 if (fread (input_buf
, 1, stat_buf
.st_size
, in
) != stat_buf
.st_size
)
2026 perror ("reading input");
2029 input_buf
[stat_buf
.st_size
] = '\0';
2030 for (d
= s
= input_buf
, s_end
= s
+ stat_buf
.st_size
- 1; *s
; s
++)
2032 if (*s
!= '\r' || s
>= s_end
|| s
[1] != '\n')
2035 stat_buf
.st_size
= d
- input_buf
;
2036 input_buf
[stat_buf
.st_size
] = '\0';
2038 /* Done with administrivia, now for some real work... */
2039 signal (SIGABRT
, signal_catcher
);
2040 signal (SIGINT
, signal_catcher
);
2041 bidi_init_it (-1, default_dir
, &iterator
);
2042 if (simulate_display
)
2044 p
= init_display_direction (default_dir
,
2045 iterator
.level_stack
[0].level
);
2048 memset (display_line
, incr
== -1 ? '>' : '<', sizeof (display_line
) - 1);
2049 display_line
[sizeof (display_line
) - 1] = '\0';
2050 base_level
= iterator
.level_stack
[0].level
;
2052 for (i
= 0; i
<= stat_buf
.st_size
; i
++)
2056 bidi_get_next_char_visually (&iterator
);
2059 if (c
== '\n' || c
== BIDI_EOB
)
2061 if (simulate_display
)
2064 /* FIXME: if -R or -L, need to init paragraph here. */
2070 else if (c
>= LRE_CHAR
&& c
<= LRM_CHAR
)
2072 if (simulate_display
)
2074 p
= continuation_line (p
, 5);
2077 memcpy (p
- 4, bidi_name
[c
], 5);
2082 memcpy (p
, bidi_name
[c
], 5);
2087 fputs (bidi_name
[c
], stdout
);
2091 if (simulate_display
)
2093 p
= continuation_line (p
, 2);
2106 printf ("^%c", (c
| 0x40));
2110 int c1
= (iterator
.type
== STRONG_R
) ? bidi_mirror_char (c
) : c
;
2112 if (simulate_display
)
2114 p
= continuation_line (p
, 1);
2122 if (iterator
.ch
== '\n')
2124 if (base_level
!= iterator
.level_stack
[0].level
)
2125 base_level
= iterator
.level_stack
[0].level
;
2126 p
= init_display_direction (default_dir
, base_level
);
2127 memset (display_line
, incr
== -1 ? '>' : '<',
2128 sizeof (display_line
) - 1);
2131 fputs (lots_of_equals
, stdout
);