1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** GUIX Component                                                        */
16 /**                                                                       */
17 /**   Utility (Utility)                                                   */
18 /**                                                                       */
19 /**************************************************************************/
20 #define GX_SOURCE_CODE
21 
22 
23 /* Include necessary system files.  */
24 
25 #include "gx_api.h"
26 #include "gx_utility.h"
27 #include "gx_system.h"
28 
29 #if defined(GX_DYNAMIC_BIDI_TEXT_SUPPORT)
30 
31 #define GX_LINK_RESOLVED_BIDI_TEXT_INFO                         \
32     if (pre)                                                    \
33     {                                                           \
34         pre -> gx_bidi_resolved_text_info_next = resolved_info; \
35     }                                                           \
36     pre = resolved_info;                                        \
37     if (!head)                                                  \
38     {                                                           \
39         head = pre;                                             \
40     }
41 
42 /**************************************************************************/
43 /*                                                                        */
44 /*  FUNCTION                                               RELEASE        */
45 /*                                                                        */
46 /*    _gx_utility_bidi_buffer_allocate                    PORTABLE C      */
47 /*                                                           6.1          */
48 /*  AUTHOR                                                                */
49 /*                                                                        */
50 /*    Kenneth Maxwell, Microsoft Corporation                              */
51 /*                                                                        */
52 /*  DESCRIPTION                                                           */
53 /*                                                                        */
54 /*    Internal helper function to calculate character count to be handled */
55 /*    and allocate a buffer for following processing.                     */
56 /*                                                                        */
57 /*  INPUT                                                                 */
58 /*                                                                        */
59 /*    context                               Bidi information control block*/
60 /*                                                                        */
61 /*  OUTPUT                                                                */
62 /*                                                                        */
63 /*    status                                Completion status             */
64 /*                                                                        */
65 /*  CALLS                                                                 */
66 /*                                                                        */
67 /*    None                                                                */
68 /*                                                                        */
69 /*  CALLED BY                                                             */
70 /*                                                                        */
71 /*    _gx_utility_bidi_paragraph_reorder                                  */
72 /*                                                                        */
73 /*  RELEASE HISTORY                                                       */
74 /*                                                                        */
75 /*    DATE              NAME                      DESCRIPTION             */
76 /*                                                                        */
77 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
78 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
79 /*                                            update with bidi context    */
80 /*                                            structure change,           */
81 /*                                            moved a pointer check to    */
82 /*                                            its caller function,        */
83 /*                                            resulting in version 6.1    */
84 /*                                                                        */
85 /**************************************************************************/
_gx_utility_bidi_buffer_allocate(GX_BIDI_CONTEXT * context)86 static UINT _gx_utility_bidi_buffer_allocate(GX_BIDI_CONTEXT *context)
87 {
88 INT                  character_count = 0;
89 GX_STRING            text;
90 ULONG                unicode;
91 INT                  max_depth = 0;
92 INT                  depth = 0;
93 INT                  level_run_count = 1;
94 INT                  bracket_pair_count = 0;
95 INT                  max_bracket_pair = 0;
96 INT                  run_stack_size;
97 INT                  explicite_stack_size;
98 GX_BIDI_BRACKET_PAIR bracket_pair;
99 GX_BIDI_TEXT_INFO   *input_info = context -> gx_bidi_context_input_info;
100 
101     text = input_info -> gx_bidi_text_info_text;
102 
103     while (text.gx_string_length > 0)
104     {
105         if ((text.gx_string_ptr[0] == GX_KEY_CARRIAGE_RETURN) ||
106             (text.gx_string_ptr[0] == GX_KEY_LINE_FEED))
107         {
108             break;
109         }
110 
111         /* Convert utf8 to unicode. */
112         unicode = 0;
113         _gx_utility_utf8_string_character_get(&text, (GX_CHAR_CODE *)&unicode, GX_NULL);
114 
115         switch (unicode)
116         {
117         case GX_BIDI_DIRECTION_FORMAT_RLE:
118         case GX_BIDI_DIRECTION_FORMAT_LRE:
119         case GX_BIDI_DIRECTION_FORMAT_RLO:
120         case GX_BIDI_DIRECTION_FORMAT_LRO:
121         case GX_BIDI_DIRECTION_FORMAT_RLI:
122         case GX_BIDI_DIRECTION_FORMAT_LRI:
123         case GX_BIDI_DIRECTION_FORMAT_FSI:
124             depth++;
125             level_run_count++;
126             break;
127 
128         case GX_BIDI_DIRECTION_FORMAT_PDF:
129         case GX_BIDI_DIRECTION_FORMAT_PDI:
130             depth--;
131             level_run_count++;
132             break;
133         default:
134             if (max_bracket_pair < GX_BIDI_MAX_BRACKET_DEPTH)
135             {
136 
137                 _gx_utility_bidi_bracket_pair_get(unicode, &bracket_pair);
138                 if (bracket_pair.gx_bidi_bracket_pair_open)
139                 {
140                     if (bracket_pair.gx_bidi_bracket_pair_open == unicode)
141                     {
142                         bracket_pair_count++;
143                         if (bracket_pair_count > max_bracket_pair)
144                         {
145                             max_bracket_pair = bracket_pair_count;
146                         }
147                     }
148                 }
149             }
150             break;
151         }
152 
153         if (depth > max_depth)
154         {
155             max_depth = depth;
156         }
157 
158         character_count++;
159     }
160 
161     if (max_depth > GX_BIDI_MAX_EXPLICIT_DEPTH + 1)
162     {
163         max_depth = GX_BIDI_MAX_EXPLICIT_DEPTH + 1;
164     }
165 
166     context -> gx_bidi_context_processced_size = input_info -> gx_bidi_text_info_text.gx_string_length - text.gx_string_length;
167     context -> gx_bidi_context_reordered_utf8_size = context -> gx_bidi_context_processced_size;
168     context -> gx_bidi_context_unit_count = character_count;
169 
170     context -> gx_bidi_context_buffer_size = sizeof(GX_BIDI_UNIT) * (UINT)(character_count);         /* unit list size. */
171 
172     if (input_info -> gx_bidi_text_info_font && input_info -> gx_bidi_text_info_display_width > 0)
173     {
174         context -> gx_bidi_context_buffer_size += sizeof(ULONG) * (UINT)character_count; /* line index cache size. */
175     }
176 
177     /* Size of buffer used for loading explicit level data
178        Will be released before level run buffer is used. */
179     explicite_stack_size = (INT)sizeof(GX_BIDI_EXPLICIT_ENTRY) * (max_depth + 1);
180 
181     /* Size of buffer used for loading level run data. */
182     run_stack_size = (INT)sizeof(GX_BIDI_LEVEL_RUN) * character_count;
183 
184     /* Size of buffer used for loading isolate run data. */
185     run_stack_size += (INT)sizeof(GX_BIDI_ISOLATE_RUN) * level_run_count + (INT)sizeof(ULONG) * character_count;
186 
187     /* Size of buffer used for loading bracket pair data. */
188     context -> gx_bidi_context_bracket_pair_size = sizeof(ULONG) * (UINT)(max_bracket_pair * 2);
189     run_stack_size += (INT)context -> gx_bidi_context_bracket_pair_size;
190     run_stack_size += (INT)sizeof(ULONG) * (INT)max_bracket_pair;
191 
192     if (run_stack_size < explicite_stack_size)
193     {
194         run_stack_size = explicite_stack_size;
195     }
196 
197     context -> gx_bidi_context_buffer_size += (UINT)run_stack_size;
198 
199     context -> gx_bidi_context_buffer = (GX_UBYTE *)_gx_system_memory_allocator(context -> gx_bidi_context_buffer_size);
200     if (context -> gx_bidi_context_buffer == GX_NULL)
201     {
202         return GX_SYSTEM_MEMORY_ERROR;
203     }
204 
205     memset(context -> gx_bidi_context_buffer, 0, (size_t)context -> gx_bidi_context_buffer_size);
206 
207     return GX_SUCCESS;
208 }
209 
210 /**************************************************************************/
211 /*                                                                        */
212 /*  FUNCTION                                               RELEASE        */
213 /*                                                                        */
214 /*    _gx_utility_bidi_initiate                           PORTABLE C      */
215 /*                                                           6.1          */
216 /*  AUTHOR                                                                */
217 /*                                                                        */
218 /*    Kenneth Maxwell, Microsoft Corporation                              */
219 /*                                                                        */
220 /*  DESCRIPTION                                                           */
221 /*                                                                        */
222 /*    Internal helper function to convert utf8 text to unicode, initiate  */
223 /*    initiate character types and calculate the total lines.             */
224 /*                                                                        */
225 /*  INPUT                                                                 */
226 /*                                                                        */
227 /*    context                               Bidi information control block*/
228 /*    font                                  Text font, if not set, the    */
229 /*                                            text is handled as a single */
230 /*                                            line                        */
231 /*    display_width                         The max width of text in one  */
232 /*                                            line , if not set, the text */
233 /*                                            is handled as a single line */
234 /*    total_lines                           Total lines of handled text   */
235 /*                                                                        */
236 /*  OUTPUT                                                                */
237 /*                                                                        */
238 /*    status                                Completion status             */
239 /*                                                                        */
240 /*  CALLS                                                                 */
241 /*                                                                        */
242 /*    None                                                                */
243 /*                                                                        */
244 /*  CALLED BY                                                             */
245 /*                                                                        */
246 /*    _gx_utility_bidi_paragraph_reorder                                  */
247 /*                                                                        */
248 /*  RELEASE HISTORY                                                       */
249 /*                                                                        */
250 /*    DATE              NAME                      DESCRIPTION             */
251 /*                                                                        */
252 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
253 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
254 /*                                            removed line breaking logic,*/
255 /*                                            resulting in version 6.1    */
256 /*                                                                        */
257 /**************************************************************************/
_gx_utility_bidi_initiate(GX_BIDI_CONTEXT * context)258 static UINT _gx_utility_bidi_initiate(GX_BIDI_CONTEXT *context)
259 {
260 GX_BIDI_TEXT_INFO *input_info = context -> gx_bidi_context_input_info;
261 INT                index = 0;
262 GX_STRING          string;
263 GX_CHAR_CODE       code;
264 GX_BIDI_UNIT      *unit;
265 
266     context -> gx_bidi_context_unit_list = (GX_BIDI_UNIT *)context -> gx_bidi_context_buffer;
267     context -> gx_bidi_context_buffer_index += sizeof(GX_BIDI_UNIT) * (UINT)context -> gx_bidi_context_unit_count;
268 
269     string = input_info -> gx_bidi_text_info_text;
270 
271     while (index < context -> gx_bidi_context_unit_count)
272     {
273         unit = &context -> gx_bidi_context_unit_list[index];
274 
275         /* Convert utf8 to unicode. */
276         _gx_utility_utf8_string_character_get(&string, &code, GX_NULL);
277         unit -> gx_bidi_unit_code = code;
278 
279         _gx_utility_bidi_character_type_get(unit -> gx_bidi_unit_code, &unit -> gx_bidi_unit_type);
280         unit -> gx_bidi_unit_org_type = unit -> gx_bidi_unit_type;
281 
282         index++;
283     }
284 
285     return GX_SUCCESS;
286 }
287 
288 /**************************************************************************/
289 /*                                                                        */
290 /*  FUNCTION                                               RELEASE        */
291 /*                                                                        */
292 /*    _gx_utility_bidi_block_level_determine              PORTABLE C      */
293 /*                                                           6.1          */
294 /*  AUTHOR                                                                */
295 /*                                                                        */
296 /*    Kenneth Maxwell, Microsoft Corporation                              */
297 /*                                                                        */
298 /*  DESCRIPTION                                                           */
299 /*                                                                        */
300 /*    Internal helper function to calculate the level of the specified    */
301 /*    text block                                                          */
302 /*                                                                        */
303 /*  INPUT                                                                 */
304 /*                                                                        */
305 /*    context                               Bidi information control block*/
306 /*    start_index                           The start index of the text   */
307 /*                                            block                       */
308 /*    end_index                             The end index of the text     */
309 /*                                            block                       */
310 /*    level                                 Buffer for level value        */
311 /*                                                                        */
312 /*  OUTPUT                                                                */
313 /*                                                                        */
314 /*    status                                Completion status             */
315 /*                                                                        */
316 /*  CALLS                                                                 */
317 /*                                                                        */
318 /*    None                                                                */
319 /*                                                                        */
320 /*  CALLED BY                                                             */
321 /*                                                                        */
322 /*    _gx_utility_bidi_paragraph_reorder                                  */
323 /*    _gx_utility_bidi_explicit_levels_determine                          */
324 /*                                                                        */
325 /*  RELEASE HISTORY                                                       */
326 /*                                                                        */
327 /*    DATE              NAME                      DESCRIPTION             */
328 /*                                                                        */
329 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
330 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
331 /*                                            resulting in version 6.1    */
332 /*                                                                        */
333 /**************************************************************************/
_gx_utility_bidi_block_level_determine(GX_BIDI_CONTEXT * context,UINT start_index,UINT end_index,GX_UBYTE * level)334 static UINT _gx_utility_bidi_block_level_determine(GX_BIDI_CONTEXT *context, UINT start_index, UINT end_index, GX_UBYTE *level)
335 {
336 INT           isolate_count = 0;
337 GX_BIDI_UNIT *unit;
338 
339     unit = &context -> gx_bidi_context_unit_list[start_index];
340 
341     while (start_index <= end_index)
342     {
343         /* Find the first character of type L, AL, or R
344            while skipping over any hcaracters between an isolate initiator and its matching PDI. */
345         switch (unit -> gx_bidi_unit_type)
346         {
347         case GX_BIDI_CHARACTER_TYPE_AL:
348         case GX_BIDI_CHARACTER_TYPE_R:
349             if (isolate_count == 0)
350             {
351                 *level = 1;
352                 return GX_SUCCESS;
353             }
354             break;
355 
356         case GX_BIDI_CHARACTER_TYPE_L:
357             if (isolate_count == 0)
358             {
359                 *level = 0;
360                 return GX_SUCCESS;
361             }
362             break;
363 
364         case GX_BIDI_CHARACTER_TYPE_RLI:
365         case GX_BIDI_CHARACTER_TYPE_LRI:
366             isolate_count++;
367             break;
368 
369         case GX_BIDI_CHARACTER_TYPE_PDI:
370             if (isolate_count)
371             {
372                 isolate_count--;
373             }
374             break;
375         }
376 
377         start_index++;
378         unit++;
379     }
380 
381     /* Otherwise, set paragraph embedding level to 0. */
382     *level = 0;
383     return GX_SUCCESS;
384 }
385 
386 /**************************************************************************/
387 /*                                                                        */
388 /*  FUNCTION                                               RELEASE        */
389 /*                                                                        */
390 /*    _gx_utility_bidi_explicit_levels_determine          PORTABLE C      */
391 /*                                                           6.1          */
392 /*  AUTHOR                                                                */
393 /*                                                                        */
394 /*    Kenneth Maxwell, Microsoft Corporation                              */
395 /*                                                                        */
396 /*  DESCRIPTION                                                           */
397 /*                                                                        */
398 /*    Internal helper function to calculate explicite level of every      */
399 /*    character.                                                          */
400 /*                                                                        */
401 /*  INPUT                                                                 */
402 /*                                                                        */
403 /*    context                               Bidi information control block*/
404 /*                                            format.                     */
405 /*                                                                        */
406 /*  OUTPUT                                                                */
407 /*                                                                        */
408 /*    status                                Completion status             */
409 /*                                                                        */
410 /*  CALLS                                                                 */
411 /*                                                                        */
412 /*    None                                                                */
413 /*                                                                        */
414 /*  CALLED BY                                                             */
415 /*                                                                        */
416 /*    _gx_utility_bidi_paragraph_reorder                                  */
417 /*                                                                        */
418 /*  RELEASE HISTORY                                                       */
419 /*                                                                        */
420 /*    DATE              NAME                      DESCRIPTION             */
421 /*                                                                        */
422 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
423 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
424 /*                                            resulting in version 6.1    */
425 /*                                                                        */
426 /**************************************************************************/
_gx_utility_bidi_explicit_levels_determine(GX_BIDI_CONTEXT * context)427 static UINT _gx_utility_bidi_explicit_levels_determine(GX_BIDI_CONTEXT *context)
428 {
429 GX_BIDI_EXPLICIT_ENTRY *stack;
430 GX_BIDI_EXPLICIT_ENTRY *entry;
431 GX_BIDI_EXPLICIT_ENTRY *last_entry;
432 INT                     stack_top = 0;
433 INT                     overflow_isolate_count = 0;
434 INT                     overflow_embedding_count = 0;
435 INT                     valid_isolate_count = 0;
436 INT                     index = 0;
437 INT                     end_index;
438 GX_UBYTE                level;
439 ULONG                   type;
440 GX_BIDI_UNIT           *unit;
441 
442     stack = (GX_BIDI_EXPLICIT_ENTRY *)(context -> gx_bidi_context_buffer + context -> gx_bidi_context_buffer_index);
443 
444     if (context -> gx_bidi_context_buffer_index > context -> gx_bidi_context_buffer_size)
445     {
446         return GX_INVALID_MEMORY_SIZE;
447     }
448     entry = stack;
449 
450     /* Push onto the stack an entry consisting of the paragraph embedding level,
451        a neutral directional override status, and a false directional isolate status. */
452     entry -> gx_bidi_explicit_level = context -> gx_bidi_context_base_level;
453     entry -> gx_bidi_explicit_override_status = GX_BIDI_OVERRIDE_STATUS_N;
454     entry -> gx_bidi_explicit_isolate_status = GX_FALSE;
455     last_entry = entry;
456     entry++;
457     stack_top++;
458 
459     unit = &context -> gx_bidi_context_unit_list[index];
460 
461     while (index < context -> gx_bidi_context_unit_count)
462     {
463         type = unit -> gx_bidi_unit_type;
464 
465         switch (type)
466         {
467         case GX_BIDI_CHARACTER_TYPE_RLE:
468         case GX_BIDI_CHARACTER_TYPE_LRE:
469         case GX_BIDI_CHARACTER_TYPE_RLO:
470         case GX_BIDI_CHARACTER_TYPE_LRO:
471             /* Handle explicit embeddings/overrides. */
472             entry -> gx_bidi_explicit_level = (GX_UBYTE)(last_entry -> gx_bidi_explicit_level + 1);
473             unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_BN;
474 
475             if (type == GX_BIDI_CHARACTER_TYPE_RLE ||
476                 type == GX_BIDI_CHARACTER_TYPE_RLO)
477             {
478                 /* Compute the least odd embedding level greater than the embedding level of the last entry. */
479                 if ((entry -> gx_bidi_explicit_level & 0x01) == 0)
480                 {
481                     entry -> gx_bidi_explicit_level = (GX_UBYTE)(entry -> gx_bidi_explicit_level + 1);
482                 }
483             }
484             else
485             {
486                 /* Compute the least even embedding level greater than the embedding level of the last entry. */
487                 if ((entry -> gx_bidi_explicit_level & 0x01) != 0)
488                 {
489                     entry -> gx_bidi_explicit_level = (GX_UBYTE)(entry -> gx_bidi_explicit_level + 1);
490                 }
491             }
492 
493             if ((entry -> gx_bidi_explicit_level <= GX_BIDI_MAX_EXPLICIT_DEPTH) &&
494                 (overflow_isolate_count == 0) &&
495                 (overflow_embedding_count == 0))
496             {
497                 /* Push an entry to stack. */
498 
499                 if (type == GX_BIDI_CHARACTER_TYPE_RLE ||
500                     type == GX_BIDI_CHARACTER_TYPE_LRE)
501                 {
502                     entry -> gx_bidi_explicit_override_status = GX_BIDI_OVERRIDE_STATUS_N;
503                 }
504                 else if (type == GX_BIDI_CHARACTER_TYPE_RLO)
505                 {
506                     entry -> gx_bidi_explicit_override_status = GX_BIDI_OVERRIDE_STATUS_R;
507                 }
508                 else
509                 {
510                     entry -> gx_bidi_explicit_override_status = GX_BIDI_OVERRIDE_STATUS_L;
511                 }
512 
513                 entry -> gx_bidi_explicit_isolate_status = GX_FALSE;
514                 last_entry = entry;
515                 entry++;
516                 stack_top++;
517             }
518             else if (overflow_isolate_count == 0)
519             {
520                 overflow_embedding_count++;
521             }
522             break;
523 
524         case GX_BIDI_CHARACTER_TYPE_RLI:
525         case GX_BIDI_CHARACTER_TYPE_LRI:
526         case GX_BIDI_CHARACTER_TYPE_FSI:
527             if (type == GX_BIDI_CHARACTER_TYPE_FSI)
528             {
529                 for (end_index = index + 1; end_index < context -> gx_bidi_context_unit_count; end_index++)
530                 {
531                     if (context -> gx_bidi_context_unit_list[end_index].gx_bidi_unit_type == GX_BIDI_CHARACTER_TYPE_PDI)
532                     {
533                         break;
534                     }
535                 }
536 
537                 _gx_utility_bidi_block_level_determine(context, (UINT)index, (UINT)end_index, &level);
538 
539                 if (level == 1)
540                 {
541                     type = GX_BIDI_CHARACTER_TYPE_RLI;
542                 }
543                 else
544                 {
545                     type = GX_BIDI_CHARACTER_TYPE_LRI;
546                 }
547             }
548 
549             /* Set the RLI's embedding level to the embedding level of the last entry. */
550             unit -> gx_bidi_unit_level = last_entry -> gx_bidi_explicit_level;
551             entry -> gx_bidi_explicit_level = (GX_UBYTE)(last_entry -> gx_bidi_explicit_level + 1);
552 
553             if (last_entry -> gx_bidi_explicit_override_status == GX_BIDI_OVERRIDE_STATUS_L)
554             {
555                 /* Reset the current character type from RLI to L if last override status is left to right. */
556                 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_L;
557             }
558             else if (last_entry -> gx_bidi_explicit_override_status == GX_BIDI_OVERRIDE_STATUS_R)
559             {
560                 /* Reset the current character type from RLI to R if last overried status is right to left. */
561                 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_R;
562             }
563 
564             if ((type == GX_BIDI_CHARACTER_TYPE_RLI && (entry -> gx_bidi_explicit_level & 0x01) == 0) ||
565                 (type == GX_BIDI_CHARACTER_TYPE_LRI && (entry -> gx_bidi_explicit_level & 0x01) != 0))
566             {
567                 entry -> gx_bidi_explicit_level = (GX_UBYTE)(entry -> gx_bidi_explicit_level + 1);
568             }
569 
570             if (entry -> gx_bidi_explicit_level <= GX_BIDI_MAX_EXPLICIT_DEPTH &&
571                 overflow_isolate_count == 0 &&
572                 overflow_embedding_count == 0)
573             {
574                 valid_isolate_count++;
575                 entry -> gx_bidi_explicit_override_status = GX_BIDI_OVERRIDE_STATUS_N;
576                 entry -> gx_bidi_explicit_isolate_status = GX_TRUE;
577                 last_entry = entry;
578                 entry++;
579                 stack_top++;
580             }
581             else
582             {
583                 /* This is an overflow RLI/LRI. */
584                 overflow_isolate_count++;
585             }
586             break;
587 
588         case GX_BIDI_CHARACTER_TYPE_PDF:
589             unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_BN;
590             if (overflow_isolate_count == 0)
591             {
592                 if (overflow_embedding_count)
593                 {
594                     overflow_embedding_count--;
595                 }
596                 else if (last_entry -> gx_bidi_explicit_isolate_status == GX_FALSE &&
597                          stack_top >= 2)
598                 {
599                     last_entry--;
600                     entry--;
601                     stack_top--;
602                 }
603             }
604             break;
605 
606         case GX_BIDI_CHARACTER_TYPE_PDI:
607             if (overflow_isolate_count > 0)
608             {
609                 /* This PDI matches an overflow isolate initiator. */
610                 overflow_isolate_count--;
611             }
612             else if (valid_isolate_count != 0)
613             {
614                 overflow_embedding_count = 0;
615 
616                 while ((stack_top > 1) &&
617                        (last_entry -> gx_bidi_explicit_isolate_status == GX_FALSE))
618                 {
619                     /* Pop the last entry. */
620                     last_entry--;
621                     entry--;
622                     stack_top--;
623                 }
624 
625                 last_entry--;
626                 entry--;
627                 stack_top--;
628                 valid_isolate_count--;
629             }
630 
631             unit -> gx_bidi_unit_level = last_entry -> gx_bidi_explicit_level;
632 
633             if (last_entry -> gx_bidi_explicit_override_status == GX_BIDI_OVERRIDE_STATUS_L)
634             {
635                 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_L;
636             }
637             else if (last_entry -> gx_bidi_explicit_override_status == GX_BIDI_OVERRIDE_STATUS_R)
638             {
639                 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_R;
640             }
641             break;
642 
643         case GX_BIDI_CHARACTER_TYPE_BN:
644             break;
645 
646         default:
647             /* Set current character's embedding level to the embedding level of the last entry. */
648             unit -> gx_bidi_unit_level = last_entry -> gx_bidi_explicit_level;
649 
650             if (last_entry -> gx_bidi_explicit_override_status == GX_BIDI_OVERRIDE_STATUS_L)
651             {
652                 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_L;
653             }
654             else if (last_entry -> gx_bidi_explicit_override_status == GX_BIDI_OVERRIDE_STATUS_R)
655             {
656                 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_R;
657             }
658             break;
659         }
660 
661         index++;
662         unit++;
663     }
664 
665     return GX_SUCCESS;
666 }
667 
668 /**************************************************************************/
669 /*                                                                        */
670 /*  FUNCTION                                               RELEASE        */
671 /*                                                                        */
672 /*    _gx_utility_bidi_level_runs_compute                 PORTABLE C      */
673 /*                                                           6.1          */
674 /*  AUTHOR                                                                */
675 /*                                                                        */
676 /*    Kenneth Maxwell, Microsoft Corporation                              */
677 /*                                                                        */
678 /*  DESCRIPTION                                                           */
679 /*                                                                        */
680 /*    Internal helper function to calculate the level runs of the         */
681 /*    specified text block                                                */
682 /*                                                                        */
683 /*  INPUT                                                                 */
684 /*                                                                        */
685 /*    context                               Bidi information control block*/
686 /*    start_index                           The start index of the text   */
687 /*                                            block                       */
688 /*    end_index                             The end index of the text     */
689 /*                                            block                       */
690 /*                                                                        */
691 /*  OUTPUT                                                                */
692 /*                                                                        */
693 /*    status                                Completion status             */
694 /*                                                                        */
695 /*  CALLS                                                                 */
696 /*                                                                        */
697 /*    None                                                                */
698 /*                                                                        */
699 /*  CALLED BY                                                             */
700 /*                                                                        */
701 /*    _gx_utility_bidi_paragraph_reorder                                  */
702 /*                                                                        */
703 /*  RELEASE HISTORY                                                       */
704 /*                                                                        */
705 /*    DATE              NAME                      DESCRIPTION             */
706 /*                                                                        */
707 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
708 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
709 /*                                            resulting in version 6.1    */
710 /*                                                                        */
711 /**************************************************************************/
_gx_utility_bidi_level_runs_compute(GX_BIDI_CONTEXT * context,INT start_index,INT end_index)712 static UINT _gx_utility_bidi_level_runs_compute(GX_BIDI_CONTEXT *context, INT start_index, INT end_index)
713 {
714 INT                run_start_index = -1;
715 INT                run_end_index;
716 INT                index = start_index;
717 GX_BIDI_LEVEL_RUN *entry;
718 GX_BIDI_LEVEL_RUN *last_entry = GX_NULL;
719 GX_UBYTE           run_level;
720 GX_BIDI_UNIT      *unit;
721 
722     if (context -> gx_bidi_context_level_runs == GX_NULL)
723     {
724         context -> gx_bidi_context_level_runs = (GX_BIDI_LEVEL_RUN *)(context -> gx_bidi_context_buffer + context -> gx_bidi_context_buffer_index);
725         context -> gx_bidi_context_buffer_index += sizeof(GX_BIDI_LEVEL_RUN) * (UINT)context -> gx_bidi_context_unit_count;
726 
727         if (context -> gx_bidi_context_buffer_index > context -> gx_bidi_context_buffer_size)
728         {
729             return GX_INVALID_MEMORY_SIZE;
730         }
731     }
732 
733     entry = context -> gx_bidi_context_level_runs;
734 
735     unit = &context -> gx_bidi_context_unit_list[index];
736     while (index <= end_index)
737     {
738         switch (unit -> gx_bidi_unit_type)
739         {
740         case GX_BIDI_CHARACTER_TYPE_BN:
741             break;
742 
743         default:
744             if (run_start_index == -1)
745             {
746                 run_start_index = index;
747                 run_level = unit -> gx_bidi_unit_level;
748             }
749             else if (run_level != unit -> gx_bidi_unit_level)
750             {
751                 entry -> gx_bidi_level_run_start_index = run_start_index;
752                 entry -> gx_bidi_level_run_end_index = run_end_index;
753                 entry -> gx_bidi_level_run_level = run_level;
754                 entry -> gx_bidi_level_run_next = GX_NULL;
755 
756                 if (last_entry)
757                 {
758                     last_entry -> gx_bidi_level_run_next = entry;
759                 }
760                 last_entry = entry;
761                 entry++;
762                 run_start_index = index;
763                 run_level = unit -> gx_bidi_unit_level;
764             }
765             run_end_index = index;
766             break;
767         }
768 
769         index++;
770         unit++;
771     }
772 
773     entry -> gx_bidi_level_run_start_index = run_start_index;
774     entry -> gx_bidi_level_run_end_index = run_end_index;
775     entry -> gx_bidi_level_run_level = run_level;
776     entry -> gx_bidi_level_run_next = GX_NULL;
777 
778     if (last_entry)
779     {
780         last_entry -> gx_bidi_level_run_next = entry;
781     }
782     return GX_SUCCESS;
783 }
784 
785 /**************************************************************************/
786 /*                                                                        */
787 /*  FUNCTION                                               RELEASE        */
788 /*                                                                        */
789 /*    _gx_utiltiy_isolate_run_sequence_append             PORTABLE C      */
790 /*                                                           6.1          */
791 /*  AUTHOR                                                                */
792 /*                                                                        */
793 /*    Kenneth Maxwell, Microsoft Corporation                              */
794 /*                                                                        */
795 /*  DESCRIPTION                                                           */
796 /*                                                                        */
797 /*    Internal helper function to append a sequence to the specified      */
798 /*    isolate run sequence.                                               */
799 /*                                                                        */
800 /*  INPUT                                                                 */
801 /*                                                                        */
802 /*    context                               Bidi information control block*/
803 /*    start_index                           Start position of the append  */
804 /*                                            sequence                    */
805 /*    end_index                             End position of the append    */
806 /*                                            sequence                    */
807 /*    siolate_run                           Pointer to isolate run        */
808 /*                                            structure                   */
809 /*                                                                        */
810 /*  OUTPUT                                                                */
811 /*                                                                        */
812 /*    status                                Completion status             */
813 /*                                                                        */
814 /*  CALLS                                                                 */
815 /*                                                                        */
816 /*    None                                                                */
817 /*                                                                        */
818 /*  CALLED BY                                                             */
819 /*                                                                        */
820 /*    _gx_utility_bidi_one_isolate_run_sequences_get                      */
821 /*                                                                        */
822 /*  RELEASE HISTORY                                                       */
823 /*                                                                        */
824 /*    DATE              NAME                      DESCRIPTION             */
825 /*                                                                        */
826 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
827 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
828 /*                                            resulting in version 6.1    */
829 /*                                                                        */
830 /**************************************************************************/
_gx_utiltiy_isolate_run_sequence_append(GX_BIDI_CONTEXT * context,INT start_index,INT end_index,GX_BIDI_ISOLATE_RUN * isolate_run)831 static UINT _gx_utiltiy_isolate_run_sequence_append(GX_BIDI_CONTEXT *context, INT start_index, INT end_index,
832                                                     GX_BIDI_ISOLATE_RUN *isolate_run)
833 {
834 INT           index;
835 GX_BIDI_UNIT *unit;
836 
837     unit = &context -> gx_bidi_context_unit_list[start_index];
838     for (index = start_index; index <= end_index; index++)
839     {
840         if (unit -> gx_bidi_unit_type == GX_BIDI_CHARACTER_TYPE_BN)
841         {
842             unit++;
843             continue;
844         }
845 
846         isolate_run -> gx_bidi_isolate_run_index_list[isolate_run -> gx_bidi_isolate_run_index_count++] = index;
847         context -> gx_bidi_context_buffer_index += sizeof(ULONG);
848 
849         unit++;
850     }
851 
852     if (context -> gx_bidi_context_buffer_index > context -> gx_bidi_context_buffer_size)
853     {
854         return GX_INVALID_MEMORY_SIZE;
855     }
856 
857     return GX_SUCCESS;
858 }
859 
860 /**************************************************************************/
861 /*                                                                        */
862 /*  FUNCTION                                               RELEASE        */
863 /*                                                                        */
864 /*    _gx_utility_bidi_one_isolate_run_sequence_get       PORTABLE C      */
865 /*                                                           6.1          */
866 /*  AUTHOR                                                                */
867 /*                                                                        */
868 /*    Kenneth Maxwell, Microsoft Corporation                              */
869 /*                                                                        */
870 /*  DESCRIPTION                                                           */
871 /*                                                                        */
872 /*    Internal helper function to calculate one isolate run sequence      */
873 /*    start from the specified level run.                                 */
874 /*                                                                        */
875 /*  INPUT                                                                 */
876 /*                                                                        */
877 /*    context                               Bidi information control block*/
878 /*    pre_level                             Embedding level of the        */
879 /*                                            previous level run          */
880 /*    level_run                             Pointer to level run structure*/
881 /*    isolate_run                           Buffer to load an isolate run */
882 /*                                            sequence                    */
883 /*                                                                        */
884 /*  OUTPUT                                                                */
885 /*                                                                        */
886 /*    status                                Completion status             */
887 /*                                                                        */
888 /*  CALLS                                                                 */
889 /*                                                                        */
890 /*    _gx_utiltiy_isolate_run_sequence_append                             */
891 /*                                                                        */
892 /*  CALLED BY                                                             */
893 /*                                                                        */
894 /*    _gx_utility_bidi_isolate_run_sequence_get                           */
895 /*                                                                        */
896 /*  RELEASE HISTORY                                                       */
897 /*                                                                        */
898 /*    DATE              NAME                      DESCRIPTION             */
899 /*                                                                        */
900 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
901 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
902 /*                                            resulting in version 6.1    */
903 /*                                                                        */
904 /**************************************************************************/
_gx_utility_bidi_one_isolate_run_sequence_get(GX_BIDI_CONTEXT * context,GX_UBYTE pre_level,GX_BIDI_LEVEL_RUN * level_run,GX_BIDI_ISOLATE_RUN * isolate_run)905 static UINT _gx_utility_bidi_one_isolate_run_sequence_get(GX_BIDI_CONTEXT *context, GX_UBYTE  pre_level,
906                                                           GX_BIDI_LEVEL_RUN *level_run, GX_BIDI_ISOLATE_RUN *isolate_run)
907 {
908 UINT          status;
909 GX_UBYTE      next_level;
910 GX_UBYTE      run_level;
911 GX_UBYTE      higher_level;
912 INT           start_index;
913 INT           end_index;
914 UINT          isolate_initiator_count;
915 GX_BIDI_UNIT *unit;
916 ULONG         last_character;
917 
918     run_level = level_run -> gx_bidi_level_run_level;
919     start_index = level_run -> gx_bidi_level_run_start_index;
920     end_index = level_run -> gx_bidi_level_run_end_index;
921 
922     isolate_run -> gx_bidi_isolate_run_index_count = 0;
923 
924     status = _gx_utiltiy_isolate_run_sequence_append(context, start_index, end_index, isolate_run);
925 
926     if (status != GX_SUCCESS)
927     {
928         return status;
929     }
930 
931     isolate_run -> gx_bidi_isolate_run_next = GX_NULL;
932 
933     last_character = context -> gx_bidi_context_unit_list[end_index].gx_bidi_unit_code;
934 
935     level_run = level_run -> gx_bidi_level_run_next;
936     isolate_initiator_count = 1;
937 
938     next_level = (level_run == GX_NULL) ? context -> gx_bidi_context_base_level : level_run -> gx_bidi_level_run_level;
939 
940     while (level_run)
941     {
942         /* while the level run last in the sequence ends with an isolate initiator that has a matching PDI,
943            append the level run containing the matching PDI to the isolate run sequence. */
944         if ((last_character != GX_BIDI_DIRECTION_FORMAT_RLI) &&
945             (last_character != GX_BIDI_DIRECTION_FORMAT_LRI) &&
946             (last_character != GX_BIDI_DIRECTION_FORMAT_FSI))
947         {
948             break;
949         }
950 
951         start_index = level_run -> gx_bidi_level_run_start_index;
952         end_index = level_run -> gx_bidi_level_run_end_index;
953 
954         unit = &context -> gx_bidi_context_unit_list[start_index];
955         if (unit -> gx_bidi_unit_code == GX_BIDI_DIRECTION_FORMAT_PDI)
956         {
957             isolate_initiator_count--;
958             if (isolate_initiator_count == 0)
959             {
960                 /* This is a matching PDI. */
961                 status = _gx_utiltiy_isolate_run_sequence_append(context, start_index, end_index, isolate_run);
962 
963                 if (status != GX_SUCCESS)
964                 {
965                     return status;
966                 }
967 
968                 last_character = context -> gx_bidi_context_unit_list[end_index].gx_bidi_unit_code;
969 
970                 if (level_run -> gx_bidi_level_run_next)
971                 {
972                     next_level = level_run -> gx_bidi_level_run_next -> gx_bidi_level_run_level;
973                 }
974                 else
975                 {
976                     next_level = context -> gx_bidi_context_base_level;
977                 }
978             }
979         }
980 
981         unit = &context -> gx_bidi_context_unit_list[end_index];
982 
983         if (unit -> gx_bidi_unit_code == GX_BIDI_DIRECTION_FORMAT_LRI ||
984             unit -> gx_bidi_unit_code == GX_BIDI_DIRECTION_FORMAT_RLI ||
985             unit -> gx_bidi_unit_code == GX_BIDI_DIRECTION_FORMAT_FSI)
986         {
987             isolate_initiator_count++;
988         }
989 
990         level_run = level_run -> gx_bidi_level_run_next;
991     }
992 
993     /* Determine sos. */
994     higher_level = (pre_level > run_level) ? pre_level : run_level;
995     isolate_run -> gx_bidi_isolate_run_sos = ((higher_level & 0x01) == 1) ? GX_BIDI_CHARACTER_TYPE_R : GX_BIDI_CHARACTER_TYPE_L;
996 
997     /* Determine eos. */
998     higher_level = (next_level > run_level) ? next_level : run_level;
999     isolate_run -> gx_bidi_isolate_run_eos = ((higher_level & 0x01) == 1) ? GX_BIDI_CHARACTER_TYPE_R : GX_BIDI_CHARACTER_TYPE_L;
1000 
1001     return GX_SUCCESS;
1002 }
1003 
1004 /**************************************************************************/
1005 /*                                                                        */
1006 /*  FUNCTION                                               RELEASE        */
1007 /*                                                                        */
1008 /*    _gx_utility_bidi_isolate_run_sequences_get          PORTABLE C      */
1009 /*                                                           6.1          */
1010 /*  AUTHOR                                                                */
1011 /*                                                                        */
1012 /*    Kenneth Maxwell, Microsoft Corporation                              */
1013 /*                                                                        */
1014 /*  DESCRIPTION                                                           */
1015 /*                                                                        */
1016 /*    Internal helper function to calculate the isolate run sequences.    */
1017 /*                                                                        */
1018 /*  INPUT                                                                 */
1019 /*                                                                        */
1020 /*    context                               Bidi information control block*/
1021 /*                                                                        */
1022 /*  OUTPUT                                                                */
1023 /*                                                                        */
1024 /*    status                                Completion status             */
1025 /*                                                                        */
1026 /*  CALLS                                                                 */
1027 /*                                                                        */
1028 /*    None                                                                */
1029 /*                                                                        */
1030 /*  CALLED BY                                                             */
1031 /*                                                                        */
1032 /*    _gx_utility_bidi_paragraph_reorder                                  */
1033 /*                                                                        */
1034 /*  RELEASE HISTORY                                                       */
1035 /*                                                                        */
1036 /*    DATE              NAME                      DESCRIPTION             */
1037 /*                                                                        */
1038 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
1039 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
1040 /*                                            resulting in version 6.1    */
1041 /*                                                                        */
1042 /**************************************************************************/
_gx_utility_bidi_isolate_run_sequences_get(GX_BIDI_CONTEXT * context)1043 static UINT _gx_utility_bidi_isolate_run_sequences_get(GX_BIDI_CONTEXT *context)
1044 {
1045 UINT                 status;
1046 INT                  level_run_start_index;
1047 INT                  level_run_end_index;
1048 INT                  isolate_initiator_count = 0;
1049 GX_BIDI_LEVEL_RUN   *level_run_entry;
1050 GX_BIDI_ISOLATE_RUN *isolate_run_entry;
1051 GX_BIDI_ISOLATE_RUN *last_isolate_run_entry = GX_NULL;
1052 GX_UBYTE             pre_level = context -> gx_bidi_context_base_level;
1053 GX_BIDI_UNIT        *unit;
1054 
1055     /* Compute level runs. */
1056     status = _gx_utility_bidi_level_runs_compute(context, 0, context -> gx_bidi_context_unit_count - 1);
1057 
1058     if (status != GX_SUCCESS)
1059     {
1060         return status;
1061     }
1062 
1063     /* Compute isolate runs. */
1064     context -> gx_bidi_context_isolate_runs = (GX_BIDI_ISOLATE_RUN *)(context -> gx_bidi_context_buffer + context -> gx_bidi_context_buffer_index);
1065 
1066     level_run_entry = context -> gx_bidi_context_level_runs;
1067     while (level_run_entry)
1068     {
1069         /* For each level run in the paragraph whose first characer is not a PDI,
1070            or is a PDI that does not match any isolate initiator,
1071            create a new isolate run sequence and initiate it to the level run. */
1072         level_run_start_index = level_run_entry -> gx_bidi_level_run_start_index;
1073         level_run_end_index = level_run_entry -> gx_bidi_level_run_end_index;
1074 
1075         unit = &context -> gx_bidi_context_unit_list[level_run_start_index];
1076 
1077         if ((unit -> gx_bidi_unit_code != GX_BIDI_DIRECTION_FORMAT_PDI) ||
1078             (isolate_initiator_count == 0))
1079         {
1080             isolate_run_entry = (GX_BIDI_ISOLATE_RUN *)(context -> gx_bidi_context_buffer + context -> gx_bidi_context_buffer_index);
1081             context -> gx_bidi_context_buffer_index += (INT)(sizeof(GX_BIDI_ISOLATE_RUN));
1082             isolate_run_entry -> gx_bidi_isolate_run_index_list = (INT *)(context -> gx_bidi_context_buffer + context -> gx_bidi_context_buffer_index);
1083 
1084             if (context -> gx_bidi_context_buffer_index > context -> gx_bidi_context_buffer_size)
1085             {
1086                 return GX_INVALID_MEMORY_SIZE;
1087             }
1088 
1089             /* Get one isolate run sequence. */
1090             _gx_utility_bidi_one_isolate_run_sequence_get(context, pre_level, level_run_entry, isolate_run_entry);
1091 
1092             if (last_isolate_run_entry)
1093             {
1094                 last_isolate_run_entry -> gx_bidi_isolate_run_next = isolate_run_entry;
1095             }
1096 
1097             last_isolate_run_entry = isolate_run_entry;
1098         }
1099 
1100         if (unit -> gx_bidi_unit_code == GX_BIDI_DIRECTION_FORMAT_PDI)
1101         {
1102             isolate_initiator_count--;
1103         }
1104 
1105         unit = &context -> gx_bidi_context_unit_list[level_run_end_index];
1106 
1107         if (unit -> gx_bidi_unit_code == GX_BIDI_DIRECTION_FORMAT_LRI ||
1108             unit -> gx_bidi_unit_code == GX_BIDI_DIRECTION_FORMAT_RLI ||
1109             unit -> gx_bidi_unit_code == GX_BIDI_DIRECTION_FORMAT_FSI)
1110         {
1111             isolate_initiator_count++;
1112         }
1113 
1114         pre_level = level_run_entry -> gx_bidi_level_run_level;
1115         level_run_entry = level_run_entry -> gx_bidi_level_run_next;
1116     }
1117 
1118     return status;
1119 }
1120 
1121 /**************************************************************************/
1122 /*                                                                        */
1123 /*  FUNCTION                                               RELEASE        */
1124 /*                                                                        */
1125 /*    _gx_utility_bidi_weak_type_resolve_1                PORTABLE C      */
1126 /*                                                           6.1          */
1127 /*  AUTHOR                                                                */
1128 /*                                                                        */
1129 /*    Kenneth Maxwell, Microsoft Corporation                              */
1130 /*                                                                        */
1131 /*  DESCRIPTION                                                           */
1132 /*                                                                        */
1133 /*    Internal helper function to apply rule 1 to weak characters in an   */
1134 /*    isolate run sequence.                                               */
1135 /*                                                                        */
1136 /*  INPUT                                                                 */
1137 /*                                                                        */
1138 /*    context                               Bidi information control block*/
1139 /*    entry                                 Pointer to an isolate run     */
1140 /*                                            sequence                    */
1141 /*                                                                        */
1142 /*  OUTPUT                                                                */
1143 /*                                                                        */
1144 /*    status                                Completion status             */
1145 /*                                                                        */
1146 /*  CALLS                                                                 */
1147 /*                                                                        */
1148 /*    None                                                                */
1149 /*                                                                        */
1150 /*  CALLED BY                                                             */
1151 /*                                                                        */
1152 /*    _gx_utility_bidi_paragraph_reorder                                  */
1153 /*                                                                        */
1154 /*  RELEASE HISTORY                                                       */
1155 /*                                                                        */
1156 /*    DATE              NAME                      DESCRIPTION             */
1157 /*                                                                        */
1158 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
1159 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
1160 /*                                            resulting in version 6.1    */
1161 /*                                                                        */
1162 /**************************************************************************/
_gx_utility_bidi_weak_type_resolve_1(GX_BIDI_CONTEXT * context,GX_BIDI_ISOLATE_RUN * entry)1163 static UINT _gx_utility_bidi_weak_type_resolve_1(GX_BIDI_CONTEXT *context, GX_BIDI_ISOLATE_RUN *entry)
1164 {
1165 INT           run_index;
1166 INT           text_index;
1167 GX_UBYTE      pre_type = 0;
1168 GX_BIDI_UNIT *unit;
1169 
1170     for (run_index = 0; run_index < entry -> gx_bidi_isolate_run_index_count; run_index++)
1171     {
1172         text_index = entry -> gx_bidi_isolate_run_index_list[run_index];
1173         unit = &context -> gx_bidi_context_unit_list[text_index];
1174 
1175         if (unit -> gx_bidi_unit_type == GX_BIDI_CHARACTER_TYPE_NSM)
1176         {
1177             if (pre_type == 0)
1178             {
1179                 /* If the NSM is at the start of the isolating run sequence, it will get the type of sos. */
1180                 unit -> gx_bidi_unit_type = entry -> gx_bidi_isolate_run_sos;
1181             }
1182             else
1183             {
1184                 switch (pre_type)
1185                 {
1186                 case GX_BIDI_CHARACTER_TYPE_RLI:
1187                 case GX_BIDI_CHARACTER_TYPE_LRI:
1188                 case GX_BIDI_CHARACTER_TYPE_PDI:
1189                     /* If the previous character type is an isolate initiator or PDI, change type to ON. */
1190                     unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_ON;
1191                     break;
1192 
1193                 default:
1194                     /* Otherwise, change type to the type of previous character. */
1195                     unit -> gx_bidi_unit_type = pre_type;
1196                     break;
1197                 }
1198             }
1199         }
1200 
1201         pre_type = unit -> gx_bidi_unit_type;
1202     }
1203     return GX_SUCCESS;
1204 }
1205 
1206 /**************************************************************************/
1207 /*                                                                        */
1208 /*  FUNCTION                                               RELEASE        */
1209 /*                                                                        */
1210 /*    _gx_utility_bidi_weak_type_resolve_2_3              PORTABLE C      */
1211 /*                                                           6.1          */
1212 /*  AUTHOR                                                                */
1213 /*                                                                        */
1214 /*    Kenneth Maxwell, Microsoft Corporation                              */
1215 /*                                                                        */
1216 /*  DESCRIPTION                                                           */
1217 /*                                                                        */
1218 /*    Internal helper function to apply rule 2 and 3 to weak characters in*/
1219 /*    an isolate run sequence.                                            */
1220 /*                                                                        */
1221 /*  INPUT                                                                 */
1222 /*                                                                        */
1223 /*    context                               Bidi information control block*/
1224 /*    entry                                 Pointer to an isolate run     */
1225 /*                                            sequence                    */
1226 /*                                                                        */
1227 /*  OUTPUT                                                                */
1228 /*                                                                        */
1229 /*    status                                Completion status             */
1230 /*                                                                        */
1231 /*  CALLS                                                                 */
1232 /*                                                                        */
1233 /*    None                                                                */
1234 /*                                                                        */
1235 /*  CALLED BY                                                             */
1236 /*                                                                        */
1237 /*    _gx_utility_bidi_paragraph_reorder                                  */
1238 /*                                                                        */
1239 /*  RELEASE HISTORY                                                       */
1240 /*                                                                        */
1241 /*    DATE              NAME                      DESCRIPTION             */
1242 /*                                                                        */
1243 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
1244 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
1245 /*                                            resulting in version 6.1    */
1246 /*                                                                        */
1247 /**************************************************************************/
_gx_utility_bidi_weak_type_resolve_2_3(GX_BIDI_CONTEXT * context,GX_BIDI_ISOLATE_RUN * entry)1248 static UINT _gx_utility_bidi_weak_type_resolve_2_3(GX_BIDI_CONTEXT *context, GX_BIDI_ISOLATE_RUN *entry)
1249 {
1250 INT           run_index = 0;
1251 INT           text_index;
1252 GX_BOOL       do_change = GX_FALSE;
1253 GX_BIDI_UNIT *unit;
1254 
1255     for (run_index = 0; run_index < entry -> gx_bidi_isolate_run_index_count; run_index++)
1256     {
1257         text_index = entry -> gx_bidi_isolate_run_index_list[run_index];
1258         unit = &context -> gx_bidi_context_unit_list[text_index];
1259 
1260         /* Search backward from each instance of a EN until the first strong type is found,
1261            If AL is found, replacing following EN to AN. */
1262 
1263         switch (unit -> gx_bidi_unit_type)
1264         {
1265         case GX_BIDI_CHARACTER_TYPE_R:
1266         case GX_BIDI_CHARACTER_TYPE_L:
1267             do_change = GX_FALSE;
1268             break;
1269 
1270         case GX_BIDI_CHARACTER_TYPE_AL:
1271             do_change = GX_TRUE;
1272 
1273             /* Change all ALs to R. */
1274             unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_R;
1275             break;
1276 
1277         case GX_BIDI_CHARACTER_TYPE_EN:
1278             if (do_change)
1279             {
1280                 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_AN;
1281             }
1282             break;
1283         }
1284     }
1285 
1286     return GX_SUCCESS;
1287 }
1288 
1289 /**************************************************************************/
1290 /*                                                                        */
1291 /*  FUNCTION                                               RELEASE        */
1292 /*                                                                        */
1293 /*    _gx_utility_bidi_weak_type_resolve_4                PORTABLE C      */
1294 /*                                                           6.1          */
1295 /*  AUTHOR                                                                */
1296 /*                                                                        */
1297 /*    Kenneth Maxwell, Microsoft Corporation                              */
1298 /*                                                                        */
1299 /*  DESCRIPTION                                                           */
1300 /*                                                                        */
1301 /*    Internal helper function to apply rule 4 to weak characters in an   */
1302 /*    isolate run sequence.                                               */
1303 /*                                                                        */
1304 /*  INPUT                                                                 */
1305 /*                                                                        */
1306 /*    context                               Bidi information control block*/
1307 /*    entry                                 Pointer to an isolate run     */
1308 /*                                            sequence                    */
1309 /*                                                                        */
1310 /*  OUTPUT                                                                */
1311 /*                                                                        */
1312 /*    status                                Completion status             */
1313 /*                                                                        */
1314 /*  CALLS                                                                 */
1315 /*                                                                        */
1316 /*    None                                                                */
1317 /*                                                                        */
1318 /*  CALLED BY                                                             */
1319 /*                                                                        */
1320 /*    _gx_utility_bidi_paragraph_reorder                                  */
1321 /*                                                                        */
1322 /*  RELEASE HISTORY                                                       */
1323 /*                                                                        */
1324 /*    DATE              NAME                      DESCRIPTION             */
1325 /*                                                                        */
1326 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
1327 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
1328 /*                                            resulting in version 6.1    */
1329 /*                                                                        */
1330 /**************************************************************************/
_gx_utility_bidi_weak_type_resolve_4(GX_BIDI_CONTEXT * context,GX_BIDI_ISOLATE_RUN * entry)1331 static UINT _gx_utility_bidi_weak_type_resolve_4(GX_BIDI_CONTEXT *context, GX_BIDI_ISOLATE_RUN *entry)
1332 {
1333 INT           run_index;
1334 INT           text_index;
1335 GX_UBYTE      pre_type = 0;
1336 GX_UBYTE      follow_type = 0;
1337 GX_BIDI_UNIT *unit;
1338 
1339     /* A single ES between two EN, change to EN,
1340        a single CS between two EN, change to EN,
1341        a single CS between two AN, change to AN. */
1342 
1343     for (run_index = 0; run_index < entry -> gx_bidi_isolate_run_index_count; run_index++)
1344     {
1345         if (run_index + 1 < entry -> gx_bidi_isolate_run_index_count)
1346         {
1347             text_index = entry -> gx_bidi_isolate_run_index_list[run_index + 1];
1348             follow_type = context -> gx_bidi_context_unit_list[text_index].gx_bidi_unit_type;
1349         }
1350 
1351         text_index = entry -> gx_bidi_isolate_run_index_list[run_index];
1352         unit = &context -> gx_bidi_context_unit_list[text_index];
1353 
1354         if (pre_type == follow_type)
1355         {
1356             if (unit -> gx_bidi_unit_type == GX_BIDI_CHARACTER_TYPE_ES &&
1357                 pre_type == GX_BIDI_CHARACTER_TYPE_EN)
1358             {
1359                 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_EN;
1360             }
1361             else if ((unit -> gx_bidi_unit_type == GX_BIDI_CHARACTER_TYPE_CS) &&
1362                      (pre_type == GX_BIDI_CHARACTER_TYPE_EN || pre_type == GX_BIDI_CHARACTER_TYPE_AN))
1363             {
1364                 unit -> gx_bidi_unit_type = pre_type;
1365             }
1366             run_index++;
1367         }
1368         else
1369         {
1370             pre_type = unit -> gx_bidi_unit_type;
1371         }
1372     }
1373 
1374     return GX_SUCCESS;
1375 }
1376 
1377 /**************************************************************************/
1378 /*                                                                        */
1379 /*  FUNCTION                                               RELEASE        */
1380 /*                                                                        */
1381 /*    _gx_utility_bidi_weak_type_resolve_5                PORTABLE C      */
1382 /*                                                           6.1          */
1383 /*  AUTHOR                                                                */
1384 /*                                                                        */
1385 /*    Kenneth Maxwell, Microsoft Corporation                              */
1386 /*                                                                        */
1387 /*  DESCRIPTION                                                           */
1388 /*                                                                        */
1389 /*    Internal helper function to apply rule 5 to weak characters in an   */
1390 /*    isolate run sequence.                                               */
1391 /*                                                                        */
1392 /*  INPUT                                                                 */
1393 /*                                                                        */
1394 /*    context                               Bidi information control block*/
1395 /*    entry                                 Pointer to an isolate run     */
1396 /*                                            sequence                    */
1397 /*                                                                        */
1398 /*  OUTPUT                                                                */
1399 /*                                                                        */
1400 /*    status                                Completion status             */
1401 /*                                                                        */
1402 /*  CALLS                                                                 */
1403 /*                                                                        */
1404 /*    None                                                                */
1405 /*                                                                        */
1406 /*  CALLED BY                                                             */
1407 /*                                                                        */
1408 /*    _gx_utility_bidi_paragraph_reorder                                  */
1409 /*                                                                        */
1410 /*  RELEASE HISTORY                                                       */
1411 /*                                                                        */
1412 /*    DATE              NAME                      DESCRIPTION             */
1413 /*                                                                        */
1414 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
1415 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
1416 /*                                            resulting in version 6.1    */
1417 /*                                                                        */
1418 /**************************************************************************/
_gx_utility_bidi_weak_type_resolve_5(GX_BIDI_CONTEXT * context,GX_BIDI_ISOLATE_RUN * entry)1419 static UINT _gx_utility_bidi_weak_type_resolve_5(GX_BIDI_CONTEXT *context, GX_BIDI_ISOLATE_RUN *entry)
1420 {
1421 
1422 INT           run_index;
1423 INT           pre_run_index;
1424 INT           text_index;
1425 GX_BOOL       do_change = GX_FALSE;
1426 GX_BIDI_UNIT *unit;
1427 
1428     /* A sequence of ETs adjacent to EN, change to all ENs. */
1429     for (run_index = 0; run_index < entry -> gx_bidi_isolate_run_index_count; run_index++)
1430     {
1431         text_index = entry -> gx_bidi_isolate_run_index_list[run_index];
1432         unit = &context -> gx_bidi_context_unit_list[text_index];
1433 
1434         if (unit -> gx_bidi_unit_type == GX_BIDI_CHARACTER_TYPE_EN)
1435         {
1436             do_change = GX_TRUE;
1437 
1438             pre_run_index = run_index - 1;
1439 
1440             while (pre_run_index >= 0)
1441             {
1442                 text_index = entry -> gx_bidi_isolate_run_index_list[pre_run_index--];
1443                 unit = &context -> gx_bidi_context_unit_list[text_index];
1444 
1445                 if (unit -> gx_bidi_unit_type == GX_BIDI_CHARACTER_TYPE_ET)
1446                 {
1447                     unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_EN;
1448                 }
1449                 else
1450                 {
1451                     break;
1452                 }
1453             }
1454         }
1455         else if (do_change && unit -> gx_bidi_unit_type == GX_BIDI_CHARACTER_TYPE_ET)
1456         {
1457             unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_EN;
1458         }
1459         else
1460         {
1461             do_change = GX_FALSE;
1462         }
1463     }
1464     return GX_SUCCESS;
1465 }
1466 
1467 /**************************************************************************/
1468 /*                                                                        */
1469 /*  FUNCTION                                               RELEASE        */
1470 /*                                                                        */
1471 /*    _gx_utility_bidi_weak_type_resolve_6                PORTABLE C      */
1472 /*                                                           6.1          */
1473 /*  AUTHOR                                                                */
1474 /*                                                                        */
1475 /*    Kenneth Maxwell, Microsoft Corporation                              */
1476 /*                                                                        */
1477 /*  DESCRIPTION                                                           */
1478 /*                                                                        */
1479 /*    Internal helper function to apply rule 6 to weak characters in an   */
1480 /*    isolate run sequence.                                               */
1481 /*                                                                        */
1482 /*  INPUT                                                                 */
1483 /*                                                                        */
1484 /*    context                               Bidi information control block*/
1485 /*    entry                                 Pointer to an isolate run     */
1486 /*                                            sequence                    */
1487 /*                                                                        */
1488 /*  OUTPUT                                                                */
1489 /*                                                                        */
1490 /*    status                                Completion status             */
1491 /*                                                                        */
1492 /*  CALLS                                                                 */
1493 /*                                                                        */
1494 /*    None                                                                */
1495 /*                                                                        */
1496 /*  CALLED BY                                                             */
1497 /*                                                                        */
1498 /*    _gx_utility_bidi_paragraph_reorder                                  */
1499 /*                                                                        */
1500 /*  RELEASE HISTORY                                                       */
1501 /*                                                                        */
1502 /*    DATE              NAME                      DESCRIPTION             */
1503 /*                                                                        */
1504 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
1505 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
1506 /*                                            resulting in version 6.1    */
1507 /*                                                                        */
1508 /**************************************************************************/
_gx_utility_bidi_weak_type_resolve_6(GX_BIDI_CONTEXT * context,GX_BIDI_ISOLATE_RUN * entry)1509 static UINT _gx_utility_bidi_weak_type_resolve_6(GX_BIDI_CONTEXT *context, GX_BIDI_ISOLATE_RUN *entry)
1510 {
1511 INT           run_index;
1512 INT           text_index;
1513 GX_BIDI_UNIT *unit;
1514 
1515     /* ES, CS, ET change to ON. */
1516     for (run_index = 0; run_index < entry -> gx_bidi_isolate_run_index_count; run_index++)
1517     {
1518         text_index = entry -> gx_bidi_isolate_run_index_list[run_index];
1519         unit = &context -> gx_bidi_context_unit_list[text_index];
1520 
1521         switch (unit -> gx_bidi_unit_type)
1522         {
1523         case GX_BIDI_CHARACTER_TYPE_ES:
1524         case GX_BIDI_CHARACTER_TYPE_CS:
1525         case GX_BIDI_CHARACTER_TYPE_ET:
1526             unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_ON;
1527             break;
1528         }
1529     }
1530     return GX_SUCCESS;
1531 }
1532 
1533 /**************************************************************************/
1534 /*                                                                        */
1535 /*  FUNCTION                                               RELEASE        */
1536 /*                                                                        */
1537 /*    _gx_utility_bidi_weak_type_resolve_7                PORTABLE C      */
1538 /*                                                           6.1          */
1539 /*  AUTHOR                                                                */
1540 /*                                                                        */
1541 /*    Kenneth Maxwell, Microsoft Corporation                              */
1542 /*                                                                        */
1543 /*  DESCRIPTION                                                           */
1544 /*                                                                        */
1545 /*    Internal helper function to apply rule 7 to weak characters in an   */
1546 /*    isolate run sequence.                                               */
1547 /*                                                                        */
1548 /*  INPUT                                                                 */
1549 /*                                                                        */
1550 /*    context                               Bidi information control block*/
1551 /*    entry                                 Pointer to an isolate run     */
1552 /*                                            sequence                    */
1553 /*                                                                        */
1554 /*  OUTPUT                                                                */
1555 /*                                                                        */
1556 /*    status                                Completion status             */
1557 /*                                                                        */
1558 /*  CALLS                                                                 */
1559 /*                                                                        */
1560 /*    None                                                                */
1561 /*                                                                        */
1562 /*  CALLED BY                                                             */
1563 /*                                                                        */
1564 /*    _gx_utility_bidi_paragraph_reorder                                  */
1565 /*                                                                        */
1566 /*  RELEASE HISTORY                                                       */
1567 /*                                                                        */
1568 /*    DATE              NAME                      DESCRIPTION             */
1569 /*                                                                        */
1570 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
1571 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
1572 /*                                            resulting in version 6.1    */
1573 /*                                                                        */
1574 /**************************************************************************/
_gx_utility_bidi_weak_type_resolve_7(GX_BIDI_CONTEXT * context,GX_BIDI_ISOLATE_RUN * entry)1575 static UINT _gx_utility_bidi_weak_type_resolve_7(GX_BIDI_CONTEXT *context, GX_BIDI_ISOLATE_RUN *entry)
1576 {
1577 INT           run_index;
1578 INT           text_index;
1579 GX_BOOL       do_change = GX_FALSE;
1580 GX_BIDI_UNIT *unit;
1581 
1582     /* Search backward from each EN until first strong type (R, L, or SOS) is found, if
1583        L is found, change type to L.*/
1584     if (entry -> gx_bidi_isolate_run_sos == GX_BIDI_CHARACTER_TYPE_L)
1585     {
1586         do_change = GX_TRUE;
1587     }
1588     else
1589     {
1590         do_change = GX_FALSE;
1591     }
1592 
1593     for (run_index = 0; run_index < entry -> gx_bidi_isolate_run_index_count; run_index++)
1594     {
1595         text_index = entry -> gx_bidi_isolate_run_index_list[run_index];
1596         unit = &context -> gx_bidi_context_unit_list[text_index];
1597 
1598         switch (unit -> gx_bidi_unit_type)
1599         {
1600         case GX_BIDI_CHARACTER_TYPE_R:
1601             do_change = GX_FALSE;
1602             break;
1603 
1604         case GX_BIDI_CHARACTER_TYPE_L:
1605             do_change = GX_TRUE;
1606             break;
1607 
1608         default:
1609             if (do_change && unit -> gx_bidi_unit_type == GX_BIDI_CHARACTER_TYPE_EN)
1610             {
1611                 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_L;
1612             }
1613             break;
1614         }
1615     }
1616     return GX_SUCCESS;
1617 }
1618 
1619 /**************************************************************************/
1620 /*                                                                        */
1621 /*  FUNCTION                                               RELEASE        */
1622 /*                                                                        */
1623 /*    _gx_utility_bidi_bracket_pair_search                PORTABLE C      */
1624 /*                                                           6.1          */
1625 /*  AUTHOR                                                                */
1626 /*                                                                        */
1627 /*    Kenneth Maxwell, Microsoft Corporation                              */
1628 /*                                                                        */
1629 /*  DESCRIPTION                                                           */
1630 /*                                                                        */
1631 /*    Internal helper function to calculate bracket pairs in an isolate   */
1632 /*    run sequence.                                                       */
1633 /*                                                                        */
1634 /*  INPUT                                                                 */
1635 /*                                                                        */
1636 /*    context                               Bidi information control block*/
1637 /*    entry                                 Pointer to an isolate run     */
1638 /*                                            sequence                    */
1639 /*    return_bracket_pair                   Buffer to load bracket pair   */
1640 /*                                            list                        */
1641 /*    return_pair_count                     Buffer to load the number of  */
1642 /*                                            bracket pair characters     */
1643 /*                                                                        */
1644 /*  OUTPUT                                                                */
1645 /*                                                                        */
1646 /*    status                                Completion status             */
1647 /*                                                                        */
1648 /*  CALLS                                                                 */
1649 /*                                                                        */
1650 /*    None                                                                */
1651 /*                                                                        */
1652 /*  CALLED BY                                                             */
1653 /*                                                                        */
1654 /*    _gx_utility_bidi_neutral_type_resolve_0                             */
1655 /*                                                                        */
1656 /*  RELEASE HISTORY                                                       */
1657 /*                                                                        */
1658 /*    DATE              NAME                      DESCRIPTION             */
1659 /*                                                                        */
1660 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
1661 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
1662 /*                                            resulting in version 6.1    */
1663 /*                                                                        */
1664 /**************************************************************************/
_gx_utility_bidi_bracket_pair_search(GX_BIDI_CONTEXT * context,GX_BIDI_ISOLATE_RUN * entry,INT ** return_bracket_pair,INT * return_pair_count)1665 static UINT _gx_utility_bidi_bracket_pair_search(GX_BIDI_CONTEXT *context, GX_BIDI_ISOLATE_RUN *entry, INT **return_bracket_pair, INT *return_pair_count)
1666 {
1667 ULONG               *stack;
1668 ULONG               *bracket_entry;
1669 ULONG               *last_bracket_entry = GX_NULL;
1670 INT                  top = 0;
1671 INT                  run_index;
1672 INT                  text_index;
1673 ULONG                character;
1674 INT                 *bracket_pair = *return_bracket_pair;
1675 INT                  bracket_pair_count = 0;
1676 GX_BIDI_BRACKET_PAIR pair;
1677 UINT                 buffer_index;
1678 INT                  depth;
1679 INT                  temp = 0;
1680 GX_BIDI_UNIT        *unit;
1681 
1682     stack = (ULONG *)(context -> gx_bidi_context_buffer + context -> gx_bidi_context_buffer_index);
1683     buffer_index = context -> gx_bidi_context_buffer_index;
1684     bracket_entry = stack;
1685 
1686     for (run_index = 0; run_index < (INT)entry -> gx_bidi_isolate_run_index_count; run_index++)
1687     {
1688         text_index = entry -> gx_bidi_isolate_run_index_list[run_index];
1689         unit = &context -> gx_bidi_context_unit_list[text_index];
1690 
1691         if (unit -> gx_bidi_unit_type != GX_BIDI_CHARACTER_TYPE_ON)
1692         {
1693             continue;
1694         }
1695 
1696         character = unit -> gx_bidi_unit_code;
1697         _gx_utility_bidi_bracket_pair_get(character, &pair);
1698 
1699         if (character == pair.gx_bidi_bracket_pair_open)
1700         {
1701             if (top >= 63)
1702             {
1703                 /* Stop processing for the remainder to the isolating run sequence. */
1704                 break;
1705             }
1706 
1707             last_bracket_entry = bracket_entry;
1708             *bracket_entry = (ULONG)run_index;
1709             bracket_entry++;
1710             top++;
1711             buffer_index += (INT)(sizeof(ULONG));
1712             if (buffer_index > context -> gx_bidi_context_buffer_size)
1713             {
1714                 return GX_INVALID_MEMORY_SIZE;
1715             }
1716         }
1717         else if (last_bracket_entry && (character == pair.gx_bidi_bracket_pair_close))
1718         {
1719             depth = 0;
1720 
1721             while (top - depth > 0)
1722             {
1723                 text_index = entry -> gx_bidi_isolate_run_index_list[*(last_bracket_entry - depth)];
1724                 unit = &context -> gx_bidi_context_unit_list[text_index];
1725 
1726                 if (unit -> gx_bidi_unit_code == pair.gx_bidi_bracket_pair_open ||
1727                     (unit -> gx_bidi_unit_code == 0x2329 && pair.gx_bidi_bracket_pair_open == 0x3008) ||
1728                     (unit -> gx_bidi_unit_code == 0x3008 && pair.gx_bidi_bracket_pair_open == 0x2329))
1729                 {
1730                     bracket_pair[bracket_pair_count++] = (INT)(*(last_bracket_entry - depth));
1731                     bracket_pair[bracket_pair_count++] = run_index;
1732                     depth++;
1733 
1734                     last_bracket_entry -= depth;
1735                     bracket_entry -= depth;
1736                     top -= depth;
1737                     buffer_index -= sizeof(ULONG) * (UINT)depth;
1738                     break;
1739                 }
1740                 depth++;
1741             }
1742         }
1743     }
1744 
1745     /* Sort list of pairs of text position in ascending order
1746        based on the text position of the openging paired bracket. */
1747     for (run_index = 0; run_index < bracket_pair_count - 2; run_index += 2)
1748     {
1749         for (text_index = run_index + 2; text_index < bracket_pair_count; text_index += 2)
1750         {
1751             if (bracket_pair[run_index] > bracket_pair[text_index])
1752             {
1753                 temp = bracket_pair[run_index];
1754                 bracket_pair[run_index] = bracket_pair[text_index];
1755                 bracket_pair[text_index] = temp;
1756 
1757                 temp = bracket_pair[run_index + 1];
1758                 bracket_pair[run_index + 1] = bracket_pair[text_index + 1];
1759                 bracket_pair[text_index + 1] = temp;
1760             }
1761         }
1762     }
1763 
1764     *return_pair_count = bracket_pair_count;
1765     return GX_SUCCESS;
1766 }
1767 
1768 /**************************************************************************/
1769 /*                                                                        */
1770 /*  FUNCTION                                               RELEASE        */
1771 /*                                                                        */
1772 /*    _gx_utility_bidi_neutral_type_resolve_0             PORTABLE C      */
1773 /*                                                           6.1          */
1774 /*  AUTHOR                                                                */
1775 /*                                                                        */
1776 /*    Kenneth Maxwell, Microsoft Corporation                              */
1777 /*                                                                        */
1778 /*  DESCRIPTION                                                           */
1779 /*                                                                        */
1780 /*    Internal helper function to apply rule 0 to neutral characters in an*/
1781 /*    isolate run sequence.                                               */
1782 /*                                                                        */
1783 /*  INPUT                                                                 */
1784 /*                                                                        */
1785 /*    context                               Bidi information control block*/
1786 /*    entry                                 Pointer to an isolate run     */
1787 /*                                            sequence                    */
1788 /*                                                                        */
1789 /*  OUTPUT                                                                */
1790 /*                                                                        */
1791 /*    status                                Completion status             */
1792 /*                                                                        */
1793 /*  CALLS                                                                 */
1794 /*                                                                        */
1795 /*    None                                                                */
1796 /*                                                                        */
1797 /*  CALLED BY                                                             */
1798 /*                                                                        */
1799 /*    _gx_utility_bidi_paragraph_reorder                                  */
1800 /*                                                                        */
1801 /*  RELEASE HISTORY                                                       */
1802 /*                                                                        */
1803 /*    DATE              NAME                      DESCRIPTION             */
1804 /*                                                                        */
1805 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
1806 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
1807 /*                                            resulting in version 6.1    */
1808 /*                                                                        */
1809 /**************************************************************************/
_gx_utility_bidi_neutral_type_resolve_0(GX_BIDI_CONTEXT * context,GX_BIDI_ISOLATE_RUN * entry)1810 static UINT _gx_utility_bidi_neutral_type_resolve_0(GX_BIDI_CONTEXT *context, GX_BIDI_ISOLATE_RUN *entry)
1811 {
1812 UINT          status;
1813 INT           index = 0;
1814 INT           start_index;
1815 INT           end_index;
1816 INT           text_index;
1817 INT          *bracket_pair;
1818 INT           bracket_pair_count = 0;
1819 GX_UBYTE      embedding_type;
1820 GX_UBYTE      oppsite_type;
1821 GX_UBYTE      type;
1822 GX_BOOL       bracket_type_changed;
1823 GX_BOOL       strong_type_found;
1824 GX_BIDI_UNIT *unit;
1825 
1826     if (!context -> gx_bidi_context_bracket_pair_size)
1827     {
1828         return GX_SUCCESS;
1829     }
1830 
1831     bracket_pair = (INT *)(context -> gx_bidi_context_buffer + context -> gx_bidi_context_buffer_index);
1832     context -> gx_bidi_context_buffer_index += context -> gx_bidi_context_bracket_pair_size;
1833 
1834     if (context -> gx_bidi_context_buffer_index > context -> gx_bidi_context_buffer_size)
1835     {
1836         return GX_INVALID_MEMORY_SIZE;
1837     }
1838 
1839     status = _gx_utility_bidi_bracket_pair_search(context, entry, &bracket_pair, &bracket_pair_count);
1840 
1841     if (status != GX_SUCCESS)
1842     {
1843         return GX_SUCCESS;
1844     }
1845 
1846     if (bracket_pair_count > 0)
1847     {
1848         text_index = entry -> gx_bidi_isolate_run_index_list[bracket_pair[0]];
1849         unit = &context -> gx_bidi_context_unit_list[text_index];
1850 
1851         if ((unit -> gx_bidi_unit_level & 0x01) == 0)
1852         {
1853             embedding_type = GX_BIDI_CHARACTER_TYPE_L;
1854             oppsite_type = GX_BIDI_CHARACTER_TYPE_R;
1855         }
1856         else
1857         {
1858             embedding_type = GX_BIDI_CHARACTER_TYPE_R;
1859             oppsite_type = GX_BIDI_CHARACTER_TYPE_L;
1860         }
1861     }
1862 
1863     for (index = 0; index < bracket_pair_count; index += 2)
1864     {
1865         strong_type_found = GX_FALSE;
1866         bracket_type_changed = GX_FALSE;
1867         for (start_index = bracket_pair[index] + 1; start_index < bracket_pair[index + 1]; start_index++)
1868         {
1869             text_index = entry -> gx_bidi_isolate_run_index_list[start_index];
1870             unit = &context -> gx_bidi_context_unit_list[text_index];
1871 
1872             type = unit -> gx_bidi_unit_type;
1873 
1874             if (type == GX_BIDI_CHARACTER_TYPE_EN ||
1875                 type == GX_BIDI_CHARACTER_TYPE_AN)
1876             {
1877                 /* Within this scope, bidirectional types EN and AN are treated as R. */
1878                 type = GX_BIDI_CHARACTER_TYPE_R;
1879             }
1880 
1881             if (type == GX_BIDI_CHARACTER_TYPE_L ||
1882                 type == GX_BIDI_CHARACTER_TYPE_R)
1883             {
1884                 /* If any strong type (either L or R) matching the embedding direction is found,
1885                    set the type for both brackets in the pair to match the embedding direction. */
1886                 strong_type_found = GX_TRUE;
1887 
1888                 if (type == embedding_type)
1889                 {
1890                     bracket_type_changed = GX_TRUE;
1891 
1892                     text_index = entry -> gx_bidi_isolate_run_index_list[bracket_pair[index]];
1893                     unit = &context -> gx_bidi_context_unit_list[text_index];
1894                     unit -> gx_bidi_unit_type = embedding_type;
1895 
1896                     text_index = entry -> gx_bidi_isolate_run_index_list[bracket_pair[index + 1]];
1897                     unit = &context -> gx_bidi_context_unit_list[text_index];
1898                     unit -> gx_bidi_unit_type = embedding_type;
1899                     break;
1900                 }
1901             }
1902         }
1903 
1904         if (!bracket_type_changed)
1905         {
1906             if (strong_type_found)
1907             {
1908                 bracket_type_changed = GX_TRUE;
1909 
1910                 end_index = bracket_pair[index] - 1;
1911                 strong_type_found = GX_FALSE;
1912                 while (end_index >= 0)
1913                 {
1914                     text_index = entry -> gx_bidi_isolate_run_index_list[end_index];
1915                     unit = &context -> gx_bidi_context_unit_list[text_index];
1916 
1917                     /* Search baackward until first strong type is found. */
1918                     type = unit -> gx_bidi_unit_type;
1919 
1920                     if (type == GX_BIDI_CHARACTER_TYPE_EN ||
1921                         type == GX_BIDI_CHARACTER_TYPE_AN)
1922                     {
1923                         /* Within this scope, bidirectional types EN and AN are treated as R. */
1924                         type = GX_BIDI_CHARACTER_TYPE_R;
1925                     }
1926 
1927                     if (type == GX_BIDI_CHARACTER_TYPE_R ||
1928                         type == GX_BIDI_CHARACTER_TYPE_L)
1929                     {
1930                         strong_type_found = GX_TRUE;
1931                         break;
1932                     }
1933 
1934                     end_index--;
1935                 }
1936 
1937                 if (!strong_type_found)
1938                 {
1939                     type = entry -> gx_bidi_isolate_run_sos;
1940                 }
1941 
1942                 if (type != oppsite_type)
1943                 {
1944                     type = embedding_type;
1945                 }
1946 
1947                 text_index = entry -> gx_bidi_isolate_run_index_list[bracket_pair[index]];
1948                 unit = &context -> gx_bidi_context_unit_list[text_index];
1949                 unit -> gx_bidi_unit_type = type;
1950 
1951                 text_index = entry -> gx_bidi_isolate_run_index_list[bracket_pair[index + 1]];
1952                 unit = &context -> gx_bidi_context_unit_list[text_index];
1953                 unit -> gx_bidi_unit_type = type;
1954             }
1955         }
1956 
1957         if (bracket_type_changed)
1958         {
1959             /* Any number of characters that had original bidirectional character type NSM that immediately follow a
1960                paired bracket which changed to L or R under N0 should change to match the type of their preceding bracket.*/
1961             start_index = bracket_pair[index] + 1;
1962             while (start_index < bracket_pair[index + 1])
1963             {
1964                 end_index = entry -> gx_bidi_isolate_run_index_list[start_index];
1965                 unit = &context -> gx_bidi_context_unit_list[end_index];
1966 
1967                 if (unit -> gx_bidi_unit_org_type == GX_BIDI_CHARACTER_TYPE_NSM)
1968                 {
1969                     unit -> gx_bidi_unit_type = type;
1970                 }
1971                 else
1972                 {
1973                     break;
1974                 }
1975                 start_index++;
1976             }
1977 
1978             start_index = bracket_pair[index + 1] + 1;
1979             while (start_index < (INT)entry -> gx_bidi_isolate_run_index_count)
1980             {
1981                 text_index = entry -> gx_bidi_isolate_run_index_list[start_index];
1982                 unit = &context -> gx_bidi_context_unit_list[text_index];
1983 
1984                 if (unit -> gx_bidi_unit_org_type == GX_BIDI_CHARACTER_TYPE_NSM)
1985                 {
1986                     unit -> gx_bidi_unit_type = type;
1987                 }
1988                 else
1989                 {
1990                     break;
1991                 }
1992                 start_index++;
1993             }
1994         }
1995     }
1996 
1997     context -> gx_bidi_context_buffer_index -= context -> gx_bidi_context_bracket_pair_size;
1998 
1999     return GX_SUCCESS;
2000 }
2001 
2002 /**************************************************************************/
2003 /*                                                                        */
2004 /*  FUNCTION                                               RELEASE        */
2005 /*                                                                        */
2006 /*    _gx_utility_bidi_neutral_type_resolve_1             PORTABLE C      */
2007 /*                                                           6.1          */
2008 /*  AUTHOR                                                                */
2009 /*                                                                        */
2010 /*    Kenneth Maxwell, Microsoft Corporation                              */
2011 /*                                                                        */
2012 /*  DESCRIPTION                                                           */
2013 /*                                                                        */
2014 /*    Internal helper function to apply rule 1 to neutral characters in an*/
2015 /*    isolate run sequence.                                               */
2016 /*                                                                        */
2017 /*  INPUT                                                                 */
2018 /*                                                                        */
2019 /*    context                               Bidi information control block*/
2020 /*    entry                                 Pointer to an isolate run     */
2021 /*                                            sequence                    */
2022 /*                                                                        */
2023 /*  OUTPUT                                                                */
2024 /*                                                                        */
2025 /*    status                                Completion status             */
2026 /*                                                                        */
2027 /*  CALLS                                                                 */
2028 /*                                                                        */
2029 /*    None                                                                */
2030 /*                                                                        */
2031 /*  CALLED BY                                                             */
2032 /*                                                                        */
2033 /*    _gx_utility_bidi_paragraph_reorder                                  */
2034 /*                                                                        */
2035 /*  RELEASE HISTORY                                                       */
2036 /*                                                                        */
2037 /*    DATE              NAME                      DESCRIPTION             */
2038 /*                                                                        */
2039 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
2040 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
2041 /*                                            resulting in version 6.1    */
2042 /*                                                                        */
2043 /**************************************************************************/
_gx_utility_bidi_neutral_type_resolve_1(GX_BIDI_CONTEXT * context,GX_BIDI_ISOLATE_RUN * entry)2044 static UINT _gx_utility_bidi_neutral_type_resolve_1(GX_BIDI_CONTEXT *context, GX_BIDI_ISOLATE_RUN *entry)
2045 {
2046 INT      run_index;
2047 INT      start_index = 0;
2048 INT      text_index;
2049 GX_UBYTE pre_type = entry -> gx_bidi_isolate_run_sos;
2050 GX_UBYTE follow_type;
2051 GX_UBYTE type;
2052 
2053     /* A sequence of NIs takes the direction of the surrounding strong text if the text
2054        on both sides has the same direction. */
2055     for (run_index = 0; run_index <= (INT)entry -> gx_bidi_isolate_run_index_count; run_index++)
2056     {
2057         if (run_index < (INT)entry -> gx_bidi_isolate_run_index_count)
2058         {
2059             text_index = entry -> gx_bidi_isolate_run_index_list[run_index];
2060             type = context -> gx_bidi_context_unit_list[text_index].gx_bidi_unit_type;
2061         }
2062         else
2063         {
2064             type = entry -> gx_bidi_isolate_run_eos;
2065         }
2066 
2067         switch (type)
2068         {
2069         case GX_BIDI_CHARACTER_TYPE_B:
2070         case GX_BIDI_CHARACTER_TYPE_S:
2071         case GX_BIDI_CHARACTER_TYPE_WS:
2072         case GX_BIDI_CHARACTER_TYPE_ON:
2073         case GX_BIDI_CHARACTER_TYPE_FSI:
2074         case GX_BIDI_CHARACTER_TYPE_LRI:
2075         case GX_BIDI_CHARACTER_TYPE_RLI:
2076         case GX_BIDI_CHARACTER_TYPE_PDI:
2077             break;
2078 
2079         default:
2080             follow_type = type;
2081 
2082             if (follow_type == GX_BIDI_CHARACTER_TYPE_EN ||
2083                 follow_type == GX_BIDI_CHARACTER_TYPE_AN)
2084             {
2085                 follow_type = GX_BIDI_CHARACTER_TYPE_R;
2086             }
2087 
2088             if (pre_type == follow_type)
2089             {
2090                 while (start_index < run_index)
2091                 {
2092                     text_index = entry -> gx_bidi_isolate_run_index_list[start_index];
2093 
2094                     context -> gx_bidi_context_unit_list[text_index].gx_bidi_unit_type = pre_type;
2095                     start_index++;
2096                 }
2097             }
2098             pre_type = follow_type;
2099             start_index = run_index + 1;
2100             break;
2101         }
2102     }
2103 
2104     return GX_SUCCESS;
2105 }
2106 
2107 /**************************************************************************/
2108 /*                                                                        */
2109 /*  FUNCTION                                               RELEASE        */
2110 /*                                                                        */
2111 /*    _gx_utility_bidi_neutral_type_resolve_2             PORTABLE C      */
2112 /*                                                           6.1          */
2113 /*  AUTHOR                                                                */
2114 /*                                                                        */
2115 /*    Kenneth Maxwell, Microsoft Corporation                              */
2116 /*                                                                        */
2117 /*  DESCRIPTION                                                           */
2118 /*                                                                        */
2119 /*    Internal helper function to apply rule 2 to neutral characters in an*/
2120 /*    isolate run sequence.                                               */
2121 /*                                                                        */
2122 /*  INPUT                                                                 */
2123 /*                                                                        */
2124 /*    context                               Bidi information control block*/
2125 /*    entry                                 Pointer to an isolate run     */
2126 /*                                            sequence                    */
2127 /*                                                                        */
2128 /*  OUTPUT                                                                */
2129 /*                                                                        */
2130 /*    status                                Completion status             */
2131 /*                                                                        */
2132 /*  CALLS                                                                 */
2133 /*                                                                        */
2134 /*    None                                                                */
2135 /*                                                                        */
2136 /*  CALLED BY                                                             */
2137 /*                                                                        */
2138 /*    _gx_utility_bidi_paragraph_reorder                                  */
2139 /*                                                                        */
2140 /*  RELEASE HISTORY                                                       */
2141 /*                                                                        */
2142 /*    DATE              NAME                      DESCRIPTION             */
2143 /*                                                                        */
2144 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
2145 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
2146 /*                                            resulting in version 6.1    */
2147 /*                                                                        */
2148 /**************************************************************************/
_gx_utility_bidi_neutral_type_resolve_2(GX_BIDI_CONTEXT * context,GX_BIDI_ISOLATE_RUN * entry)2149 static UINT _gx_utility_bidi_neutral_type_resolve_2(GX_BIDI_CONTEXT *context, GX_BIDI_ISOLATE_RUN *entry)
2150 {
2151 INT           run_index = 0;
2152 INT           text_index;
2153 GX_BIDI_UNIT *unit;
2154 
2155     /* Any remaining NIs take the embedding direction. */
2156     for (run_index = 0; run_index < entry -> gx_bidi_isolate_run_index_count; run_index++)
2157     {
2158         text_index = entry -> gx_bidi_isolate_run_index_list[run_index];
2159         unit = &context -> gx_bidi_context_unit_list[text_index];
2160 
2161         switch (unit -> gx_bidi_unit_type)
2162         {
2163         case GX_BIDI_CHARACTER_TYPE_B:
2164         case GX_BIDI_CHARACTER_TYPE_S:
2165         case GX_BIDI_CHARACTER_TYPE_WS:
2166         case GX_BIDI_CHARACTER_TYPE_ON:
2167         case GX_BIDI_CHARACTER_TYPE_FSI:
2168         case GX_BIDI_CHARACTER_TYPE_LRI:
2169         case GX_BIDI_CHARACTER_TYPE_RLI:
2170         case GX_BIDI_CHARACTER_TYPE_PDI:
2171             if ((unit -> gx_bidi_unit_level & 0x01) == 0)
2172             {
2173                 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_L;
2174             }
2175             else
2176             {
2177                 unit -> gx_bidi_unit_type = GX_BIDI_CHARACTER_TYPE_R;
2178             }
2179             break;
2180         }
2181     }
2182 
2183     return GX_SUCCESS;
2184 }
2185 
2186 /**************************************************************************/
2187 /*                                                                        */
2188 /*  FUNCTION                                               RELEASE        */
2189 /*                                                                        */
2190 /*    _gx_utility_bidi_implicit_level_resolve             PORTABLE C      */
2191 /*                                                           6.1          */
2192 /*  AUTHOR                                                                */
2193 /*                                                                        */
2194 /*    Kenneth Maxwell, Microsoft Corporation                              */
2195 /*                                                                        */
2196 /*  DESCRIPTION                                                           */
2197 /*                                                                        */
2198 /*    Internal helper function to increase the embedding level of text    */
2199 /*    based on the resolved character type.                               */
2200 /*                                                                        */
2201 /*  INPUT                                                                 */
2202 /*                                                                        */
2203 /*    context                               Bidi information control block*/
2204 /*    entry                                 Pointer to an isolate run     */
2205 /*                                            sequence                    */
2206 /*                                                                        */
2207 /*  OUTPUT                                                                */
2208 /*                                                                        */
2209 /*    status                                Completion status             */
2210 /*                                                                        */
2211 /*  CALLS                                                                 */
2212 /*                                                                        */
2213 /*    None                                                                */
2214 /*                                                                        */
2215 /*  CALLED BY                                                             */
2216 /*                                                                        */
2217 /*    _gx_utility_bidi_paragraph_reorder                                  */
2218 /*                                                                        */
2219 /*  RELEASE HISTORY                                                       */
2220 /*                                                                        */
2221 /*    DATE              NAME                      DESCRIPTION             */
2222 /*                                                                        */
2223 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
2224 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
2225 /*                                            resulting in version 6.1    */
2226 /*                                                                        */
2227 /**************************************************************************/
_gx_utility_bidi_implicit_level_resolve(GX_BIDI_CONTEXT * context,GX_BIDI_ISOLATE_RUN * entry)2228 static UINT _gx_utility_bidi_implicit_level_resolve(GX_BIDI_CONTEXT *context, GX_BIDI_ISOLATE_RUN *entry)
2229 {
2230 INT           run_index;
2231 INT           text_index;
2232 GX_BIDI_UNIT *unit;
2233 
2234     /* Any remaining NIs take the embedding direction. */
2235     for (run_index = 0; run_index < entry -> gx_bidi_isolate_run_index_count; run_index++)
2236     {
2237         text_index = entry -> gx_bidi_isolate_run_index_list[run_index];
2238         unit = &context -> gx_bidi_context_unit_list[text_index];
2239 
2240         if ((unit -> gx_bidi_unit_level & 0x01) == 0)
2241         {
2242             /* For all characers with an even embedding level,
2243                 those of type R go up ove level and those of type AN or EN go up two levels. */
2244             switch (unit -> gx_bidi_unit_type)
2245             {
2246             case GX_BIDI_CHARACTER_TYPE_R:
2247                 unit -> gx_bidi_unit_level++;
2248                 break;
2249 
2250             case GX_BIDI_CHARACTER_TYPE_AN:
2251             case GX_BIDI_CHARACTER_TYPE_EN:
2252                 unit -> gx_bidi_unit_level = (GX_UBYTE)(unit -> gx_bidi_unit_level + 2);
2253                 break;
2254             }
2255         }
2256 
2257         if ((unit -> gx_bidi_unit_level & 0x01) == 1)
2258         {
2259             /* For all characers with an odd embedding level,
2260                 those of type L, EN and AN go up ove level. */
2261             switch (unit -> gx_bidi_unit_type)
2262             {
2263             case GX_BIDI_CHARACTER_TYPE_L:
2264             case GX_BIDI_CHARACTER_TYPE_EN:
2265             case GX_BIDI_CHARACTER_TYPE_AN:
2266                 unit -> gx_bidi_unit_level++;
2267                 break;
2268             }
2269         }
2270     }
2271 
2272     return GX_SUCCESS;
2273 }
2274 
2275 /**************************************************************************/
2276 /*                                                                        */
2277 /*  FUNCTION                                               RELEASE        */
2278 /*                                                                        */
2279 /*    _gx_utility_bidi_isolate_run_sequences_resolve      PORTABLE C      */
2280 /*                                                           6.1          */
2281 /*  AUTHOR                                                                */
2282 /*                                                                        */
2283 /*    Kenneth Maxwell, Microsoft Corporation                              */
2284 /*                                                                        */
2285 /*  DESCRIPTION                                                           */
2286 /*                                                                        */
2287 /*    Internal helper function to determine the embedding levels of the   */
2288 /*    text.                                                               */
2289 /*                                                                        */
2290 /*  INPUT                                                                 */
2291 /*                                                                        */
2292 /*    context                               Bidi information control block*/
2293 /*                                                                        */
2294 /*  OUTPUT                                                                */
2295 /*                                                                        */
2296 /*    status                                Completion status             */
2297 /*                                                                        */
2298 /*  CALLS                                                                 */
2299 /*                                                                        */
2300 /*    None                                                                */
2301 /*                                                                        */
2302 /*  CALLED BY                                                             */
2303 /*                                                                        */
2304 /*    _gx_utility_bidi_paragraph_reorder                                  */
2305 /*                                                                        */
2306 /*  RELEASE HISTORY                                                       */
2307 /*                                                                        */
2308 /*    DATE              NAME                      DESCRIPTION             */
2309 /*                                                                        */
2310 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
2311 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
2312 /*                                            resulting in version 6.1    */
2313 /*                                                                        */
2314 /**************************************************************************/
_gx_utility_bidi_isolate_run_sequences_resolve(GX_BIDI_CONTEXT * context)2315 static UINT _gx_utility_bidi_isolate_run_sequences_resolve(GX_BIDI_CONTEXT *context)
2316 {
2317 UINT                 status = GX_SUCCESS;
2318 
2319 GX_BIDI_ISOLATE_RUN *entry = context -> gx_bidi_context_isolate_runs;
2320 
2321     while (entry)
2322     {
2323         status = _gx_utility_bidi_weak_type_resolve_1(context, entry);
2324 
2325         if (status != GX_SUCCESS)
2326         {
2327             break;
2328         }
2329 
2330         status = _gx_utility_bidi_weak_type_resolve_2_3(context, entry);
2331 
2332         if (status != GX_SUCCESS)
2333         {
2334             break;
2335         }
2336         status = _gx_utility_bidi_weak_type_resolve_4(context, entry);
2337 
2338         if (status != GX_SUCCESS)
2339         {
2340             break;
2341         }
2342         status = _gx_utility_bidi_weak_type_resolve_5(context, entry);
2343 
2344         if (status != GX_SUCCESS)
2345         {
2346             break;
2347         }
2348         status = _gx_utility_bidi_weak_type_resolve_6(context, entry);
2349 
2350         if (status != GX_SUCCESS)
2351         {
2352             break;
2353         }
2354 
2355         status = _gx_utility_bidi_weak_type_resolve_7(context, entry);
2356 
2357         if (status != GX_SUCCESS)
2358         {
2359             break;
2360         }
2361 
2362         /* Process bracket pairs. */
2363         status = _gx_utility_bidi_neutral_type_resolve_0(context, entry);
2364 
2365         if (status != GX_SUCCESS)
2366         {
2367             break;
2368         }
2369 
2370         status = _gx_utility_bidi_neutral_type_resolve_1(context, entry);
2371 
2372         if (status != GX_SUCCESS)
2373         {
2374             break;
2375         }
2376 
2377         status = _gx_utility_bidi_neutral_type_resolve_2(context, entry);
2378 
2379         if (status != GX_SUCCESS)
2380         {
2381             break;
2382         }
2383 
2384         status = _gx_utility_bidi_implicit_level_resolve(context, entry);
2385 
2386         if (status != GX_SUCCESS)
2387         {
2388             break;
2389         }
2390 
2391         entry = entry -> gx_bidi_isolate_run_next;
2392     }
2393 
2394     return status;
2395 }
2396 
2397 /**************************************************************************/
2398 /*                                                                        */
2399 /*  FUNCTION                                               RELEASE        */
2400 /*                                                                        */
2401 /*    _gx_utility_bidi_reordering_resolve_1               PORTABLE C      */
2402 /*                                                           6.1.9        */
2403 /*  AUTHOR                                                                */
2404 /*                                                                        */
2405 /*    Kenneth Maxwell, Microsoft Corporation                              */
2406 /*                                                                        */
2407 /*  DESCRIPTION                                                           */
2408 /*                                                                        */
2409 /*    Internal helper function to reset the embedding level of some       */
2410 /*    characters in specified text block.                                 */
2411 /*                                                                        */
2412 /*  INPUT                                                                 */
2413 /*                                                                        */
2414 /*    context                               Bidi information control block*/
2415 /*                                                                        */
2416 /*  OUTPUT                                                                */
2417 /*                                                                        */
2418 /*    status                                Completion status             */
2419 /*    start_index                           Start index of the text block */
2420 /*    end_index                             End index of the text block   */
2421 /*                                                                        */
2422 /*  CALLS                                                                 */
2423 /*                                                                        */
2424 /*    None                                                                */
2425 /*                                                                        */
2426 /*  CALLED BY                                                             */
2427 /*                                                                        */
2428 /*    _gx_utility_bidi_paragraph_reorder                                  */
2429 /*                                                                        */
2430 /*  RELEASE HISTORY                                                       */
2431 /*                                                                        */
2432 /*    DATE              NAME                      DESCRIPTION             */
2433 /*                                                                        */
2434 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
2435 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
2436 /*                                            resulting in version 6.1    */
2437 /*  10-15-2021     Kenneth Maxwell          Modified comment(s),          */
2438 /*                                            corrected logic,            */
2439 /*                                            resulting in version 6.1.9  */
2440 /*                                                                        */
2441 /**************************************************************************/
_gx_utility_bidi_reordering_resolve_1(GX_BIDI_CONTEXT * context,INT start_index,INT end_index)2442 static UINT _gx_utility_bidi_reordering_resolve_1(GX_BIDI_CONTEXT *context, INT start_index, INT end_index)
2443 {
2444 INT           index;
2445 INT           pre_index;
2446 GX_BOOL       check_before;
2447 GX_BIDI_UNIT *unit;
2448 GX_BIDI_UNIT *pre_unit;
2449 USHORT        mirror;
2450 
2451     for (index = start_index; index <= end_index; index++)
2452     {
2453         check_before = GX_FALSE;
2454         unit = &context -> gx_bidi_context_unit_list[index];
2455 
2456         switch (unit -> gx_bidi_unit_org_type)
2457         {
2458         case GX_BIDI_CHARACTER_TYPE_S:
2459         case GX_BIDI_CHARACTER_TYPE_B:
2460             /* Reset segment separators and paragraph separators to the paragraph embedding level. */
2461             unit -> gx_bidi_unit_level = context -> gx_bidi_context_base_level;
2462             check_before = GX_TRUE;
2463             break;
2464 
2465         default:
2466             if (index == context -> gx_bidi_context_unit_count - 1)
2467             {
2468                 index = context -> gx_bidi_context_unit_count;
2469                 check_before = GX_TRUE;
2470             }
2471             break;
2472         }
2473 
2474         if (check_before)
2475         {
2476             /* Any sequence of whitespace or isolate formatting characters preceding a
2477                segment/paragraph separator or at the end of the text, reset to paragraph level. */
2478             pre_index = index - 1;
2479             pre_unit = &context -> gx_bidi_context_unit_list[pre_index];
2480             while (pre_index >= 0)
2481             {
2482                 if (pre_unit -> gx_bidi_unit_type == GX_BIDI_CHARACTER_TYPE_BN)
2483                 {
2484                     pre_index--;
2485                     pre_unit--;
2486                     continue;
2487                 }
2488 
2489                 switch (pre_unit -> gx_bidi_unit_org_type)
2490                 {
2491                 case GX_BIDI_CHARACTER_TYPE_WS:
2492                 case GX_BIDI_CHARACTER_TYPE_FSI:
2493                 case GX_BIDI_CHARACTER_TYPE_LRI:
2494                 case GX_BIDI_CHARACTER_TYPE_RLI:
2495                 case GX_BIDI_CHARACTER_TYPE_PDI:
2496                     pre_unit -> gx_bidi_unit_level = context -> gx_bidi_context_base_level;
2497                     break;
2498 
2499                 default:
2500                     pre_index = -1;
2501                     break;
2502                 }
2503                 pre_index--;
2504                 pre_unit--;
2505             }
2506         }
2507 
2508         if (unit -> gx_bidi_unit_type == GX_BIDI_CHARACTER_TYPE_R &&
2509             unit -> gx_bidi_unit_code < 0xffff)
2510         {
2511             /* Mirror */
2512             _gx_utility_bidi_mirroring_get((USHORT)unit -> gx_bidi_unit_code, &mirror);
2513 
2514             if (mirror)
2515             {
2516                 unit -> gx_bidi_unit_code = mirror;
2517             }
2518         }
2519     }
2520     return GX_SUCCESS;
2521 }
2522 
2523 /**************************************************************************/
2524 /*                                                                        */
2525 /*  FUNCTION                                               RELEASE        */
2526 /*                                                                        */
2527 /*    _gx_utility_bidi_reordering_resolve_2               PORTABLE C      */
2528 /*                                                           6.1          */
2529 /*  AUTHOR                                                                */
2530 /*                                                                        */
2531 /*    Kenneth Maxwell, Microsoft Corporation                              */
2532 /*                                                                        */
2533 /*  DESCRIPTION                                                           */
2534 /*                                                                        */
2535 /*    Internal helper function to reverse text for the specified text     */
2536 /*    block.                                                              */
2537 /*                                                                        */
2538 /*  INPUT                                                                 */
2539 /*                                                                        */
2540 /*    context                               Bidi information control block*/
2541 /*                                                                        */
2542 /*  OUTPUT                                                                */
2543 /*                                                                        */
2544 /*    status                                Completion status             */
2545 /*    start_index                           Start index of the text block */
2546 /*    end_index                             End index of the text block   */
2547 /*                                                                        */
2548 /*  CALLS                                                                 */
2549 /*                                                                        */
2550 /*    None                                                                */
2551 /*                                                                        */
2552 /*  CALLED BY                                                             */
2553 /*                                                                        */
2554 /*    _gx_utility_bidi_paragraph_reorder                                  */
2555 /*                                                                        */
2556 /*  RELEASE HISTORY                                                       */
2557 /*                                                                        */
2558 /*    DATE              NAME                      DESCRIPTION             */
2559 /*                                                                        */
2560 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
2561 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
2562 /*                                            resulting in version 6.1    */
2563 /*                                                                        */
2564 /**************************************************************************/
_gx_utility_bidi_reordering_resolve_2(GX_BIDI_CONTEXT * context,INT start_index,INT end_index)2565 static UINT _gx_utility_bidi_reordering_resolve_2(GX_BIDI_CONTEXT *context, INT start_index, INT end_index)
2566 {
2567 INT                max_level;
2568 INT                min_level;
2569 INT                level;
2570 INT                index;
2571 INT                run_start_index;
2572 INT                run_end_index;
2573 GX_BIDI_LEVEL_RUN *entry;
2574 GX_BIDI_LEVEL_RUN *next_entry;
2575 GX_BIDI_UNIT      *unit;
2576 GX_BIDI_UNIT      *tail_unit;
2577 GX_BIDI_UNIT       temp;
2578 INT                count;
2579 
2580     _gx_utility_bidi_level_runs_compute(context, start_index, end_index);
2581 
2582     /* Find max level. */
2583     entry = context -> gx_bidi_context_level_runs;
2584     if (entry)
2585     {
2586         unit = &context -> gx_bidi_context_unit_list[entry -> gx_bidi_level_run_start_index];
2587         max_level = unit -> gx_bidi_unit_level;
2588         min_level = max_level;
2589         entry = entry -> gx_bidi_level_run_next;
2590     }
2591 
2592     while (entry)
2593     {
2594         unit = &context -> gx_bidi_context_unit_list[entry -> gx_bidi_level_run_start_index];
2595 
2596         if (unit -> gx_bidi_unit_level > max_level)
2597         {
2598             max_level = unit -> gx_bidi_unit_level;
2599         }
2600         else if (unit -> gx_bidi_unit_level < min_level)
2601         {
2602             min_level = unit -> gx_bidi_unit_level;
2603         }
2604         entry = entry -> gx_bidi_level_run_next;
2605     }
2606 
2607     if ((min_level & 0x01) == 0)
2608     {
2609         min_level += 1;
2610     }
2611 
2612     /* From highest level, reverse any contiguous sequence of characters that are at that level or higher. */
2613     for (level = max_level; level >= min_level; level--)
2614     {
2615         entry = context -> gx_bidi_context_level_runs;
2616 
2617         while (entry)
2618         {
2619             run_start_index = entry -> gx_bidi_level_run_start_index;
2620             run_end_index = entry -> gx_bidi_level_run_end_index;
2621 
2622             next_entry = entry -> gx_bidi_level_run_next;
2623             unit = &context -> gx_bidi_context_unit_list[run_start_index];
2624 
2625             if (unit -> gx_bidi_unit_level >= level)
2626             {
2627                 while (next_entry &&
2628                        context -> gx_bidi_context_unit_list[next_entry -> gx_bidi_level_run_start_index].gx_bidi_unit_level >= level)
2629                 {
2630                     run_end_index = next_entry -> gx_bidi_level_run_end_index;
2631                     next_entry = next_entry -> gx_bidi_level_run_next;
2632                 }
2633 
2634                 count = (run_end_index - run_start_index + 1) >> 1;
2635 
2636                 /* Reverse characters. */
2637                 unit = &context -> gx_bidi_context_unit_list[run_start_index];
2638                 tail_unit = &context -> gx_bidi_context_unit_list[run_end_index];
2639 
2640                 for (index = 0; index < count; index++)
2641                 {
2642                     temp = *unit;
2643                     *unit = *tail_unit;
2644                     *tail_unit = temp;
2645 
2646                     unit++;
2647                     tail_unit--;
2648                 }
2649             }
2650             entry = next_entry;
2651         }
2652     }
2653 
2654     context -> gx_bidi_context_buffer_index -= sizeof(GX_BIDI_LEVEL_RUN) * (UINT)context -> gx_bidi_context_unit_count;
2655 
2656     return GX_SUCCESS;
2657 }
2658 
2659 /**************************************************************************/
2660 /*                                                                        */
2661 /*  FUNCTION                                               RELEASE        */
2662 /*                                                                        */
2663 /*    _gx_utility_bidi_line_break                         PORTABLE C      */
2664 /*                                                           6.1          */
2665 /*  AUTHOR                                                                */
2666 /*                                                                        */
2667 /*    Kenneth Maxwell, Microsoft Corporation                              */
2668 /*                                                                        */
2669 /*  DESCRIPTION                                                           */
2670 /*                                                                        */
2671 /*    Internal helper function to break text into lines.                  */
2672 /*                                                                        */
2673 /*  INPUT                                                                 */
2674 /*                                                                        */
2675 /*    context                               Bidi information control block*/
2676 /*                                                                        */
2677 /*  OUTPUT                                                                */
2678 /*                                                                        */
2679 /*    status                                Completion status             */
2680 /*                                                                        */
2681 /*  CALLS                                                                 */
2682 /*                                                                        */
2683 /*    None                                                                */
2684 /*                                                                        */
2685 /*  CALLED BY                                                             */
2686 /*                                                                        */
2687 /*    _gx_utility_bidi_paragraph_reorder                                  */
2688 /*                                                                        */
2689 /*  RELEASE HISTORY                                                       */
2690 /*                                                                        */
2691 /*    DATE              NAME                      DESCRIPTION             */
2692 /*                                                                        */
2693 /*  09-30-2020     Kenneth Maxwell          Initial Version 6.1           */
2694 /*                                                                        */
2695 /**************************************************************************/
_gx_utility_bidi_line_break(GX_BIDI_CONTEXT * context)2696 static UINT _gx_utility_bidi_line_break(GX_BIDI_CONTEXT *context)
2697 {
2698 GX_BIDI_TEXT_INFO *input_info = context -> gx_bidi_context_input_info;
2699 INT                index = 0;
2700 GX_STRING          ch;
2701 UINT               glyph_len;
2702 GX_VALUE           glyph_width;
2703 UINT               line = 0;
2704 GX_BIDI_UNIT      *unit;
2705 GX_UBYTE           utf8[6];
2706 INT                display_number = 0;
2707 INT                display_width = 0;
2708 INT                line_break_display_number = 0;
2709 INT                line_break_display_width = 0;
2710 INT                line_index = -1;
2711 
2712     unit = context -> gx_bidi_context_unit_list;
2713 
2714     if ((!input_info -> gx_bidi_text_info_font) || (input_info -> gx_bidi_text_info_display_width <= 0))
2715     {
2716         context -> gx_bidi_context_total_lines = 1;
2717         return GX_SUCCESS;
2718     }
2719 
2720     context -> gx_bidi_context_line_index_cache = (INT *)(context -> gx_bidi_context_buffer + context -> gx_bidi_context_buffer_index);
2721     context -> gx_bidi_context_line_index_cache[0] = 0;
2722 
2723     for (index = 0; index < context -> gx_bidi_context_unit_count; index++)
2724     {
2725         _gx_utility_unicode_to_utf8(unit -> gx_bidi_unit_code, utf8, &glyph_len);
2726 
2727         ch.gx_string_ptr = (GX_CHAR *)utf8;
2728         ch.gx_string_length = glyph_len;
2729         _gx_system_string_width_get_ext(input_info -> gx_bidi_text_info_font, &ch, &glyph_width);
2730 
2731         if ((display_width + glyph_width > input_info -> gx_bidi_text_info_display_width) &&
2732             (display_number > 0) &&
2733             (ch.gx_string_ptr[0] != ' '))
2734         {
2735             /* Breadk line. */
2736             if (line_break_display_number)
2737             {
2738                 line_index += line_break_display_number;
2739                 display_number -= line_break_display_number;
2740                 display_width -= line_break_display_width;
2741             }
2742             else
2743             {
2744                 line_index += display_number;
2745                 display_number = 0;
2746                 display_width = 0;
2747             }
2748 
2749             context -> gx_bidi_context_line_index_cache[line++] = line_index;
2750             line_break_display_number = 0;
2751             line_break_display_width = 0;
2752         }
2753 
2754         display_width += glyph_width;
2755         display_number++;
2756 
2757         if ((ch.gx_string_ptr[0] == ' ') ||
2758             (ch.gx_string_ptr[0] == ',') ||
2759             (ch.gx_string_ptr[0] == ';'))
2760         {
2761             line_break_display_number = display_number;
2762             line_break_display_width = display_width;
2763         }
2764 
2765         unit++;
2766     }
2767 
2768     context -> gx_bidi_context_line_index_cache[line++] = context -> gx_bidi_context_unit_count - 1;
2769     context -> gx_bidi_context_total_lines = line;
2770 
2771     context -> gx_bidi_context_buffer_index += sizeof(INT *) * line;
2772 
2773     return GX_SUCCESS;
2774 }
2775 
2776 /**************************************************************************/
2777 /*                                                                        */
2778 /*  FUNCTION                                               RELEASE        */
2779 /*                                                                        */
2780 /*    _gx_utility_bidi_reordering_resolve                 PORTABLE C      */
2781 /*                                                           6.1          */
2782 /*  AUTHOR                                                                */
2783 /*                                                                        */
2784 /*    Kenneth Maxwell, Microsoft Corporation                              */
2785 /*                                                                        */
2786 /*  DESCRIPTION                                                           */
2787 /*                                                                        */
2788 /*    Internal helper function to reorder text based on resolved embedding*/
2789 /*    levels or each line.                                                */
2790 /*                                                                        */
2791 /*  INPUT                                                                 */
2792 /*                                                                        */
2793 /*    context                               Bidi information control block*/
2794 /*    total_lines                           Total lines of the text       */
2795 /*    returned_utf8_text                    Pointer to the utf8 string of */
2796 /*                                            the first line, following   */
2797 /*                                            lines are linked one after  */
2798 /*                                            another.                    */
2799 /*                                                                        */
2800 /*  OUTPUT                                                                */
2801 /*                                                                        */
2802 /*    status                                Completion status             */
2803 /*                                                                        */
2804 /*  CALLS                                                                 */
2805 /*                                                                        */
2806 /*    None                                                                */
2807 /*                                                                        */
2808 /*  CALLED BY                                                             */
2809 /*                                                                        */
2810 /*    _gx_utility_bidi_paragraph_reorder                                  */
2811 /*                                                                        */
2812 /*  RELEASE HISTORY                                                       */
2813 /*                                                                        */
2814 /*    DATE              NAME                      DESCRIPTION             */
2815 /*                                                                        */
2816 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
2817 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
2818 /*                                            update with bidi context    */
2819 /*                                            structure change,           */
2820 /*                                            resulting in version 6.1    */
2821 /*                                                                        */
2822 /**************************************************************************/
_gx_utility_bidi_reordering_resolve(GX_BIDI_CONTEXT * context,GX_BIDI_RESOLVED_TEXT_INFO ** resolved_info)2823 static UINT _gx_utility_bidi_reordering_resolve(GX_BIDI_CONTEXT *context, GX_BIDI_RESOLVED_TEXT_INFO **resolved_info)
2824 {
2825 UINT                        status = GX_SUCCESS;
2826 INT                         start_index = 0;
2827 INT                         end_index;
2828 UINT                        line_index;
2829 GX_STRING                  *out_text_list = GX_NULL;
2830 GX_CHAR                    *line_text;
2831 ULONG                       byte_size;
2832 INT                         index;
2833 UINT                        glyph_count;
2834 GX_BIDI_UNIT               *unit;
2835 GX_BIDI_RESOLVED_TEXT_INFO *bidi_text;
2836 
2837     byte_size = context -> gx_bidi_context_total_lines * (sizeof(GX_BIDI_RESOLVED_TEXT_INFO) + sizeof(GX_STRING));
2838     byte_size += context -> gx_bidi_context_reordered_utf8_size + context -> gx_bidi_context_total_lines;
2839 
2840     bidi_text = (GX_BIDI_RESOLVED_TEXT_INFO *)_gx_system_memory_allocator(byte_size);
2841 
2842     if (!bidi_text)
2843     {
2844         return GX_SYSTEM_MEMORY_ERROR;
2845     }
2846 
2847     memset(bidi_text, 0, (size_t)byte_size);
2848 
2849     bidi_text -> gx_bidi_resolved_text_info_text = (GX_STRING *)(bidi_text + 1);
2850     bidi_text -> gx_bidi_resolved_text_info_total_lines = context -> gx_bidi_context_total_lines;
2851 
2852     *resolved_info = bidi_text;
2853 
2854     out_text_list = bidi_text -> gx_bidi_resolved_text_info_text;
2855     line_text = (GX_CHAR *)(out_text_list + context -> gx_bidi_context_total_lines);
2856 
2857 
2858     for (line_index = 0; line_index < context -> gx_bidi_context_total_lines; line_index++)
2859     {
2860         if (context -> gx_bidi_context_total_lines == 1)
2861         {
2862             end_index = context -> gx_bidi_context_unit_count - 1;
2863         }
2864         else
2865         {
2866             end_index = context -> gx_bidi_context_line_index_cache[line_index];
2867         }
2868 
2869         status = _gx_utility_bidi_reordering_resolve_1(context, start_index, end_index);
2870 
2871         if (status == GX_SUCCESS)
2872         {
2873             status = _gx_utility_bidi_reordering_resolve_2(context, start_index, end_index);
2874         }
2875 
2876         if (status == GX_SUCCESS)
2877         {
2878             unit = &context -> gx_bidi_context_unit_list[start_index];
2879 
2880             out_text_list -> gx_string_ptr = line_text;
2881 
2882             /* Convert unicode to utf8 text. */
2883             for (index = start_index; index <= end_index; index++)
2884             {
2885                 switch (unit -> gx_bidi_unit_type)
2886                 {
2887                 case GX_BIDI_CHARACTER_TYPE_BN:
2888                     /* Skip above characters. */
2889                     break;
2890 
2891                 default:
2892                     if (unit -> gx_bidi_unit_code)
2893                     {
2894                         if (unit -> gx_bidi_unit_code < 0x80)
2895                         {
2896                             *(GX_UBYTE *)(line_text) = (GX_UBYTE)(unit -> gx_bidi_unit_code);
2897                             glyph_count = 1;
2898                         }
2899                         else
2900                         {
2901 
2902                             _gx_utility_unicode_to_utf8(unit -> gx_bidi_unit_code, (GX_UBYTE *)line_text, &glyph_count);
2903                         }
2904                         line_text += glyph_count;
2905                         out_text_list -> gx_string_length += glyph_count;
2906                     }
2907                     break;
2908                 }
2909 
2910                 unit++;
2911             }
2912 
2913             line_text++;
2914             out_text_list++;
2915         }
2916 
2917         start_index = end_index + 1;
2918     }
2919 
2920     return status;
2921 }
2922 
2923 /**************************************************************************/
2924 /*                                                                        */
2925 /*  FUNCTION                                               RELEASE        */
2926 /*                                                                        */
2927 /*    _gx_utility_bidi_one_paragraph_reorder              PORTABLE C      */
2928 /*                                                           6.1.10       */
2929 /*  AUTHOR                                                                */
2930 /*                                                                        */
2931 /*    Kenneth Maxwell, Microsoft Corporation                              */
2932 /*                                                                        */
2933 /*  DESCRIPTION                                                           */
2934 /*                                                                        */
2935 /*    This function reorders a bidi text for displaying.                  */
2936 /*                                                                        */
2937 /*  INPUT                                                                 */
2938 /*                                                                        */
2939 /*    text_info                             Pointer to bidi text          */
2940 /*    reordered_text                        Reordered text, each line is  */
2941 /*                                            ended a with string         */
2942 /*                                            terminator '\0', multi line */
2943 /*                                            strings are linked one after*/
2944 /*                                            another                     */
2945 /*    processed_count                       The processed text size in    */
2946 /*                                            byte                        */
2947 /*                                                                        */
2948 /*  OUTPUT                                                                */
2949 /*                                                                        */
2950 /*    status                                Completion status             */
2951 /*                                                                        */
2952 /*  CALLS                                                                 */
2953 /*                                                                        */
2954 /*    None                                                                */
2955 /*                                                                        */
2956 /*  CALLED BY                                                             */
2957 /*                                                                        */
2958 /*    _gx_utility_bidi_paragraph_reorder                                  */
2959 /*                                                                        */
2960 /*  RELEASE HISTORY                                                       */
2961 /*                                                                        */
2962 /*    DATE              NAME                      DESCRIPTION             */
2963 /*                                                                        */
2964 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
2965 /*  09-30-2020     Kenneth Maxwell          Modified comment(s), modified */
2966 /*                                            line breaking logic,        */
2967 /*                                            supported Arabic shaping,   */
2968 /*                                            updated with resolved text  */
2969 /*                                            info structure change,      */
2970 /*                                            resulting in version 6.1    */
2971 /*  01-31-2022     Kenneth Maxwell          Modified comment(s), modified */
2972 /*                                            base level set logic,       */
2973 /*                                            resulting in version 6.1.10 */
2974 /*                                                                        */
2975 /**************************************************************************/
_gx_utility_bidi_one_paragraph_reorder(GX_BIDI_TEXT_INFO * input_info,GX_BIDI_RESOLVED_TEXT_INFO ** resolved_info,UINT * processed_size)2976 static UINT _gx_utility_bidi_one_paragraph_reorder(GX_BIDI_TEXT_INFO *input_info, GX_BIDI_RESOLVED_TEXT_INFO **resolved_info, UINT *processed_size)
2977 {
2978 UINT            status;
2979 GX_BIDI_CONTEXT context;
2980 
2981     memset(&context, 0, sizeof(GX_BIDI_CONTEXT));
2982     context.gx_bidi_context_input_info = input_info;
2983 
2984     /* Allocate buffer needed for bidi text reordering. */
2985     status = _gx_utility_bidi_buffer_allocate(&context);
2986 
2987     if (status == GX_SUCCESS)
2988     {
2989         status = _gx_utility_bidi_initiate(&context);
2990     }
2991 
2992     if (status == GX_SUCCESS)
2993     {
2994         switch (input_info -> gx_bidi_text_info_direction)
2995         {
2996         case GX_LANGUAGE_DIRECTION_LTR:
2997             context.gx_bidi_context_base_level = 0;
2998             break;
2999 
3000         case GX_LANGUAGE_DIRECTION_RTL:
3001             context.gx_bidi_context_base_level = 1;
3002             break;
3003 
3004         default:
3005             /* Compute paragraph embedding_level. */
3006             status = _gx_utility_bidi_block_level_determine(&context, 0,
3007                                                             (UINT)(context.gx_bidi_context_unit_count - 1),
3008                                                             &context.gx_bidi_context_base_level);
3009             break;
3010         }
3011     }
3012 
3013     if (status == GX_SUCCESS)
3014     {
3015         /* Compute explicie level for every character. */
3016         status = _gx_utility_bidi_explicit_levels_determine(&context);
3017     }
3018 
3019     if (status == GX_SUCCESS)
3020     {
3021         /* Compute isolate run sequences. */
3022         status = _gx_utility_bidi_isolate_run_sequences_get(&context);
3023     }
3024 
3025     if (status == GX_SUCCESS)
3026     {
3027         /* Apply rules to each isolate run sequence. */
3028         status = _gx_utility_bidi_isolate_run_sequences_resolve(&context);
3029     }
3030 
3031 #if defined(GX_DYNAMIC_ARABIC_SHAPING_SUPPORT)
3032     if (status == GX_SUCCESS)
3033     {
3034         status = _gx_utility_bidi_arabic_shaping(&context);
3035     }
3036 #endif
3037 
3038     if (status == GX_SUCCESS)
3039     {
3040         /* Broke paragraph text into lines. */
3041         status = _gx_utility_bidi_line_break(&context);
3042     }
3043 
3044     if (status == GX_SUCCESS)
3045     {
3046         /* Reorder text of each line for display. */
3047         status = _gx_utility_bidi_reordering_resolve(&context, resolved_info);
3048     }
3049 
3050     if (status == GX_SUCCESS)
3051     {
3052         if (processed_size)
3053         {
3054             *processed_size = context.gx_bidi_context_processced_size;
3055         }
3056 
3057         _gx_system_memory_free(context.gx_bidi_context_buffer);
3058     }
3059 
3060     return status;
3061 }
3062 
3063 
3064 
3065 /**************************************************************************/
3066 /*                                                                        */
3067 /*  FUNCTION                                               RELEASE        */
3068 /*                                                                        */
3069 /*    _gx_utility_bidi_paragraph_reorder                  PORTABLE C      */
3070 /*                                                           6.1.3        */
3071 /*  AUTHOR                                                                */
3072 /*                                                                        */
3073 /*    Kenneth Maxwell, Microsoft Corporation                              */
3074 /*                                                                        */
3075 /*  DESCRIPTION                                                           */
3076 /*                                                                        */
3077 /*    This function reorders a bidi text for displaying.                  */
3078 /*                                                                        */
3079 /*  INPUT                                                                 */
3080 /*                                                                        */
3081 /*    input_info                            Pointer to bidi text info     */
3082 /*    reordered_text                        Reordered text information    */
3083 /*                                                                        */
3084 /*  OUTPUT                                                                */
3085 /*                                                                        */
3086 /*    status                                Completion status             */
3087 /*                                                                        */
3088 /*  CALLS                                                                 */
3089 /*                                                                        */
3090 /*    None                                                                */
3091 /*                                                                        */
3092 /*  CALLED BY                                                             */
3093 /*                                                                        */
3094 /*    Application Code                                                    */
3095 /*                                                                        */
3096 /*  RELEASE HISTORY                                                       */
3097 /*                                                                        */
3098 /*    DATE              NAME                      DESCRIPTION             */
3099 /*                                                                        */
3100 /*  09-30-2020     Kenneth Maxwell          Initial Version 6.1           */
3101 /*  12-31-2020     Kenneth Maxwell          Modified comment(s),          */
3102 /*                                            made this function a public */
3103 /*                                            api,                        */
3104 /*                                            resulting in version 6.1.3  */
3105 /*                                                                        */
3106 /**************************************************************************/
_gx_utility_bidi_paragraph_reorder(GX_BIDI_TEXT_INFO * input_info,GX_BIDI_RESOLVED_TEXT_INFO ** resolved_info_head)3107 UINT _gx_utility_bidi_paragraph_reorder(GX_BIDI_TEXT_INFO *input_info, GX_BIDI_RESOLVED_TEXT_INFO **resolved_info_head)
3108 {
3109     input_info->gx_bidi_text_info_direction = -1;
3110 
3111     return _gx_utility_bidi_paragraph_reorder_ext(input_info, resolved_info_head);
3112 }
3113 
3114 /**************************************************************************/
3115 /*                                                                        */
3116 /*  FUNCTION                                               RELEASE        */
3117 /*                                                                        */
3118 /*    _gx_utility_bidi_paragraph_reorder_ext              PORTABLE C      */
3119 /*                                                           6.1.10       */
3120 /*  AUTHOR                                                                */
3121 /*                                                                        */
3122 /*    Kenneth Maxwell, Microsoft Corporation                              */
3123 /*                                                                        */
3124 /*  DESCRIPTION                                                           */
3125 /*                                                                        */
3126 /*    This function reorders a bidi text for displaying.                  */
3127 /*                                                                        */
3128 /*  INPUT                                                                 */
3129 /*                                                                        */
3130 /*    input_info                            Pointer to bidi text info     */
3131 /*    reordered_text                        Reordered text information    */
3132 /*                                                                        */
3133 /*  OUTPUT                                                                */
3134 /*                                                                        */
3135 /*    status                                Completion status             */
3136 /*                                                                        */
3137 /*  CALLS                                                                 */
3138 /*                                                                        */
3139 /*    None                                                                */
3140 /*                                                                        */
3141 /*  CALLED BY                                                             */
3142 /*                                                                        */
3143 /*    Application Code                                                    */
3144 /*                                                                        */
3145 /*  RELEASE HISTORY                                                       */
3146 /*                                                                        */
3147 /*    DATE              NAME                      DESCRIPTION             */
3148 /*                                                                        */
3149 /*  01-31-2022     Ting Zhu                 Initial Version 6.1.10        */
3150 /*                                                                        */
3151 /**************************************************************************/
_gx_utility_bidi_paragraph_reorder_ext(GX_BIDI_TEXT_INFO * input_info,GX_BIDI_RESOLVED_TEXT_INFO ** resolved_info_head)3152 UINT _gx_utility_bidi_paragraph_reorder_ext(GX_BIDI_TEXT_INFO *input_info, GX_BIDI_RESOLVED_TEXT_INFO **resolved_info_head)
3153 {
3154 UINT                        status = GX_SUCCESS;
3155 GX_BIDI_TEXT_INFO           text_info;
3156 GX_BIDI_RESOLVED_TEXT_INFO *resolved_info;
3157 GX_BIDI_RESOLVED_TEXT_INFO *head = GX_NULL;
3158 GX_BIDI_RESOLVED_TEXT_INFO *pre = GX_NULL;
3159 UINT                        line_size;
3160 UINT                        line_break_counts = 0;
3161 GX_STRING                   string = input_info -> gx_bidi_text_info_text;
3162 
3163     if (!_gx_system_memory_allocator)
3164     {
3165         return GX_SYSTEM_MEMORY_ERROR;
3166     }
3167 
3168     text_info = *input_info;
3169 
3170     while (string.gx_string_length > 0)
3171     {
3172         if (string.gx_string_ptr[0] == GX_KEY_CARRIAGE_RETURN)
3173         {
3174             if ((string.gx_string_length > 1) && (string.gx_string_ptr[1] == GX_KEY_LINE_FEED))
3175             {
3176                 line_size = 2;
3177             }
3178             else
3179             {
3180                 line_size = 1;
3181             }
3182             line_break_counts++;
3183         }
3184         else if (string.gx_string_ptr[0] == GX_KEY_LINE_FEED)
3185         {
3186             line_size = 1;
3187             line_break_counts++;
3188         }
3189         else
3190         {
3191             line_size = 0;
3192         }
3193 
3194         if (((line_break_counts > 1) && (!line_size)) ||
3195             ((line_break_counts > 0) && (line_size == string.gx_string_length)))
3196         {
3197             /* Collect blank lines as one bidi resolved text info instance. */
3198             resolved_info = (GX_BIDI_RESOLVED_TEXT_INFO *)_gx_system_memory_allocator(sizeof(GX_BIDI_RESOLVED_TEXT_INFO));
3199             if (!resolved_info)
3200             {
3201                 status = GX_SYSTEM_MEMORY_ERROR;
3202                 break;
3203             }
3204 
3205             memset(resolved_info, 0, sizeof(GX_BIDI_RESOLVED_TEXT_INFO));
3206 
3207             if (!line_size)
3208             {
3209                 resolved_info -> gx_bidi_resolved_text_info_total_lines = (UINT)(line_break_counts - 1);
3210             }
3211             else
3212             {
3213                 resolved_info -> gx_bidi_resolved_text_info_total_lines = line_break_counts;
3214             }
3215 
3216             GX_LINK_RESOLVED_BIDI_TEXT_INFO
3217         }
3218 
3219         if (!line_size)
3220         {
3221             /* Start bidi text reorderding for one paragraph. */
3222             text_info.gx_bidi_text_info_text = string;
3223             status = _gx_utility_bidi_one_paragraph_reorder(&text_info, &resolved_info, &line_size);
3224 
3225             if (status != GX_SUCCESS)
3226             {
3227                 break;
3228             }
3229 
3230             GX_LINK_RESOLVED_BIDI_TEXT_INFO
3231 
3232             line_break_counts = 0;
3233         }
3234 
3235         /* Increment string pointer and decrement string length. */
3236         string.gx_string_ptr += line_size;
3237         string.gx_string_length -= line_size;
3238     }
3239 
3240     if (status == GX_SUCCESS)
3241     {
3242         *resolved_info_head = head;
3243     }
3244     else if (head)
3245     {
3246         /* Clean generated resolved bidi text link. */
3247         _gx_utility_bidi_resolved_text_info_delete(&head);
3248     }
3249 
3250     return status;
3251 }
3252 #endif
3253 
3254