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) 2000 Helix Code, Inc.
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., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22 #include <config.h>
23 #include "gtkhtmldebug.h"
24 #include "htmlcolor.h"
25 #include "htmlcolorset.h"
26 #include "htmlengine.h"
27 #include "htmlengine-edit.h"
28 #include "htmlengine-save.h"
29 #include "htmlimage.h"
30 #include "htmlpainter.h"
31 #include "htmlsearch.h"
32 #include "htmltable.h"
33 #include "htmltablepriv.h"
34 #include "htmltablecell.h"
35
36 #include "htmlshape.h"
37 #include "htmlstyle.h"
38 #include "htmlframe.h"
39 #include "htmlframeset.h"
40
41
42 HTMLFramesetClass html_frameset_class;
43 static HTMLObjectClass *parent_class = NULL;
44
45 static gint
html_frameset_get_view_height(HTMLFrameset * set)46 html_frameset_get_view_height (HTMLFrameset *set)
47 {
48 HTMLObject *o = HTML_OBJECT (set);
49
50 while (o->parent != NULL) {
51 if (HTML_OBJECT_TYPE (o->parent) == HTML_TYPE_FRAMESET) {
52 return (o->ascent + o->descent);
53 }
54 o = o->parent;
55 }
56 return html_engine_get_view_height (set->parent->engine);
57 }
58
59 static gint
html_frameset_get_view_width(HTMLFrameset * set)60 html_frameset_get_view_width (HTMLFrameset *set)
61 {
62 HTMLObject *o = HTML_OBJECT (set);
63
64 while (o->parent != NULL) {
65 if (HTML_OBJECT_TYPE (o->parent) == HTML_TYPE_FRAMESET) {
66 return html_engine_get_view_width (HTML_FRAMESET (o->parent)->parent->engine);
67 }
68
69 o = o->parent;
70 }
71 return html_engine_get_view_width (set->parent->engine);
72 }
73
74 gboolean
html_frameset_append(HTMLFrameset * set,HTMLObject * frame)75 html_frameset_append (HTMLFrameset *set,
76 HTMLObject *frame)
77 {
78 g_return_val_if_fail (frame != NULL, FALSE);
79 g_return_val_if_fail (set != NULL, FALSE);
80
81 if (set->frames->len >= set->cols->len * set->rows->len)
82 return FALSE;
83
84 g_ptr_array_add (set->frames, frame);
85 html_object_set_parent (frame, HTML_OBJECT (set));
86 return TRUE;
87 }
88
89 static void
calc_dimension(GPtrArray * dim,gint * span,gint total)90 calc_dimension (GPtrArray *dim,
91 gint *span,
92 gint total)
93 {
94 HTMLLength *len;
95 gint i;
96 gint adj;
97 gint remain;
98 gint num_frac = 0;
99 gboolean changed;
100
101 g_return_if_fail (dim != NULL && span != NULL);
102
103 remain = total;
104 for (i = 0; i < dim->len; i++) {
105 len = g_ptr_array_index (dim, i);
106 span[i] = 0;
107
108 if (len->type == HTML_LENGTH_TYPE_PIXELS)
109 span[i] = len->val;
110 else if (len->type == HTML_LENGTH_TYPE_FRACTION)
111 num_frac += len->val;
112 else if (len->type == HTML_LENGTH_TYPE_PERCENT)
113 span[i] = (total * len->val) / 100;
114
115 remain -= span[i];
116 }
117
118 if (remain > 0 && num_frac) {
119 adj = remain / num_frac;
120 for (i = 0; i < dim->len; i++) {
121 len = g_ptr_array_index (dim, i);
122 if (len->type == HTML_LENGTH_TYPE_FRACTION) {
123 span[i] = adj * len->val;
124 remain -= span[i];
125 }
126 }
127 }
128
129 adj = 1;
130 if (remain < 0)
131 adj = -1;
132
133 changed = FALSE;
134 i = 0;
135 while (remain != 0) {
136 if (span[i] > 0) {
137 span[i] += adj;
138 remain -= adj;
139 changed = TRUE;
140 }
141
142 i++;
143 if (i >= dim->len) {
144 i = 0;
145 if (!changed)
146 break;
147 changed = FALSE;
148 }
149 }
150 }
151
152 static gboolean
html_frameset_real_calc_size(HTMLObject * o,HTMLPainter * painter,GList ** changed_objs)153 html_frameset_real_calc_size (HTMLObject *o,
154 HTMLPainter *painter,
155 GList **changed_objs)
156 {
157 HTMLFrameset *set = HTML_FRAMESET (o);
158 HTMLObject *frame = NULL;
159
160 gint view_width;
161 gint view_height;
162
163 gint remain_x;
164 gint remain_y;
165 gint r, c, i;
166
167 gint *widths;
168 gint *heights;
169
170 view_width = html_frameset_get_view_width (set);
171 view_height = html_frameset_get_view_height (set);
172
173 o->ascent = view_height;
174 o->width = view_width;
175 o->descent = 0;
176
177 heights = g_malloc (set->rows->len * sizeof (gint));
178 widths = g_malloc (set->cols->len * sizeof (gint));
179
180 calc_dimension (set->cols, widths, view_width);
181 calc_dimension (set->rows, heights, view_height);
182
183 remain_y = view_height;
184 for (r = 0; r < set->rows->len; r++) {
185
186 remain_x = view_width;
187 for (c = 0; c < set->cols->len; c++) {
188 i = (r * set->cols->len) + c;
189
190 if (i < set->frames->len) {
191 frame = g_ptr_array_index (set->frames, i);
192
193 if (HTML_OBJECT_TYPE (frame) == HTML_TYPE_FRAME)
194 html_frame_set_size (HTML_FRAME (frame), widths[c], heights[r]);
195 else {
196 HTML_OBJECT (frame)->width = widths[c];
197 HTML_OBJECT (frame)->ascent = heights[r];
198 HTML_OBJECT (frame)->descent = 0;
199 }
200 html_object_calc_size (HTML_OBJECT (frame), painter, changed_objs);
201
202 HTML_OBJECT (frame)->x = view_width - remain_x;
203 HTML_OBJECT (frame)->y = view_height + heights[r] - remain_y;
204
205 }
206
207 remain_x -= widths[c];
208 }
209
210 remain_y -= heights[r];
211 }
212
213 g_free (widths);
214 g_free (heights);
215 return TRUE;
216 }
217
218 void
html_frameset_init(HTMLFrameset * set,GtkHTML * parent,const gchar * rows,const gchar * cols)219 html_frameset_init (HTMLFrameset *set,
220 GtkHTML *parent,
221 const gchar *rows,
222 const gchar *cols)
223 {
224 html_object_init (HTML_OBJECT (set), HTML_OBJECT_CLASS (&html_frameset_class));
225 set->parent = parent;
226
227 set->cols = NULL;
228 set->rows = NULL;
229
230 set->cols = g_ptr_array_new ();
231 set->rows = g_ptr_array_new ();
232
233 if (cols == NULL)
234 cols = "100%";
235
236 html_length_array_parse (set->cols, cols);
237
238 if (rows == NULL)
239 rows = "100%";
240
241 html_length_array_parse (set->rows, rows);
242
243 set->frames = g_ptr_array_new ();
244 }
245
246 static void
draw(HTMLObject * o,HTMLPainter * p,gint x,gint y,gint width,gint height,gint tx,gint ty)247 draw (HTMLObject *o,
248 HTMLPainter *p,
249 gint x,
250 gint y,
251 gint width,
252 gint height,
253 gint tx,
254 gint ty)
255 {
256 HTMLFrameset *set;
257 gint i;
258 set = HTML_FRAMESET (o);
259
260 tx += o->x;
261 ty += o->y - o->ascent;
262
263 /* Do nothing by default. We don't know how to paint ourselves. */
264 for (i = 0; i < set->frames->len; i++) {
265 html_object_draw (HTML_OBJECT (g_ptr_array_index (set->frames, i)),
266 p, x - o->x, y - o->y + o->ascent,
267 width, height,
268 tx, ty);
269 }
270 }
271
272 static void
destroy(HTMLObject * self)273 destroy (HTMLObject *self)
274 {
275 HTMLFrameset *set;
276 gint i;
277
278 set = HTML_FRAMESET (self);
279 for (i = 0; i < set->frames->len; i++)
280 html_object_destroy (g_ptr_array_index (set->frames, i));
281
282 html_length_array_destroy (set->cols);
283 html_length_array_destroy (set->rows);
284
285 (* parent_class->destroy) (self);
286 }
287
288 static void
set_max_width(HTMLObject * o,HTMLPainter * painter,gint w)289 set_max_width (HTMLObject *o,
290 HTMLPainter *painter,
291 gint w)
292 {
293 HTMLFrameset *set = HTML_FRAMESET (o);
294 gint remain_x;
295 gint c, i;
296 gint *widths;
297
298 (* HTML_OBJECT_CLASS (parent_class)->set_max_width) (o, painter, w);
299 widths = g_malloc (set->cols->len * sizeof (gint));
300
301 calc_dimension (set->cols, widths, w);
302
303 remain_x = w;
304 for (i = 0; i < set->frames->len; i++) {
305 c = i % set->cols->len;
306 if (i < set->frames->len)
307 html_object_set_max_width (HTML_OBJECT (g_ptr_array_index (set->frames, i)), painter, widths[c]);
308 remain_x -= widths[c];
309 }
310 g_free (widths);
311 }
312
313 static HTMLObject *
check_point(HTMLObject * self,HTMLPainter * painter,gint x,gint y,guint * offset_return,gboolean for_cursor)314 check_point (HTMLObject *self,
315 HTMLPainter *painter,
316 gint x,
317 gint y,
318 guint *offset_return,
319 gboolean for_cursor)
320 {
321 HTMLFrameset *set = HTML_FRAMESET (self);
322 HTMLObject *obj;
323 gint i;
324
325 x -= self->x;
326 y -= self->y - self->ascent;
327
328 for (i = 0; i < set->frames->len; i++) {
329 obj = html_object_check_point (g_ptr_array_index (set->frames, i), painter,
330 x, y, offset_return, for_cursor);
331
332 if (obj != NULL)
333 return obj;
334
335 }
336
337 return NULL;
338 }
339
340 static gboolean
is_container(HTMLObject * self)341 is_container (HTMLObject *self)
342 {
343 return TRUE;
344 }
345
346 /* static void
347 reset (HTMLObject *self)
348 {
349 HTMLFrameset *set;
350 gint i;
351 *
352 (* HTML_OBJECT_CLASS (parent_class)->reset) (self);
353 set = HTML_FRAMESET (self);
354 for (i = 0; i < set->frames->len; i++)
355 html_object_reset (g_ptr_array_index (set->frames, i));
356 *
357 } */
358
359 static void
forall(HTMLObject * self,HTMLEngine * e,HTMLObjectForallFunc func,gpointer data)360 forall (HTMLObject *self,
361 HTMLEngine *e,
362 HTMLObjectForallFunc func,
363 gpointer data)
364 {
365 HTMLFrameset *set;
366 gint i;
367
368 set = HTML_FRAMESET (self);
369 for (i = 0; i < set->frames->len; i++)
370 html_object_forall (g_ptr_array_index (set->frames, i), e, func, data);
371 (* func) (self, e, data);
372 }
373
374 HTMLObject *
html_frameset_new(GtkHTML * parent,gchar * rows,gchar * cols)375 html_frameset_new (GtkHTML *parent,
376 gchar *rows,
377 gchar *cols)
378 {
379 HTMLFrameset *set;
380
381 set = g_new (HTMLFrameset, 1);
382
383 html_frameset_init (set, parent, rows, cols);
384
385 return HTML_OBJECT (set);
386 }
387
388 static gint
calc_min_width(HTMLObject * o,HTMLPainter * p)389 calc_min_width (HTMLObject *o,
390 HTMLPainter *p)
391 {
392 return -1;
393 }
394
395 void
html_frameset_type_init(void)396 html_frameset_type_init (void)
397 {
398 html_frameset_class_init (&html_frameset_class, HTML_TYPE_FRAMESET, sizeof (HTMLFrameset));
399 }
400
401 void
html_frameset_class_init(HTMLFramesetClass * klass,HTMLType type,guint object_size)402 html_frameset_class_init (HTMLFramesetClass *klass,
403 HTMLType type,
404 guint object_size)
405 {
406 HTMLObjectClass *object_class = HTML_OBJECT_CLASS (klass);
407
408 html_object_class_init (object_class, type, object_size);
409
410 object_class->calc_size = html_frameset_real_calc_size;
411 object_class->draw = draw;
412 object_class->destroy = destroy;
413 object_class->check_point = check_point;
414 object_class->set_max_width = set_max_width;
415
416 /* object_class->draw_background = draw_background; */
417 object_class->forall = forall;
418 /* object_class->reset = reset; */
419 object_class->is_container = is_container;
420
421 object_class->calc_min_width = calc_min_width;
422 /*
423 object_class->copy = copy;
424 object_class->op_copy = op_copy;
425 object_class->op_cut = op_cut;
426 object_class->split = split;
427 object_class->merge = merge;
428 object_class->accepts_cursor = accepts_cursor;
429 object_class->destroy = destroy;
430 object_class->calc_preferred_width = calc_preferred_width;
431 object_class->find_anchor = find_anchor;
432 object_class->is_container = is_container;
433 object_class->search = search;
434 object_class->fit_line = fit_line;
435 object_class->append_selection_string = append_selection_string;
436 object_class->head = head;
437 object_class->tail = tail;
438 object_class->next = next;
439 object_class->prev = prev;
440 object_class->save = save;
441 object_class->save_plain = save_plain;
442 object_class->check_page_split = check_page_split;
443 object_class->get_bg_color = get_bg_color;
444 object_class->get_recursive_length = get_recursive_length;
445 object_class->remove_child = remove_child;
446 */
447
448 parent_class = &html_object_class;
449 }
450
451