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