1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * anjuta-token-list.c
4 * Copyright (C) Sébastien Granjoux 2009 <seb.sfo@free.fr>
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "anjuta-token-list.h"
21
22 #include "libanjuta/anjuta-debug.h"
23
24 #include <string.h>
25 #include <stdio.h>
26
27 /* Type definition
28 *---------------------------------------------------------------------------*/
29
30 typedef struct _AnjutaTokenStyleSeparator AnjutaTokenStyleSeparator;
31
32 struct _AnjutaTokenStyleSeparator
33 {
34 guint count;
35 gchar *value;
36 gboolean eol;
37 };
38
39 struct _AnjutaTokenStyle
40 {
41 guint max_width;
42 GHashTable *separator;
43 AnjutaTokenStyle *base;
44 };
45
46 /* Private functions
47 *---------------------------------------------------------------------------*/
48
49 static void
free_separator(AnjutaTokenStyleSeparator * sep,gpointer user_data)50 free_separator (AnjutaTokenStyleSeparator *sep, gpointer user_data)
51 {
52 g_free (sep->value);
53 g_slice_free (AnjutaTokenStyleSeparator, sep);
54 }
55
56 static void
free_separator_list(guint key,GList * value,gpointer user_data)57 free_separator_list (guint key, GList *value, gpointer user_data)
58 {
59 /* Free list elements */
60 g_list_foreach (value, (GFunc)free_separator, NULL);
61 g_list_free (value);
62 }
63
64 static AnjutaTokenStyleSeparator*
anjuta_token_style_insert_separator(AnjutaTokenStyle * style,guint key,const gchar * value)65 anjuta_token_style_insert_separator (AnjutaTokenStyle *style, guint key, const gchar *value)
66 {
67 GList *list;
68 GList *last = NULL;
69 GList *sibling = NULL;
70 AnjutaTokenStyleSeparator *sep;
71
72
73 /* Look the separator is already registered */
74 list = (GList *)g_hash_table_lookup (style->separator, GINT_TO_POINTER (key));
75 if (list != NULL)
76 {
77 for (sibling = list; sibling != NULL; sibling = g_list_next(sibling))
78 {
79 sep = (AnjutaTokenStyleSeparator *)sibling->data;
80
81 /* Keep the first separator with count = 1, to insert the new one if
82 * not found */
83 if ((last == NULL) && (sep->count == 1)) last = sibling;
84
85 if (value == NULL)
86 {
87 if (sep->value == NULL)
88 {
89 sep->count++;
90 break;
91 }
92 }
93 else if ((sep->value != NULL) && (strcmp (sep->value, value) == 0))
94 {
95 sep->count++;
96 break;
97 }
98 }
99 }
100
101 if (sibling != NULL)
102 {
103 /* Increment the separator count, Move it if needed */
104 for (last = g_list_previous (sibling); last != NULL; last = g_list_previous (sibling))
105 {
106 if (((AnjutaTokenStyleSeparator *)sibling->data)->count >= ((AnjutaTokenStyleSeparator *)last->data)->count)
107 {
108 last->next = sibling->next;
109 sibling->next = last;
110 sibling->prev = last->prev;
111 last->prev = sibling;
112 }
113 else
114 {
115 break;
116 }
117 }
118
119 if (last == NULL)
120 {
121 /* Update the list head */
122 list = sibling;
123 g_hash_table_replace (style->separator, GINT_TO_POINTER (key), list);
124 }
125
126 return (AnjutaTokenStyleSeparator *)sibling->data;
127 }
128 else
129 {
130 /* Create a new separator */
131 sep = g_slice_new0 (AnjutaTokenStyleSeparator);
132 sep->count = 1;
133 sep->value = g_strdup (value);
134 sep->eol = value == NULL ? FALSE : strchr (value, '\n') != NULL;
135 list = g_list_insert_before (list, last, sep);
136 g_hash_table_replace (style->separator, GINT_TO_POINTER (key), list);
137
138 return sep;
139 }
140 }
141
142 static AnjutaTokenStyleSeparator*
anjuta_token_style_insert_separator_between(AnjutaTokenStyle * style,gint next,gint prev,const gchar * value)143 anjuta_token_style_insert_separator_between (AnjutaTokenStyle *style, gint next, gint prev, const gchar *value)
144 {
145 return anjuta_token_style_insert_separator (style, ((guint)prev & 0xFFFF) | (((guint)next & 0xFFFF) << 16), value);
146 }
147
148 static AnjutaToken*
anjuta_token_style_lookup(AnjutaTokenStyle * style,AnjutaTokenType type,gboolean eol)149 anjuta_token_style_lookup (AnjutaTokenStyle *style, AnjutaTokenType type, gboolean eol)
150 {
151 GList *list;
152
153 list = g_hash_table_lookup (style->separator, GINT_TO_POINTER (type));
154 if ((list == NULL) && (style->base != NULL))
155 {
156 return anjuta_token_style_lookup (style->base, type, eol);
157 }
158 else
159 {
160 return anjuta_token_new_string (ANJUTA_TOKEN_NAME, ((AnjutaTokenStyleSeparator *)list->data)->value);
161 }
162 }
163
164 /* Public style functions
165 *---------------------------------------------------------------------------*/
166
167 void
anjuta_token_style_update(AnjutaTokenStyle * style,AnjutaToken * list)168 anjuta_token_style_update (AnjutaTokenStyle *style, AnjutaToken *list)
169 {
170 AnjutaToken *token;
171 AnjutaToken *next_token;
172 guint prev = 0;
173 guint next = 0;
174 guint line_width = 0;
175 guint sep_count = 0;
176
177 /* Initialize first line width */
178 for (token = list; token != NULL; token = anjuta_token_previous (token))
179 {
180 gchar *value;
181 gchar *eol = NULL;
182 gsize len = 0;
183
184 value = anjuta_token_evaluate (token);
185 if (value != NULL)
186 {
187 eol = strrchr (value, '\n');
188 len = strlen (value);
189 g_free (value);
190 }
191
192 if (eol != NULL)
193 {
194 line_width = value + len - eol;
195 break;
196 }
197
198 line_width += len;
199 }
200
201 for (token = anjuta_token_first_item (list); token != NULL; token = next_token)
202 {
203 gchar *value = NULL;
204 const gchar *eol;
205 gsize len;
206 gint type;
207
208 next_token = anjuta_token_next_item (token);
209 type = anjuta_token_get_type (token);
210 next = next_token == NULL ? 0 : anjuta_token_get_type (next_token);
211
212 value = anjuta_token_evaluate (token);
213 if (value == NULL) continue;
214
215 len = strlen (value);
216 eol = strrchr (value, '\n');
217 if (eol != NULL) len -= (eol - value);
218 g_free (value);
219
220 line_width += len;
221
222 switch (type)
223 {
224 case ANJUTA_TOKEN_START:
225 case ANJUTA_TOKEN_LAST:
226 case ANJUTA_TOKEN_NEXT:
227 break;
228 default:
229 if (eol != NULL)
230 {
231 line_width = len;
232 sep_count = 0;
233 }
234 continue;
235 }
236
237 value = anjuta_token_evaluate (token);
238 anjuta_token_style_insert_separator_between (style, 0, type, value);
239 if (type == ANJUTA_TOKEN_NEXT)
240 {
241 anjuta_token_style_insert_separator_between (style, next, prev, value);
242 anjuta_token_style_insert_separator_between (style, next, ANJUTA_TOKEN_ANY, value);
243 anjuta_token_style_insert_separator_between (style, ANJUTA_TOKEN_ANY, prev, value);
244 }
245 g_free (value);
246
247 if (eol == NULL)
248 {
249 sep_count++;
250 }
251 else
252 {
253 if ((sep_count > 1) && (line_width > style->max_width))
254 {
255 style->max_width = line_width;
256 }
257 sep_count = 0;
258 line_width = len;
259 }
260 }
261 }
262
263 void
anjuta_token_style_format(AnjutaTokenStyle * style,AnjutaToken * list)264 anjuta_token_style_format (AnjutaTokenStyle *style, AnjutaToken *list)
265 {
266 AnjutaToken *item;
267 AnjutaToken *last;
268 AnjutaToken *text;
269 AnjutaToken *prev;
270
271 /* Find following tokens */
272 for (last = list; last != NULL; last = anjuta_token_next (last))
273 {
274 /* Get all tokens in group */
275 last = anjuta_token_last (last);
276
277 gint flags = anjuta_token_get_flags (last);
278 if (!(flags & (ANJUTA_TOKEN_ADDED | ANJUTA_TOKEN_REMOVED))) break;
279 }
280
281 /* Find previous token */
282 for (prev = list; prev != NULL; prev = anjuta_token_previous (prev))
283 {
284 gint flags = anjuta_token_get_flags (prev);
285 if ((anjuta_token_get_length (prev) != 0) && !(flags & (ANJUTA_TOKEN_ADDED | ANJUTA_TOKEN_REMOVED))) break;
286 list = prev;
287 }
288
289 for (item = list; (item != NULL) && (item != last); item = anjuta_token_next (item))
290 {
291 if ((anjuta_token_get_flags (item) & ANJUTA_TOKEN_ADDED) &&
292 !(anjuta_token_get_flags (item) & ANJUTA_TOKEN_REMOVED))
293 {
294 switch (anjuta_token_get_type (item))
295 {
296 case ANJUTA_TOKEN_START:
297 text = anjuta_token_style_lookup (style, ANJUTA_TOKEN_START, FALSE);
298 anjuta_token_set_flags (text, ANJUTA_TOKEN_ADDED);
299 anjuta_token_insert_after (item, text);
300 anjuta_token_merge (item, text);
301 item = text;
302 break;
303 case ANJUTA_TOKEN_NEXT:
304 text = anjuta_token_style_lookup (style, ANJUTA_TOKEN_NEXT, FALSE);
305 anjuta_token_set_flags (text, ANJUTA_TOKEN_ADDED);
306 anjuta_token_insert_after (item, text);
307 anjuta_token_merge (item, text);
308 item = text;
309 break;
310 case ANJUTA_TOKEN_LAST:
311 text = anjuta_token_style_lookup (style, ANJUTA_TOKEN_LAST, FALSE);
312 anjuta_token_set_flags (text, ANJUTA_TOKEN_ADDED);
313 anjuta_token_insert_after (item, text);
314 anjuta_token_merge (item, text);
315 item = text;
316 break;
317 default:
318 break;
319 }
320 }
321 }
322 }
323
324 /* Word functions
325 *---------------------------------------------------------------------------*/
326
327 /**
328 * anjuta_token_first_word:
329 * @list: a #AnjutaToken object being a list
330 *
331 * Get the first word of the list. A word is an item in the list which is not
332 * a space or a separator.
333 *
334 * Return value: A #AnjutaToken representing the first word or %NULL.
335 */
336 AnjutaToken *
anjuta_token_first_word(AnjutaToken * list)337 anjuta_token_first_word (AnjutaToken *list)
338 {
339 AnjutaToken *item;
340
341 for (item = anjuta_token_first_item (list); item != NULL; item = anjuta_token_next_item (item))
342 {
343 if (anjuta_token_list (item) != list)
344 {
345 item = NULL;
346 break;
347 }
348 switch (anjuta_token_get_type (item))
349 {
350 case ANJUTA_TOKEN_START:
351 case ANJUTA_TOKEN_NEXT:
352 continue;
353 case ANJUTA_TOKEN_LAST:
354 item = NULL;
355 break;
356 default:
357 if (anjuta_token_is_empty (item) || (anjuta_token_get_flags(item) & ANJUTA_TOKEN_REMOVED)) continue;
358 break;
359 }
360 break;
361 }
362
363 return item;
364 }
365
366 AnjutaToken *
anjuta_token_next_word(AnjutaToken * item)367 anjuta_token_next_word (AnjutaToken *item)
368 {
369 AnjutaToken *next;
370
371 for (next = anjuta_token_next_item (item); next != NULL; next = anjuta_token_next_item (next))
372 {
373 if (anjuta_token_list (item) != anjuta_token_list (next))
374 {
375 next = NULL;
376 break;
377 }
378 switch (anjuta_token_get_type (next))
379 {
380 case ANJUTA_TOKEN_START:
381 case ANJUTA_TOKEN_NEXT:
382 continue;
383 case ANJUTA_TOKEN_LAST:
384 next = NULL;
385 break;
386 default:
387 if (anjuta_token_is_empty (next) || (anjuta_token_get_flags(next) & ANJUTA_TOKEN_REMOVED)) continue;
388 break;
389 }
390 break;
391 }
392
393 return next;
394 }
395
396 AnjutaToken *
anjuta_token_nth_word(AnjutaToken * list,guint n)397 anjuta_token_nth_word (AnjutaToken *list, guint n)
398 {
399 AnjutaToken *item;
400 gboolean no_item = TRUE;
401
402 for (item = anjuta_token_first_item (list); item != NULL; item = anjuta_token_next_item (item))
403 {
404 if (anjuta_token_list (item) != list)
405 {
406 item = NULL;
407 break;
408 }
409 switch (anjuta_token_get_type (item))
410 {
411 case ANJUTA_TOKEN_START:
412 break;
413 case ANJUTA_TOKEN_NEXT:
414 if (no_item)
415 {
416 if (n == 0) return NULL;
417 n--;
418 }
419 no_item = TRUE;
420 break;
421 case ANJUTA_TOKEN_LAST:
422 return NULL;
423 default:
424 if (n == 0) return item;
425 n--;
426 no_item = FALSE;
427 break;
428 }
429 }
430
431 return NULL;
432 }
433
434 AnjutaToken *
anjuta_token_replace_nth_word(AnjutaToken * list,guint n,AnjutaToken * item)435 anjuta_token_replace_nth_word (AnjutaToken *list, guint n, AnjutaToken *item)
436 {
437 AnjutaToken *token;
438 gboolean no_item = TRUE;
439
440 token = anjuta_token_first_item (list);
441 if (token == NULL)
442 {
443 token = anjuta_token_insert_after (token, anjuta_token_new_static (ANJUTA_TOKEN_LAST | ANJUTA_TOKEN_ADDED, NULL));
444 anjuta_token_merge (list, token);
445 }
446
447 for (n++;;)
448 {
449 AnjutaToken *next;
450
451 switch (anjuta_token_get_type (token))
452 {
453 case ANJUTA_TOKEN_LAST:
454 if (no_item)
455 {
456 n--;
457 if (n == 0)
458 {
459 token = anjuta_token_insert_before (token, item);
460 return token;
461 }
462 }
463 token = anjuta_token_insert_before (token, anjuta_token_new_static (ANJUTA_TOKEN_NEXT | ANJUTA_TOKEN_ADDED, NULL));
464 no_item = TRUE;
465 break;
466 case ANJUTA_TOKEN_NEXT:
467 if (no_item)
468 {
469 n--;
470 if (n == 0)
471 {
472 token = anjuta_token_insert_before (token, item);
473 return token;
474 }
475 }
476 no_item = TRUE;
477 break;
478 case ANJUTA_TOKEN_ITEM:
479 n--;
480 if (n == 0)
481 {
482 anjuta_token_set_flags (token, ANJUTA_TOKEN_REMOVED);
483 token = anjuta_token_insert_before (token, item);
484 return token;
485 }
486 no_item = FALSE;
487 break;
488 default:
489 break;
490 }
491
492 next = anjuta_token_next_item (token);
493 if (next == NULL)
494 {
495 token = anjuta_token_insert_after (token, anjuta_token_new_static (ANJUTA_TOKEN_LAST | ANJUTA_TOKEN_ADDED, NULL));
496 anjuta_token_merge (list, token);
497 }
498 else
499 {
500 token = next;
501 }
502 }
503 }
504
505 AnjutaToken *
anjuta_token_insert_word_before(AnjutaToken * list,AnjutaToken * sibling,AnjutaToken * item)506 anjuta_token_insert_word_before (AnjutaToken *list, AnjutaToken *sibling, AnjutaToken *item)
507 {
508 AnjutaToken *token;
509
510 if (list == NULL) list = anjuta_token_list (sibling);
511
512 for (token = anjuta_token_first_item (list); token != NULL;)
513 {
514 AnjutaToken *next;
515
516 switch (anjuta_token_get_type (token))
517 {
518 case ANJUTA_TOKEN_LAST:
519 anjuta_token_insert_before (token, anjuta_token_new_static (ANJUTA_TOKEN_NEXT | ANJUTA_TOKEN_ADDED, NULL));
520 anjuta_token_insert_before (token, item);
521 return item;
522 case ANJUTA_TOKEN_START:
523 if (token == sibling)
524 {
525 anjuta_token_insert_after (token, anjuta_token_new_static (ANJUTA_TOKEN_NEXT | ANJUTA_TOKEN_ADDED, NULL));
526 anjuta_token_insert_after (token, item);
527 return item;
528 }
529 break;
530 case ANJUTA_TOKEN_NEXT:
531 if (token == sibling)
532 {
533 token = anjuta_token_insert_before (token, item);
534 anjuta_token_insert_before (token, anjuta_token_new_static (ANJUTA_TOKEN_NEXT | ANJUTA_TOKEN_ADDED, NULL));
535 return item;
536 }
537 break;
538 default:
539 if (token == sibling)
540 {
541 anjuta_token_insert_before (token, item);
542 anjuta_token_insert_before (token, anjuta_token_new_static (ANJUTA_TOKEN_NEXT | ANJUTA_TOKEN_ADDED, NULL));
543 return item;
544 }
545 break;
546 }
547
548 next = anjuta_token_next_item (token);
549 if (next == NULL)
550 {
551 token = anjuta_token_insert_after (token, anjuta_token_new_static (ANJUTA_TOKEN_NEXT | ANJUTA_TOKEN_ADDED, NULL));
552 anjuta_token_insert_after (token, item);
553 return item;
554 }
555 token = next;
556 }
557
558 anjuta_token_prepend_items (list, item);
559
560 return item;
561 }
562
563 AnjutaToken *
anjuta_token_insert_word_after(AnjutaToken * list,AnjutaToken * sibling,AnjutaToken * item)564 anjuta_token_insert_word_after (AnjutaToken *list, AnjutaToken *sibling, AnjutaToken *item)
565 {
566 AnjutaToken *token;
567
568 if (list == NULL) list = anjuta_token_list (sibling);
569
570 for (token = anjuta_token_first_item (list); token != NULL;)
571 {
572 AnjutaToken *next;
573
574 next = anjuta_token_next_item (token);
575
576 switch (anjuta_token_get_type (token))
577 {
578 case ANJUTA_TOKEN_LAST:
579 anjuta_token_insert_before (token, anjuta_token_new_static (ANJUTA_TOKEN_NEXT | ANJUTA_TOKEN_ADDED, NULL));
580 anjuta_token_insert_before (token, item);
581 return item;
582 case ANJUTA_TOKEN_START:
583 if ((sibling == NULL) || (token == sibling))
584 {
585 if (next != NULL) anjuta_token_insert_after (token, anjuta_token_new_static (ANJUTA_TOKEN_NEXT | ANJUTA_TOKEN_ADDED, NULL));
586 anjuta_token_insert_after (token, item);
587 return item;
588 }
589 break;
590 case ANJUTA_TOKEN_NEXT:
591 if (token == sibling)
592 {
593 token = anjuta_token_insert_after (token, item);
594 anjuta_token_insert_after (token, anjuta_token_new_static (ANJUTA_TOKEN_NEXT | ANJUTA_TOKEN_ADDED, NULL));
595 return item;
596 }
597 break;
598 default:
599 if (token == sibling)
600 {
601 token = anjuta_token_insert_after (token, anjuta_token_new_static (ANJUTA_TOKEN_NEXT | ANJUTA_TOKEN_ADDED, NULL));
602 anjuta_token_insert_after (token, item);
603 return item;
604 }
605 break;
606 }
607
608 if (next == NULL)
609 {
610 token = anjuta_token_insert_after (token, anjuta_token_new_static (ANJUTA_TOKEN_NEXT | ANJUTA_TOKEN_ADDED, NULL));
611 anjuta_token_insert_after (token, item);
612 return item;
613 }
614 token = next;
615 }
616
617 anjuta_token_prepend_items (list, item);
618
619 return item;
620 }
621
622 AnjutaToken*
anjuta_token_remove_word(AnjutaToken * token)623 anjuta_token_remove_word (AnjutaToken *token)
624 {
625 AnjutaToken *next;
626
627 anjuta_token_set_flags (token, ANJUTA_TOKEN_REMOVED);
628 next = anjuta_token_next_item (token);
629 if ((next != NULL) && (anjuta_token_list (token) == anjuta_token_list (next)) && (anjuta_token_get_type (next) == ANJUTA_TOKEN_NEXT))
630 {
631 /* Remove following separator */
632 anjuta_token_set_flags (next, ANJUTA_TOKEN_REMOVED);
633 }
634 else
635 {
636 next = anjuta_token_previous_item (token);
637 if ((next != NULL) && (anjuta_token_list (token) == anjuta_token_list (next)) && (anjuta_token_get_type (next) == ANJUTA_TOKEN_NEXT))
638 {
639 /* Remove previous separator */
640 anjuta_token_set_flags (next, ANJUTA_TOKEN_REMOVED);
641 }
642 else
643 {
644 next = NULL;
645 }
646 }
647
648 return next;
649 }
650
651 /**
652 * anjuta_token_remove_list:
653 * @token: a #AnjutaToken corresponding to a list
654 *
655 * Remove a complete list of token.
656 *
657 * Return value: A #AnjutaToken representing the following token
658 */
659 AnjutaToken *
anjuta_token_remove_list(AnjutaToken * list)660 anjuta_token_remove_list (AnjutaToken *list)
661 {
662 AnjutaToken *next;
663 AnjutaToken *prev;
664
665 if (!(anjuta_token_get_flags(list) & ANJUTA_TOKEN_REMOVED))
666 {
667 anjuta_token_set_flags (list, ANJUTA_TOKEN_REMOVED);
668
669 prev = anjuta_token_previous_item (list);
670 if (prev != NULL)
671 {
672 if (anjuta_token_get_type (prev) == ANJUTA_TOKEN_EOL)
673 {
674 /* Remove line above if empty */
675 AnjutaToken *prev_prev = anjuta_token_previous_item (prev);
676
677 if ((prev_prev == NULL) || (anjuta_token_get_type (prev_prev) == ANJUTA_TOKEN_EOL) || (anjuta_token_get_type (prev_prev) == ANJUTA_TOKEN_COMMENT))
678 {
679 anjuta_token_set_flags (prev, ANJUTA_TOKEN_REMOVED);
680 }
681 }
682 else if (anjuta_token_get_type (prev) == ANJUTA_TOKEN_COMMENT)
683 {
684 /* Remove comment above if there is an empty line after it */
685 do
686 {
687 prev = anjuta_token_previous_item (prev);
688 }
689 while ((prev != NULL) && (anjuta_token_get_type (prev) == ANJUTA_TOKEN_COMMENT));
690
691 if ((prev != NULL) && (anjuta_token_get_type (prev) == ANJUTA_TOKEN_EOL))
692 {
693 prev = list;
694 do
695 {
696 anjuta_token_set_flags (prev, ANJUTA_TOKEN_REMOVED);
697 prev = anjuta_token_previous_item (prev);
698 }
699 while ((prev != NULL) && (anjuta_token_get_type (prev) == ANJUTA_TOKEN_COMMENT));
700 }
701 }
702 }
703 }
704
705 next = anjuta_token_next_item (list);
706 if (next != NULL)
707 {
708 if (anjuta_token_get_type (next) == ANJUTA_TOKEN_EOL)
709 {
710 anjuta_token_set_flags (next, ANJUTA_TOKEN_REMOVED);
711 }
712 next = anjuta_token_next_item (next);
713 }
714
715 return next;
716 }
717
718 AnjutaToken *
anjuta_token_insert_token_list(gboolean after,AnjutaToken * pos,...)719 anjuta_token_insert_token_list (gboolean after, AnjutaToken *pos,...)
720 {
721 AnjutaToken *first = NULL;
722 GList *group = NULL;
723 va_list args;
724 gint type;
725
726 va_start (args, pos);
727
728 for (type = va_arg (args, gint); type != 0; type = va_arg (args, gint))
729 {
730 gchar *string = va_arg (args, gchar *);
731 AnjutaToken *token;
732
733 if (pos == NULL)
734 {
735 pos = token = anjuta_token_new_string (type | ANJUTA_TOKEN_ADDED, string);
736 after = TRUE;
737 }
738 else
739 {
740 if (after)
741 {
742 pos = token = anjuta_token_insert_after (pos, anjuta_token_new_string (type | ANJUTA_TOKEN_ADDED, string));
743 }
744 else
745 {
746 token = anjuta_token_insert_before (pos, anjuta_token_new_string (type | ANJUTA_TOKEN_ADDED, string));
747 }
748 }
749 if (first == NULL) first = token;
750
751 if (group != NULL)
752 {
753 anjuta_token_merge ((AnjutaToken *)group->data, token);
754 }
755
756 if (string == NULL)
757 {
758 switch (type)
759 {
760 case ANJUTA_TOKEN_LIST:
761 break;
762 default:
763 group = g_list_delete_link (group, group);
764 break;
765 }
766 group = g_list_prepend (group, token);
767 }
768 }
769 g_list_free (group);
770
771 va_end (args);
772
773 return first;
774 }
775
776 AnjutaToken *
anjuta_token_find_type(AnjutaToken * list,gint flags,AnjutaTokenType * types)777 anjuta_token_find_type (AnjutaToken *list, gint flags, AnjutaTokenType* types)
778 {
779 AnjutaToken *tok;
780 AnjutaToken *last = NULL;
781
782 for (tok = list; tok != NULL; tok = anjuta_token_next (tok))
783 {
784 AnjutaTokenType *type;
785 for (type = types; *type != 0; type++)
786 {
787 if (anjuta_token_get_type (tok) == *type)
788 {
789 last = tok;
790 if (flags & ANJUTA_TOKEN_SEARCH_NOT) break;
791 if (!(flags & ANJUTA_TOKEN_SEARCH_LAST)) break;
792 }
793 }
794 if ((flags & ANJUTA_TOKEN_SEARCH_NOT) && (*type == 0)) break;
795 }
796
797 return last;
798 }
799
800 AnjutaToken *
anjuta_token_skip_comment(AnjutaToken * token)801 anjuta_token_skip_comment (AnjutaToken *token)
802 {
803 if (token == NULL) return NULL;
804
805 for (;;)
806 {
807 for (;;)
808 {
809 AnjutaToken *next = anjuta_token_next (token);
810
811 if (next == NULL) return token;
812
813 switch (anjuta_token_get_type (token))
814 {
815 case ANJUTA_TOKEN_FILE:
816 case ANJUTA_TOKEN_SPACE:
817 token = next;
818 continue;
819 case ANJUTA_TOKEN_COMMENT:
820 token = next;
821 break;
822 default:
823 return token;
824 }
825 break;
826 }
827
828 for (;;)
829 {
830 AnjutaToken *next = anjuta_token_next (token);
831
832 if (next == NULL) return token;
833 token = next;
834 if (anjuta_token_get_type (token) == ANJUTA_TOKEN_EOL) break;
835 }
836 }
837 }
838
839 /* Constructor & Destructor
840 *---------------------------------------------------------------------------*/
841
842 AnjutaTokenStyle *
anjuta_token_style_new(const gchar * start,const gchar * next,const gchar * eol,const gchar * last,guint max_width)843 anjuta_token_style_new (const gchar *start, const gchar *next, const gchar *eol, const gchar *last, guint max_width)
844 {
845 AnjutaTokenStyle *style;
846
847 style = g_slice_new0 (AnjutaTokenStyle);
848 style->max_width = max_width;
849
850 style->separator = g_hash_table_new (g_direct_hash, NULL);
851 anjuta_token_style_insert_separator (style, ANJUTA_TOKEN_START, start);
852 anjuta_token_style_insert_separator (style, ANJUTA_TOKEN_NEXT, next);
853 anjuta_token_style_insert_separator (style, ANJUTA_TOKEN_NEXT, eol);
854 anjuta_token_style_insert_separator (style, ANJUTA_TOKEN_LAST, last);
855
856 return style;
857 }
858
859 AnjutaTokenStyle *
anjuta_token_style_new_from_base(AnjutaTokenStyle * base)860 anjuta_token_style_new_from_base (AnjutaTokenStyle *base)
861 {
862 AnjutaTokenStyle *style;
863
864 style = g_slice_new0 (AnjutaTokenStyle);
865 style->max_width = base->max_width;
866 style->base = base;
867
868 style->separator = g_hash_table_new (g_direct_hash, NULL);
869
870 return style;
871 }
872
873 void
anjuta_token_style_free(AnjutaTokenStyle * style)874 anjuta_token_style_free (AnjutaTokenStyle *style)
875 {
876 g_hash_table_foreach (style->separator, (GHFunc)free_separator_list, NULL);
877 g_hash_table_destroy (style->separator);
878 g_slice_free (AnjutaTokenStyle, style);
879 }
880