source: trunk/third/gtkhtml3/src/htmlclue.c @ 21116

Revision 21116, 19.5 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21115, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2/*  This file is part of the GtkHTML library.
3
4    Copyright (C) 1997 Martin Jones (mjones@kde.org)
5    Copyright (C) 1997 Torben Weis (weis@kde.org)
6    Copyright (C) 1999, 2000 Helix Code, Inc.
7
8    This library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Library General Public
10    License as published by the Free Software Foundation; either
11    version 2 of the License, or (at your option) any later version.
12
13    This library is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Library General Public License for more details.
17
18    You should have received a copy of the GNU Library General Public License
19    along with this library; see the file COPYING.LIB.  If not, write to
20    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21    Boston, MA 02111-1307, USA.
22*/
23
24#include <config.h>
25#include "htmlclue.h"
26#include "htmlclueflow.h"
27#include "htmlobject.h"
28#include "htmlsearch.h"
29#include "htmltextslave.h"
30#include "htmltype.h"
31
32
33#define HC_CLASS(x) (HTML_CLUE_CLASS (HTML_OBJECT (x)->klass))
34
35HTMLClueClass html_clue_class;
36static HTMLObjectClass *parent_class = NULL;
37
38static void set_parent (HTMLObject *o, HTMLObject *tail, HTMLObject *parent);
39
40
41/* HTMLObject methods.  */
42
43static void
44destroy (HTMLObject *o)
45{
46        HTMLObject *p;
47        HTMLObject *next;
48
49        for (p = HTML_CLUE (o)->head; p != NULL; p = next) {
50                next = p->next;
51                html_object_destroy (p);
52        }
53        HTML_CLUE (o)->head = NULL;
54        HTML_CLUE (o)->tail = NULL;
55                       
56        HTML_OBJECT_CLASS (parent_class)->destroy (o);
57}
58
59static gint
60get_n_children (HTMLObject *o)
61{
62        HTMLObject *cur = HTML_CLUE (o)->head;
63        gint n_children = 0;
64
65        while (cur) {
66                n_children ++;
67                cur = html_object_next_not_slave (cur);
68        }
69
70        return n_children;
71}
72
73static HTMLObject *
74get_child (HTMLObject *o, gint index)
75{
76        HTMLObject *cur = HTML_CLUE (o)->head;
77
78        g_return_val_if_fail (index >= 0, NULL);
79
80        while (cur) {
81                if (!index)
82                        break;
83                index --;
84                cur = html_object_next_not_slave (cur);
85        }
86
87        return cur;
88}
89
90static gint
91get_child_index (HTMLObject *self, HTMLObject *child)
92{
93        HTMLObject *cur = HTML_CLUE (self)->head;
94        gint index = 0;
95
96        while (cur) {
97                if (cur == child)
98                        return index;
99                index ++;
100                cur = html_object_next_not_slave (cur);
101        }
102
103        return -1;
104}
105
106static guint
107get_recursive_length (HTMLObject *self)
108{
109        HTMLObject *o = HTML_CLUE (self)->head;
110        guint len = 0;
111
112        while (o) {
113                len += html_object_get_recursive_length (o);
114                o = o->next;
115        }
116
117        return len;
118}
119
120static void
121copy (HTMLObject *self,
122      HTMLObject *dest)
123{
124        (* HTML_OBJECT_CLASS (parent_class)->copy) (self, dest);
125
126        HTML_CLUE (dest)->head = NULL;
127        HTML_CLUE (dest)->tail = NULL;
128        HTML_CLUE (dest)->curr = NULL;
129
130        HTML_CLUE (dest)->valign = HTML_CLUE (self)->valign;
131        HTML_CLUE (dest)->halign = HTML_CLUE (self)->halign;
132}
133
134static HTMLObject *
135op_helper (HTMLObject *self, HTMLEngine *e, GList *from, GList *to, GList *left, GList *right, guint *len, gboolean cut)
136{
137        HTMLClue *clue = HTML_CLUE (self);
138        HTMLObject *cc;
139        HTMLObject *o, *last, *cnext, *child;
140
141        cc   = html_object_dup (self);
142        o    = (from) ? HTML_OBJECT (from->data) : clue->head;
143        last = (to)   ? HTML_OBJECT (to->data)   : clue->tail;
144
145        if ((o == NULL) && (last == NULL))
146                return cc;
147
148        if (HTML_IS_TEXT_SLAVE (last))
149                last = html_object_prev_not_slave (last);
150
151        g_assert (o->parent == self);
152        g_assert (last->parent == self);
153
154        while (o) {
155                cnext = html_object_next_not_slave (o);
156                child = cut ? html_object_op_cut (o, e,
157                                              html_object_get_bound_list (o, from),
158                                              html_object_get_bound_list (o, to),
159                                              left ? left->next : NULL, right ? right->next : NULL, len)
160                        : html_object_op_copy (o, cc, e,
161                                               html_object_get_bound_list (o, from),
162                                               html_object_get_bound_list (o, to), len);
163                if (child)
164                        html_clue_append (HTML_CLUE (cc), child);
165
166                if (o == last)
167                        break;
168                o = cnext;
169        }
170
171        return cc;
172}
173
174static HTMLObject *
175op_copy (HTMLObject *self, HTMLObject *parent, HTMLEngine *e, GList *from, GList *to, guint *len)
176{
177        return op_helper (self, e, from, to, NULL, NULL, len, FALSE);
178}
179
180static HTMLObject *
181op_cut (HTMLObject *self, HTMLEngine *e, GList *from, GList *to, GList *left, GList *right, guint *len)
182{
183        HTMLObject *rv;
184        HTMLClue *clue;
185
186        clue = HTML_CLUE (self);
187        rv   = op_helper (self, e, from, to, left, right, len, TRUE);
188        if (!clue->head) {
189                if (self->parent)
190                        html_object_remove_child (self->parent, self);
191                html_object_destroy (self);
192        } else
193                html_object_change_set (self, HTML_CHANGE_ALL_CALC);
194
195        return rv;
196}
197
198static gboolean
199merge (HTMLObject *self, HTMLObject *with, HTMLEngine *e, GList **left, GList **right, HTMLCursor *cursor)
200{
201        HTMLClue   *clue1, *clue2;
202
203        clue1 = HTML_CLUE (self);
204        clue2 = HTML_CLUE (with);
205
206        html_clue_append (clue1, clue2->head);
207        clue2->head = NULL;
208        clue2->tail = NULL;
209
210        html_object_change_set (self, HTML_CHANGE_ALL_CALC);
211        return TRUE;
212}
213
214static void
215remove_child (HTMLObject *self, HTMLObject *child)
216{
217        html_clue_remove (HTML_CLUE (self), child);
218}
219
220static void
221split (HTMLObject *self, HTMLEngine *e, HTMLObject *child, gint offset, gint level, GList **left, GList **right)
222{
223        HTMLObject *dup;
224        HTMLClue *clue;
225
226        clue = HTML_CLUE (self);
227        dup  = html_object_dup (self);
228
229        HTML_CLUE (dup)->tail  = HTML_CLUE (self)->tail;
230        HTML_CLUE (self)->tail = child->prev;
231        if (child->prev)
232                        child->prev->next = NULL;
233        child->prev = NULL;
234        if (child == HTML_CLUE (self)->head)
235                HTML_CLUE (self)->head = NULL;
236        HTML_CLUE (dup)->head  = child;
237        set_parent (child, NULL, dup);
238
239        if (self->parent && HTML_OBJECT_TYPE (self->parent) != HTML_TYPE_TABLE)
240                html_clue_append_after (HTML_CLUE (self->parent), dup, self);
241
242        self->x = 0;
243        self->y = 0;
244
245        *left  = g_list_prepend (*left, self);
246        *right = g_list_prepend (*right, dup);
247
248        level--;
249        if (level)
250                html_object_split (self->parent, e, dup, 0, level, left, right);
251}
252
253static void
254draw (HTMLObject *o,
255      HTMLPainter *p,
256      gint x, gint y,
257      gint width, gint height,
258      gint tx, gint ty)
259{
260        HTMLObject *obj;
261       
262        if (y + height < o->y - o->ascent || y > o->y + o->descent)
263                return;
264
265        tx += o->x;
266        ty += o->y - o->ascent;
267       
268        for (obj = HTML_CLUE (o)->head; obj != 0; obj = obj->next) {
269                if (!(obj->flags & HTML_OBJECT_FLAG_ALIGNED)) {
270                        html_object_draw (obj,
271                                          p,
272                                          x - o->x, y - (o->y - o->ascent),
273                                          width, height,
274                                          tx, ty);
275                }
276        }
277}
278
279static void
280set_max_height (HTMLObject *o, HTMLPainter *painter, gint height)
281{
282        HTMLClue *clue = HTML_CLUE (o);
283        HTMLObject *obj;
284
285        if (o->ascent < height) {
286                for (obj = HTML_CLUE (o)->head; obj != 0; obj = obj->next) {
287                        html_object_set_max_height (obj, painter, height);
288                        if (clue->valign == HTML_VALIGN_MIDDLE)
289                                obj->y += (height - o->ascent)/2;
290                        else if (clue->valign == HTML_VALIGN_BOTTOM)
291                                obj->y += height - o->ascent;
292                }
293
294                o->ascent = height;
295        }
296}
297
298static void
299reset (HTMLObject *clue)
300{
301        HTMLObject *obj;
302
303        for (obj = HTML_CLUE (clue)->head; obj != NULL; obj = obj->next)
304                html_object_reset (obj);
305
306        HTML_CLUE (clue)->curr = NULL;
307
308        (* HTML_OBJECT_CLASS (parent_class)->reset) (HTML_OBJECT (clue));
309}
310
311static gboolean
312html_clue_real_calc_size (HTMLObject *o, HTMLPainter *painter, GList **changed_objs)
313{
314        gboolean changed;
315
316        /* If we have already called calc_size for the children, then just
317           continue from the last object done in previous call. */
318        if (HTML_CLUE (o)->curr == NULL) {
319                o->ascent = 0;
320                HTML_CLUE (o)->curr = HTML_CLUE (o)->head;
321        }
322
323        changed = FALSE;
324
325        while (HTML_CLUE (o)->curr != NULL) {
326                changed |= html_object_calc_size (HTML_CLUE (o)->curr, painter, changed_objs);
327                HTML_CLUE (o)->curr = HTML_CLUE (o)->curr->next;
328        }
329
330        /* Remember the last object so that we can start from here next time
331           we are called */
332        HTML_CLUE (o)->curr = HTML_CLUE (o)->tail;
333
334        return changed;
335}
336
337static gint
338calc_preferred_width (HTMLObject *o,
339                      HTMLPainter *painter)
340{
341        gint prefWidth = 0;
342        HTMLObject *obj;
343       
344        for (obj = HTML_CLUE (o)->head; obj != 0; obj = obj->next) {
345                gint w;
346
347                w = html_object_calc_preferred_width (obj, painter);
348                if (w > prefWidth)
349                        prefWidth = w;
350        }
351
352        return prefWidth;
353}
354
355/* FIXME: This should be in HTMLClueV.  */
356static gint
357calc_min_width (HTMLObject *o,
358                HTMLPainter *painter)
359{
360        HTMLObject *obj;
361        gint minWidth = 0;
362       
363        for (obj = HTML_CLUE (o)->head; obj != 0; obj = obj->next) {
364                gint w;
365
366                w = html_object_calc_min_width (obj, painter);
367                if (w > minWidth)
368                        minWidth = w;
369        }
370       
371        return minWidth;
372}
373
374static HTMLAnchor *
375find_anchor (HTMLObject *self, const char *name, gint *x, gint *y)
376{
377        HTMLClue *clue;
378        HTMLObject *obj;
379        HTMLAnchor *anchor;
380
381        *x += self->x;
382        *y += self->y - self->ascent;
383
384        clue = HTML_CLUE (self);
385
386        for ( obj = clue->head; obj != NULL; obj = obj->next ) {
387                if ((anchor = html_object_find_anchor ( obj, name, x, y)) != 0 )
388                        return anchor;
389        }
390
391        *x -= self->x;
392        *y -= self->y - self->ascent;
393
394        return 0;
395}
396
397static HTMLObject*
398check_point (HTMLObject *o,
399             HTMLPainter *painter,
400             gint x, gint y,
401             guint *offset_return,
402             gboolean for_cursor)
403{
404        HTMLObject *obj;
405        HTMLObject *obj2;
406
407        if (x < o->x || x >= o->x + o->width
408            || y >= o->y + o->descent || y < o->y - o->ascent)
409                return NULL;
410
411        x = x - o->x;
412        y = y - o->y + o->ascent;
413
414        for (obj = HTML_CLUE (o)->head; obj != 0; obj = obj->next) {
415                obj2 = html_object_check_point (obj, painter,
416                                                x, y, offset_return,
417                                                for_cursor);
418                if (obj2 != NULL)
419                        return obj2;
420        }
421
422        return NULL;
423}
424
425static gint
426check_page_split (HTMLObject *self, HTMLPainter *painter, gint y)
427{
428        HTMLClue *clue;
429        HTMLObject *p;
430        gint last_under = 0;
431
432        clue = HTML_CLUE (self);
433        for (p = clue->head; p != NULL; p = p->next) {
434                gint y1, y2;
435
436                y1 = p->y - p->ascent;
437                y2 = p->y + p->descent;
438
439                if (y1 > y)
440                        return last_under;
441
442                if (y >= y1 && y < y2)
443                        return html_object_check_page_split (p, painter, y - y1) + y1;
444                last_under = y2;
445        }
446
447        return y;
448}
449
450static void
451forall (HTMLObject *self,
452        HTMLEngine *e,
453        HTMLObjectForallFunc func,
454        gpointer data)
455{
456        HTMLObject *p, *pnext;
457
458        for (p = HTML_CLUE (self)->head; p != NULL; p = pnext) {
459                pnext = p->next;
460                html_object_forall (p, e, func, data);
461        }
462
463        html_object_class.forall (self, e, func, data);
464}
465
466static gboolean
467is_container (HTMLObject *self)
468{
469        return TRUE;
470}
471
472static gboolean
473save (HTMLObject *self,
474      HTMLEngineSaveState *state)
475{
476        HTMLObject *p;
477        HTMLClue *clue;
478
479        clue = HTML_CLUE (self);
480
481        for (p = clue->head; p != NULL; p = p->next) {
482                if (! html_object_save (p, state))
483                    return FALSE;
484        }
485
486        return TRUE;
487}
488
489static gboolean
490save_plain (HTMLObject *self,
491            HTMLEngineSaveState *state,
492            gint requested_width)
493{
494        HTMLObject *p;
495        HTMLClue *clue;
496
497        clue = HTML_CLUE (self);
498
499        for (p = clue->head; p != NULL; p = p->next) {
500                if (! html_object_save_plain (p, state, requested_width))
501                    return FALSE;
502        }
503
504        return TRUE;
505}
506
507/* HTMLClue methods.  */
508
509static gint
510get_left_clear (HTMLClue *o, gint y)
511{
512        return y;
513}
514
515static gint
516get_right_clear (HTMLClue *o, gint y)
517{
518        return y;
519}
520
521static void
522find_free_area (HTMLClue *clue,
523                HTMLPainter *painter,
524                gint y,
525                gint width, gint height,
526                gint indent, gint *y_pos,
527                gint *lmargin, gint *rmargin)
528{
529        *y_pos = y;
530        *lmargin = 0;
531        *rmargin = MAX (HTML_OBJECT (clue)->max_width, HTML_OBJECT (clue)->width);
532}
533
534static void
535append_right_aligned (HTMLClue *clue, HTMLPainter *painter, HTMLClue *aclue, gint *lmargin, gint *rmargin, gint indent)
536{
537        /* This needs to be implemented in the subclasses.  */
538        g_warning ("`%s' does not implement `append_right_aligned()'.",
539                   html_type_name (HTML_OBJECT_TYPE (clue)));
540}
541
542static gboolean
543appended (HTMLClue *clue, HTMLClue *aclue)
544{
545        return FALSE;
546}
547
548static gboolean
549search (HTMLObject *obj, HTMLSearch *info)
550{
551        HTMLObject *cur;
552        HTMLClue *clue = HTML_CLUE (obj);
553        gboolean next = FALSE;
554
555        /* search_next? */
556        if (html_search_child_on_stack (info, obj)) {
557                cur  = html_search_pop (info);
558                cur = (info->forward) ? cur->next : cur->prev;
559                next = TRUE;
560        } else
561                cur = (info->forward) ? clue->head : clue->tail;
562
563        while (cur) {
564                html_search_push (info, cur);
565                if (html_object_search (cur, info))
566                        return TRUE;
567
568                html_search_pop (info);
569                cur = (info->forward) ? cur->next : cur->prev;
570        }
571
572        if (next)
573                return html_search_next_parent (info);
574
575        return FALSE;
576}
577
578static void
579append_selection_string (HTMLObject *self,
580                         GString *buffer)
581{
582        HTMLObject *o = HTML_CLUE (self)->head;
583
584        while (o) {
585                html_object_append_selection_string (o, buffer);
586                o = o->next;
587        }
588}
589
590static HTMLObject *
591head (HTMLObject *self)
592{
593        return HTML_CLUE (self)->head;
594}
595
596static HTMLObject *
597tail (HTMLObject *self)
598{
599        HTMLObject *obj;
600
601        obj = HTML_CLUE (self)->tail;
602        return (obj && HTML_OBJECT_TYPE (obj) == HTML_TYPE_TEXTSLAVE) ? html_object_prev_not_slave (obj) : obj;
603}
604
605
606void
607html_clue_type_init (void)
608{
609        html_clue_class_init (&html_clue_class, HTML_TYPE_CLUE, sizeof (HTMLClue));
610}
611
612void
613html_clue_class_init (HTMLClueClass *klass,
614                      HTMLType type,
615                      guint size)
616{
617        HTMLObjectClass *object_class;
618
619        g_return_if_fail (klass != NULL);
620
621        object_class = HTML_OBJECT_CLASS (klass);
622        html_object_class_init (object_class, type, size);
623       
624        /* HTMLObject functions */
625        object_class->destroy = destroy;
626        object_class->copy = copy;
627        object_class->op_copy = op_copy;
628        object_class->op_cut = op_cut;
629        object_class->merge = merge;
630        object_class->remove_child = remove_child;
631        object_class->split = split;
632        object_class->draw = draw;
633        object_class->set_max_height = set_max_height;
634        object_class->reset = reset;
635        object_class->calc_size = html_clue_real_calc_size;
636        object_class->calc_preferred_width = calc_preferred_width;
637        object_class->calc_min_width = calc_min_width;
638        object_class->check_point = check_point;
639        object_class->check_page_split = check_page_split;
640        object_class->find_anchor = find_anchor;
641        object_class->forall = forall;
642        object_class->is_container = is_container;
643        object_class->save = save;
644        object_class->save_plain = save_plain;
645        object_class->search = search;
646        object_class->append_selection_string = append_selection_string;
647        object_class->head = head;
648        object_class->tail = tail;
649        object_class->get_recursive_length = get_recursive_length;
650        object_class->get_n_children = get_n_children;
651        object_class->get_child = get_child;
652        object_class->get_child_index = get_child_index;
653
654        /* HTMLClue methods.  */
655        klass->get_left_clear = get_left_clear;
656        klass->get_right_clear = get_right_clear;
657        klass->find_free_area = find_free_area;
658        klass->append_right_aligned = append_right_aligned;
659        klass->appended = appended;
660
661        parent_class = &html_object_class;
662}
663
664void
665html_clue_init (HTMLClue *clue,
666                HTMLClueClass *klass)
667{
668        HTMLObject *object;
669
670        object = HTML_OBJECT (clue);
671        html_object_init (object, HTML_OBJECT_CLASS (klass));
672
673        clue->head = NULL;
674        clue->tail = NULL;
675        clue->curr = NULL;
676
677        clue->valign = HTML_VALIGN_TOP;
678        clue->halign = HTML_HALIGN_LEFT;
679}
680
681
682gint
683html_clue_get_left_clear (HTMLClue *clue, gint y)
684{
685        return (* HC_CLASS (clue)->get_left_clear) (clue, y);
686}
687
688gint
689html_clue_get_right_clear (HTMLClue *clue, gint y)
690{
691        return (* HC_CLASS (clue)->get_right_clear) (clue, y);
692}
693
694void
695html_clue_find_free_area (HTMLClue *clue,
696                          HTMLPainter *painter,
697                          gint y,
698                          gint width, gint height, gint indent, gint *y_pos,
699                          gint *lmargin, gint *rmargin)
700{
701        (* HC_CLASS (clue)->find_free_area) (clue, painter, y, width, height, indent, y_pos, lmargin, rmargin);
702}
703
704void
705html_clue_append_right_aligned (HTMLClue *clue, HTMLPainter *painter,
706                                HTMLClue *aclue, gint *lmargin, gint *rmargin, gint indent)
707{
708        g_assert (clue != NULL);
709        g_assert (aclue != NULL);
710
711        html_object_change_set (HTML_OBJECT (clue), HTML_OBJECT (aclue)->change);
712
713        (* HC_CLASS (clue)->append_right_aligned) (clue, painter, aclue, lmargin, rmargin, indent);
714}
715
716void
717html_clue_append_left_aligned (HTMLClue *clue, HTMLPainter *painter,
718                               HTMLClue *aclue, gint *lmargin, gint *rmargin, gint indent)
719{
720        g_assert (clue != NULL);
721        g_assert (aclue != NULL);
722
723        html_object_change_set (HTML_OBJECT (clue), HTML_OBJECT (aclue)->change);
724
725        (* HC_CLASS (clue)->append_left_aligned) (clue, painter, aclue, lmargin, rmargin, indent);
726}
727
728gboolean
729html_clue_appended (HTMLClue *clue, HTMLClue *aclue)
730{
731        return (* HC_CLASS (clue)->appended) (clue, aclue);
732}
733
734
735/* Utility functions.  */
736
737static HTMLObject *
738get_tail (HTMLObject *p)
739{
740        if (p == NULL)
741                return NULL;
742
743        while (p->next != NULL)
744                p = p->next;
745
746        return p;
747}
748
749static void
750set_parent (HTMLObject *o,
751            HTMLObject *tail,
752            HTMLObject *parent)
753{
754        while (o) {
755                html_object_set_parent (o, parent);
756                if (o == tail)
757                        break;
758                o = o->next;
759        }
760}
761
762/**
763 * html_clue_append_after:
764 * @clue: An HTMLClue.
765 * @o: An HTMLObject.
766 * @where: A child of @clue.
767 *
768 * Insert @o and its successors in @clue after @clue's element @where.
769 **/
770void
771html_clue_append_after (HTMLClue *clue,
772                        HTMLObject *o,
773                        HTMLObject *where)
774{
775        HTMLObject *tail;
776
777        g_return_if_fail (o != NULL);
778        g_return_if_fail (html_object_is_clue (HTML_OBJECT (clue)));
779
780        if (where == NULL) {
781                html_clue_prepend (clue, o);
782                return;
783        }
784        g_return_if_fail (where->parent == HTML_OBJECT (clue));
785
786        html_object_change_set (HTML_OBJECT (clue), o->change);
787
788        tail = get_tail (o);
789
790        if (where->next != NULL)
791                where->next->prev = tail;
792        tail->next = where->next;
793
794        where->next = o;
795        o->prev = where;
796
797        if (where == clue->tail)
798                clue->tail = tail;
799
800        set_parent (o, tail, HTML_OBJECT (clue));
801}
802
803/**
804 * html_clue_append:
805 * @clue: An HTMLClue.
806 * @o: An HTMLObject.
807 *
808 * Append @o and its successors to @clue.
809 **/
810void
811html_clue_append (HTMLClue *clue,
812                  HTMLObject *o)
813{
814        HTMLObject *tail;
815
816        g_return_if_fail (clue != NULL);
817        g_return_if_fail (html_object_is_clue (HTML_OBJECT (clue)));
818        g_return_if_fail (o != NULL);
819
820        html_object_change_set (HTML_OBJECT (clue), o->change);
821
822        tail = get_tail (o);
823
824        if (! clue->head) {
825                clue->head = o;
826                o->prev = NULL;
827        } else {
828                clue->tail->next = o;
829                o->prev = clue->tail;
830        }
831
832        clue->tail = tail;
833        tail->next = NULL;
834
835        html_object_set_parent (o, HTML_OBJECT (clue));
836
837        set_parent (o, tail, HTML_OBJECT (clue));
838}
839
840/**
841 * html_clue_prepend:
842 * @clue: An HTMLClue.
843 * @o: An HTMLObject.
844 *
845 * Prepend @o and its successors to @clue.
846 **/
847void
848html_clue_prepend (HTMLClue *clue,
849                   HTMLObject *o)
850{
851        HTMLObject *tail;
852
853        g_return_if_fail (clue != NULL);
854        g_return_if_fail (o != NULL);
855
856        html_object_change_set (HTML_OBJECT (clue), o->change);
857
858        tail = get_tail (o);
859
860        if (! clue->head) {
861                clue->head = o;
862                clue->tail = tail;
863                o->prev = NULL;
864        } else {
865                o->next = clue->head;
866                clue->head->prev = o;
867                clue->head = o;
868        }
869
870        o->prev = NULL;
871
872        set_parent (o, tail, HTML_OBJECT (clue));
873}
874
875/**
876 * html_clue_remove:
877 * @clue: An HTMLClue.
878 * @o: An HTMLObject.
879 *
880 * Remove object @o from the clue.
881 **/
882void
883html_clue_remove (HTMLClue *clue,
884                  HTMLObject *o)
885{
886        g_return_if_fail (clue != NULL);
887        g_return_if_fail (o != NULL);
888        g_return_if_fail (clue == HTML_CLUE (o->parent));
889
890        if (o == clue->head)
891                clue->head = o->next;
892        if (o == clue->tail)
893                clue->tail = o->prev;
894
895        if (o->next != NULL)
896                o->next->prev = o->prev;
897        if (o->prev != NULL)
898                o->prev->next = o->next;
899
900        o->parent = NULL;
901        o->prev = NULL;
902        o->next = NULL;
903}
904
905void
906html_clue_remove_text_slaves (HTMLClue *clue)
907{
908        HTMLObject *p;
909        HTMLObject *pnext;
910
911        g_return_if_fail (clue != NULL);
912
913        for (p = clue->head; p != NULL; p = pnext) {
914                pnext = p->next;
915
916                if (HTML_OBJECT_TYPE (p) == HTML_TYPE_TEXTSLAVE) {
917                        html_clue_remove (clue, p);
918                        html_object_destroy (p);
919                }
920        }
921}
922
923
924gboolean
925html_clue_is_empty (HTMLClue *clue)
926{
927        if (clue->head == NULL)
928                return TRUE;
929        if (clue->head == clue->tail
930            && HTML_IS_CLUEFLOW (clue->head) && html_clueflow_is_empty (HTML_CLUEFLOW (clue->head)))
931                return TRUE;
932        return FALSE;
933}
Note: See TracBrowser for help on using the repository browser.