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