1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* This file is part of the GtkHTML library.
3  *
4  * Copyright (C) 1997 Martin Jones (mjones@kde.org)
5  * Copyright (C) 1997 Torben Weis (weis@kde.org)
6  * Copyright (C) 2000 Helix Code, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22 */
23 
24 #include <config.h>
25 #include <glib/gi18n-lib.h>
26 #include "htmlcolor.h"
27 #include "htmlcolorset.h"
28 #include "htmlengine-save.h"
29 #include "htmlenumutils.h"
30 #include "htmlrule.h"
31 #include "htmlpainter.h"
32 #include "htmlsettings.h"
33 #include "gtkhtml.h"
34 
35 
36 HTMLRuleClass html_rule_class;
37 static HTMLObjectClass *parent_class = NULL;
38 
39 
40 /* HTMLObject methods.  */
41 
42 #define HTML_RULE_MIN_SIZE 12
43 
44 static void
copy(HTMLObject * self,HTMLObject * dest)45 copy (HTMLObject *self,
46       HTMLObject *dest)
47 {
48 	(* HTML_OBJECT_CLASS (parent_class)->copy) (self, dest);
49 
50 	HTML_RULE (dest)->length = HTML_RULE (self)->length;
51 	HTML_RULE (dest)->size   = HTML_RULE (self)->size;
52 	HTML_RULE (dest)->shade  = HTML_RULE (self)->shade;
53 	HTML_RULE (dest)->halign = HTML_RULE (self)->halign;
54 }
55 
56 static void
set_max_width(HTMLObject * o,HTMLPainter * painter,gint max_width)57 set_max_width (HTMLObject *o,
58                HTMLPainter *painter,
59                gint max_width)
60 {
61 	o->max_width = max_width;
62 }
63 
64 static gint
calc_min_width(HTMLObject * o,HTMLPainter * painter)65 calc_min_width (HTMLObject *o,
66                 HTMLPainter *painter)
67 {
68 	gint pixel_size;
69 
70 	pixel_size = html_painter_get_pixel_size (painter);
71 
72 	if (HTML_RULE (o)->length > 0)
73 		return HTML_RULE (o)->length * pixel_size;
74 
75 	return pixel_size;
76 }
77 
78 static HTMLFitType
fit_line(HTMLObject * o,HTMLPainter * painter,gboolean start_of_line,gboolean first_run,gboolean next_to_floating,gint width_left)79 fit_line (HTMLObject *o,
80           HTMLPainter *painter,
81           gboolean start_of_line,
82           gboolean first_run,
83           gboolean next_to_floating,
84           gint width_left)
85 {
86 	if (!start_of_line)
87 		return HTML_FIT_NONE;
88 	o->width = MIN (width_left, o->max_width);
89 
90 	if (o->percent == 0) {
91 		gint pixel_size = html_painter_get_pixel_size (painter);
92 		if (HTML_RULE (o)->length * pixel_size < width_left) {
93 			o->width = HTML_RULE (o)->length * pixel_size;
94 		} else
95 			o->width = width_left;
96 	}
97 
98 	return (next_to_floating && width_left <= 0) ? HTML_FIT_NONE : HTML_FIT_COMPLETE;
99 }
100 
101 static gboolean
html_rule_real_calc_size(HTMLObject * self,HTMLPainter * painter,GList ** changed_objs)102 html_rule_real_calc_size (HTMLObject *self,
103                           HTMLPainter *painter,
104                           GList **changed_objs)
105 {
106 	HTMLRule *rule;
107 	gint ascent, descent;
108 	gint pixel_size;
109 	gint height;
110 	gboolean changed;
111 
112 	rule = HTML_RULE (self);
113 	pixel_size = html_painter_get_pixel_size (painter);
114 
115 	if (rule->size >= HTML_RULE_MIN_SIZE) {
116 		height = rule->size;
117 	} else {
118 		height = HTML_RULE_MIN_SIZE;
119 	}
120 
121 	ascent = (height / 2 + height % 2 + 1) * pixel_size;
122 	descent = (height / 2 + 1) * pixel_size;
123 
124 	changed = FALSE;
125 
126 	if (self->width > self->max_width) {
127 		self->width = self->max_width;
128 		changed = TRUE;
129 	}
130 
131 	if (ascent != self->ascent) {
132 		self->ascent = ascent;
133 		changed = TRUE;
134 	}
135 
136 	if (descent != self->descent) {
137 		self->descent = descent;
138 		changed = TRUE;
139 	}
140 
141 	return changed;
142 }
143 
144 static void
html_rule_draw(HTMLObject * o,HTMLPainter * p,gint x,gint y,gint width,gint height,gint tx,gint ty)145 html_rule_draw (HTMLObject *o,
146       HTMLPainter *p,
147       gint x,
148                 gint y,
149       gint width,
150                 gint height,
151       gint tx,
152                 gint ty)
153 {
154 	HTMLRule *rule;
155 	guint w, h;
156 	gint xp, yp;
157 	gint pixel_size = html_painter_get_pixel_size (p);
158 	HTMLEngine *e;
159 
160 	if (p->widget && GTK_IS_HTML (p->widget))
161 		e = html_object_engine (o, GTK_HTML (p->widget)->engine);
162 	else
163 		return;
164 
165 	rule = HTML_RULE (o);
166 
167 	if (y + height < o->y - o->ascent || y > o->y + o->descent)
168 		return;
169 
170 	h = rule->size * pixel_size;
171 	xp = o->x + tx;
172 	yp = o->y + ty - (rule->size / 2 + rule->size % 2) * pixel_size;
173 
174 	if (o->percent == 0)
175 		w = o->width;
176 	else
177 		/* The cast to `gdouble' is to avoid overflow (eg. when
178 		 * printing).  */
179 		w = ((gdouble) o->width * o->percent) / 100;
180 
181 	switch (rule->halign) {
182 	case HTML_HALIGN_LEFT:
183 		break;
184 	case HTML_HALIGN_CENTER:
185 	case HTML_HALIGN_NONE:
186 		/* Default is `align=center' according to the specs.  */
187 		xp += (o->width - w) / 2;
188 		break;
189 	case HTML_HALIGN_RIGHT:
190 		xp += o->width - w;
191 		break;
192 	default:
193 		g_warning ("Unknown HTMLRule alignment %d.", rule->halign);
194 	}
195 
196 	if (rule->shade)
197 		html_painter_draw_border (p,
198 					  &((html_colorset_get_color (e->settings->color_set, HTMLBgColor))->color),
199 					  xp, yp, w, h, HTML_BORDER_INSET, 1);
200 	else {
201 		html_painter_set_pen (p, &html_colorset_get_color_allocated (e->settings->color_set, p,
202 									     HTMLTextColor)->color);
203 		html_painter_fill_rect (p, xp, yp, w, h);
204 	}
205 }
206 
207 static gboolean
accepts_cursor(HTMLObject * self)208 accepts_cursor (HTMLObject *self)
209 {
210 	return TRUE;
211 }
212 
213 static gboolean
save(HTMLObject * self,HTMLEngineSaveState * state)214 save (HTMLObject *self,
215       HTMLEngineSaveState *state)
216 {
217 	gchar *size;
218 	const gchar *shade;
219 	gchar *align;
220 	gchar *length;
221 	gboolean rv;
222 
223 	size   = HTML_RULE (self)->size == 2 ? g_strdup ("") : g_strdup_printf (" SIZE=\"%d\"", HTML_RULE (self)->size);
224 	shade  = HTML_RULE (self)->shade ? "" : " NOSHADE";
225 	length = HTML_RULE (self)->length
226 		? g_strdup_printf (" LENGTH=\"%d\"", HTML_RULE (self)->length)
227 		: (self->percent > 0 && self->percent != 100 ? g_strdup_printf (" LENGTH=\"%d%%\"", self->percent) : g_strdup (""));
228 	align = g_strdup_printf (" ALIGN=\"%s\"", html_halign_name (HTML_RULE (self)->halign));
229 
230 	rv = html_engine_save_output_string (state, "\n<HR%s%s%s%s>\n", shade, size, length, align);
231 
232 	g_free (align);
233 	g_free (length);
234 	g_free (size);
235 
236 	return rv;
237 }
238 
239 static gboolean
save_plain(HTMLObject * self,HTMLEngineSaveState * state,gint requested_width)240 save_plain (HTMLObject *self,
241             HTMLEngineSaveState *state,
242             gint requested_width)
243 {
244 	gint i;
245 
246 	if (!html_engine_save_output_string (state, "\n"))
247 		return FALSE;
248 
249 	/* Fixme no alignment or percent */
250 	for (i = 0; i < requested_width; i++)
251 		if (!html_engine_save_output_string (state, "_"))
252 			return FALSE;
253 
254 	if (!html_engine_save_output_string (state, "\n"))
255 		return FALSE;
256 
257 	return TRUE;
258 }
259 
260 void
html_rule_type_init(void)261 html_rule_type_init (void)
262 {
263 	html_rule_class_init (&html_rule_class, HTML_TYPE_RULE, sizeof (HTMLRule));
264 }
265 
266 void
html_rule_class_init(HTMLRuleClass * klass,HTMLType type,guint object_size)267 html_rule_class_init (HTMLRuleClass *klass,
268                       HTMLType type,
269                       guint object_size)
270 {
271 	HTMLObjectClass *object_class;
272 
273 	object_class = HTML_OBJECT_CLASS (klass);
274 
275 	html_object_class_init (object_class, type, object_size);
276 
277 	object_class->copy = copy;
278 	object_class->draw = html_rule_draw;
279 	object_class->set_max_width = set_max_width;
280 	object_class->calc_min_width = calc_min_width;
281 	object_class->fit_line = fit_line;
282 	object_class->calc_size = html_rule_real_calc_size;
283 	object_class->accepts_cursor = accepts_cursor;
284 	object_class->save = save;
285 	object_class->save_plain = save_plain;
286 
287 	parent_class = &html_object_class;
288 }
289 
290 void
html_rule_init(HTMLRule * rule,HTMLRuleClass * klass,gint length,gint percent,gint size,gboolean shade,HTMLHAlignType halign)291 html_rule_init (HTMLRule *rule,
292                 HTMLRuleClass *klass,
293                 gint length,
294                 gint percent,
295                 gint size,
296                 gboolean shade,
297                 HTMLHAlignType halign)
298 {
299 	HTMLObject *object;
300 
301 	object = HTML_OBJECT (rule);
302 
303 	html_object_init (object, HTML_OBJECT_CLASS (klass));
304 
305 	if (size < 1)
306 		size = 1;	/* FIXME why? */
307 	rule->size = size;
308 
309 	object->percent = percent;
310 
311 	rule->length = length;
312 	rule->shade  = shade;
313 	rule->halign = halign;
314 
315 	if (percent > 0) {
316 		object->flags &= ~ HTML_OBJECT_FLAG_FIXEDWIDTH;
317 		rule->length = 0;
318 	} else if (rule->length > 0) {
319 		object->flags |= HTML_OBJECT_FLAG_FIXEDWIDTH;
320 	} else {
321 		object->flags &= ~ HTML_OBJECT_FLAG_FIXEDWIDTH;
322 	}
323 }
324 
325 HTMLObject *
html_rule_new(gint length,gint percent,gint size,gboolean shade,HTMLHAlignType halign)326 html_rule_new (gint length,
327                gint percent,
328                gint size,
329                gboolean shade,
330                HTMLHAlignType halign)
331 {
332 	HTMLRule *rule;
333 
334 	rule = g_new (HTMLRule, 1);
335 	html_rule_init (rule, &html_rule_class, length, percent,
336 			size, shade, halign);
337 
338 	return HTML_OBJECT (rule);
339 }
340 
341