Bug Summary

File:lapiz/lapiztextregion.c
Warning:line 331, column 4
Value stored to 'start_node' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name lapiztextregion.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/lapiz -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I .. -I .. -I . -I ./smclient -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/ctk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/local/include/ctksourceview-4 -I /usr/local/include/libbean-1.0 -I /usr/include/gobject-introspection-1.0 -I /usr/include/gobject-introspection-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -D DATADIR="/usr/share" -D LAPIZ_DATADIR="/usr/share/lapiz" -D LIBDIR="/usr/lib" -D PIC -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/lapiz -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-08-26-222817-32832-1 -x c lapiztextregion.c
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
2 *
3 * lapiztextregion.h - CtkTextMark based region utility functions
4 *
5 * This file is part of the CtkSourceView widget
6 *
7 * Copyright (C) 2002 Gustavo Giráldez <gustavo.giraldez@gmx.net>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
23 */
24
25#ifdef HAVE_CONFIG_H1
26#include <config.h>
27#endif
28
29#include <glib.h>
30
31#include "lapiztextregion.h"
32
33
34#undef ENABLE_DEBUG
35/*
36#define ENABLE_DEBUG
37*/
38
39#ifdef ENABLE_DEBUG
40#define DEBUG(x) (x)
41#else
42#define DEBUG(x)
43#endif
44
45typedef struct _Subregion {
46 CtkTextMark *start;
47 CtkTextMark *end;
48} Subregion;
49
50struct _LapizTextRegion {
51 CtkTextBuffer *buffer;
52 GList *subregions;
53 guint32 time_stamp;
54};
55
56typedef struct _LapizTextRegionIteratorReal LapizTextRegionIteratorReal;
57
58struct _LapizTextRegionIteratorReal {
59 LapizTextRegion *region;
60 guint32 region_time_stamp;
61
62 GList *subregions;
63};
64
65
66/* ----------------------------------------------------------------------
67 Private interface
68 ---------------------------------------------------------------------- */
69
70/* Find and return a subregion node which contains the given text
71 iter. If left_side is TRUE, return the subregion which contains
72 the text iter or which is the leftmost; else return the rightmost
73 subregion */
74static GList *
75find_nearest_subregion (LapizTextRegion *region,
76 const CtkTextIter *iter,
77 GList *begin,
78 gboolean leftmost,
79 gboolean include_edges)
80{
81 GList *l, *retval;
82
83 g_return_val_if_fail (region != NULL && iter != NULL, NULL)do { if ((region != ((void*)0) && iter != ((void*)0))
) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "region != NULL && iter != NULL"); return
(((void*)0)); } } while (0)
;
84
85 if (!begin)
86 begin = region->subregions;
87
88 if (begin)
89 retval = begin->prev;
90 else
91 retval = NULL((void*)0);
92
93 for (l = begin; l; l = l->next) {
94 CtkTextIter sr_iter;
95 Subregion *sr = l->data;
96 gint cmp;
97
98 if (!leftmost) {
99 ctk_text_buffer_get_iter_at_mark (region->buffer, &sr_iter, sr->end);
100 cmp = ctk_text_iter_compare (iter, &sr_iter);
101 if (cmp < 0 || (cmp == 0 && include_edges)) {
102 retval = l;
103 break;
104 }
105
106 } else {
107 ctk_text_buffer_get_iter_at_mark (region->buffer, &sr_iter, sr->start);
108 cmp = ctk_text_iter_compare (iter, &sr_iter);
109 if (cmp > 0 || (cmp == 0 && include_edges))
110 retval = l;
111 else
112 break;
113 }
114 }
115 return retval;
116}
117
118/* ----------------------------------------------------------------------
119 Public interface
120 ---------------------------------------------------------------------- */
121
122LapizTextRegion *
123lapiz_text_region_new (CtkTextBuffer *buffer)
124{
125 LapizTextRegion *region;
126
127 g_return_val_if_fail (buffer != NULL, NULL)do { if ((buffer != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "buffer != NULL")
; return (((void*)0)); } } while (0)
;
128
129 region = g_new (LapizTextRegion, 1)((LapizTextRegion *) g_malloc_n ((1), sizeof (LapizTextRegion
)))
;
130 region->buffer = buffer;
131 region->subregions = NULL((void*)0);
132 region->time_stamp = 0;
133
134 return region;
135}
136
137void
138lapiz_text_region_destroy (LapizTextRegion *region, gboolean delete_marks)
139{
140 g_return_if_fail (region != NULL)do { if ((region != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL")
; return; } } while (0)
;
141
142 while (region->subregions) {
143 Subregion *sr = region->subregions->data;
144 if (delete_marks) {
145 ctk_text_buffer_delete_mark (region->buffer, sr->start);
146 ctk_text_buffer_delete_mark (region->buffer, sr->end);
147 }
148 g_free (sr);
149 region->subregions = g_list_delete_link (region->subregions,
150 region->subregions);
151 }
152 region->buffer = NULL((void*)0);
153 region->time_stamp = 0;
154
155 g_free (region);
156}
157
158CtkTextBuffer *
159lapiz_text_region_get_buffer (LapizTextRegion *region)
160{
161 g_return_val_if_fail (region != NULL, NULL)do { if ((region != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL")
; return (((void*)0)); } } while (0)
;
162
163 return region->buffer;
164}
165
166static void
167lapiz_text_region_clear_zero_length_subregions (LapizTextRegion *region)
168{
169 CtkTextIter start, end;
170 GList *node;
171
172 g_return_if_fail (region != NULL)do { if ((region != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL")
; return; } } while (0)
;
173
174 for (node = region->subregions; node; ) {
175 Subregion *sr = node->data;
176 ctk_text_buffer_get_iter_at_mark (region->buffer, &start, sr->start);
177 ctk_text_buffer_get_iter_at_mark (region->buffer, &end, sr->end);
178 if (ctk_text_iter_equal (&start, &end)) {
179 ctk_text_buffer_delete_mark (region->buffer, sr->start);
180 ctk_text_buffer_delete_mark (region->buffer, sr->end);
181 g_free (sr);
182 if (node == region->subregions)
183 region->subregions = node = g_list_delete_link (node, node);
184 else
185 node = g_list_delete_link (node, node);
186
187 ++region->time_stamp;
188
189 } else {
190 node = node->next;
191 }
192 }
193}
194
195void
196lapiz_text_region_add (LapizTextRegion *region,
197 const CtkTextIter *_start,
198 const CtkTextIter *_end)
199{
200 GList *start_node, *end_node;
201 CtkTextIter start, end;
202
203 g_return_if_fail (region != NULL && _start != NULL && _end != NULL)do { if ((region != ((void*)0) && _start != ((void*)0
) && _end != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL && _start != NULL && _end != NULL"
); return; } } while (0)
;
204
205 start = *_start;
206 end = *_end;
207
208 DEBUG (g_print ("---\n"));
209 DEBUG (lapiz_text_region_debug_print (region));
210 DEBUG (g_message ("region_add (%d, %d)",
211 ctk_text_iter_get_offset (&start),
212 ctk_text_iter_get_offset (&end)));
213
214 ctk_text_iter_order (&start, &end);
215
216 /* don't add zero-length regions */
217 if (ctk_text_iter_equal (&start, &end))
218 return;
219
220 /* find bounding subregions */
221 start_node = find_nearest_subregion (region, &start, NULL((void*)0), FALSE(0), TRUE(!(0)));
222 end_node = find_nearest_subregion (region, &end, start_node, TRUE(!(0)), TRUE(!(0)));
223
224 if (start_node == NULL((void*)0) || end_node == NULL((void*)0) || end_node == start_node->prev) {
225 /* create the new subregion */
226 Subregion *sr = g_new0 (Subregion, 1)((Subregion *) g_malloc0_n ((1), sizeof (Subregion)));
227 sr->start = ctk_text_buffer_create_mark (region->buffer, NULL((void*)0), &start, TRUE(!(0)));
228 sr->end = ctk_text_buffer_create_mark (region->buffer, NULL((void*)0), &end, FALSE(0));
229
230 if (start_node == NULL((void*)0)) {
231 /* append the new region */
232 region->subregions = g_list_append (region->subregions, sr);
233
234 } else if (end_node == NULL((void*)0)) {
235 /* prepend the new region */
236 region->subregions = g_list_prepend (region->subregions, sr);
237
238 } else {
239 /* we are in the middle of two subregions */
240 region->subregions = g_list_insert_before (region->subregions,
241 start_node, sr);
242 }
243 }
244 else {
245 CtkTextIter iter;
246 Subregion *sr = start_node->data;
247 if (start_node != end_node) {
248 /* we need to merge some subregions */
249 GList *l = start_node->next;
250 Subregion *q;
251
252 ctk_text_buffer_delete_mark (region->buffer, sr->end);
253 while (l != end_node) {
254 q = l->data;
255 ctk_text_buffer_delete_mark (region->buffer, q->start);
256 ctk_text_buffer_delete_mark (region->buffer, q->end);
257 g_free (q);
258 l = g_list_delete_link (l, l);
259 }
260 q = l->data;
261 ctk_text_buffer_delete_mark (region->buffer, q->start);
262 sr->end = q->end;
263 g_free (q);
264 l = g_list_delete_link (l, l);
265 }
266 /* now move marks if that action expands the region */
267 ctk_text_buffer_get_iter_at_mark (region->buffer, &iter, sr->start);
268 if (ctk_text_iter_compare (&iter, &start) > 0)
269 ctk_text_buffer_move_mark (region->buffer, sr->start, &start);
270 ctk_text_buffer_get_iter_at_mark (region->buffer, &iter, sr->end);
271 if (ctk_text_iter_compare (&iter, &end) < 0)
272 ctk_text_buffer_move_mark (region->buffer, sr->end, &end);
273 }
274
275 ++region->time_stamp;
276
277 DEBUG (lapiz_text_region_debug_print (region));
278}
279
280void
281lapiz_text_region_subtract (LapizTextRegion *region,
282 const CtkTextIter *_start,
283 const CtkTextIter *_end)
284{
285 GList *start_node, *end_node, *node;
286 CtkTextIter sr_start_iter, sr_end_iter;
287 gboolean done;
288 gboolean start_is_outside, end_is_outside;
289 Subregion *sr;
290 CtkTextIter start, end;
291
292 g_return_if_fail (region != NULL && _start != NULL && _end != NULL)do { if ((region != ((void*)0) && _start != ((void*)0
) && _end != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL && _start != NULL && _end != NULL"
); return; } } while (0)
;
293
294 start = *_start;
295 end = *_end;
296
297 DEBUG (g_print ("---\n"));
298 DEBUG (lapiz_text_region_debug_print (region));
299 DEBUG (g_message ("region_substract (%d, %d)",
300 ctk_text_iter_get_offset (&start),
301 ctk_text_iter_get_offset (&end)));
302
303 ctk_text_iter_order (&start, &end);
304
305 /* find bounding subregions */
306 start_node = find_nearest_subregion (region, &start, NULL((void*)0), FALSE(0), FALSE(0));
307 end_node = find_nearest_subregion (region, &end, start_node, TRUE(!(0)), FALSE(0));
308
309 /* easy case first */
310 if (start_node == NULL((void*)0) || end_node == NULL((void*)0) || end_node == start_node->prev)
311 return;
312
313 /* deal with the start point */
314 start_is_outside = end_is_outside = FALSE(0);
315
316 sr = start_node->data;
317 ctk_text_buffer_get_iter_at_mark (region->buffer, &sr_start_iter, sr->start);
318 ctk_text_buffer_get_iter_at_mark (region->buffer, &sr_end_iter, sr->end);
319
320 if (ctk_text_iter_in_range (&start, &sr_start_iter, &sr_end_iter) &&
321 !ctk_text_iter_equal (&start, &sr_start_iter)) {
322 /* the starting point is inside the first subregion */
323 if (ctk_text_iter_in_range (&end, &sr_start_iter, &sr_end_iter) &&
324 !ctk_text_iter_equal (&end, &sr_end_iter)) {
325 /* the ending point is also inside the first
326 subregion: we need to split */
327 Subregion *new_sr = g_new0 (Subregion, 1)((Subregion *) g_malloc0_n ((1), sizeof (Subregion)));
328 new_sr->end = sr->end;
329 new_sr->start = ctk_text_buffer_create_mark (region->buffer,
330 NULL((void*)0), &end, TRUE(!(0)));
331 start_node = g_list_insert_before (start_node, start_node->next, new_sr);
Value stored to 'start_node' is never read
332
333 sr->end = ctk_text_buffer_create_mark (region->buffer,
334 NULL((void*)0), &start, FALSE(0));
335
336 /* no further processing needed */
337 DEBUG (g_message ("subregion splitted"));
338
339 return;
340 } else {
341 /* the ending point is outside, so just move
342 the end of the subregion to the starting point */
343 ctk_text_buffer_move_mark (region->buffer, sr->end, &start);
344 }
345 } else {
346 /* the starting point is outside (and so to the left)
347 of the first subregion */
348 DEBUG (g_message ("start is outside"));
349
350 start_is_outside = TRUE(!(0));
351 }
352
353 /* deal with the end point */
354 if (start_node != end_node) {
355 sr = end_node->data;
356 ctk_text_buffer_get_iter_at_mark (region->buffer, &sr_start_iter, sr->start);
357 ctk_text_buffer_get_iter_at_mark (region->buffer, &sr_end_iter, sr->end);
358 }
359
360 if (ctk_text_iter_in_range (&end, &sr_start_iter, &sr_end_iter) &&
361 !ctk_text_iter_equal (&end, &sr_end_iter)) {
362 /* ending point is inside, move the start mark */
363 ctk_text_buffer_move_mark (region->buffer, sr->start, &end);
364 } else {
365 end_is_outside = TRUE(!(0));
366 DEBUG (g_message ("end is outside"));
367
368 }
369
370 /* finally remove any intermediate subregions */
371 done = FALSE(0);
372 node = start_node;
373
374 while (!done) {
375 if (node == end_node)
376 /* we are done, exit in the next iteration */
377 done = TRUE(!(0));
378
379 if ((node == start_node && !start_is_outside) ||
380 (node == end_node && !end_is_outside)) {
381 /* skip starting or ending node */
382 node = node->next;
383 } else {
384 GList *l = node->next;
385 sr = node->data;
386 ctk_text_buffer_delete_mark (region->buffer, sr->start);
387 ctk_text_buffer_delete_mark (region->buffer, sr->end);
388 g_free (sr);
389 region->subregions = g_list_delete_link (region->subregions,
390 node);
391 node = l;
392 }
393 }
394
395 ++region->time_stamp;
396
397 DEBUG (lapiz_text_region_debug_print (region));
398
399 /* now get rid of empty subregions */
400 lapiz_text_region_clear_zero_length_subregions (region);
401
402 DEBUG (lapiz_text_region_debug_print (region));
403}
404
405gint
406lapiz_text_region_subregions (LapizTextRegion *region)
407{
408 g_return_val_if_fail (region != NULL, 0)do { if ((region != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL")
; return (0); } } while (0)
;
409
410 return g_list_length (region->subregions);
411}
412
413gboolean
414lapiz_text_region_nth_subregion (LapizTextRegion *region,
415 guint subregion,
416 CtkTextIter *start,
417 CtkTextIter *end)
418{
419 Subregion *sr;
420
421 g_return_val_if_fail (region != NULL, FALSE)do { if ((region != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL")
; return ((0)); } } while (0)
;
422
423 sr = g_list_nth_data (region->subregions, subregion);
424 if (sr == NULL((void*)0))
425 return FALSE(0);
426
427 if (start)
428 ctk_text_buffer_get_iter_at_mark (region->buffer, start, sr->start);
429 if (end)
430 ctk_text_buffer_get_iter_at_mark (region->buffer, end, sr->end);
431
432 return TRUE(!(0));
433}
434
435LapizTextRegion *
436lapiz_text_region_intersect (LapizTextRegion *region,
437 const CtkTextIter *_start,
438 const CtkTextIter *_end)
439{
440 GList *start_node, *end_node, *node;
441 CtkTextIter sr_start_iter, sr_end_iter;
442 Subregion *sr, *new_sr;
443 gboolean done;
444 LapizTextRegion *new_region;
445 CtkTextIter start, end;
446
447 g_return_val_if_fail (region != NULL && _start != NULL && _end != NULL, NULL)do { if ((region != ((void*)0) && _start != ((void*)0
) && _end != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL && _start != NULL && _end != NULL"
); return (((void*)0)); } } while (0)
;
448
449 start = *_start;
450 end = *_end;
451
452 ctk_text_iter_order (&start, &end);
453
454 /* find bounding subregions */
455 start_node = find_nearest_subregion (region, &start, NULL((void*)0), FALSE(0), FALSE(0));
456 end_node = find_nearest_subregion (region, &end, start_node, TRUE(!(0)), FALSE(0));
457
458 /* easy case first */
459 if (start_node == NULL((void*)0) || end_node == NULL((void*)0) || end_node == start_node->prev)
460 return NULL((void*)0);
461
462 new_region = lapiz_text_region_new (region->buffer);
463 done = FALSE(0);
464
465 sr = start_node->data;
466 ctk_text_buffer_get_iter_at_mark (region->buffer, &sr_start_iter, sr->start);
467 ctk_text_buffer_get_iter_at_mark (region->buffer, &sr_end_iter, sr->end);
468
469 /* starting node */
470 if (ctk_text_iter_in_range (&start, &sr_start_iter, &sr_end_iter)) {
471 new_sr = g_new0 (Subregion, 1)((Subregion *) g_malloc0_n ((1), sizeof (Subregion)));
472 new_region->subregions = g_list_prepend (new_region->subregions, new_sr);
473
474 new_sr->start = ctk_text_buffer_create_mark (new_region->buffer, NULL((void*)0),
475 &start, TRUE(!(0)));
476 if (start_node == end_node) {
477 /* things will finish shortly */
478 done = TRUE(!(0));
479 if (ctk_text_iter_in_range (&end, &sr_start_iter, &sr_end_iter))
480 new_sr->end = ctk_text_buffer_create_mark (new_region->buffer,
481 NULL((void*)0), &end, FALSE(0));
482 else
483 new_sr->end = ctk_text_buffer_create_mark (new_region->buffer,
484 NULL((void*)0), &sr_end_iter,
485 FALSE(0));
486 } else {
487 new_sr->end = ctk_text_buffer_create_mark (new_region->buffer, NULL((void*)0),
488 &sr_end_iter, FALSE(0));
489 }
490 node = start_node->next;
491 } else {
492 /* start should be the same as the subregion, so copy it in the loop */
493 node = start_node;
494 }
495
496 if (!done) {
497 while (node != end_node) {
498 /* copy intermediate subregions verbatim */
499 sr = node->data;
500 ctk_text_buffer_get_iter_at_mark (region->buffer, &sr_start_iter,
501 sr->start);
502 ctk_text_buffer_get_iter_at_mark (region->buffer, &sr_end_iter, sr->end);
503
504 new_sr = g_new0 (Subregion, 1)((Subregion *) g_malloc0_n ((1), sizeof (Subregion)));
505 new_region->subregions = g_list_prepend (new_region->subregions, new_sr);
506 new_sr->start = ctk_text_buffer_create_mark (new_region->buffer, NULL((void*)0),
507 &sr_start_iter, TRUE(!(0)));
508 new_sr->end = ctk_text_buffer_create_mark (new_region->buffer, NULL((void*)0),
509 &sr_end_iter, FALSE(0));
510 /* next node */
511 node = node->next;
512 }
513
514 /* ending node */
515 sr = node->data;
516 ctk_text_buffer_get_iter_at_mark (region->buffer, &sr_start_iter, sr->start);
517 ctk_text_buffer_get_iter_at_mark (region->buffer, &sr_end_iter, sr->end);
518
519 new_sr = g_new0 (Subregion, 1)((Subregion *) g_malloc0_n ((1), sizeof (Subregion)));
520 new_region->subregions = g_list_prepend (new_region->subregions, new_sr);
521
522 new_sr->start = ctk_text_buffer_create_mark (new_region->buffer, NULL((void*)0),
523 &sr_start_iter, TRUE(!(0)));
524
525 if (ctk_text_iter_in_range (&end, &sr_start_iter, &sr_end_iter))
526 new_sr->end = ctk_text_buffer_create_mark (new_region->buffer, NULL((void*)0),
527 &end, FALSE(0));
528 else
529 new_sr->end = ctk_text_buffer_create_mark (new_region->buffer, NULL((void*)0),
530 &sr_end_iter, FALSE(0));
531 }
532
533 new_region->subregions = g_list_reverse (new_region->subregions);
534 return new_region;
535}
536
537static gboolean
538check_iterator (LapizTextRegionIteratorReal *real)
539{
540 if ((real->region == NULL((void*)0)) ||
541 (real->region_time_stamp != real->region->time_stamp))
542 {
543 g_warning("Invalid iterator: either the iterator "
544 "is uninitialized, or the region "
545 "has been modified since the iterator "
546 "was created.");
547
548 return FALSE(0);
549 }
550
551 return TRUE(!(0));
552}
553
554void
555lapiz_text_region_get_iterator (LapizTextRegion *region,
556 LapizTextRegionIterator *iter,
557 guint start)
558{
559 LapizTextRegionIteratorReal *real;
560
561 g_return_if_fail (region != NULL)do { if ((region != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL")
; return; } } while (0)
;
562 g_return_if_fail (iter != NULL)do { if ((iter != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
; } } while (0)
;
563
564 real = (LapizTextRegionIteratorReal *)iter;
565
566 /* region->subregions may be NULL, -> end iter */
567
568 real->region = region;
569 real->subregions = g_list_nth (region->subregions, start);
570 real->region_time_stamp = region->time_stamp;
571}
572
573gboolean
574lapiz_text_region_iterator_is_end (LapizTextRegionIterator *iter)
575{
576 LapizTextRegionIteratorReal *real;
577
578 g_return_val_if_fail (iter != NULL, FALSE)do { if ((iter != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
((0)); } } while (0)
;
579
580 real = (LapizTextRegionIteratorReal *)iter;
581 g_return_val_if_fail (check_iterator (real), FALSE)do { if ((check_iterator (real))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "check_iterator (real)"
); return ((0)); } } while (0)
;
582
583 return (real->subregions == NULL((void*)0));
584}
585
586gboolean
587lapiz_text_region_iterator_next (LapizTextRegionIterator *iter)
588{
589 LapizTextRegionIteratorReal *real;
590
591 g_return_val_if_fail (iter != NULL, FALSE)do { if ((iter != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
((0)); } } while (0)
;
592
593 real = (LapizTextRegionIteratorReal *)iter;
594 g_return_val_if_fail (check_iterator (real), FALSE)do { if ((check_iterator (real))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "check_iterator (real)"
); return ((0)); } } while (0)
;
595
596 if (real->subregions != NULL((void*)0)) {
597 real->subregions = g_list_next (real->subregions)((real->subregions) ? (((GList *)(real->subregions))->
next) : ((void*)0))
;
598 return TRUE(!(0));
599 }
600 else
601 return FALSE(0);
602}
603
604void
605lapiz_text_region_iterator_get_subregion (LapizTextRegionIterator *iter,
606 CtkTextIter *start,
607 CtkTextIter *end)
608{
609 LapizTextRegionIteratorReal *real;
610 Subregion *sr;
611
612 g_return_if_fail (iter != NULL)do { if ((iter != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
; } } while (0)
;
613
614 real = (LapizTextRegionIteratorReal *)iter;
615 g_return_if_fail (check_iterator (real))do { if ((check_iterator (real))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "check_iterator (real)"
); return; } } while (0)
;
616 g_return_if_fail (real->subregions != NULL)do { if ((real->subregions != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "real->subregions != NULL"
); return; } } while (0)
;
617
618 sr = (Subregion*)real->subregions->data;
619 g_return_if_fail (sr != NULL)do { if ((sr != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "sr != NULL"); return
; } } while (0)
;
620
621 if (start)
622 ctk_text_buffer_get_iter_at_mark (real->region->buffer, start, sr->start);
623 if (end)
624 ctk_text_buffer_get_iter_at_mark (real->region->buffer, end, sr->end);
625}
626
627void
628lapiz_text_region_debug_print (LapizTextRegion *region)
629{
630 GList *l;
631
632 g_return_if_fail (region != NULL)do { if ((region != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL")
; return; } } while (0)
;
633
634 g_print ("Subregions: ");
635 l = region->subregions;
636 while (l) {
637 Subregion *sr = l->data;
638 CtkTextIter iter1, iter2;
639 ctk_text_buffer_get_iter_at_mark (region->buffer, &iter1, sr->start);
640 ctk_text_buffer_get_iter_at_mark (region->buffer, &iter2, sr->end);
641 g_print ("%d-%d ", ctk_text_iter_get_offset (&iter1),
642 ctk_text_iter_get_offset (&iter2));
643 l = l->next;
644 }
645 g_print ("\n");
646}