2 * fribidi-run.c - text run data type
5 * Behdad Esfahbod, 2001, 2002, 2004
6 * Dov Grobgeld, 1999, 2000, 2017
8 * Copyright (C) 2004 Sharif FarsiWeb, Inc
9 * Copyright (C) 2001,2002 Behdad Esfahbod
10 * Copyright (C) 1999,2000,2017 Dov Grobgeld
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public License
23 * along with this library, in a file named COPYING; if not, write to the
24 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 * Boston, MA 02110-1301, USA
27 * For licensing issues, contact <fribidi.license@gmail.com>.
32 #include <fribidi-bidi-types.h>
35 #include "bidi-types.h"
42 register FriBidiRun *run;
44 run = fribidi_malloc (sizeof (FriBidiRun));
49 run->len = run->pos = run->level = run->isolate_level = 0;
50 run->next = run->prev = run->prev_isolate = run->next_isolate = NULL;
60 register FriBidiRun *run;
67 run->type = FRIBIDI_TYPE_SENTINEL;
68 run->level = FRIBIDI_SENTINEL;
69 run->pos = FRIBIDI_SENTINEL;
70 run->len = FRIBIDI_SENTINEL;
71 run->next = run->prev = run;
85 fribidi_validate_run_list (run_list);
88 register FriBidiRun *pp;
91 pp->prev->next = NULL;
95 register FriBidiRun *p;
106 run_list_encode_bidi_types (
108 const FriBidiCharType *bidi_types,
109 const FriBidiBracketType *bracket_types,
110 const FriBidiStrIndex len
113 FriBidiRun *list, *last;
114 register FriBidiRun *run = NULL;
117 fribidi_assert (bidi_types);
119 /* Create the list sentinel */
120 list = new_run_list ();
125 /* Scan over the character types */
126 for (i = 0; i < len; i++)
128 register FriBidiCharType char_type = bidi_types[i];
129 register FriBidiBracketType bracket_type = FRIBIDI_NO_BRACKET;
131 bracket_type = bracket_types[i];
133 if (char_type != last->type
134 || bracket_type != FRIBIDI_NO_BRACKET /* Always separate bracket into single char runs! */
135 || last->bracket_type != FRIBIDI_NO_BRACKET
136 || FRIBIDI_IS_ISOLATE(char_type)
142 run->type = char_type;
144 last->len = run->pos - last->pos;
147 run->bracket_type = bracket_type;
152 /* Close the circle */
153 last->len = len - last->pos;
160 /* Memory allocation failed */
161 free_run_list (list);
165 fribidi_validate_run_list (list);
170 /* override the run list 'base', with the runs in the list 'over', to
171 reinsert the previously-removed explicit codes (at X9) from
172 'explicits_list' back into 'type_rl_list' for example. This is used at the
173 end of I2 to restore the explicit marks, and also to reset the character
174 types of characters at L1.
176 it is assumed that the 'pos' of the first element in 'base' list is not
177 more than the 'pos' of the first element of the 'over' list, and the
178 'pos' of the last element of the 'base' list is not less than the 'pos'
179 of the last element of the 'over' list. these two conditions are always
180 satisfied for the two usages mentioned above.
186 use some explanatory names instead of p, q, ...
187 rewrite comment above to remove references to special usage.
194 fribidi_boolean preserve_length
197 register FriBidiRun *p = base, *q, *r, *s, *t;
198 register FriBidiStrIndex pos = 0, pos2;
199 fribidi_boolean status = false;
201 fribidi_validate_run_list (base);
202 fribidi_validate_run_list (over);
204 for_run_list (q, over)
207 (!q->len || q->pos < pos) continue;
209 while (p->next->type != FRIBIDI_TYPE_SENTINEL && p->next->pos <= pos)
211 /* now p is the element that q must be inserted 'in'. */
214 while (r->next->type != FRIBIDI_TYPE_SENTINEL && r->next->pos < pos2)
218 /* now r is the last element that q affects. */
222 /* split p into at most 3 intervals, and insert q in the place of
223 the second interval, set r to be the third part. */
224 /* third part needed? */
225 if (p->pos + p->len > pos2)
233 r->isolate_level = p->isolate_level;
235 r->len = p->pos + p->len - pos2;
242 (p->pos + p->len >= pos)
244 /* first part needed? */
246 /* cut the end of p. */
247 p->len = pos - p->pos;
259 (p->pos + p->len >= pos)
263 /* cut the end of p. */
264 p->len = pos - p->pos;
270 if (r->pos + r->len > pos2)
272 /* cut the beginning of r. */
273 r->len = r->pos + r->len - pos2;
279 /* remove the elements between p and r. */
280 for (s = p->next; s != r;)
287 /* before updating the next and prev runs to point to the inserted q,
288 we must remember the next element of q in the 'over' list.
300 fribidi_validate_run_list (base);
303 free_run_list (over);
311 fribidi_validate_run_list (
312 FriBidiRun *run_list /* input run list */
315 register FriBidiRun *q;
317 fribidi_assert (run_list);
318 fribidi_assert (run_list->next);
319 fribidi_assert (run_list->next->prev == run_list);
320 fribidi_assert (run_list->type == FRIBIDI_TYPE_SENTINEL);
321 for_run_list (q, run_list)
323 fribidi_assert (q->next);
324 fribidi_assert (q->next->prev == q);
326 fribidi_assert (q == run_list);
331 /* Editor directions:
332 * vim:textwidth=78:tabstop=8:shiftwidth=2:autoindent:cindent