source: trunk/third/gtkhtml/src/htmlclue.c @ 18136

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