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

Revision 18136, 22.1 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/*
3    Copyright (C) 1997 Martin Jones (mjones@kde.org)
4              (C) 1997 Torben Weis (weis@kde.org)
5
6    This library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Library General Public
8    License as published by the Free Software Foundation; either
9    version 2 of the License, or (at your option) any later version.
10
11    This library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Library General Public License for more details.
15
16    You should have received a copy of the GNU Library General Public License
17    along with this library; see the file COPYING.LIB.  If not, write to
18    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.
20*/
21
22#include <config.h>
23#include "htmlcluealigned.h"
24#include "htmlcluev.h"
25#include "htmlengine.h"
26#include "htmlpainter.h"
27
28
29HTMLClueVClass html_cluev_class;
30
31static HTMLClueClass *parent_class = NULL;
32
33
34/* FIXME this must be rewritten as the multiple type casts make my head spin.
35   The types in `HTMLClueAligned' are chosen wrong.  */
36static void
37remove_aligned_by_parent ( HTMLClueV *cluev,
38                           HTMLObject *p )
39{
40    HTMLClueAligned *tmp;
41        HTMLObject *obj;
42
43    tmp = 0;
44    obj = cluev->align_left_list;
45
46    while ( obj ) {
47                if ( obj->parent == p ) {
48                        if ( tmp ) {
49                                tmp->next_aligned = HTML_CLUEALIGNED (obj)->next_aligned;
50                                tmp = HTML_CLUEALIGNED (obj);
51                        } else {
52                                cluev->align_left_list
53                                        = HTML_OBJECT (HTML_CLUEALIGNED (obj)->next_aligned);
54                                tmp = 0;
55                        }
56                } else {
57                        tmp = HTML_CLUEALIGNED (obj);
58                }
59
60                obj = HTML_OBJECT (HTML_CLUEALIGNED (obj)->next_aligned);
61    }
62
63    tmp = 0;
64    obj = cluev->align_right_list;
65
66    while ( obj ) {
67                if ( obj->parent == p ) {
68                        if ( tmp ) {
69                                tmp->next_aligned = HTML_CLUEALIGNED (obj)->next_aligned;
70                                tmp = HTML_CLUEALIGNED (obj);
71                        } else {
72                                cluev->align_right_list
73                                        = HTML_OBJECT (HTML_CLUEALIGNED (obj)->next_aligned);
74                                tmp = 0;
75                        }
76                } else {
77                        tmp = HTML_CLUEALIGNED (obj);
78                }
79
80                obj = HTML_OBJECT (HTML_CLUEALIGNED (obj)->next_aligned);
81    }
82}
83
84static HTMLObject *
85cluev_next_aligned (HTMLObject *aclue)
86{
87        return HTML_OBJECT (HTML_CLUEALIGNED (aclue)->next_aligned);
88}
89
90static gint
91get_lmargin (HTMLObject *o, HTMLPainter *painter)
92{
93        return HTML_CLUEV (o)->padding * html_painter_get_pixel_size (painter)
94                + (o->parent ?  html_object_get_left_margin (o->parent, painter, o->y, TRUE) : 0);
95}
96
97static void
98add_clear_area_behind (GList **changed_objs, HTMLObject *o, gint x, gint y, gint w, gint h)
99{
100        HTMLObjectClearRectangle *cr;
101
102        cr = g_new (HTMLObjectClearRectangle, 1);
103
104        cr->object = o;
105        cr->x = x;
106        cr->y = y;
107        cr->width = w;
108        cr->height = h;
109
110        *changed_objs = g_list_prepend (*changed_objs, cr);
111        /* NULL meens: clear rectangle follows */
112        *changed_objs = g_list_prepend (*changed_objs, NULL);
113}
114
115static gboolean
116do_layout (HTMLObject *o, HTMLPainter *painter, gboolean calc_size, GList **changed_objs)
117{
118        HTMLClueV *cluev;
119        HTMLClue *clue;
120        HTMLObject *obj;
121        HTMLObject *aclue;
122        GList *local_changed_objs;
123        gint lmargin;
124        gboolean changed;
125        gint old_width, old_ascent, old_descent;
126        gint new_x;
127        gint pixel_size;
128        gint padding;
129        gint padding2;
130        gboolean first_change;
131        gint first_y_off = 0;
132
133        /* printf ("HTMLClueV::do_layout\n"); */
134
135        cluev = HTML_CLUEV (o);
136        clue = HTML_CLUE (o);
137
138        pixel_size = html_painter_get_pixel_size (painter);
139        padding    = pixel_size * cluev->padding;
140        padding2   = 2 * padding;
141
142        old_width = o->width;
143        old_ascent = o->ascent;
144        old_descent = o->descent;
145
146        changed = FALSE;
147        first_change = TRUE;
148        local_changed_objs = NULL;
149
150        lmargin = get_lmargin (o, painter);
151
152        /* If we have already called calc_size for the children, then just
153           continue from the last object done in previous call. */
154       
155        if (clue->curr != NULL) {
156                if (clue->curr->prev)
157                        o->ascent = clue->curr->prev->y + clue->curr->prev->descent;
158                else
159                        o->ascent = padding;
160                remove_aligned_by_parent (cluev, clue->curr);
161        } else {
162                o->width = 0;
163                o->ascent = padding;
164                o->descent = 0;
165                clue->curr = clue->head;
166        }
167
168        while (clue->curr != NULL) {
169                gint old_y, old_y_off, new_y_off;
170                /* Set an initial ypos so that the alignment stuff knows where
171                   the top of this object is */
172                old_y = clue->curr->y;
173                old_y_off = clue->curr->y - clue->curr->ascent;
174                clue->curr->y = o->ascent;
175
176                switch (html_object_get_clear (clue->curr)) {
177                case HTML_CLEAR_ALL: {
178                        gint y;
179
180                        do {
181                                y = clue->curr->y;
182                                clue->curr->y = html_clue_get_left_clear (clue, clue->curr->y);
183                                clue->curr->y = html_clue_get_right_clear (clue, clue->curr->y);
184                        } while (clue->curr->y != y);
185                        break;
186                }
187                case HTML_CLEAR_LEFT:
188                        clue->curr->y = html_clue_get_left_clear (clue, clue->curr->y);
189                        break;
190                case HTML_CLEAR_RIGHT:
191                        clue->curr->y = html_clue_get_right_clear (clue, clue->curr->y);
192                        break;
193                case HTML_CLEAR_NONE:
194                        break;
195                }
196
197                o->ascent = clue->curr->y;
198                lmargin = get_lmargin (o, painter);
199
200
201                if (calc_size)
202                        changed |= html_object_calc_size (clue->curr, painter, changed_objs);
203
204                if (o->width < clue->curr->width + padding2)
205                        o->width = clue->curr->width + padding2;
206                o->ascent += clue->curr->ascent + clue->curr->descent;
207
208                new_y_off = o->ascent - clue->curr->descent - clue->curr->ascent;
209                if (clue->curr->x != lmargin || old_y_off != new_y_off) {
210                        if (changed_objs) {
211                                /* printf ("y: %d ", o->ascent - clue->curr->descent); */
212                                if (first_change) {
213                                        first_change = FALSE;
214                                        /* if it's new one (y == 0) clear from new y_off, else from old one or new one,
215                                           which one is higher */
216                                        first_y_off = old_y && old_y_off < new_y_off ? old_y_off : new_y_off;
217                                        /* printf ("\nfirst_y_off: %d x %d --> %d\n", old_y_off, new_y_off, first_y_off); */
218                                }
219                                html_object_add_to_changed (&local_changed_objs, clue->curr);
220                        }
221                }
222                clue->curr->x = lmargin;
223                clue->curr->y = o->ascent - clue->curr->descent;
224
225                clue->curr = clue->curr->next;
226        }
227
228        o->ascent += padding;
229
230        /* Remember the last object so that we can start from here next time
231           we are called. */
232        clue->curr = clue->tail;
233
234        if (o->max_width != 0 && o->width < o->max_width)
235                o->width = o->max_width;
236       
237        if (clue->halign == HTML_HALIGN_CENTER) {
238                for (obj = clue->head; obj != 0; obj = obj->next) {
239                        new_x = lmargin + (o->width - obj->width - padding2) / 2;
240                        if (obj->x != new_x) {
241                                obj->x = new_x;
242                                changed = TRUE;
243                        }
244                }
245        } else if (clue->halign == HTML_HALIGN_RIGHT) {
246                for (obj = clue->head; obj != 0; obj = obj->next) {
247                        new_x = lmargin + (o->width - obj->width - padding2);
248                        if (obj->x != new_x) {
249                                obj->x = new_x;
250                                changed = TRUE;
251                        }
252                }
253        }
254       
255        for (aclue = cluev->align_left_list; aclue != NULL; aclue = cluev_next_aligned (aclue)) {
256                if (aclue->y + aclue->parent->y - aclue->parent->ascent > o->ascent)
257                        o->ascent = aclue->y + aclue->parent->y - aclue->parent->ascent;
258        }
259
260        for (aclue = cluev->align_right_list; aclue != NULL; aclue = cluev_next_aligned (aclue)) {
261                if (aclue->y + aclue->parent->y - aclue->parent->ascent > o->ascent)
262                        o->ascent = aclue->y + aclue->parent->y - aclue->parent->ascent;
263        }
264
265        if (! changed
266            && (o->ascent != old_ascent || o->descent != old_descent || o->width != old_width))
267                changed = TRUE;
268
269        if (changed_objs && local_changed_objs) {
270                if (!first_change && o->width > o->max_width) {
271                        add_clear_area_behind (changed_objs, o, o->max_width, first_y_off,
272                                               o->width - o->max_width, o->ascent + o->descent - first_y_off);
273                }
274                *changed_objs = g_list_concat (local_changed_objs, *changed_objs);
275        }
276
277        return changed;
278}
279
280
281/* HTMLObject methods.  */
282
283static void
284copy (HTMLObject *self,
285      HTMLObject *dest)
286{
287        (* HTML_OBJECT_CLASS (parent_class)->copy) (self, dest);
288
289        HTML_CLUEV (dest)->padding = HTML_CLUEV (self)->padding;
290
291        HTML_CLUEV (dest)->align_left_list = NULL;
292        HTML_CLUEV (dest)->align_right_list = NULL;
293}
294
295static gboolean
296calc_size (HTMLObject *o, HTMLPainter *painter, GList **changed_objs)
297{
298        return do_layout (o, painter, TRUE, changed_objs);
299}
300
301static gint
302calc_min_width (HTMLObject *o,
303                HTMLPainter *painter)
304{
305        return (* HTML_OBJECT_CLASS (parent_class)->calc_min_width) (o, painter)
306                + 2 * html_painter_get_pixel_size (painter) * HTML_CLUEV (o)->padding;
307}
308
309static gint
310calc_preferred_width (HTMLObject *o,
311                      HTMLPainter *painter)
312{
313        return (* HTML_OBJECT_CLASS (parent_class)->calc_preferred_width) (o, painter)
314                + 2 * html_painter_get_pixel_size (painter) * HTML_CLUEV (o)->padding;
315}
316
317static void
318set_max_width (HTMLObject *o, HTMLPainter *painter, gint max_width)
319{
320        HTMLObject *obj;
321
322        o->max_width = max_width;
323        max_width   -= 2 * HTML_CLUEV (o)->padding * html_painter_get_pixel_size (painter);
324        for (obj = HTML_CLUE (o)->head; obj != NULL; obj = obj->next)
325                html_object_set_max_width (obj, painter, max_width);
326}
327
328static void
329reset (HTMLObject *clue)
330{
331        HTMLClueV *cluev;
332
333        cluev = HTML_CLUEV (clue);
334
335        HTML_OBJECT_CLASS (&html_clue_class)->reset (clue);
336
337        cluev->align_left_list = NULL;
338        cluev->align_right_list = NULL;
339}
340
341static void
342draw (HTMLObject *o,
343      HTMLPainter *p,
344      gint x, gint y,
345      gint width, gint height,
346      gint tx, gint ty)
347{
348        HTMLObject *aclue;
349
350        HTML_OBJECT_CLASS (&html_clue_class)->draw (o,
351                                                    p,
352                                                    x, y ,
353                                                    width, height,
354                                                    tx, ty);
355
356        if (y + height < o->y - o->ascent || y > o->y + o->descent)
357                return;
358
359        tx += o->x;
360        ty += o->y - o->ascent;
361
362        for ( aclue = HTML_CLUEV (o)->align_left_list;
363              aclue != NULL;
364              aclue = cluev_next_aligned (aclue) ) {
365                html_object_draw (aclue,
366                                  p,
367                                  x - o->x - aclue->parent->x,
368                                  y - (o->y - o->ascent) - (aclue->parent->y - aclue->parent->ascent),
369                                  width - aclue->parent->x, height,
370                                  tx + aclue->parent->x,
371                                  ty + aclue->parent->y - aclue->parent->ascent);
372        }
373
374        for (aclue = HTML_CLUEV (o)->align_right_list;
375             aclue != NULL;
376             aclue = cluev_next_aligned (aclue)) {
377                html_object_draw (aclue,
378                                  p,
379                                  x - o->x - aclue->parent->x,
380                                  y - (o->y - o->ascent) - (aclue->parent->y - aclue->parent->ascent),
381                                  width - aclue->parent->x, height,
382                                  tx + aclue->parent->x,
383                                  ty + aclue->parent->y - aclue->parent->ascent);
384        }
385}
386
387static HTMLObject *
388check_point (HTMLObject *self,
389             HTMLPainter *painter,
390             gint x, gint y,
391             guint *offset_return,
392             gboolean for_cursor)
393{
394        HTMLObject *p;
395        HTMLObject *obj;
396        HTMLClueAligned *clue;
397
398        if (x < self->x || x >= self->x + self->width
399            || y < self->y - self->ascent || y >= self->y + self->descent)
400                return NULL;
401
402        x = x - self->x;
403        y = y - self->y + self->ascent;
404
405        for (clue = HTML_CLUEALIGNED (HTML_CLUEV (self)->align_left_list);
406             clue != NULL;
407             clue = clue->next_aligned) {
408                HTMLObject *parent;
409
410                parent = HTML_OBJECT (clue)->parent;
411                obj = html_object_check_point (HTML_OBJECT (clue),
412                                               painter,
413                                               x - HTML_OBJECT (clue)->parent->x,
414                                               y - HTML_OBJECT (clue)->parent->y + HTML_OBJECT (clue)->parent->ascent,
415                                               offset_return,
416                                               for_cursor);
417                if (obj != NULL) {
418                        return obj;
419                }
420        }
421
422        for (clue = HTML_CLUEALIGNED (HTML_CLUEV (self)->align_right_list);
423             clue != NULL;
424             clue = clue->next_aligned) {
425                HTMLObject *parent;
426
427                parent = HTML_OBJECT (clue)->parent;
428                obj = html_object_check_point (HTML_OBJECT (clue),
429                                               painter,
430                                               x - HTML_OBJECT (clue)->parent->x,
431                                               y - HTML_OBJECT (clue)->parent->y + HTML_OBJECT (clue)->parent->ascent,
432                                               offset_return,
433                                               for_cursor);
434                if (obj != NULL) {
435                        return obj;
436                }
437        }
438
439        for (p = HTML_CLUE (self)->head; p != 0; p = p->next) {
440                gint x1, y1;
441
442                if (! for_cursor) {
443                        x1 = x;
444                        y1 = y;
445                } else {
446                        if (x >= p->x + p->width) {
447                                x1 = MAX (0, p->x + p->width - 1);
448                        } else if (x < p->x) {
449                                x1 = p->x;
450                        } else {
451                                x1 = x;
452                        }
453
454                        if (p->next == NULL && y > p->y + p->descent - 1) {
455                                x1 = MAX (0, p->x + p->width - 1);
456                                y1 = p->y + p->descent - 1;
457                        } else if (p->prev == NULL && y < p->y - p->ascent) {
458                                y1 = p->y - p->ascent;
459                        } else {
460                                y1 = y;
461                        }
462                }
463
464                obj = html_object_check_point (p, painter, x1, y1, offset_return, for_cursor);
465                if (obj != NULL)
466                        return obj;
467        }
468
469        return NULL;
470}
471
472static gboolean
473relayout (HTMLObject *self,
474          HTMLEngine *engine,
475          HTMLObject *child)
476{
477        gint prev_width, prev_ascent, prev_descent;
478        gboolean changed;
479
480        if (html_engine_frozen (engine))
481                return FALSE;
482
483        if (child == NULL)
484                child = HTML_CLUE (self)->head;
485        html_object_calc_size (child, engine->painter, FALSE);
486
487        HTML_CLUE (self)->curr = NULL;
488
489        prev_width = self->width;
490        prev_ascent = self->ascent;
491        prev_descent = self->descent;
492
493        changed = do_layout (self, engine->painter, FALSE, FALSE);
494        if (changed)
495                html_engine_queue_draw (engine, self);
496
497        if (prev_width == self->width
498            && prev_ascent == self->ascent
499            && prev_descent == self->descent)
500                return FALSE;
501
502        if (self->parent == NULL) {
503                /* FIXME resize the widget, e.g. scrollbars and such.  */
504                html_engine_queue_draw (engine, self);
505
506                /* FIXME extreme ugliness.  */
507                self->x = 0;
508                self->y = self->ascent;
509        } else {
510                /* Relayout our parent starting from us.  */
511                if (! html_object_relayout (self->parent, engine, self))
512                        html_engine_queue_draw (engine, self);
513        }
514
515        /* If the object has shrunk, we have to clean the areas around
516           it so that we don't leave garbage on the screen.  FIXME:
517           this wastes some time if there is an object on the right of
518           or under this one.  */
519
520        if (prev_ascent + prev_descent > self->ascent + self->descent)
521                html_engine_queue_clear (engine,
522                                         self->x,
523                                         self->y + self->descent,
524                                         self->width,
525                                         (prev_ascent + prev_descent
526                                          - (self->ascent + self->descent)));
527
528        if (prev_width > self->width)
529                html_engine_queue_clear (engine,
530                                         self->x + self->width,
531                                         self->y - self->ascent,
532                                         prev_width - self->width,
533                                         self->ascent + self->descent);
534
535        return TRUE;
536}
537
538static gint
539get_left_margin (HTMLObject *self, HTMLPainter *painter, gint y, gboolean with_aligned)
540{
541        HTMLObject *aclue;
542        HTMLClueV *cluev;
543        gint margin;
544
545        cluev = HTML_CLUEV (self);
546        margin = 0;
547       
548        if (with_aligned)
549                for (aclue = cluev->align_left_list;
550                     aclue != NULL;
551                     aclue = cluev_next_aligned (aclue)) {
552                        if ((aclue->y - aclue->ascent + aclue->parent->y - aclue->parent->ascent
553                             <= y)
554                            && (aclue->y + aclue->parent->y - aclue->parent->ascent
555                                > y))
556                                margin = aclue->x + aclue->width;
557                }
558
559        return margin;
560}
561
562static gint
563get_right_margin (HTMLObject *self, HTMLPainter *painter, gint y, gboolean with_aligned)
564{
565        HTMLClueV *cluev;
566        /* FIXME: Should be HTMLAligned */
567        HTMLObject *aclue;
568        gint margin;
569       
570        cluev = HTML_CLUEV (self);
571        margin = self->max_width - 2 * cluev->padding * html_painter_get_pixel_size (painter);
572
573        if (with_aligned)
574                for (aclue = cluev->align_right_list;
575                     aclue != NULL;
576                     aclue = cluev_next_aligned (aclue)) {
577                        if ((aclue->y - aclue->ascent + aclue->parent->y - aclue->parent->ascent) <= y
578                            && aclue->y + aclue->parent->y - aclue->parent->ascent > y)
579                                margin = aclue->x;
580                }
581       
582        return margin;
583}
584
585
586/* HTMLClue methods.  */
587
588static void
589find_free_area (HTMLClue *clue, HTMLPainter *painter, gint y, gint width, gint height,
590                gint indent, gint *y_pos, gint *_lmargin, gint *_rmargin)
591{
592        HTMLClueV *cluev = HTML_CLUEV (clue);
593        gint try_y = y;
594        gint lmargin;
595        gint rmargin;
596        gint lm, rm;
597        HTMLObject *aclue;
598        gint next_y, top_y, base_y=0;
599
600        next_y = 0;
601        while (1) {
602                lmargin = indent;
603                rmargin = HTML_OBJECT (clue)->max_width - 2 * cluev->padding * html_painter_get_pixel_size (painter);
604               
605                for (aclue = cluev->align_left_list; aclue != 0; aclue = cluev_next_aligned (aclue)) {
606                        base_y = (aclue->y + aclue->parent->y
607                                  - aclue->parent->ascent);
608                        top_y = base_y - aclue->ascent;
609
610                        if ((top_y < try_y + height) && (base_y > try_y)) {
611                                lm = aclue->x + aclue->width;
612                                if (lm > lmargin)
613                                        lmargin = lm;
614                               
615                                if ((next_y == 0) || (base_y < next_y)) {
616                                        next_y = base_y;
617
618                                }
619                        }
620                }
621
622                for (aclue = cluev->align_right_list; aclue != 0; aclue = cluev_next_aligned (aclue)) {
623                        base_y = (aclue->y + aclue->parent->y
624                                  - aclue->parent->ascent);
625                        top_y = base_y - aclue->ascent;
626
627                        if ((top_y < try_y + height) && (base_y > try_y)) {
628                                rm = aclue->x;
629                                if (rm < rmargin)
630                                        rmargin = rm;
631                               
632                                if ((next_y == 0) || (base_y < next_y)) {
633                                        next_y = base_y;
634                                }
635                        }
636                }
637               
638                if (lmargin == indent
639                    && rmargin == MAX (HTML_OBJECT (clue)->max_width, HTML_OBJECT (clue)->width))
640                        break;
641               
642                if ((rmargin - lmargin) >= width)
643                        break;
644
645                if (try_y == next_y)
646                        break;
647
648                try_y = next_y;
649        }
650       
651        *y_pos = MAX (y, try_y);
652
653        *_rmargin = rmargin;
654        *_lmargin = lmargin;
655}
656
657static gboolean
658appended (HTMLClue *clue, HTMLClue *aclue)
659{
660        /* Returns whether aclue is already in the alignList */
661        HTMLClueAligned *aligned;
662       
663        if (aclue->halign == HTML_HALIGN_LEFT) {
664                aligned = HTML_CLUEALIGNED (HTML_CLUEV (clue)->align_left_list);
665        }
666        else {
667                aligned = HTML_CLUEALIGNED (HTML_CLUEV (clue)->align_right_list);
668        }
669
670        while (aligned) {
671                if (aligned == HTML_CLUEALIGNED (aclue))
672                        return TRUE;
673                aligned = HTML_CLUEALIGNED (aligned->next_aligned);
674        }
675        return FALSE;
676}
677
678static void
679append_left_aligned (HTMLClue *clue, HTMLPainter *painter, HTMLClue *aclue, gint *lmargin, gint *rmargin, gint indent)
680{
681        gint y_pos, y_inc;
682
683        html_clue_find_free_area (clue, painter,
684                                  HTML_OBJECT (aclue)->parent->y,
685                                  HTML_OBJECT (aclue)->width,
686                                  HTML_OBJECT (aclue)->ascent + HTML_OBJECT (aclue)->descent,
687                                  indent, &y_pos, lmargin, rmargin);
688
689        /* Set position */
690        y_inc = y_pos - HTML_OBJECT (aclue)->parent->y;
691
692        HTML_OBJECT (aclue)->x = *lmargin;
693        HTML_OBJECT (aclue)->y = HTML_OBJECT (aclue)->parent->ascent + HTML_OBJECT (aclue)->ascent + y_inc;
694
695        /* Insert clue in align list */
696        if (!HTML_CLUEV (clue)->align_left_list) {
697                HTML_CLUEV (clue)->align_left_list = HTML_OBJECT (aclue);
698                HTML_CLUEALIGNED (aclue)->next_aligned = NULL;
699        } else {
700                HTMLClueAligned *obj = HTML_CLUEALIGNED (HTML_CLUEV (clue)->align_left_list);
701                while (obj->next_aligned) {
702                        if (obj == HTML_CLUEALIGNED (aclue))
703                                return;
704                        obj = obj->next_aligned;
705                }
706                if (obj == HTML_CLUEALIGNED (aclue))
707                        return;
708
709                obj->next_aligned = HTML_CLUEALIGNED (aclue);
710                HTML_CLUEALIGNED (aclue)->next_aligned = NULL;
711        }
712
713        *lmargin += HTML_OBJECT (aclue)->width;
714}
715
716static void
717append_right_aligned (HTMLClue *clue, HTMLPainter *painter, HTMLClue *aclue, gint *lmargin, gint *rmargin, gint indent)
718{
719        gint y_pos, y_inc;
720
721        html_clue_find_free_area (clue, painter, HTML_OBJECT (aclue)->parent->y,
722                                  HTML_OBJECT (aclue)->width,
723                                  HTML_OBJECT (aclue)->ascent + HTML_OBJECT (aclue)->descent, indent,
724                                  &y_pos, lmargin, rmargin);
725
726        *rmargin -= HTML_OBJECT (aclue)->width;
727
728        /* Set position */
729        y_inc = y_pos - HTML_OBJECT (aclue)->parent->y;
730
731        HTML_OBJECT (aclue)->x = *rmargin;
732        HTML_OBJECT (aclue)->y = HTML_OBJECT (aclue)->parent->ascent + HTML_OBJECT (aclue)->ascent + y_inc;
733
734        /* Insert clue in align list */
735        if (!HTML_CLUEV (clue)->align_right_list) {
736                HTML_CLUEV (clue)->align_right_list = HTML_OBJECT (aclue);
737                HTML_CLUEALIGNED (aclue)->next_aligned = NULL;
738        } else {
739                HTMLClueAligned *obj = HTML_CLUEALIGNED (HTML_CLUEV (clue)->align_right_list);
740                while (obj->next_aligned) {
741                        if (obj == HTML_CLUEALIGNED (aclue))
742                                return;
743                        obj = obj->next_aligned;
744                }
745                if (obj == HTML_CLUEALIGNED (aclue))
746                        return;
747
748                obj->next_aligned = HTML_CLUEALIGNED (aclue);
749                HTML_CLUEALIGNED (aclue)->next_aligned = NULL;
750        }
751}
752
753static gint
754get_left_clear (HTMLClue *self,
755                gint y)
756{
757        HTMLObject *p;
758        gint top_y, base_y;
759
760        /* XXX we assume the parent's size has already been calculated here.  */
761       
762        for (p = HTML_CLUEV (self)->align_left_list;
763             p != NULL;
764             p = HTML_OBJECT (HTML_CLUEALIGNED (p)->next_aligned)) {
765                base_y = p->y + p->parent->y - p->parent->ascent;
766                top_y = base_y - p->ascent;
767
768                if (top_y <= y && y < base_y + p->descent)
769                        y = base_y + p->descent;
770        }
771
772        return y;
773}
774
775static gint
776get_right_clear (HTMLClue *self,
777                 gint y)
778{
779        HTMLObject *p;
780        gint top_y, base_y;
781
782        /* XXX we assume the parent's size has already been calculated here.  */
783       
784        for (p = HTML_CLUEV (self)->align_right_list;
785             p != NULL;
786             p = HTML_OBJECT (HTML_CLUEALIGNED (p)->next_aligned)) {
787                base_y = p->y + p->parent->y - p->parent->ascent;
788                top_y = base_y - p->ascent;
789
790                if (top_y <= y && y < base_y + p->descent)
791                        y = base_y + p->descent;
792        }
793
794        return y;
795}
796
797
798void
799html_cluev_type_init (void)
800{
801        html_cluev_class_init (&html_cluev_class, HTML_TYPE_CLUEV, sizeof (HTMLClueV));
802}
803
804void
805html_cluev_class_init (HTMLClueVClass *klass,
806                       HTMLType type,
807                       guint size)
808{
809        HTMLObjectClass *object_class;
810        HTMLClueClass *clue_class;
811
812        object_class = HTML_OBJECT_CLASS (klass);
813        clue_class = HTML_CLUE_CLASS (klass);
814
815        html_clue_class_init (clue_class, type, size);
816
817        object_class->copy = copy;
818        object_class->calc_size = calc_size;
819        object_class->calc_min_width = calc_min_width;
820        object_class->calc_preferred_width = calc_preferred_width;
821        object_class->relayout = relayout;
822        object_class->set_max_width = set_max_width;
823        object_class->reset = reset;
824        object_class->draw = draw;
825        object_class->check_point = check_point;
826        object_class->get_left_margin = get_left_margin;
827        object_class->get_right_margin = get_right_margin;
828
829        clue_class->get_left_clear = get_left_clear;
830        clue_class->get_right_clear = get_right_clear;
831        clue_class->find_free_area = find_free_area;
832        clue_class->appended = appended;
833        clue_class->append_left_aligned = append_left_aligned;
834        clue_class->append_right_aligned = append_right_aligned;
835
836        parent_class = &html_clue_class;
837}
838
839void
840html_cluev_init (HTMLClueV *cluev,
841                 HTMLClueVClass *klass,
842                 gint x, gint y,
843                 gint percent)
844{
845        HTMLObject *object;
846        HTMLClue *clue;
847
848        object = HTML_OBJECT (cluev);
849        clue = HTML_CLUE (cluev);
850
851        html_clue_init (clue, HTML_CLUE_CLASS (klass));
852
853        object->x = x;
854        object->y = y;
855        object->percent = percent;
856
857        clue->valign = HTML_VALIGN_BOTTOM;
858        clue->halign = HTML_HALIGN_LEFT;
859        clue->head = clue->tail = clue->curr = 0;
860
861        cluev->align_left_list = 0;
862        cluev->align_right_list = 0;
863        cluev->padding = 0;
864}
865
866HTMLObject *
867html_cluev_new (gint x, gint y, gint percent)
868{
869        HTMLClueV *cluev;
870
871        cluev = g_new (HTMLClueV, 1);
872        html_cluev_init (cluev, &html_cluev_class, x, y, percent);
873       
874        return HTML_OBJECT (cluev);
875}
Note: See TracBrowser for help on using the repository browser.