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

Revision 21116, 22.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/*
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
116html_cluev_do_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                case HTML_CLEAR_INHERIT:
196                        /* TODO */
197                        break;
198                }
199
200                o->ascent = clue->curr->y;
201                lmargin = get_lmargin (o, painter);
202
203
204                if (calc_size)
205                        changed |= html_object_calc_size (clue->curr, painter, changed_objs);
206
207                if (o->width < clue->curr->width + padding2)
208                        o->width = clue->curr->width + padding2;
209                o->ascent += clue->curr->ascent + clue->curr->descent;
210
211                new_y_off = o->ascent - clue->curr->descent - clue->curr->ascent;
212                if (clue->curr->x != lmargin || old_y_off != new_y_off) {
213                        if (changed_objs) {
214                                /* printf ("y: %d ", o->ascent - clue->curr->descent); */
215                                if (first_change) {
216                                        first_change = FALSE;
217                                        /* if it's new one (y == 0) clear from new y_off, else from old one or new one,
218                                           which one is higher */
219                                        first_y_off = old_y && old_y_off < new_y_off ? old_y_off : new_y_off;
220                                        /* printf ("\nfirst_y_off: %d x %d --> %d\n", old_y_off, new_y_off, first_y_off); */
221                                }
222                                html_object_add_to_changed (&local_changed_objs, clue->curr);
223                        }
224                }
225                clue->curr->x = lmargin;
226                clue->curr->y = o->ascent - clue->curr->descent;
227
228                clue->curr = clue->curr->next;
229        }
230
231        o->ascent += padding;
232
233        /* Remember the last object so that we can start from here next time
234           we are called. */
235        clue->curr = clue->tail;
236
237        if (o->max_width != 0 && o->width < o->max_width)
238                o->width = o->max_width;
239       
240        if (clue->halign == HTML_HALIGN_CENTER) {
241                for (obj = clue->head; obj != 0; obj = obj->next) {
242                        new_x = lmargin + (o->width - obj->width - padding2) / 2;
243                        if (obj->x != new_x) {
244                                obj->x = new_x;
245                                changed = TRUE;
246                        }
247                }
248        } else if (clue->halign == HTML_HALIGN_RIGHT) {
249                for (obj = clue->head; obj != 0; obj = obj->next) {
250                        new_x = lmargin + (o->width - obj->width - padding2);
251                        if (obj->x != new_x) {
252                                obj->x = new_x;
253                                changed = TRUE;
254                        }
255                }
256        }
257       
258        for (aclue = cluev->align_left_list; aclue != NULL; aclue = cluev_next_aligned (aclue)) {
259                if (aclue->y + aclue->parent->y - aclue->parent->ascent > o->ascent)
260                        o->ascent = aclue->y + aclue->parent->y - aclue->parent->ascent;
261        }
262
263        for (aclue = cluev->align_right_list; aclue != NULL; aclue = cluev_next_aligned (aclue)) {
264                if (aclue->y + aclue->parent->y - aclue->parent->ascent > o->ascent)
265                        o->ascent = aclue->y + aclue->parent->y - aclue->parent->ascent;
266        }
267
268        if (! changed
269            && (o->ascent != old_ascent || o->descent != old_descent || o->width != old_width))
270                changed = TRUE;
271
272        if (changed_objs && local_changed_objs) {
273                if (!first_change && o->width > o->max_width) {
274                        add_clear_area_behind (changed_objs, o, o->max_width, first_y_off,
275                                               o->width - o->max_width, o->ascent + o->descent - first_y_off);
276                }
277                *changed_objs = g_list_concat (local_changed_objs, *changed_objs);
278        }
279
280        return changed;
281}
282
283
284/* HTMLObject methods.  */
285
286static void
287copy (HTMLObject *self,
288      HTMLObject *dest)
289{
290        (* HTML_OBJECT_CLASS (parent_class)->copy) (self, dest);
291
292        HTML_CLUEV (dest)->padding = HTML_CLUEV (self)->padding;
293
294        HTML_CLUEV (dest)->align_left_list = NULL;
295        HTML_CLUEV (dest)->align_right_list = NULL;
296}
297
298static gboolean
299html_cluev_real_calc_size (HTMLObject *o, HTMLPainter *painter, GList **changed_objs)
300{
301        return html_cluev_do_layout (o, painter, TRUE, changed_objs);
302}
303
304static gint
305calc_min_width (HTMLObject *o,
306                HTMLPainter *painter)
307{
308        return (* HTML_OBJECT_CLASS (parent_class)->calc_min_width) (o, painter)
309                + 2 * html_painter_get_pixel_size (painter) * HTML_CLUEV (o)->padding;
310}
311
312static gint
313calc_preferred_width (HTMLObject *o,
314                      HTMLPainter *painter)
315{
316        return (* HTML_OBJECT_CLASS (parent_class)->calc_preferred_width) (o, painter)
317                + 2 * html_painter_get_pixel_size (painter) * HTML_CLUEV (o)->padding;
318}
319
320static void
321set_max_width (HTMLObject *o, HTMLPainter *painter, gint max_width)
322{
323        HTMLObject *obj;
324
325        o->max_width = max_width;
326        max_width   -= 2 * HTML_CLUEV (o)->padding * html_painter_get_pixel_size (painter);
327        for (obj = HTML_CLUE (o)->head; obj != NULL; obj = obj->next)
328                html_object_set_max_width (obj, painter, max_width);
329}
330
331static void
332set_max_height (HTMLObject *o, HTMLPainter *painter, gint height)
333{
334        HTMLClue *clue = HTML_CLUE (o);
335
336        html_object_calc_size (o, painter, NULL);
337        if (o->ascent < height) {
338                (* HTML_OBJECT_CLASS (parent_class)->set_max_height) (o, painter, height);
339                clue->curr = NULL;
340        }
341}
342
343static void
344reset (HTMLObject *clue)
345{
346        HTMLClueV *cluev;
347
348        cluev = HTML_CLUEV (clue);
349
350        HTML_OBJECT_CLASS (&html_clue_class)->reset (clue);
351
352        cluev->align_left_list = NULL;
353        cluev->align_right_list = NULL;
354}
355
356static void
357draw (HTMLObject *o,
358      HTMLPainter *p,
359      gint x, gint y,
360      gint width, gint height,
361      gint tx, gint ty)
362{
363        HTMLObject *aclue;
364
365        HTML_OBJECT_CLASS (&html_clue_class)->draw (o,
366                                                    p,
367                                                    x, y ,
368                                                    width, height,
369                                                    tx, ty);
370
371        if (y + height < o->y - o->ascent || y > o->y + o->descent)
372                return;
373
374        tx += o->x;
375        ty += o->y - o->ascent;
376
377        for ( aclue = HTML_CLUEV (o)->align_left_list;
378              aclue != NULL;
379              aclue = cluev_next_aligned (aclue) ) {
380                html_object_draw (aclue,
381                                  p,
382                                  x - o->x - aclue->parent->x,
383                                  y - (o->y - o->ascent) - (aclue->parent->y - aclue->parent->ascent),
384                                  width - aclue->parent->x, height,
385                                  tx + aclue->parent->x,
386                                  ty + aclue->parent->y - aclue->parent->ascent);
387        }
388
389        for (aclue = HTML_CLUEV (o)->align_right_list;
390             aclue != NULL;
391             aclue = cluev_next_aligned (aclue)) {
392                html_object_draw (aclue,
393                                  p,
394                                  x - o->x - aclue->parent->x,
395                                  y - (o->y - o->ascent) - (aclue->parent->y - aclue->parent->ascent),
396                                  width - aclue->parent->x, height,
397                                  tx + aclue->parent->x,
398                                  ty + aclue->parent->y - aclue->parent->ascent);
399        }
400}
401
402static HTMLObject *
403check_point (HTMLObject *self,
404             HTMLPainter *painter,
405             gint x, gint y,
406             guint *offset_return,
407             gboolean for_cursor)
408{
409        HTMLObject *p;
410        HTMLObject *obj;
411        HTMLClueAligned *clue;
412
413        if (x < self->x || x >= self->x + self->width
414            || y < self->y - self->ascent || y >= self->y + self->descent)
415                return NULL;
416
417        x = x - self->x;
418        y = y - self->y + self->ascent;
419
420        for (clue = HTML_CLUEALIGNED (HTML_CLUEV (self)->align_left_list);
421             clue != NULL;
422             clue = clue->next_aligned) {
423                HTMLObject *parent;
424
425                parent = HTML_OBJECT (clue)->parent;
426                obj = html_object_check_point (HTML_OBJECT (clue),
427                                               painter,
428                                               x - HTML_OBJECT (clue)->parent->x,
429                                               y - HTML_OBJECT (clue)->parent->y + HTML_OBJECT (clue)->parent->ascent,
430                                               offset_return,
431                                               for_cursor);
432                if (obj != NULL) {
433                        return obj;
434                }
435        }
436
437        for (clue = HTML_CLUEALIGNED (HTML_CLUEV (self)->align_right_list);
438             clue != NULL;
439             clue = clue->next_aligned) {
440                HTMLObject *parent;
441
442                parent = HTML_OBJECT (clue)->parent;
443                obj = html_object_check_point (HTML_OBJECT (clue),
444                                               painter,
445                                               x - HTML_OBJECT (clue)->parent->x,
446                                               y - HTML_OBJECT (clue)->parent->y + HTML_OBJECT (clue)->parent->ascent,
447                                               offset_return,
448                                               for_cursor);
449                if (obj != NULL) {
450                        return obj;
451                }
452        }
453
454        for (p = HTML_CLUE (self)->head; p != 0; p = p->next) {
455                gint x1, y1;
456
457                if (! for_cursor) {
458                        x1 = x;
459                        y1 = y;
460                } else {
461                        if (x >= p->x + p->width) {
462                                x1 = MAX (0, p->x + p->width - 1);
463                        } else if (x < p->x) {
464                                x1 = p->x;
465                        } else {
466                                x1 = x;
467                        }
468
469                        if (p->next == NULL && y > p->y + p->descent - 1) {
470                                x1 = MAX (0, p->x + p->width - 1);
471                                y1 = p->y + p->descent - 1;
472                        } else if (p->prev == NULL && y < p->y - p->ascent) {
473                                y1 = p->y - p->ascent;
474                        } else {
475                                y1 = y;
476                        }
477                }
478
479                obj = html_object_check_point (p, painter, x1, y1, offset_return, for_cursor);
480                if (obj != NULL)
481                        return obj;
482        }
483
484        return NULL;
485}
486
487static gboolean
488relayout (HTMLObject *self,
489          HTMLEngine *engine,
490          HTMLObject *child)
491{
492        gint prev_width, prev_ascent, prev_descent;
493        gboolean changed;
494
495        if (html_engine_frozen (engine))
496                return FALSE;
497
498        if (child == NULL)
499                child = HTML_CLUE (self)->head;
500        html_object_calc_size (child, engine->painter, FALSE);
501
502        HTML_CLUE (self)->curr = NULL;
503
504        prev_width = self->width;
505        prev_ascent = self->ascent;
506        prev_descent = self->descent;
507
508        changed = html_cluev_do_layout (self, engine->painter, FALSE, FALSE);
509        if (changed)
510                html_engine_queue_draw (engine, self);
511
512        if (prev_width == self->width
513            && prev_ascent == self->ascent
514            && prev_descent == self->descent)
515                return FALSE;
516
517        if (self->parent == NULL) {
518                /* FIXME resize the widget, e.g. scrollbars and such.  */
519                html_engine_queue_draw (engine, self);
520
521                /* FIXME extreme ugliness.  */
522                self->x = 0;
523                self->y = self->ascent;
524        } else {
525                /* Relayout our parent starting from us.  */
526                if (! html_object_relayout (self->parent, engine, self))
527                        html_engine_queue_draw (engine, self);
528        }
529
530        /* If the object has shrunk, we have to clean the areas around
531           it so that we don't leave garbage on the screen.  FIXME:
532           this wastes some time if there is an object on the right of
533           or under this one.  */
534
535        if (prev_ascent + prev_descent > self->ascent + self->descent)
536                html_engine_queue_clear (engine,
537                                         self->x,
538                                         self->y + self->descent,
539                                         self->width,
540                                         (prev_ascent + prev_descent
541                                          - (self->ascent + self->descent)));
542
543        if (prev_width > self->width)
544                html_engine_queue_clear (engine,
545                                         self->x + self->width,
546                                         self->y - self->ascent,
547                                         prev_width - self->width,
548                                         self->ascent + self->descent);
549
550        return TRUE;
551}
552
553static gint
554get_left_margin (HTMLObject *self, HTMLPainter *painter, gint y, gboolean with_aligned)
555{
556        HTMLObject *aclue;
557        HTMLClueV *cluev;
558        gint margin;
559
560        cluev = HTML_CLUEV (self);
561        margin = 0;
562       
563        if (with_aligned)
564                for (aclue = cluev->align_left_list;
565                     aclue != NULL;
566                     aclue = cluev_next_aligned (aclue)) {
567                        if ((aclue->y - aclue->ascent + aclue->parent->y - aclue->parent->ascent
568                             <= y)
569                            && (aclue->y + aclue->parent->y - aclue->parent->ascent
570                                > y))
571                                margin = aclue->x + aclue->width;
572                }
573
574        return margin;
575}
576
577static gint
578get_right_margin (HTMLObject *self, HTMLPainter *painter, gint y, gboolean with_aligned)
579{
580        HTMLClueV *cluev;
581        /* FIXME: Should be HTMLAligned */
582        HTMLObject *aclue;
583        gint margin;
584       
585        cluev = HTML_CLUEV (self);
586        margin = self->max_width - 2 * cluev->padding * html_painter_get_pixel_size (painter);
587
588        if (with_aligned)
589                for (aclue = cluev->align_right_list;
590                     aclue != NULL;
591                     aclue = cluev_next_aligned (aclue)) {
592                        if ((aclue->y - aclue->ascent + aclue->parent->y - aclue->parent->ascent) <= y
593                            && aclue->y + aclue->parent->y - aclue->parent->ascent > y)
594                                margin = aclue->x;
595                }
596       
597        return margin;
598}
599
600
601/* HTMLClue methods.  */
602
603static void
604find_free_area (HTMLClue *clue, HTMLPainter *painter, gint y, gint width, gint height,
605                gint indent, gint *y_pos, gint *_lmargin, gint *_rmargin)
606{
607        HTMLClueV *cluev = HTML_CLUEV (clue);
608        gint try_y = y;
609        gint lmargin;
610        gint rmargin;
611        gint lm, rm;
612        HTMLObject *aclue;
613        gint next_y, top_y, base_y=0;
614
615        next_y = 0;
616        while (1) {
617                lmargin = indent;
618                rmargin = HTML_OBJECT (clue)->max_width - 2 * cluev->padding * html_painter_get_pixel_size (painter);
619               
620                for (aclue = cluev->align_left_list; aclue != 0; aclue = cluev_next_aligned (aclue)) {
621                        base_y = (aclue->y + aclue->parent->y
622                                  - aclue->parent->ascent);
623                        top_y = base_y - aclue->ascent;
624
625                        if ((top_y < try_y + height) && (base_y > try_y)) {
626                                lm = aclue->x + aclue->width;
627                                if (lm > lmargin)
628                                        lmargin = lm;
629                               
630                                if ((next_y == 0) || (base_y < next_y)) {
631                                        next_y = base_y;
632
633                                }
634                        }
635                }
636
637                for (aclue = cluev->align_right_list; aclue != 0; aclue = cluev_next_aligned (aclue)) {
638                        base_y = (aclue->y + aclue->parent->y
639                                  - aclue->parent->ascent);
640                        top_y = base_y - aclue->ascent;
641
642                        if ((top_y < try_y + height) && (base_y > try_y)) {
643                                rm = aclue->x;
644                                if (rm < rmargin)
645                                        rmargin = rm;
646                               
647                                if ((next_y == 0) || (base_y < next_y)) {
648                                        next_y = base_y;
649                                }
650                        }
651                }
652               
653                if (lmargin == indent
654                    && rmargin == MAX (HTML_OBJECT (clue)->max_width, HTML_OBJECT (clue)->width))
655                        break;
656               
657                if ((rmargin - lmargin) >= width)
658                        break;
659
660                if (try_y == next_y)
661                        break;
662
663                try_y = next_y;
664        }
665       
666        *y_pos = MAX (y, try_y);
667
668        *_rmargin = rmargin;
669        *_lmargin = lmargin;
670}
671
672static gboolean
673appended (HTMLClue *clue, HTMLClue *aclue)
674{
675        /* Returns whether aclue is already in the alignList */
676        HTMLClueAligned *aligned;
677       
678        if (aclue->halign == HTML_HALIGN_LEFT) {
679                aligned = HTML_CLUEALIGNED (HTML_CLUEV (clue)->align_left_list);
680        }
681        else {
682                aligned = HTML_CLUEALIGNED (HTML_CLUEV (clue)->align_right_list);
683        }
684
685        while (aligned) {
686                if (aligned == HTML_CLUEALIGNED (aclue))
687                        return TRUE;
688                aligned = HTML_CLUEALIGNED (aligned->next_aligned);
689        }
690        return FALSE;
691}
692
693static void
694append_left_aligned (HTMLClue *clue, HTMLPainter *painter, HTMLClue *aclue, gint *lmargin, gint *rmargin, gint indent)
695{
696        gint y_pos, y_inc;
697
698        html_clue_find_free_area (clue, painter,
699                                  HTML_OBJECT (aclue)->parent->y,
700                                  HTML_OBJECT (aclue)->width,
701                                  HTML_OBJECT (aclue)->ascent + HTML_OBJECT (aclue)->descent,
702                                  indent, &y_pos, lmargin, rmargin);
703
704        /* Set position */
705        y_inc = y_pos - HTML_OBJECT (aclue)->parent->y;
706
707        HTML_OBJECT (aclue)->x = *lmargin;
708        HTML_OBJECT (aclue)->y = HTML_OBJECT (aclue)->parent->ascent + HTML_OBJECT (aclue)->ascent + y_inc;
709
710        /* Insert clue in align list */
711        if (!HTML_CLUEV (clue)->align_left_list) {
712                HTML_CLUEV (clue)->align_left_list = HTML_OBJECT (aclue);
713                HTML_CLUEALIGNED (aclue)->next_aligned = NULL;
714        } else {
715                HTMLClueAligned *obj = HTML_CLUEALIGNED (HTML_CLUEV (clue)->align_left_list);
716                while (obj->next_aligned) {
717                        if (obj == HTML_CLUEALIGNED (aclue))
718                                return;
719                        obj = obj->next_aligned;
720                }
721                if (obj == HTML_CLUEALIGNED (aclue))
722                        return;
723
724                obj->next_aligned = HTML_CLUEALIGNED (aclue);
725                HTML_CLUEALIGNED (aclue)->next_aligned = NULL;
726        }
727
728        *lmargin += HTML_OBJECT (aclue)->width;
729}
730
731static void
732append_right_aligned (HTMLClue *clue, HTMLPainter *painter, HTMLClue *aclue, gint *lmargin, gint *rmargin, gint indent)
733{
734        gint y_pos, y_inc;
735
736        html_clue_find_free_area (clue, painter, HTML_OBJECT (aclue)->parent->y,
737                                  HTML_OBJECT (aclue)->width,
738                                  HTML_OBJECT (aclue)->ascent + HTML_OBJECT (aclue)->descent, indent,
739                                  &y_pos, lmargin, rmargin);
740
741        *rmargin -= HTML_OBJECT (aclue)->width;
742
743        /* Set position */
744        y_inc = y_pos - HTML_OBJECT (aclue)->parent->y;
745
746        HTML_OBJECT (aclue)->x = *rmargin;
747        HTML_OBJECT (aclue)->y = HTML_OBJECT (aclue)->parent->ascent + HTML_OBJECT (aclue)->ascent + y_inc;
748
749        /* Insert clue in align list */
750        if (!HTML_CLUEV (clue)->align_right_list) {
751                HTML_CLUEV (clue)->align_right_list = HTML_OBJECT (aclue);
752                HTML_CLUEALIGNED (aclue)->next_aligned = NULL;
753        } else {
754                HTMLClueAligned *obj = HTML_CLUEALIGNED (HTML_CLUEV (clue)->align_right_list);
755                while (obj->next_aligned) {
756                        if (obj == HTML_CLUEALIGNED (aclue))
757                                return;
758                        obj = obj->next_aligned;
759                }
760                if (obj == HTML_CLUEALIGNED (aclue))
761                        return;
762
763                obj->next_aligned = HTML_CLUEALIGNED (aclue);
764                HTML_CLUEALIGNED (aclue)->next_aligned = NULL;
765        }
766}
767
768static gint
769get_left_clear (HTMLClue *self,
770                gint y)
771{
772        HTMLObject *p;
773        gint top_y, base_y;
774
775        /* XXX we assume the parent's size has already been calculated here.  */
776       
777        for (p = HTML_CLUEV (self)->align_left_list;
778             p != NULL;
779             p = HTML_OBJECT (HTML_CLUEALIGNED (p)->next_aligned)) {
780                base_y = p->y + p->parent->y - p->parent->ascent;
781                top_y = base_y - p->ascent;
782
783                if (top_y <= y && y < base_y + p->descent)
784                        y = base_y + p->descent;
785        }
786
787        return y;
788}
789
790static gint
791get_right_clear (HTMLClue *self,
792                 gint y)
793{
794        HTMLObject *p;
795        gint top_y, base_y;
796
797        /* XXX we assume the parent's size has already been calculated here.  */
798       
799        for (p = HTML_CLUEV (self)->align_right_list;
800             p != NULL;
801             p = HTML_OBJECT (HTML_CLUEALIGNED (p)->next_aligned)) {
802                base_y = p->y + p->parent->y - p->parent->ascent;
803                top_y = base_y - p->ascent;
804
805                if (top_y <= y && y < base_y + p->descent)
806                        y = base_y + p->descent;
807        }
808
809        return y;
810}
811
812
813void
814html_cluev_type_init (void)
815{
816        html_cluev_class_init (&html_cluev_class, HTML_TYPE_CLUEV, sizeof (HTMLClueV));
817}
818
819void
820html_cluev_class_init (HTMLClueVClass *klass,
821                       HTMLType type,
822                       guint size)
823{
824        HTMLObjectClass *object_class;
825        HTMLClueClass *clue_class;
826
827        object_class = HTML_OBJECT_CLASS (klass);
828        clue_class = HTML_CLUE_CLASS (klass);
829
830        html_clue_class_init (clue_class, type, size);
831
832        object_class->copy = copy;
833        object_class->calc_size = html_cluev_real_calc_size;
834        object_class->calc_min_width = calc_min_width;
835        object_class->calc_preferred_width = calc_preferred_width;
836        object_class->relayout = relayout;
837        object_class->set_max_width = set_max_width;
838        object_class->set_max_height = set_max_height;
839        object_class->reset = reset;
840        object_class->draw = draw;
841        object_class->check_point = check_point;
842        object_class->get_left_margin = get_left_margin;
843        object_class->get_right_margin = get_right_margin;
844
845        clue_class->get_left_clear = get_left_clear;
846        clue_class->get_right_clear = get_right_clear;
847        clue_class->find_free_area = find_free_area;
848        clue_class->appended = appended;
849        clue_class->append_left_aligned = append_left_aligned;
850        clue_class->append_right_aligned = append_right_aligned;
851
852        parent_class = &html_clue_class;
853}
854
855void
856html_cluev_init (HTMLClueV *cluev,
857                 HTMLClueVClass *klass,
858                 gint x, gint y,
859                 gint percent)
860{
861        HTMLObject *object;
862        HTMLClue *clue;
863
864        object = HTML_OBJECT (cluev);
865        clue = HTML_CLUE (cluev);
866
867        html_clue_init (clue, HTML_CLUE_CLASS (klass));
868
869        object->x = x;
870        object->y = y;
871        object->percent = percent;
872
873        clue->valign = HTML_VALIGN_BOTTOM;
874        clue->halign = HTML_HALIGN_LEFT;
875        clue->head = clue->tail = clue->curr = 0;
876
877        cluev->align_left_list = 0;
878        cluev->align_right_list = 0;
879        cluev->padding = 0;
880}
881
882HTMLObject *
883html_cluev_new (gint x, gint y, gint percent)
884{
885        HTMLClueV *cluev;
886
887        cluev = g_new (HTMLClueV, 1);
888        html_cluev_init (cluev, &html_cluev_class, x, y, percent);
889       
890        return HTML_OBJECT (cluev);
891}
Note: See TracBrowser for help on using the repository browser.