2 * fribidi-run.c - text run data type
4 * $Id: fribidi-run.c,v 1.8 2006-01-31 03:23:13 behdad Exp $
6 * $Date: 2006-01-31 03:23:13 $
8 * $Source: /home/behdad/src/fdo/fribidi/togit/git/../fribidi/fribidi2/lib/fribidi-run.c,v $
11 * Behdad Esfahbod, 2001, 2002, 2004
12 * Dov Grobgeld, 1999, 2000
14 * Copyright (C) 2004 Sharif FarsiWeb, Inc
15 * Copyright (C) 2001,2002 Behdad Esfahbod
16 * Copyright (C) 1999,2000 Dov Grobgeld
18 * This library is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU Lesser General Public
20 * License as published by the Free Software Foundation; either
21 * version 2.1 of the License, or (at your option) any later version.
23 * This library is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 * Lesser General Public License for more details.
28 * You should have received a copy of the GNU Lesser General Public License
29 * along with this library, in a file named COPYING; if not, write to the
30 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
31 * Boston, MA 02110-1301, USA
33 * For licensing issues, contact <license@farsiweb.info>.
38 #include <fribidi-bidi-types.h>
42 #include "bidi-types.h"
44 #if USE_SIMPLE_MALLOC+0
46 static FriBidiRun *free_runs = NULL;
54 register FriBidiRun *run;
56 #if USE_SIMPLE_MALLOC+0
57 run = fribidi_malloc (sizeof (FriBidiRun));
58 #else /* !USE_SIMPLE_MALLOC */
62 free_runs = run->next;
66 static FriBidiMemChunk *run_mem_chunk = NULL;
70 run_mem_chunk = fribidi_chunk_new_for_type (FriBidiRun);
74 run = fribidi_chunk_new (FriBidiRun, run_mem_chunk);
78 #endif /* !USE_SIMPLE_MALLOC */
83 run->len = run->pos = run->level = 0;
84 run->next = run->prev = NULL;
96 #if USE_SIMPLE_MALLOC+0
98 #else /* !USE_SIMPLE_MALLOC */
99 run->next = free_runs;
101 #endif /* !USE_SIMPLE_MALLOC */
109 register FriBidiRun *run;
116 run->type = FRIBIDI_TYPE_SENTINEL;
117 run->level = FRIBIDI_SENTINEL;
118 run->pos = FRIBIDI_SENTINEL;
119 run->len = FRIBIDI_SENTINEL;
120 run->next = run->prev = run;
134 fribidi_validate_run_list (run_list);
136 #if USE_SIMPLE_MALLOC+0
138 register FriBidiRun *pp;
141 pp->prev->next = NULL;
145 register FriBidiRun *p;
152 #else /* !USE_SIMPLE_MALLOC */
153 run_list->prev->next = free_runs;
154 free_runs = run_list;
155 #endif /* !USE_SIMPLE_MALLOC */
160 run_list_encode_bidi_types (
162 const FriBidiCharType *bidi_types,
163 const FriBidiStrIndex len
166 FriBidiRun *list, *last;
167 register FriBidiRun *run = NULL;
170 fribidi_assert (bidi_types);
172 /* Create the list sentinel */
173 list = new_run_list ();
178 /* Scan over the character types */
179 for (i = 0; i < len; i++)
181 register FriBidiCharType char_type = bidi_types[i];
182 if (char_type != last->type)
187 run->type = char_type;
189 last->len = run->pos - last->pos;
196 /* Close the circle */
197 last->len = len - last->pos;
204 /* Memory allocation failed */
205 free_run_list (list);
209 fribidi_validate_run_list (list);
214 /* override the run list 'base', with the runs in the list 'over', to
215 reinsert the previously-removed explicit codes (at X9) from
216 'explicits_list' back into 'type_rl_list' for example. This is used at the
217 end of I2 to restore the explicit marks, and also to reset the character
218 types of characters at L1.
220 it is assumed that the 'pos' of the first element in 'base' list is not
221 more than the 'pos' of the first element of the 'over' list, and the
222 'pos' of the last element of the 'base' list is not less than the 'pos'
223 of the last element of the 'over' list. these two conditions are always
224 satisfied for the two usages mentioned above.
230 use some explanatory names instead of p, q, ...
231 rewrite comment above to remove references to special usage.
238 fribidi_boolean preserve_length
241 register FriBidiRun *p = base, *q, *r, *s, *t;
242 register FriBidiStrIndex pos = 0, pos2;
243 fribidi_boolean status = false;
245 fribidi_validate_run_list (base);
246 fribidi_validate_run_list (over);
248 for_run_list (q, over)
251 (!q->len || q->pos < pos) continue;
253 while (p->next->type != FRIBIDI_TYPE_SENTINEL && p->next->pos <= pos)
255 /* now p is the element that q must be inserted 'in'. */
258 while (r->next->type != FRIBIDI_TYPE_SENTINEL && r->next->pos < pos2)
262 /* now r is the last element that q affects. */
266 /* split p into at most 3 intervals, and insert q in the place of
267 the second interval, set r to be the third part. */
268 /* third part needed? */
269 if (p->pos + p->len > pos2)
278 r->len = p->pos + p->len - pos2;
285 (p->pos + p->len >= pos)
287 /* first part needed? */
289 /* cut the end of p. */
290 p->len = pos - p->pos;
302 (p->pos + p->len >= pos)
306 /* cut the end of p. */
307 p->len = pos - p->pos;
313 if (r->pos + r->len > pos2)
315 /* cut the begining of r. */
316 r->len = r->pos + r->len - pos2;
322 /* remove the elements between p and r. */
323 for (s = p->next; s != r;)
330 /* before updating the next and prev runs to point to the inserted q,
331 we must remember the next element of q in the 'over' list.
343 fribidi_validate_run_list (base);
346 free_run_list (over);
354 fribidi_validate_run_list (
355 FriBidiRun *run_list /* input run list */
358 register FriBidiRun *q;
360 fribidi_assert (run_list);
361 fribidi_assert (run_list->next);
362 fribidi_assert (run_list->next->prev == run_list);
363 fribidi_assert (run_list->type == FRIBIDI_TYPE_SENTINEL);
364 for_run_list (q, run_list)
366 fribidi_assert (q->next);
367 fribidi_assert (q->next->prev == q);
369 fribidi_assert (q == run_list);
374 /* Editor directions:
375 * vim:textwidth=78:tabstop=8:shiftwidth=2:autoindent:cindent