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) 1999, 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., 59 Temple Place - Suite 330, |
---|
21 | Boston, MA 02111-1307, USA. |
---|
22 | */ |
---|
23 | |
---|
24 | #include <config.h> |
---|
25 | #include <string.h> |
---|
26 | #include <glib/gdataset.h> |
---|
27 | #include <glib/gquark.h> |
---|
28 | |
---|
29 | #include "htmlclue.h" |
---|
30 | #include "htmlclueflow.h" |
---|
31 | #include "htmlcluealigned.h" |
---|
32 | #include "htmlcluev.h" |
---|
33 | #include "htmlcolor.h" |
---|
34 | #include "htmlcolorset.h" |
---|
35 | #include "htmlcursor.h" |
---|
36 | #include "htmlengine.h" |
---|
37 | #include "htmlengine-edit.h" |
---|
38 | #include "htmlengine-save.h" |
---|
39 | #include "htmlframe.h" |
---|
40 | #include "htmlinterval.h" |
---|
41 | #include "htmlobject.h" |
---|
42 | #include "htmlpainter.h" |
---|
43 | #include "htmltable.h" |
---|
44 | #include "htmltext.h" |
---|
45 | #include "htmlrule.h" |
---|
46 | #include "htmltype.h" |
---|
47 | #include "htmlsettings.h" |
---|
48 | |
---|
49 | #include "gtkhtmldebug.h" |
---|
50 | |
---|
51 | |
---|
52 | HTMLObjectClass html_object_class; |
---|
53 | |
---|
54 | #define HO_CLASS(x) HTML_OBJECT_CLASS (HTML_OBJECT (x)->klass) |
---|
55 | |
---|
56 | static void |
---|
57 | destroy (HTMLObject *self) |
---|
58 | { |
---|
59 | #define GTKHTML_MEM_DEBUG 1 |
---|
60 | #if GTKHTML_MEM_DEBUG |
---|
61 | self->parent = HTML_OBJECT (0xdeadbeef); |
---|
62 | self->next = HTML_OBJECT (0xdeadbeef); |
---|
63 | self->prev = HTML_OBJECT (0xdeadbeef); |
---|
64 | #else |
---|
65 | self->next = NULL; |
---|
66 | self->prev = NULL; |
---|
67 | #endif |
---|
68 | |
---|
69 | g_datalist_clear (&self->object_data); |
---|
70 | g_datalist_clear (&self->object_data_nocp); |
---|
71 | |
---|
72 | if (self->redraw_pending) { |
---|
73 | self->free_pending = TRUE; |
---|
74 | } else { |
---|
75 | g_free (self); |
---|
76 | } |
---|
77 | } |
---|
78 | |
---|
79 | static void |
---|
80 | copy (HTMLObject *self, |
---|
81 | HTMLObject *dest) |
---|
82 | { |
---|
83 | dest->klass = self->klass; |
---|
84 | dest->parent = NULL; |
---|
85 | dest->prev = NULL; |
---|
86 | dest->next = NULL; |
---|
87 | dest->x = 0; |
---|
88 | dest->y = 0; |
---|
89 | dest->ascent = self->ascent; |
---|
90 | dest->descent = self->descent; |
---|
91 | dest->width = self->width; |
---|
92 | dest->min_width = self->min_width; |
---|
93 | dest->max_width = self->max_width; |
---|
94 | dest->pref_width = self->pref_width; |
---|
95 | dest->percent = self->percent; |
---|
96 | dest->flags = self->flags; |
---|
97 | dest->redraw_pending = FALSE; |
---|
98 | dest->selected = FALSE; |
---|
99 | dest->free_pending = FALSE; |
---|
100 | dest->change = self->change; |
---|
101 | dest->draw_focused = FALSE; |
---|
102 | |
---|
103 | g_datalist_init (&dest->object_data); |
---|
104 | html_object_copy_data_from_object (dest, self); |
---|
105 | |
---|
106 | g_datalist_init (&dest->object_data_nocp); |
---|
107 | } |
---|
108 | |
---|
109 | static HTMLObject * |
---|
110 | op_copy (HTMLObject *self, HTMLObject *parent, HTMLEngine *e, GList *from, GList *to, guint *len) |
---|
111 | { |
---|
112 | if ((!from || GPOINTER_TO_INT (from->data) == 0) |
---|
113 | && (!to || GPOINTER_TO_INT (to->data) == html_object_get_length (self))) { |
---|
114 | *len += html_object_get_recursive_length (self); |
---|
115 | |
---|
116 | return html_object_dup (self); |
---|
117 | } else |
---|
118 | return html_engine_new_text_empty (e); |
---|
119 | } |
---|
120 | |
---|
121 | static HTMLObject * |
---|
122 | op_cut (HTMLObject *self, HTMLEngine *e, GList *from, GList *to, GList *left, GList *right, guint *len) |
---|
123 | { |
---|
124 | if ((!from || GPOINTER_TO_INT (from->data) == 0) |
---|
125 | && (!to || GPOINTER_TO_INT (to->data) == html_object_get_length (self))) { |
---|
126 | if (!html_object_could_remove_whole (self, from, to, left, right)) { |
---|
127 | HTMLObject *empty = html_engine_new_text_empty (e); |
---|
128 | |
---|
129 | if (e->cursor->object == self) |
---|
130 | e->cursor->object = empty; |
---|
131 | html_clue_append_after (HTML_CLUE (self->parent), empty, self); |
---|
132 | html_object_change_set (empty, HTML_CHANGE_ALL_CALC); |
---|
133 | html_object_check_cut_lists (self, empty, left, right); |
---|
134 | } else |
---|
135 | html_object_move_cursor_before_remove (self, e); |
---|
136 | |
---|
137 | html_object_change_set (self, HTML_CHANGE_ALL_CALC); |
---|
138 | html_object_change_set (self->parent, HTML_CHANGE_ALL_CALC); |
---|
139 | /* force parent redraw */ |
---|
140 | self->parent->width = 0; |
---|
141 | html_object_remove_child (self->parent, self); |
---|
142 | *len += html_object_get_recursive_length (self); |
---|
143 | |
---|
144 | return self; |
---|
145 | } else |
---|
146 | return html_engine_new_text_empty (e); |
---|
147 | } |
---|
148 | |
---|
149 | static gboolean |
---|
150 | merge (HTMLObject *self, HTMLObject *with, HTMLEngine *e, GList **left, GList **right, HTMLCursor *cursor) |
---|
151 | { |
---|
152 | if (self->parent) { |
---|
153 | html_object_change_set (self->parent, HTML_CHANGE_ALL_CALC); |
---|
154 | self->parent->width = 0; |
---|
155 | } |
---|
156 | |
---|
157 | return FALSE; |
---|
158 | } |
---|
159 | |
---|
160 | static void |
---|
161 | remove_child (HTMLObject *self, HTMLObject *child) |
---|
162 | { |
---|
163 | g_warning ("REMOVE CHILD unimplemented for "); |
---|
164 | gtk_html_debug_dump_object_type (self); |
---|
165 | g_assert_not_reached (); |
---|
166 | } |
---|
167 | |
---|
168 | static void |
---|
169 | split (HTMLObject *self, HTMLEngine *e, HTMLObject *child, gint offset, gint level, GList **left, GList **right) |
---|
170 | { |
---|
171 | if (child || (offset && html_object_get_length (self) != offset)) { |
---|
172 | g_warning ("don't know how to SPLIT "); |
---|
173 | gtk_html_debug_dump_object_type (self); |
---|
174 | return; |
---|
175 | } |
---|
176 | |
---|
177 | if (offset) { |
---|
178 | if (!self->next) { |
---|
179 | html_clue_append (HTML_CLUE (self->parent), html_engine_new_text_empty (e)); |
---|
180 | } |
---|
181 | *left = g_list_prepend (*left, self); |
---|
182 | *right = g_list_prepend (*right, self->next); |
---|
183 | } else { |
---|
184 | if (!self->prev) { |
---|
185 | e->cursor->object = html_engine_new_text_empty (e); |
---|
186 | e->cursor->offset = 0; |
---|
187 | html_clue_prepend (HTML_CLUE (self->parent), e->cursor->object); |
---|
188 | } |
---|
189 | *left = g_list_prepend (*left, self->prev); |
---|
190 | *right = g_list_prepend (*right, self); |
---|
191 | } |
---|
192 | level--; |
---|
193 | |
---|
194 | if (level && self->parent) |
---|
195 | html_object_split (self->parent, e, offset ? self->next : self, 0, level, left, right); |
---|
196 | } |
---|
197 | |
---|
198 | static void |
---|
199 | draw (HTMLObject *o, |
---|
200 | HTMLPainter *p, |
---|
201 | gint x, gint y, |
---|
202 | gint width, gint height, |
---|
203 | gint tx, gint ty) |
---|
204 | { |
---|
205 | /* Do nothing by default. We don't know how to paint ourselves. */ |
---|
206 | } |
---|
207 | |
---|
208 | static gboolean |
---|
209 | is_transparent (HTMLObject *self) |
---|
210 | { |
---|
211 | return TRUE; |
---|
212 | } |
---|
213 | |
---|
214 | static HTMLFitType |
---|
215 | fit_line (HTMLObject *o, |
---|
216 | HTMLPainter *painter, |
---|
217 | gboolean start_of_line, |
---|
218 | gboolean first_run, |
---|
219 | gboolean next_to_floating, |
---|
220 | gint width_left) |
---|
221 | { |
---|
222 | return (o->width <= width_left || (first_run && !next_to_floating)) ? HTML_FIT_COMPLETE : HTML_FIT_NONE; |
---|
223 | } |
---|
224 | |
---|
225 | static gboolean |
---|
226 | html_object_real_calc_size (HTMLObject *o, HTMLPainter *painter, GList **changed_objs) |
---|
227 | { |
---|
228 | return FALSE; |
---|
229 | } |
---|
230 | |
---|
231 | static gint |
---|
232 | calc_min_width (HTMLObject *o, HTMLPainter *painter) |
---|
233 | { |
---|
234 | html_object_calc_size (o, painter, FALSE); |
---|
235 | return o->width; |
---|
236 | } |
---|
237 | |
---|
238 | static gint |
---|
239 | calc_preferred_width (HTMLObject *o, HTMLPainter *painter) |
---|
240 | { |
---|
241 | html_object_calc_size (o, painter, FALSE); |
---|
242 | return o->width; |
---|
243 | } |
---|
244 | |
---|
245 | static void |
---|
246 | set_max_width (HTMLObject *o, HTMLPainter *painter, gint max_width) |
---|
247 | { |
---|
248 | o->max_width = max_width; |
---|
249 | } |
---|
250 | |
---|
251 | static void |
---|
252 | set_max_height (HTMLObject *o, HTMLPainter *painter, gint max_height) |
---|
253 | { |
---|
254 | } |
---|
255 | |
---|
256 | static gint |
---|
257 | get_left_margin (HTMLObject *self, HTMLPainter *painter, gint y, gboolean with_aligned) |
---|
258 | { |
---|
259 | return 0; |
---|
260 | } |
---|
261 | |
---|
262 | static gint |
---|
263 | get_right_margin (HTMLObject *self, HTMLPainter *painter, gint y, gboolean with_aligned) |
---|
264 | { |
---|
265 | return MAX (self->max_width, self->width); |
---|
266 | } |
---|
267 | |
---|
268 | static void |
---|
269 | set_painter (HTMLObject *o, HTMLPainter *painter) |
---|
270 | { |
---|
271 | } |
---|
272 | |
---|
273 | static void |
---|
274 | reset (HTMLObject *o) |
---|
275 | { |
---|
276 | /* o->width = 0; |
---|
277 | o->ascent = 0; |
---|
278 | o->descent = 0; */ |
---|
279 | } |
---|
280 | |
---|
281 | static const gchar * |
---|
282 | get_url (HTMLObject *o, gint offset) |
---|
283 | { |
---|
284 | return NULL; |
---|
285 | } |
---|
286 | |
---|
287 | static const gchar * |
---|
288 | get_target (HTMLObject *o, gint offset) |
---|
289 | { |
---|
290 | return NULL; |
---|
291 | } |
---|
292 | |
---|
293 | static const gchar * |
---|
294 | get_src (HTMLObject *o) |
---|
295 | { |
---|
296 | return NULL; |
---|
297 | } |
---|
298 | |
---|
299 | static HTMLAnchor * |
---|
300 | find_anchor (HTMLObject *o, |
---|
301 | const gchar *name, |
---|
302 | gint *x, gint *y) |
---|
303 | { |
---|
304 | return NULL; |
---|
305 | } |
---|
306 | |
---|
307 | static void |
---|
308 | set_bg_color (HTMLObject *o, |
---|
309 | GdkColor *color) |
---|
310 | { |
---|
311 | } |
---|
312 | |
---|
313 | static GdkColor * |
---|
314 | get_bg_color (HTMLObject *o, |
---|
315 | HTMLPainter *p) |
---|
316 | { |
---|
317 | if (o->parent) |
---|
318 | return html_object_get_bg_color (o->parent, p); |
---|
319 | |
---|
320 | if (p->widget && GTK_IS_HTML (p->widget)) |
---|
321 | return &((html_colorset_get_color (GTK_HTML (p->widget)->engine->settings->color_set, |
---|
322 | HTMLBgColor))->color); |
---|
323 | return NULL; |
---|
324 | } |
---|
325 | |
---|
326 | static HTMLObject* |
---|
327 | check_point (HTMLObject *self, |
---|
328 | HTMLPainter *painter, |
---|
329 | gint x, gint y, |
---|
330 | guint *offset_return, |
---|
331 | gboolean for_cursor) |
---|
332 | { |
---|
333 | if (x >= self->x |
---|
334 | && x < self->x + self->width |
---|
335 | && y >= self->y - self->ascent |
---|
336 | && y < self->y + self->descent) { |
---|
337 | if (offset_return != NULL) |
---|
338 | *offset_return = 0; |
---|
339 | return self; |
---|
340 | } |
---|
341 | |
---|
342 | return NULL; |
---|
343 | } |
---|
344 | |
---|
345 | static gboolean |
---|
346 | relayout (HTMLObject *self, |
---|
347 | HTMLEngine *engine, |
---|
348 | HTMLObject *child) |
---|
349 | { |
---|
350 | /* FIXME int types of this stuff might change in `htmlobject.h', |
---|
351 | remember to sync. */ |
---|
352 | guint prev_width; |
---|
353 | guint prev_ascent, prev_descent; |
---|
354 | gboolean changed; |
---|
355 | |
---|
356 | if (html_engine_frozen (engine)) |
---|
357 | return FALSE; |
---|
358 | |
---|
359 | prev_width = self->width; |
---|
360 | prev_ascent = self->ascent; |
---|
361 | prev_descent = self->descent; |
---|
362 | |
---|
363 | /* Notice that this will reset ascent and descent which we |
---|
364 | need afterwards. Yeah, yuck, bleargh. */ |
---|
365 | html_object_reset (self); |
---|
366 | |
---|
367 | /* Crappy hack to make crappy htmlclueflow.c happy. */ |
---|
368 | if (self->y < self->ascent + self->descent) { |
---|
369 | g_warning ("htmlobject.c:relayout -- Eeek! This should not happen! " |
---|
370 | "Y value < height of object!\n"); |
---|
371 | self->y = 0; |
---|
372 | } else { |
---|
373 | self->y -= prev_ascent + prev_descent; |
---|
374 | } |
---|
375 | |
---|
376 | changed = html_object_calc_size (self, engine->painter, FALSE); |
---|
377 | |
---|
378 | if (prev_width == self->width |
---|
379 | && prev_ascent == self->ascent |
---|
380 | && prev_descent == self->descent) { |
---|
381 | gtk_html_debug_log (engine->widget, |
---|
382 | "relayout: %s %p did not change.\n", |
---|
383 | html_type_name (HTML_OBJECT_TYPE (self)), |
---|
384 | self); |
---|
385 | if (changed) |
---|
386 | html_engine_queue_draw (engine, self); |
---|
387 | |
---|
388 | return FALSE; |
---|
389 | } |
---|
390 | |
---|
391 | gtk_html_debug_log (engine->widget, "relayout: %s %p changed.\n", |
---|
392 | html_type_name (HTML_OBJECT_TYPE (self)), self); |
---|
393 | |
---|
394 | if (self->parent == NULL) { |
---|
395 | /* FIXME resize the widget, e.g. scrollbars and such. */ |
---|
396 | html_engine_queue_draw (engine, self); |
---|
397 | |
---|
398 | /* FIXME extreme ugliness. */ |
---|
399 | self->x = 0; |
---|
400 | self->y = self->ascent; |
---|
401 | } else { |
---|
402 | /* Relayout our parent starting from us. */ |
---|
403 | if (! html_object_relayout (self->parent, engine, self)) |
---|
404 | html_engine_queue_draw (engine, self); |
---|
405 | } |
---|
406 | |
---|
407 | /* If the object has shrunk, we have to clean the areas around |
---|
408 | it so that we don't leave garbage on the screen. FIXME: |
---|
409 | this wastes some time if there is an object on the right of |
---|
410 | or under this one. */ |
---|
411 | |
---|
412 | if (prev_ascent + prev_descent > self->ascent + self->descent) |
---|
413 | html_engine_queue_clear (engine, |
---|
414 | self->x, |
---|
415 | self->y + self->descent, |
---|
416 | self->width, |
---|
417 | (prev_ascent + prev_descent |
---|
418 | - (self->ascent + self->descent))); |
---|
419 | |
---|
420 | if (prev_width > self->width) |
---|
421 | html_engine_queue_clear (engine, |
---|
422 | self->x + self->width, |
---|
423 | self->y - self->ascent, |
---|
424 | prev_width - self->width, |
---|
425 | self->ascent + self->descent); |
---|
426 | |
---|
427 | return TRUE; |
---|
428 | } |
---|
429 | |
---|
430 | static HTMLVAlignType |
---|
431 | get_valign (HTMLObject *self) |
---|
432 | { |
---|
433 | return HTML_VALIGN_BOTTOM; |
---|
434 | } |
---|
435 | |
---|
436 | static gboolean |
---|
437 | accepts_cursor (HTMLObject *self) |
---|
438 | { |
---|
439 | return FALSE; |
---|
440 | } |
---|
441 | |
---|
442 | static void |
---|
443 | get_cursor (HTMLObject *self, |
---|
444 | HTMLPainter *painter, |
---|
445 | guint offset, |
---|
446 | gint *x1, gint *y1, |
---|
447 | gint *x2, gint *y2) |
---|
448 | { |
---|
449 | html_object_get_cursor_base (self, painter, offset, x2, y2); |
---|
450 | |
---|
451 | *x1 = *x2; |
---|
452 | *y1 = *y2 - self->ascent; |
---|
453 | *y2 += self->descent - 1; |
---|
454 | } |
---|
455 | |
---|
456 | static void |
---|
457 | get_cursor_base (HTMLObject *self, |
---|
458 | HTMLPainter *painter, |
---|
459 | guint offset, |
---|
460 | gint *x, gint *y) |
---|
461 | { |
---|
462 | html_object_calc_abs_position (self, x, y); |
---|
463 | |
---|
464 | if (offset > 0) |
---|
465 | *x += self->width; |
---|
466 | } |
---|
467 | |
---|
468 | static guint |
---|
469 | get_length (HTMLObject *self) |
---|
470 | { |
---|
471 | return html_object_accepts_cursor (self) ? 1 : 0; |
---|
472 | } |
---|
473 | |
---|
474 | static guint |
---|
475 | get_line_length (HTMLObject *self, HTMLPainter *p, gint line_offset) |
---|
476 | { |
---|
477 | return html_object_get_length (self); |
---|
478 | } |
---|
479 | |
---|
480 | static guint |
---|
481 | get_recursive_length (HTMLObject *self) |
---|
482 | { |
---|
483 | return html_object_get_length (self); |
---|
484 | } |
---|
485 | |
---|
486 | static gboolean |
---|
487 | select_range (HTMLObject *self, |
---|
488 | HTMLEngine *engine, |
---|
489 | guint start, |
---|
490 | gint length, |
---|
491 | gboolean queue_draw) |
---|
492 | { |
---|
493 | gboolean selected; |
---|
494 | gboolean changed; |
---|
495 | |
---|
496 | selected = length > 0 || (length == -1 && start < html_object_get_length (self)) || html_object_is_container (self) ? TRUE : FALSE; |
---|
497 | changed = (! selected && self->selected) || (selected && ! self->selected) ? TRUE : FALSE; |
---|
498 | |
---|
499 | self->selected = selected; |
---|
500 | |
---|
501 | return changed; |
---|
502 | } |
---|
503 | |
---|
504 | static void |
---|
505 | append_selection_string (HTMLObject *self, |
---|
506 | GString *buffer) |
---|
507 | { |
---|
508 | } |
---|
509 | |
---|
510 | static void |
---|
511 | forall (HTMLObject *self, |
---|
512 | HTMLEngine *e, |
---|
513 | HTMLObjectForallFunc func, |
---|
514 | gpointer data) |
---|
515 | { |
---|
516 | (* func) (self, e, data); |
---|
517 | } |
---|
518 | |
---|
519 | static HTMLEngine * |
---|
520 | get_engine (HTMLObject *self, |
---|
521 | HTMLEngine *e) |
---|
522 | { |
---|
523 | return e; |
---|
524 | } |
---|
525 | |
---|
526 | static gboolean |
---|
527 | is_container (HTMLObject *self) |
---|
528 | { |
---|
529 | return FALSE; |
---|
530 | } |
---|
531 | |
---|
532 | static gboolean |
---|
533 | save (HTMLObject *self, |
---|
534 | HTMLEngineSaveState *state) |
---|
535 | { |
---|
536 | return TRUE; |
---|
537 | } |
---|
538 | |
---|
539 | static gboolean |
---|
540 | save_plain (HTMLObject *self, |
---|
541 | HTMLEngineSaveState *state, |
---|
542 | gint requested_width) |
---|
543 | { |
---|
544 | return TRUE; |
---|
545 | } |
---|
546 | |
---|
547 | static gint |
---|
548 | check_page_split (HTMLObject *self, HTMLPainter *p, gint y) |
---|
549 | { |
---|
550 | return 0; |
---|
551 | } |
---|
552 | |
---|
553 | static gboolean |
---|
554 | search (HTMLObject *self, HTMLSearch *info) |
---|
555 | { |
---|
556 | /* not found by default */ |
---|
557 | return FALSE; |
---|
558 | } |
---|
559 | |
---|
560 | static HTMLObject * |
---|
561 | next (HTMLObject *self, HTMLObject *child) |
---|
562 | { |
---|
563 | return child->next; |
---|
564 | } |
---|
565 | |
---|
566 | static HTMLObject * |
---|
567 | prev (HTMLObject *self, HTMLObject *child) |
---|
568 | { |
---|
569 | return child->prev; |
---|
570 | } |
---|
571 | |
---|
572 | static HTMLObject * |
---|
573 | head (HTMLObject *self) |
---|
574 | { |
---|
575 | return NULL; |
---|
576 | } |
---|
577 | |
---|
578 | static HTMLObject * |
---|
579 | tail (HTMLObject *self) |
---|
580 | { |
---|
581 | return NULL; |
---|
582 | } |
---|
583 | |
---|
584 | static HTMLClearType |
---|
585 | get_clear (HTMLObject *self) |
---|
586 | { |
---|
587 | return HTML_CLEAR_NONE; |
---|
588 | } |
---|
589 | |
---|
590 | /* Class initialization. */ |
---|
591 | |
---|
592 | void |
---|
593 | html_object_type_init (void) |
---|
594 | { |
---|
595 | html_object_class_init (&html_object_class, HTML_TYPE_OBJECT, sizeof (HTMLObject)); |
---|
596 | } |
---|
597 | |
---|
598 | void |
---|
599 | html_object_class_init (HTMLObjectClass *klass, |
---|
600 | HTMLType type, |
---|
601 | guint object_size) |
---|
602 | { |
---|
603 | g_return_if_fail (klass != NULL); |
---|
604 | |
---|
605 | /* Set type. */ |
---|
606 | klass->type = type; |
---|
607 | klass->object_size = object_size; |
---|
608 | |
---|
609 | /* Install virtual methods. */ |
---|
610 | klass->destroy = destroy; |
---|
611 | klass->copy = copy; |
---|
612 | klass->op_copy = op_copy; |
---|
613 | klass->op_cut = op_cut; |
---|
614 | klass->merge = merge; |
---|
615 | klass->remove_child = remove_child; |
---|
616 | klass->split = split; |
---|
617 | klass->draw = draw; |
---|
618 | klass->is_transparent = is_transparent; |
---|
619 | klass->fit_line = fit_line; |
---|
620 | klass->calc_size = html_object_real_calc_size; |
---|
621 | klass->set_max_width = set_max_width; |
---|
622 | klass->set_max_height = set_max_height; |
---|
623 | klass->get_left_margin = get_left_margin; |
---|
624 | klass->get_right_margin = get_right_margin; |
---|
625 | klass->set_painter = set_painter; |
---|
626 | klass->reset = reset; |
---|
627 | klass->calc_min_width = calc_min_width; |
---|
628 | klass->calc_preferred_width = calc_preferred_width; |
---|
629 | klass->get_url = get_url; |
---|
630 | klass->get_target = get_target; |
---|
631 | klass->get_src = get_src; |
---|
632 | klass->find_anchor = find_anchor; |
---|
633 | klass->set_link = NULL; |
---|
634 | klass->set_bg_color = set_bg_color; |
---|
635 | klass->get_bg_color = get_bg_color; |
---|
636 | klass->check_point = check_point; |
---|
637 | klass->relayout = relayout; |
---|
638 | klass->get_valign = get_valign; |
---|
639 | klass->accepts_cursor = accepts_cursor; |
---|
640 | klass->get_cursor = get_cursor; |
---|
641 | klass->get_cursor_base = get_cursor_base; |
---|
642 | klass->select_range = select_range; |
---|
643 | klass->append_selection_string = append_selection_string; |
---|
644 | klass->forall = forall; |
---|
645 | klass->is_container = is_container; |
---|
646 | klass->save = save; |
---|
647 | klass->save_plain = save_plain; |
---|
648 | klass->check_page_split = check_page_split; |
---|
649 | klass->search = search; |
---|
650 | klass->search_next = search; |
---|
651 | klass->get_length = get_length; |
---|
652 | klass->get_line_length = get_line_length; |
---|
653 | klass->get_recursive_length = get_recursive_length; |
---|
654 | klass->next = next; |
---|
655 | klass->prev = prev; |
---|
656 | klass->head = head; |
---|
657 | klass->tail = tail; |
---|
658 | klass->get_engine = get_engine; |
---|
659 | klass->get_clear = get_clear; |
---|
660 | } |
---|
661 | |
---|
662 | void |
---|
663 | html_object_init (HTMLObject *o, |
---|
664 | HTMLObjectClass *klass) |
---|
665 | { |
---|
666 | o->klass = klass; |
---|
667 | |
---|
668 | o->parent = NULL; |
---|
669 | o->prev = NULL; |
---|
670 | o->next = NULL; |
---|
671 | |
---|
672 | /* we don't have any info cached in the beginning */ |
---|
673 | o->change = HTML_CHANGE_ALL; |
---|
674 | |
---|
675 | o->x = 0; |
---|
676 | o->y = 0; |
---|
677 | |
---|
678 | o->ascent = 0; |
---|
679 | o->descent = 0; |
---|
680 | |
---|
681 | o->width = 0; |
---|
682 | o->max_width = 0; |
---|
683 | o->min_width = 0; |
---|
684 | o->pref_width = 0; |
---|
685 | o->percent = 0; |
---|
686 | |
---|
687 | o->flags = HTML_OBJECT_FLAG_FIXEDWIDTH; /* FIXME Why? */ |
---|
688 | |
---|
689 | o->redraw_pending = FALSE; |
---|
690 | o->free_pending = FALSE; |
---|
691 | o->selected = FALSE; |
---|
692 | o->draw_focused = FALSE; |
---|
693 | |
---|
694 | g_datalist_init (&o->object_data); |
---|
695 | g_datalist_init (&o->object_data_nocp); |
---|
696 | } |
---|
697 | |
---|
698 | HTMLObject * |
---|
699 | html_object_new (HTMLObject *parent) |
---|
700 | { |
---|
701 | HTMLObject *o; |
---|
702 | |
---|
703 | o = g_new0 (HTMLObject, 1); |
---|
704 | html_object_init (o, &html_object_class); |
---|
705 | |
---|
706 | return o; |
---|
707 | } |
---|
708 | |
---|
709 | |
---|
710 | /* Object duplication. */ |
---|
711 | |
---|
712 | HTMLObject * |
---|
713 | html_object_dup (HTMLObject *object) |
---|
714 | { |
---|
715 | HTMLObject *new; |
---|
716 | |
---|
717 | g_return_val_if_fail (object != NULL, NULL); |
---|
718 | |
---|
719 | new = g_malloc (object->klass->object_size); |
---|
720 | html_object_copy (object, new); |
---|
721 | |
---|
722 | return new; |
---|
723 | } |
---|
724 | |
---|
725 | HTMLObject * |
---|
726 | html_object_op_copy (HTMLObject *self, HTMLObject *parent, HTMLEngine *e, GList *from, GList *to, guint *len) |
---|
727 | { |
---|
728 | return (* HO_CLASS (self)->op_copy) (self, parent, e, from, to, len); |
---|
729 | } |
---|
730 | |
---|
731 | HTMLObject * |
---|
732 | html_object_op_cut (HTMLObject *self, HTMLEngine *e, GList *from, GList *to, GList *left, GList *right, guint *len) |
---|
733 | { |
---|
734 | return (* HO_CLASS (self)->op_cut) (self, e, from, to, left, right, len); |
---|
735 | } |
---|
736 | |
---|
737 | gboolean |
---|
738 | html_object_merge (HTMLObject *self, HTMLObject *with, HTMLEngine *e, GList **left, GList **right, HTMLCursor *cursor) |
---|
739 | { |
---|
740 | if ((HTML_OBJECT_TYPE (self) == HTML_OBJECT_TYPE (with) |
---|
741 | /* FIXME */ |
---|
742 | || (HTML_OBJECT_TYPE (self) == HTML_TYPE_TABLECELL && HTML_OBJECT_TYPE (with) == HTML_TYPE_CLUEV) |
---|
743 | || (HTML_OBJECT_TYPE (with) == HTML_TYPE_TABLECELL && HTML_OBJECT_TYPE (self) == HTML_TYPE_CLUEV)) |
---|
744 | && (* HO_CLASS (self)->merge) (self, with, e, left, right, cursor)) { |
---|
745 | if (with->parent) |
---|
746 | html_object_remove_child (with->parent, with); |
---|
747 | html_object_destroy (with); |
---|
748 | return TRUE; |
---|
749 | } |
---|
750 | return FALSE; |
---|
751 | } |
---|
752 | |
---|
753 | void |
---|
754 | html_object_remove_child (HTMLObject *self, HTMLObject *child) |
---|
755 | { |
---|
756 | g_assert (self); |
---|
757 | g_assert (child); |
---|
758 | |
---|
759 | (* HO_CLASS (self)->remove_child) (self, child); |
---|
760 | } |
---|
761 | |
---|
762 | void |
---|
763 | html_object_split (HTMLObject *self, HTMLEngine *e, HTMLObject *child, gint offset, gint level, |
---|
764 | GList **left, GList **right) |
---|
765 | { |
---|
766 | g_assert (self); |
---|
767 | |
---|
768 | (* HO_CLASS (self)->split) (self, e, child, offset, level, left, right); |
---|
769 | } |
---|
770 | |
---|
771 | |
---|
772 | void |
---|
773 | html_object_set_parent (HTMLObject *o, HTMLObject *parent) |
---|
774 | { |
---|
775 | o->parent = parent; |
---|
776 | } |
---|
777 | |
---|
778 | |
---|
779 | static void |
---|
780 | frame_offset (HTMLObject *o, |
---|
781 | gint *x_return, gint *y_return) |
---|
782 | { |
---|
783 | if (html_object_is_frame (o)) { |
---|
784 | HTMLEngine *e = html_object_get_engine (o, NULL); |
---|
785 | *x_return -= e->x_offset; |
---|
786 | *y_return -= e->y_offset; |
---|
787 | } |
---|
788 | } |
---|
789 | |
---|
790 | void |
---|
791 | html_object_calc_abs_position (HTMLObject *o, |
---|
792 | gint *x_return, gint *y_return) |
---|
793 | { |
---|
794 | HTMLObject *p; |
---|
795 | |
---|
796 | g_return_if_fail (o != NULL); |
---|
797 | |
---|
798 | *x_return = o->x; |
---|
799 | *y_return = o->y; |
---|
800 | |
---|
801 | frame_offset (o, x_return, y_return); |
---|
802 | |
---|
803 | for (p = o->parent; p != NULL; p = p->parent) { |
---|
804 | *x_return += p->x; |
---|
805 | *y_return += p->y - p->ascent; |
---|
806 | |
---|
807 | frame_offset (p, x_return, y_return); |
---|
808 | } |
---|
809 | } |
---|
810 | |
---|
811 | GdkRectangle * |
---|
812 | html_object_get_bounds (HTMLObject *o, GdkRectangle *bounds) |
---|
813 | { |
---|
814 | if (!bounds) |
---|
815 | bounds = g_new (GdkRectangle, 1); |
---|
816 | |
---|
817 | bounds->x = o->x; |
---|
818 | bounds->y = o->y - o->ascent; |
---|
819 | bounds->width = o->width; |
---|
820 | bounds->height = o->ascent + o->descent; |
---|
821 | |
---|
822 | return bounds; |
---|
823 | } |
---|
824 | |
---|
825 | gboolean |
---|
826 | html_object_intersect (HTMLObject *o, GdkRectangle *result, gint x, gint y, gint width, gint height) |
---|
827 | { |
---|
828 | GdkRectangle b; |
---|
829 | GdkRectangle a; |
---|
830 | |
---|
831 | a.x = x; |
---|
832 | a.y = y; |
---|
833 | a.width = width; |
---|
834 | a.height = height; |
---|
835 | |
---|
836 | return gdk_rectangle_intersect (html_object_get_bounds (o, &b), &a, result); |
---|
837 | } |
---|
838 | |
---|
839 | |
---|
840 | /* Virtual methods. */ |
---|
841 | |
---|
842 | void |
---|
843 | html_object_destroy (HTMLObject *self) |
---|
844 | { |
---|
845 | (* HO_CLASS (self)->destroy) (self); |
---|
846 | } |
---|
847 | |
---|
848 | void |
---|
849 | html_object_copy (HTMLObject *self, |
---|
850 | HTMLObject *dest) |
---|
851 | { |
---|
852 | (* HO_CLASS (self)->copy) (self, dest); |
---|
853 | } |
---|
854 | |
---|
855 | void |
---|
856 | html_object_draw (HTMLObject *o, |
---|
857 | HTMLPainter *p, |
---|
858 | gint x, gint y, |
---|
859 | gint width, gint height, |
---|
860 | gint tx, gint ty) |
---|
861 | { |
---|
862 | (* HO_CLASS (o)->draw) (o, p, x, y, width, height, tx, ty); |
---|
863 | } |
---|
864 | |
---|
865 | gboolean |
---|
866 | html_object_is_transparent (HTMLObject *self) |
---|
867 | { |
---|
868 | g_return_val_if_fail (self != NULL, TRUE); |
---|
869 | |
---|
870 | return (* HO_CLASS (self)->is_transparent) (self); |
---|
871 | } |
---|
872 | |
---|
873 | HTMLFitType |
---|
874 | html_object_fit_line (HTMLObject *o, |
---|
875 | HTMLPainter *painter, |
---|
876 | gboolean start_of_line, |
---|
877 | gboolean first_run, |
---|
878 | gboolean next_to_floating, |
---|
879 | gint width_left) |
---|
880 | { |
---|
881 | return (* HO_CLASS (o)->fit_line) (o, painter, start_of_line, first_run, next_to_floating, width_left); |
---|
882 | } |
---|
883 | |
---|
884 | gboolean |
---|
885 | html_object_calc_size (HTMLObject *o, HTMLPainter *painter, GList **changed_objs) |
---|
886 | { |
---|
887 | gboolean rv; |
---|
888 | |
---|
889 | rv = (* HO_CLASS (o)->calc_size) (o, painter, changed_objs); |
---|
890 | o->change &= ~HTML_CHANGE_SIZE; |
---|
891 | |
---|
892 | return rv; |
---|
893 | } |
---|
894 | |
---|
895 | void |
---|
896 | html_object_set_max_width (HTMLObject *o, HTMLPainter *painter, gint max_width) |
---|
897 | { |
---|
898 | (* HO_CLASS (o)->set_max_width) (o, painter, max_width); |
---|
899 | } |
---|
900 | |
---|
901 | void |
---|
902 | html_object_set_max_height (HTMLObject *o, HTMLPainter *painter, gint max_height) |
---|
903 | { |
---|
904 | (* HO_CLASS (o)->set_max_height) (o, painter, max_height); |
---|
905 | } |
---|
906 | |
---|
907 | gint |
---|
908 | html_object_get_left_margin (HTMLObject *self, HTMLPainter *painter, gint y, gboolean with_aligned) |
---|
909 | { |
---|
910 | return (* HO_CLASS (self)->get_left_margin) (self, painter, y, with_aligned); |
---|
911 | } |
---|
912 | |
---|
913 | gint |
---|
914 | html_object_get_right_margin (HTMLObject *self, HTMLPainter *painter, gint y, gboolean with_aligned) |
---|
915 | { |
---|
916 | return (* HO_CLASS (self)->get_right_margin) (self, painter, y, with_aligned); |
---|
917 | } |
---|
918 | |
---|
919 | static void |
---|
920 | set_painter_forall (HTMLObject *o, HTMLEngine *e, gpointer data) |
---|
921 | { |
---|
922 | (* HO_CLASS (o)->set_painter) (o, HTML_PAINTER (data)); |
---|
923 | } |
---|
924 | |
---|
925 | void |
---|
926 | html_object_set_painter (HTMLObject *o, HTMLPainter *painter) |
---|
927 | { |
---|
928 | html_object_forall (o, NULL, set_painter_forall, painter); |
---|
929 | } |
---|
930 | |
---|
931 | void |
---|
932 | html_object_reset (HTMLObject *o) |
---|
933 | { |
---|
934 | (* HO_CLASS (o)->reset) (o); |
---|
935 | } |
---|
936 | |
---|
937 | gint |
---|
938 | html_object_calc_min_width (HTMLObject *o, |
---|
939 | HTMLPainter *painter) |
---|
940 | { |
---|
941 | if (o->change & HTML_CHANGE_MIN_WIDTH) { |
---|
942 | o->min_width = (* HO_CLASS (o)->calc_min_width) (o, painter); |
---|
943 | o->change &= ~HTML_CHANGE_MIN_WIDTH; |
---|
944 | } |
---|
945 | return o->min_width; |
---|
946 | } |
---|
947 | |
---|
948 | gint |
---|
949 | html_object_calc_preferred_width (HTMLObject *o, |
---|
950 | HTMLPainter *painter) |
---|
951 | { |
---|
952 | if (o->change & HTML_CHANGE_PREF_WIDTH) { |
---|
953 | o->pref_width = (* HO_CLASS (o)->calc_preferred_width) (o, painter); |
---|
954 | o->change &= ~HTML_CHANGE_PREF_WIDTH; |
---|
955 | } |
---|
956 | return o->pref_width; |
---|
957 | } |
---|
958 | |
---|
959 | #if 0 |
---|
960 | gint |
---|
961 | html_object_get_uris (HTMLObject *o, char **link, char **target, char **src) |
---|
962 | { |
---|
963 | return TRUE; |
---|
964 | } |
---|
965 | #endif |
---|
966 | |
---|
967 | const gchar * |
---|
968 | html_object_get_url (HTMLObject *o, gint offset) |
---|
969 | { |
---|
970 | return (* HO_CLASS (o)->get_url) (o, offset); |
---|
971 | } |
---|
972 | |
---|
973 | const gchar * |
---|
974 | html_object_get_target (HTMLObject *o, gint offset) |
---|
975 | { |
---|
976 | return (* HO_CLASS (o)->get_target) (o, offset); |
---|
977 | } |
---|
978 | |
---|
979 | gchar * |
---|
980 | html_object_get_complete_url (HTMLObject *o, gint offset) |
---|
981 | { |
---|
982 | const gchar *url, *target; |
---|
983 | |
---|
984 | url = html_object_get_url (o, offset); |
---|
985 | target = html_object_get_target (o, offset); |
---|
986 | return url || target ? g_strconcat (url ? url : "#", url ? (target && *target ? "#" : NULL) : target, |
---|
987 | url ? target : NULL, NULL) : NULL; |
---|
988 | } |
---|
989 | |
---|
990 | const gchar * |
---|
991 | html_object_get_src (HTMLObject *o) |
---|
992 | { |
---|
993 | return (* HO_CLASS (o)->get_src) (o); |
---|
994 | } |
---|
995 | |
---|
996 | HTMLAnchor * |
---|
997 | html_object_find_anchor (HTMLObject *o, |
---|
998 | const gchar *name, |
---|
999 | gint *x, gint *y) |
---|
1000 | { |
---|
1001 | return (* HO_CLASS (o)->find_anchor) (o, name, x, y); |
---|
1002 | } |
---|
1003 | |
---|
1004 | void |
---|
1005 | html_object_set_bg_color (HTMLObject *o, GdkColor *color) |
---|
1006 | { |
---|
1007 | (* HO_CLASS (o)->set_bg_color) (o, color); |
---|
1008 | } |
---|
1009 | |
---|
1010 | GdkColor * |
---|
1011 | html_object_get_bg_color (HTMLObject *o, HTMLPainter *p) |
---|
1012 | { |
---|
1013 | return (* HO_CLASS (o)->get_bg_color) (o, p); |
---|
1014 | } |
---|
1015 | |
---|
1016 | HTMLObject * |
---|
1017 | html_object_check_point (HTMLObject *self, |
---|
1018 | HTMLPainter *painter, |
---|
1019 | gint x, gint y, |
---|
1020 | guint *offset_return, |
---|
1021 | gboolean for_cursor) |
---|
1022 | { |
---|
1023 | if (self->width == 0 || self->ascent + self->descent == 0) |
---|
1024 | return NULL; |
---|
1025 | |
---|
1026 | return (* HO_CLASS (self)->check_point) (self, painter, x, y, offset_return, for_cursor); |
---|
1027 | } |
---|
1028 | |
---|
1029 | gboolean |
---|
1030 | html_object_relayout (HTMLObject *self, |
---|
1031 | HTMLEngine *engine, |
---|
1032 | HTMLObject *child) |
---|
1033 | { |
---|
1034 | g_return_val_if_fail (self != NULL, TRUE); |
---|
1035 | return (* HO_CLASS (self)->relayout) (self, engine, child); |
---|
1036 | } |
---|
1037 | |
---|
1038 | HTMLVAlignType |
---|
1039 | html_object_get_valign (HTMLObject *self) |
---|
1040 | { |
---|
1041 | g_return_val_if_fail (self != NULL, HTML_VALIGN_BOTTOM); |
---|
1042 | |
---|
1043 | return (* HO_CLASS (self)->get_valign) (self); |
---|
1044 | } |
---|
1045 | |
---|
1046 | gboolean |
---|
1047 | html_object_accepts_cursor (HTMLObject *self) |
---|
1048 | { |
---|
1049 | return (* HO_CLASS (self)->accepts_cursor) (self); |
---|
1050 | } |
---|
1051 | |
---|
1052 | /* Warning: `calc_size()' must have been called on `self' before this so that |
---|
1053 | this works correctly. */ |
---|
1054 | void |
---|
1055 | html_object_get_cursor (HTMLObject *self, |
---|
1056 | HTMLPainter *painter, |
---|
1057 | guint offset, |
---|
1058 | gint *x1, gint *y1, |
---|
1059 | gint *x2, gint *y2) |
---|
1060 | { |
---|
1061 | (* HO_CLASS (self)->get_cursor) (self, painter, offset, x1, y1, x2, y2); |
---|
1062 | if (!html_object_is_text (self) && *y2 - *y1 < 10) { |
---|
1063 | gint missing = 10 - (*y2 - *y1); |
---|
1064 | |
---|
1065 | *y1 -= (missing >> 1) + ((missing >> 1) & 1); |
---|
1066 | *y2 += missing >> 1; |
---|
1067 | } |
---|
1068 | } |
---|
1069 | |
---|
1070 | /* Warning: `calc_size()' must have been called on `self' before this so that |
---|
1071 | this works correctly. */ |
---|
1072 | void |
---|
1073 | html_object_get_cursor_base (HTMLObject *self, |
---|
1074 | HTMLPainter *painter, |
---|
1075 | guint offset, |
---|
1076 | gint *x, gint *y) |
---|
1077 | { |
---|
1078 | (* HO_CLASS (self)->get_cursor_base) (self, painter, offset, x, y); |
---|
1079 | } |
---|
1080 | |
---|
1081 | |
---|
1082 | gboolean |
---|
1083 | html_object_select_range (HTMLObject *self, |
---|
1084 | HTMLEngine *engine, |
---|
1085 | guint start, |
---|
1086 | gint length, |
---|
1087 | gboolean queue_draw) |
---|
1088 | { |
---|
1089 | return (* HO_CLASS (self)->select_range) (self, engine, start, length, queue_draw); |
---|
1090 | } |
---|
1091 | |
---|
1092 | void |
---|
1093 | html_object_append_selection_string (HTMLObject *self, |
---|
1094 | GString *buffer) |
---|
1095 | { |
---|
1096 | g_return_if_fail (self != NULL); |
---|
1097 | g_return_if_fail (buffer != NULL); |
---|
1098 | |
---|
1099 | (* HO_CLASS (self)->append_selection_string) (self, buffer); |
---|
1100 | } |
---|
1101 | |
---|
1102 | HTMLEngine * |
---|
1103 | html_object_get_engine (HTMLObject *self, HTMLEngine *e) |
---|
1104 | { |
---|
1105 | return (* HO_CLASS (self)->get_engine) (self, e); |
---|
1106 | } |
---|
1107 | |
---|
1108 | HTMLEngine * |
---|
1109 | html_object_engine (HTMLObject *o, HTMLEngine *e) |
---|
1110 | { |
---|
1111 | while (o) { |
---|
1112 | e = html_object_get_engine (o, e); |
---|
1113 | if (html_object_is_frame (o)) |
---|
1114 | break; |
---|
1115 | o = o->parent; |
---|
1116 | } |
---|
1117 | |
---|
1118 | return e; |
---|
1119 | } |
---|
1120 | |
---|
1121 | void |
---|
1122 | html_object_forall (HTMLObject *self, |
---|
1123 | HTMLEngine *e, |
---|
1124 | HTMLObjectForallFunc func, |
---|
1125 | gpointer data) |
---|
1126 | { |
---|
1127 | (* HO_CLASS (self)->forall) (self, e, func, data); |
---|
1128 | } |
---|
1129 | |
---|
1130 | /* Ugly. We should have an `is_a' implementation. */ |
---|
1131 | gboolean |
---|
1132 | html_object_is_container (HTMLObject *self) |
---|
1133 | { |
---|
1134 | return (* HO_CLASS (self)->is_container) (self); |
---|
1135 | } |
---|
1136 | |
---|
1137 | |
---|
1138 | /* Ugly. We should have an `is_a' implementation. */ |
---|
1139 | |
---|
1140 | gboolean |
---|
1141 | html_object_is_text (HTMLObject *object) |
---|
1142 | { |
---|
1143 | HTMLType type; |
---|
1144 | |
---|
1145 | g_return_val_if_fail (object != NULL, FALSE); |
---|
1146 | |
---|
1147 | type = HTML_OBJECT_TYPE (object); |
---|
1148 | |
---|
1149 | return (type == HTML_TYPE_TEXT || type == HTML_TYPE_LINKTEXT); |
---|
1150 | } |
---|
1151 | |
---|
1152 | gboolean |
---|
1153 | html_object_is_clue (HTMLObject *object) |
---|
1154 | { |
---|
1155 | HTMLType type; |
---|
1156 | |
---|
1157 | g_return_val_if_fail (object != NULL, FALSE); |
---|
1158 | |
---|
1159 | type = HTML_OBJECT_TYPE (object); |
---|
1160 | |
---|
1161 | return (type == HTML_TYPE_CLUE || type == HTML_TYPE_CLUEV || type == HTML_TYPE_TABLECELL |
---|
1162 | || type == HTML_TYPE_CLUEFLOW || type == HTML_TYPE_CLUEALIGNED); |
---|
1163 | } |
---|
1164 | |
---|
1165 | HTMLObject * |
---|
1166 | html_object_next_not_type (HTMLObject *object, HTMLType t) |
---|
1167 | { |
---|
1168 | HTMLObject *p; |
---|
1169 | |
---|
1170 | g_return_val_if_fail (object != NULL, NULL); |
---|
1171 | g_return_val_if_fail (object->parent, NULL); |
---|
1172 | |
---|
1173 | p = html_object_next (object->parent, object); |
---|
1174 | while (p && HTML_OBJECT_TYPE (p) == t) |
---|
1175 | p = html_object_next (p->parent, p); |
---|
1176 | |
---|
1177 | return p; |
---|
1178 | } |
---|
1179 | |
---|
1180 | HTMLObject * |
---|
1181 | html_object_prev_not_type (HTMLObject *object, HTMLType t) |
---|
1182 | { |
---|
1183 | HTMLObject *p; |
---|
1184 | |
---|
1185 | g_return_val_if_fail (object != NULL, NULL); |
---|
1186 | g_return_val_if_fail (object->parent, NULL); |
---|
1187 | |
---|
1188 | p = html_object_prev (object->parent, object); |
---|
1189 | while (p && HTML_OBJECT_TYPE (p) == t) |
---|
1190 | p = html_object_prev (p->parent, p); |
---|
1191 | |
---|
1192 | return p; |
---|
1193 | } |
---|
1194 | |
---|
1195 | HTMLObject * |
---|
1196 | html_object_next_not_slave (HTMLObject *object) |
---|
1197 | { |
---|
1198 | return html_object_next_not_type (object, HTML_TYPE_TEXTSLAVE); |
---|
1199 | } |
---|
1200 | |
---|
1201 | HTMLObject * |
---|
1202 | html_object_prev_not_slave (HTMLObject *object) |
---|
1203 | { |
---|
1204 | return html_object_prev_not_type (object, HTML_TYPE_TEXTSLAVE); |
---|
1205 | } |
---|
1206 | |
---|
1207 | |
---|
1208 | gboolean |
---|
1209 | html_object_save (HTMLObject *self, |
---|
1210 | HTMLEngineSaveState *state) |
---|
1211 | { |
---|
1212 | return (* HO_CLASS (self)->save) (self, state); |
---|
1213 | } |
---|
1214 | |
---|
1215 | gboolean |
---|
1216 | html_object_save_plain (HTMLObject *self, |
---|
1217 | HTMLEngineSaveState *state, |
---|
1218 | gint requested_width) |
---|
1219 | { |
---|
1220 | return (* HO_CLASS (self)->save_plain) (self, state, requested_width); |
---|
1221 | } |
---|
1222 | |
---|
1223 | gint |
---|
1224 | html_object_check_page_split (HTMLObject *self, HTMLPainter *p, gint y) |
---|
1225 | { |
---|
1226 | g_return_val_if_fail (self != NULL, 0); |
---|
1227 | |
---|
1228 | return (* HO_CLASS (self)->check_page_split) (self, p, y); |
---|
1229 | } |
---|
1230 | |
---|
1231 | void |
---|
1232 | html_object_change_set (HTMLObject *self, HTMLChangeFlags f) |
---|
1233 | { |
---|
1234 | HTMLObject *obj = self; |
---|
1235 | |
---|
1236 | g_assert (self != NULL); |
---|
1237 | |
---|
1238 | if (f != HTML_CHANGE_NONE) { |
---|
1239 | while (obj) { |
---|
1240 | obj->change |= f; |
---|
1241 | obj = obj->parent; |
---|
1242 | } |
---|
1243 | } |
---|
1244 | } |
---|
1245 | |
---|
1246 | static void |
---|
1247 | change (HTMLObject *o, HTMLEngine *e, gpointer data) |
---|
1248 | { |
---|
1249 | o->change |= GPOINTER_TO_INT (data); |
---|
1250 | } |
---|
1251 | |
---|
1252 | void |
---|
1253 | html_object_change_set_down (HTMLObject *self, HTMLChangeFlags f) |
---|
1254 | { |
---|
1255 | html_object_forall (self, NULL, (HTMLObjectForallFunc) change, GINT_TO_POINTER (f)); |
---|
1256 | } |
---|
1257 | |
---|
1258 | gboolean |
---|
1259 | html_object_search (HTMLObject *self, HTMLSearch *info) |
---|
1260 | { |
---|
1261 | return (* HO_CLASS (self)->search) (self, info); |
---|
1262 | } |
---|
1263 | |
---|
1264 | gboolean |
---|
1265 | html_object_search_next (HTMLObject *self, HTMLSearch *info) |
---|
1266 | { |
---|
1267 | return (* HO_CLASS (self)->search_next) (self, info); |
---|
1268 | } |
---|
1269 | |
---|
1270 | HTMLObject * |
---|
1271 | html_object_set_link (HTMLObject *self, |
---|
1272 | HTMLColor *color, |
---|
1273 | const gchar *url, |
---|
1274 | const gchar *target) |
---|
1275 | { |
---|
1276 | return (HO_CLASS (self)->set_link) ? (* HO_CLASS (self)->set_link) (self, color, url, target) : NULL; |
---|
1277 | } |
---|
1278 | |
---|
1279 | HTMLObject * |
---|
1280 | html_object_remove_link (HTMLObject *self, |
---|
1281 | HTMLColor *color) |
---|
1282 | { |
---|
1283 | return (HO_CLASS (self)->set_link) ? (* HO_CLASS (self)->set_link) (self, color, NULL, NULL) : NULL; |
---|
1284 | } |
---|
1285 | |
---|
1286 | guint |
---|
1287 | html_object_get_length (HTMLObject *self) |
---|
1288 | { |
---|
1289 | return (* HO_CLASS (self)->get_length) (self); |
---|
1290 | } |
---|
1291 | |
---|
1292 | guint |
---|
1293 | html_object_get_line_length (HTMLObject *self, HTMLPainter *p, gint line_offset) |
---|
1294 | { |
---|
1295 | return (* HO_CLASS (self)->get_line_length) (self, p, line_offset); |
---|
1296 | } |
---|
1297 | |
---|
1298 | guint |
---|
1299 | html_object_get_recursive_length (HTMLObject *self) |
---|
1300 | { |
---|
1301 | return (* HO_CLASS (self)->get_recursive_length) (self); |
---|
1302 | } |
---|
1303 | |
---|
1304 | HTMLObject * |
---|
1305 | html_object_next_by_type (HTMLObject *self, HTMLType t) |
---|
1306 | { |
---|
1307 | HTMLObject *next; |
---|
1308 | |
---|
1309 | g_assert (self); |
---|
1310 | |
---|
1311 | next = self->next; |
---|
1312 | while (next && HTML_OBJECT_TYPE (next) != t) |
---|
1313 | next = next->next; |
---|
1314 | |
---|
1315 | return next; |
---|
1316 | } |
---|
1317 | |
---|
1318 | HTMLObject * |
---|
1319 | html_object_prev_by_type (HTMLObject *self, HTMLType t) |
---|
1320 | { |
---|
1321 | HTMLObject *prev; |
---|
1322 | |
---|
1323 | g_assert (self); |
---|
1324 | |
---|
1325 | prev = self->prev; |
---|
1326 | while (prev && HTML_OBJECT_TYPE (prev) != t) |
---|
1327 | prev = prev->prev; |
---|
1328 | |
---|
1329 | return prev; |
---|
1330 | } |
---|
1331 | |
---|
1332 | /* Movement functions */ |
---|
1333 | |
---|
1334 | HTMLObject * |
---|
1335 | html_object_next (HTMLObject *self, HTMLObject *child) |
---|
1336 | { |
---|
1337 | return (* HO_CLASS (self)->next) (self, child); |
---|
1338 | } |
---|
1339 | |
---|
1340 | HTMLObject * |
---|
1341 | html_object_prev (HTMLObject *self, HTMLObject *child) |
---|
1342 | { |
---|
1343 | return (* HO_CLASS (self)->prev) (self, child); |
---|
1344 | } |
---|
1345 | |
---|
1346 | HTMLObject * |
---|
1347 | html_object_head (HTMLObject *self) |
---|
1348 | { |
---|
1349 | return (* HO_CLASS (self)->head) (self); |
---|
1350 | } |
---|
1351 | |
---|
1352 | HTMLObject * |
---|
1353 | html_object_tail (HTMLObject *self) |
---|
1354 | { |
---|
1355 | return (* HO_CLASS (self)->tail) (self); |
---|
1356 | } |
---|
1357 | |
---|
1358 | HTMLObject * |
---|
1359 | html_object_tail_not_slave (HTMLObject *self) |
---|
1360 | { |
---|
1361 | HTMLObject *o = html_object_tail (self); |
---|
1362 | |
---|
1363 | if (o && HTML_OBJECT_TYPE (o) == HTML_TYPE_TEXTSLAVE) |
---|
1364 | o = html_object_prev_not_slave (o); |
---|
1365 | return o; |
---|
1366 | } |
---|
1367 | |
---|
1368 | gboolean |
---|
1369 | html_object_cursor_forward (HTMLObject *self, HTMLCursor *cursor) |
---|
1370 | { |
---|
1371 | gint len; |
---|
1372 | |
---|
1373 | g_assert (self); |
---|
1374 | g_assert (cursor->object == self); |
---|
1375 | |
---|
1376 | if (html_object_is_container (self)) |
---|
1377 | return FALSE; |
---|
1378 | |
---|
1379 | len = html_object_get_length (self); |
---|
1380 | if (cursor->offset < len) { |
---|
1381 | cursor->offset ++; |
---|
1382 | cursor->position ++; |
---|
1383 | return TRUE; |
---|
1384 | } else |
---|
1385 | return FALSE; |
---|
1386 | } |
---|
1387 | |
---|
1388 | gboolean |
---|
1389 | html_object_cursor_backward (HTMLObject *self, HTMLCursor *cursor) |
---|
1390 | { |
---|
1391 | HTMLObject *prev; |
---|
1392 | |
---|
1393 | g_assert (self); |
---|
1394 | g_assert (cursor->object == self); |
---|
1395 | |
---|
1396 | if (html_object_is_container (self)) |
---|
1397 | return FALSE; |
---|
1398 | |
---|
1399 | if (cursor->offset > 1 || (cursor->offset > 0 && (! (prev = html_object_prev_not_slave (self)) |
---|
1400 | || HTML_IS_CLUEALIGNED (prev) || !html_object_accepts_cursor (prev)))) { |
---|
1401 | cursor->offset --; |
---|
1402 | cursor->position --; |
---|
1403 | return TRUE; |
---|
1404 | } |
---|
1405 | |
---|
1406 | return FALSE; |
---|
1407 | } |
---|
1408 | |
---|
1409 | /********************* |
---|
1410 | * movement on leafs |
---|
1411 | */ |
---|
1412 | |
---|
1413 | /* go up in tree so long as we can get object in neighborhood given by function next_fn */ |
---|
1414 | |
---|
1415 | static HTMLObject * |
---|
1416 | next_object_uptree (HTMLObject *obj, HTMLObject * (*next_fn ) (HTMLObject *, HTMLObject *)) |
---|
1417 | { |
---|
1418 | HTMLObject *next = NULL; |
---|
1419 | |
---|
1420 | while (obj->parent && !(next = (*next_fn) (obj->parent, obj))) |
---|
1421 | obj = obj->parent; |
---|
1422 | |
---|
1423 | return next; |
---|
1424 | } |
---|
1425 | |
---|
1426 | /* go down in tree to leaf in way given by down_fn children */ |
---|
1427 | |
---|
1428 | static HTMLObject * |
---|
1429 | move_object_downtree (HTMLObject *obj, HTMLObject * (*down_fn ) (HTMLObject *)) |
---|
1430 | { |
---|
1431 | HTMLObject *down; |
---|
1432 | |
---|
1433 | while ((down = (*down_fn) (obj))) |
---|
1434 | obj = down; |
---|
1435 | |
---|
1436 | return obj; |
---|
1437 | } |
---|
1438 | |
---|
1439 | static HTMLObject * |
---|
1440 | move_object (HTMLObject *obj, HTMLObject * (*next_fn ) (HTMLObject *, HTMLObject *), HTMLObject * (*down_fn ) (HTMLObject *)) |
---|
1441 | { |
---|
1442 | obj = next_object_uptree (obj, next_fn); |
---|
1443 | if (obj) |
---|
1444 | obj = move_object_downtree (obj, down_fn); |
---|
1445 | return obj; |
---|
1446 | } |
---|
1447 | |
---|
1448 | HTMLObject * |
---|
1449 | html_object_next_leaf (HTMLObject *self) |
---|
1450 | { |
---|
1451 | return move_object (self, html_object_next, html_object_head); |
---|
1452 | } |
---|
1453 | |
---|
1454 | HTMLObject * |
---|
1455 | html_object_next_leaf_not_type (HTMLObject *self, HTMLType t) |
---|
1456 | { |
---|
1457 | HTMLObject *rv = self; |
---|
1458 | while ((rv = html_object_next_leaf (rv)) && HTML_OBJECT_TYPE (rv) == t); |
---|
1459 | |
---|
1460 | return rv; |
---|
1461 | } |
---|
1462 | |
---|
1463 | HTMLObject * |
---|
1464 | html_object_prev_leaf (HTMLObject *self) |
---|
1465 | { |
---|
1466 | return move_object (self, html_object_prev, html_object_tail); |
---|
1467 | } |
---|
1468 | |
---|
1469 | HTMLObject * |
---|
1470 | html_object_prev_leaf_not_type (HTMLObject *self, HTMLType t) |
---|
1471 | { |
---|
1472 | HTMLObject *rv = self; |
---|
1473 | while ((rv = html_object_prev_leaf (rv)) && HTML_OBJECT_TYPE (rv) == t); |
---|
1474 | |
---|
1475 | return rv; |
---|
1476 | } |
---|
1477 | |
---|
1478 | /* movement on cursor accepting objects */ |
---|
1479 | |
---|
1480 | /* go up in tree so long as we can get object in neighborhood given by function next_fn */ |
---|
1481 | |
---|
1482 | static HTMLObject * |
---|
1483 | next_object_uptree_cursor (HTMLObject *obj, HTMLObject * (*next_fn ) (HTMLObject *)) |
---|
1484 | { |
---|
1485 | HTMLObject *next = NULL; |
---|
1486 | |
---|
1487 | while (obj->parent && !(next = (*next_fn) (obj))) { |
---|
1488 | obj = obj->parent; |
---|
1489 | if (html_object_accepts_cursor (obj)) |
---|
1490 | return obj; |
---|
1491 | } |
---|
1492 | |
---|
1493 | return next; |
---|
1494 | } |
---|
1495 | |
---|
1496 | /* go down in tree to leaf in way given by down_fn children */ |
---|
1497 | |
---|
1498 | static HTMLObject * |
---|
1499 | move_object_downtree_cursor (HTMLObject *obj, HTMLObject * (*down_fn ) (HTMLObject *), HTMLObject * (*next_fn ) (HTMLObject *)) |
---|
1500 | { |
---|
1501 | HTMLObject *last_obj = obj; |
---|
1502 | |
---|
1503 | while ((obj = (*down_fn) (obj))) { |
---|
1504 | if (html_object_accepts_cursor (obj)) |
---|
1505 | break; |
---|
1506 | last_obj = obj; |
---|
1507 | } |
---|
1508 | |
---|
1509 | if (!obj && last_obj) { |
---|
1510 | obj = last_obj; |
---|
1511 | |
---|
1512 | while ((obj = (*next_fn) (obj))) |
---|
1513 | if (html_object_accepts_cursor (obj)) |
---|
1514 | break; |
---|
1515 | } |
---|
1516 | |
---|
1517 | return obj; |
---|
1518 | } |
---|
1519 | |
---|
1520 | static HTMLObject * |
---|
1521 | move_object_cursor (HTMLObject *obj, gint *offset, gboolean forward, |
---|
1522 | HTMLObject * (*next_fn ) (HTMLObject *), HTMLObject * (*down_fn ) (HTMLObject *)) |
---|
1523 | { |
---|
1524 | HTMLObject *down, *before; |
---|
1525 | |
---|
1526 | do { |
---|
1527 | gboolean found = FALSE; |
---|
1528 | if (((*offset == 0 && forward) || (*offset && !forward)) && html_object_is_container (obj)) |
---|
1529 | if ((down = (*down_fn) (obj))) { |
---|
1530 | down = move_object_downtree_cursor (down, down_fn, next_fn); |
---|
1531 | if (down) { |
---|
1532 | if (html_object_is_container (down)) |
---|
1533 | *offset = forward ? 0 : 1; |
---|
1534 | return down; |
---|
1535 | } |
---|
1536 | } |
---|
1537 | |
---|
1538 | before = obj; |
---|
1539 | do { |
---|
1540 | obj = next_object_uptree_cursor (obj, next_fn); |
---|
1541 | if (obj) { |
---|
1542 | if (html_object_accepts_cursor (obj)) { |
---|
1543 | if (html_object_is_container (obj)) |
---|
1544 | *offset = before->parent == obj->parent |
---|
1545 | ? forward ? 0 : 1 |
---|
1546 | : forward ? 1 : 0; |
---|
1547 | found = TRUE; |
---|
1548 | } else { |
---|
1549 | HTMLObject *down; |
---|
1550 | down = move_object_downtree_cursor (obj, down_fn, next_fn); |
---|
1551 | if (down) { |
---|
1552 | if (html_object_is_container (down)) |
---|
1553 | *offset = forward ? 0 : 1; |
---|
1554 | obj = down; |
---|
1555 | found = TRUE; |
---|
1556 | } |
---|
1557 | } |
---|
1558 | } |
---|
1559 | } while (obj && !found); |
---|
1560 | } while (obj && !html_object_accepts_cursor (obj)); |
---|
1561 | |
---|
1562 | return obj; |
---|
1563 | } |
---|
1564 | |
---|
1565 | HTMLObject * |
---|
1566 | html_object_next_cursor (HTMLObject *self, gint *offset) |
---|
1567 | { |
---|
1568 | return move_object_cursor (self, offset, TRUE, html_object_next_not_slave, html_object_head); |
---|
1569 | } |
---|
1570 | |
---|
1571 | HTMLObject * |
---|
1572 | html_object_prev_cursor (HTMLObject *self, gint *offset) |
---|
1573 | { |
---|
1574 | return move_object_cursor (self, offset, FALSE, html_object_prev_not_slave, html_object_tail_not_slave); |
---|
1575 | } |
---|
1576 | |
---|
1577 | /***/ |
---|
1578 | |
---|
1579 | guint |
---|
1580 | html_object_get_bytes (HTMLObject *self) |
---|
1581 | { |
---|
1582 | return html_object_is_text (self) ? html_text_get_bytes (HTML_TEXT (self)) : html_object_get_length (self); |
---|
1583 | } |
---|
1584 | |
---|
1585 | guint |
---|
1586 | html_object_get_index (HTMLObject *self, guint offset) |
---|
1587 | { |
---|
1588 | return html_object_is_text (self) ? html_text_get_index (HTML_TEXT (self), offset) : offset; |
---|
1589 | } |
---|
1590 | |
---|
1591 | void |
---|
1592 | html_object_set_data_nocp (HTMLObject *object, const gchar *key, const gchar *value) |
---|
1593 | { |
---|
1594 | g_datalist_set_data_full (&object->object_data_nocp, key, g_strdup (value), g_free); |
---|
1595 | } |
---|
1596 | |
---|
1597 | void |
---|
1598 | html_object_set_data_full_nocp (HTMLObject *object, const gchar *key, const gpointer value, GDestroyNotify func) |
---|
1599 | { |
---|
1600 | g_datalist_set_data_full (&object->object_data_nocp, key, value, func); |
---|
1601 | } |
---|
1602 | |
---|
1603 | gpointer |
---|
1604 | html_object_get_data_nocp (HTMLObject *object, const gchar *key) |
---|
1605 | { |
---|
1606 | return g_datalist_get_data (&object->object_data_nocp, key); |
---|
1607 | } |
---|
1608 | |
---|
1609 | void |
---|
1610 | html_object_set_data (HTMLObject *object, const gchar *key, const gchar *value) |
---|
1611 | { |
---|
1612 | g_datalist_set_data_full (&object->object_data, key, g_strdup (value), g_free); |
---|
1613 | } |
---|
1614 | |
---|
1615 | void |
---|
1616 | html_object_set_data_full (HTMLObject *object, const gchar *key, const gpointer value, GDestroyNotify func) |
---|
1617 | { |
---|
1618 | g_datalist_set_data_full (&object->object_data, key, value, func); |
---|
1619 | } |
---|
1620 | |
---|
1621 | gpointer |
---|
1622 | html_object_get_data (HTMLObject *object, const gchar *key) |
---|
1623 | { |
---|
1624 | return g_datalist_get_data (&object->object_data, key); |
---|
1625 | } |
---|
1626 | |
---|
1627 | static void |
---|
1628 | copy_data (GQuark key_id, gpointer data, gpointer user_data) |
---|
1629 | { |
---|
1630 | HTMLObject *o = HTML_OBJECT (user_data); |
---|
1631 | |
---|
1632 | g_datalist_id_set_data_full (&o->object_data, |
---|
1633 | key_id, |
---|
1634 | g_strdup ((gchar *) data), g_free); |
---|
1635 | } |
---|
1636 | |
---|
1637 | void |
---|
1638 | html_object_copy_data_from_object (HTMLObject *dst, HTMLObject *src) |
---|
1639 | { |
---|
1640 | g_datalist_foreach (&src->object_data, copy_data, dst); |
---|
1641 | } |
---|
1642 | |
---|
1643 | static void |
---|
1644 | object_save_data (GQuark key_id, gpointer data, gpointer user_data) |
---|
1645 | { |
---|
1646 | HTMLEngineSaveState *state = (HTMLEngineSaveState *) user_data; |
---|
1647 | const gchar *str; |
---|
1648 | |
---|
1649 | str = html_engine_get_class_data (state->engine, state->save_data_class_name, g_quark_to_string (key_id)); |
---|
1650 | /* printf ("object %s %s\n", g_quark_to_string (key_id), str); */ |
---|
1651 | if (!str) { |
---|
1652 | /* printf ("save %s %s -> %s\n", state->save_data_class_name, g_quark_to_string (key_id), (gchar *) data); */ |
---|
1653 | html_engine_save_output_string (state, "<!--+GtkHTML:<DATA class=\"%s\" key=\"%s\" value=\"%s\">-->", |
---|
1654 | state->save_data_class_name, g_quark_to_string (key_id), (char *) data); |
---|
1655 | html_engine_set_class_data (state->engine, state->save_data_class_name, g_quark_to_string (key_id), data); |
---|
1656 | } |
---|
1657 | } |
---|
1658 | |
---|
1659 | static void |
---|
1660 | handle_object_data (gpointer key, gpointer value, gpointer data) |
---|
1661 | { |
---|
1662 | HTMLEngineSaveState *state = (HTMLEngineSaveState *) data; |
---|
1663 | gchar *str; |
---|
1664 | |
---|
1665 | str = html_object_get_data (HTML_OBJECT (state->save_data_object), key); |
---|
1666 | /* printf ("handle: %s %s %s %s\n", state->save_data_class_name, key, value, str); */ |
---|
1667 | if (!str) { |
---|
1668 | /* printf ("clear\n"); */ |
---|
1669 | html_engine_save_output_string (state, "<!--+GtkHTML:<DATA class=\"%s\" clear=\"%s\">-->", |
---|
1670 | state->save_data_class_name, (char *) key); |
---|
1671 | state->data_to_remove = g_slist_prepend (state->data_to_remove, key); |
---|
1672 | } else if (strcmp (value, str)) { |
---|
1673 | /* printf ("change\n"); */ |
---|
1674 | html_engine_save_output_string (state, "<!--+GtkHTML:<DATA class=\"%s\" key=\"%s\" value=\"%s\">-->", |
---|
1675 | state->save_data_class_name, (char *) key, str); |
---|
1676 | html_engine_set_class_data (state->engine, state->save_data_class_name, key, value); |
---|
1677 | } |
---|
1678 | } |
---|
1679 | |
---|
1680 | static void |
---|
1681 | clear_data (gchar *key, HTMLEngineSaveState *state) |
---|
1682 | { |
---|
1683 | html_engine_clear_class_data (state->engine, state->save_data_class_name, key); |
---|
1684 | } |
---|
1685 | |
---|
1686 | gboolean |
---|
1687 | html_object_save_data (HTMLObject *self, HTMLEngineSaveState *state) |
---|
1688 | { |
---|
1689 | if (state->engine->save_data) { |
---|
1690 | GHashTable *t; |
---|
1691 | state->save_data_class_name = html_type_name (self->klass->type); |
---|
1692 | state->save_data_object = self; |
---|
1693 | t = html_engine_get_class_table (state->engine, state->save_data_class_name); |
---|
1694 | if (t) { |
---|
1695 | state->data_to_remove = NULL; |
---|
1696 | g_hash_table_foreach (t, handle_object_data, state); |
---|
1697 | g_slist_foreach (state->data_to_remove, (GFunc) clear_data, state); |
---|
1698 | g_slist_free (state->data_to_remove); |
---|
1699 | state->data_to_remove = NULL; |
---|
1700 | } |
---|
1701 | g_datalist_foreach (&self->object_data, object_save_data, state); |
---|
1702 | } |
---|
1703 | |
---|
1704 | return TRUE; |
---|
1705 | } |
---|
1706 | |
---|
1707 | GList * |
---|
1708 | html_object_get_bound_list (HTMLObject *self, GList *list) |
---|
1709 | { |
---|
1710 | return list && list->next |
---|
1711 | ? (HTML_OBJECT (list->data) == self ? list->next : NULL) |
---|
1712 | : NULL; |
---|
1713 | } |
---|
1714 | |
---|
1715 | void |
---|
1716 | html_object_move_cursor_before_remove (HTMLObject *o, HTMLEngine *e) |
---|
1717 | { |
---|
1718 | if (e->cursor->object == o) { |
---|
1719 | if (html_object_next_not_slave (o)) |
---|
1720 | e->cursor->object = html_object_next_not_slave (o); |
---|
1721 | else |
---|
1722 | e->cursor->object = html_object_prev_not_slave (o); |
---|
1723 | } |
---|
1724 | } |
---|
1725 | |
---|
1726 | gboolean |
---|
1727 | html_object_could_remove_whole (HTMLObject *o, GList *from, GList *to, GList *left, GList *right) |
---|
1728 | { |
---|
1729 | return ((!from && !to) |
---|
1730 | || html_object_next_not_slave (HTML_OBJECT (o)) |
---|
1731 | || html_object_prev_not_slave (HTML_OBJECT (o))) |
---|
1732 | && ((!left || o != left->data) && (!right || o != right->data)); |
---|
1733 | |
---|
1734 | } |
---|
1735 | |
---|
1736 | void |
---|
1737 | html_object_check_cut_lists (HTMLObject *self, HTMLObject *replacement, GList *left, GList *right) |
---|
1738 | { |
---|
1739 | if (left && left->data == self) |
---|
1740 | left->data = replacement; |
---|
1741 | if (right && right->data == self) |
---|
1742 | right->data = replacement; |
---|
1743 | } |
---|
1744 | |
---|
1745 | |
---|
1746 | typedef struct { |
---|
1747 | HTMLInterval *i; |
---|
1748 | GString *buffer; |
---|
1749 | gboolean in; |
---|
1750 | } tmpSelData; |
---|
1751 | |
---|
1752 | static void |
---|
1753 | select_object (HTMLObject *o, HTMLEngine *e, gpointer data) |
---|
1754 | { |
---|
1755 | tmpSelData *d = (tmpSelData *) data; |
---|
1756 | |
---|
1757 | if (o == d->i->from.object) |
---|
1758 | d->in = TRUE; |
---|
1759 | if (d->in) |
---|
1760 | html_object_select_range (o, NULL, |
---|
1761 | html_interval_get_start (d->i, o), |
---|
1762 | html_interval_get_length (d->i, o), FALSE); |
---|
1763 | |
---|
1764 | if (o == d->i->to.object) |
---|
1765 | d->in = FALSE; |
---|
1766 | } |
---|
1767 | |
---|
1768 | static void |
---|
1769 | unselect_object (HTMLObject *o, HTMLEngine *e, gpointer data) |
---|
1770 | { |
---|
1771 | o->selected = FALSE; |
---|
1772 | } |
---|
1773 | |
---|
1774 | gchar * |
---|
1775 | html_object_get_selection_string (HTMLObject *o, HTMLEngine *e) |
---|
1776 | { |
---|
1777 | HTMLObject *tail; |
---|
1778 | tmpSelData data; |
---|
1779 | gchar *string; |
---|
1780 | |
---|
1781 | g_assert (o); |
---|
1782 | |
---|
1783 | tail = html_object_get_tail_leaf (o); |
---|
1784 | data.buffer = g_string_new (NULL); |
---|
1785 | data.in = FALSE; |
---|
1786 | data.i = html_interval_new (html_object_get_head_leaf (o), tail, 0, html_object_get_length (tail)); |
---|
1787 | |
---|
1788 | html_interval_forall (data.i, e, select_object, &data); |
---|
1789 | html_object_append_selection_string (o, data.buffer); |
---|
1790 | html_interval_forall (data.i, e, unselect_object, NULL); |
---|
1791 | |
---|
1792 | html_interval_destroy (data.i); |
---|
1793 | string = data.buffer->str; |
---|
1794 | g_string_free (data.buffer, FALSE); |
---|
1795 | |
---|
1796 | return string; |
---|
1797 | } |
---|
1798 | |
---|
1799 | HTMLObject * |
---|
1800 | html_object_get_tail_leaf (HTMLObject *o) |
---|
1801 | { |
---|
1802 | HTMLObject *tail, *rv = o; |
---|
1803 | |
---|
1804 | do { |
---|
1805 | tail = html_object_tail_not_slave (rv); |
---|
1806 | if (tail) |
---|
1807 | rv = tail; |
---|
1808 | } while (tail); |
---|
1809 | |
---|
1810 | return rv; |
---|
1811 | } |
---|
1812 | |
---|
1813 | HTMLObject * |
---|
1814 | html_object_get_head_leaf (HTMLObject *o) |
---|
1815 | { |
---|
1816 | HTMLObject *head, *rv = o; |
---|
1817 | |
---|
1818 | do { |
---|
1819 | head = html_object_head (rv); |
---|
1820 | if (head) |
---|
1821 | rv = head; |
---|
1822 | } while (head); |
---|
1823 | |
---|
1824 | return rv; |
---|
1825 | } |
---|
1826 | |
---|
1827 | HTMLObject * |
---|
1828 | html_object_nth_parent (HTMLObject *self, gint n) |
---|
1829 | { |
---|
1830 | while (self && n > 0) { |
---|
1831 | self = self->parent; |
---|
1832 | n --; |
---|
1833 | } |
---|
1834 | |
---|
1835 | return self; |
---|
1836 | } |
---|
1837 | |
---|
1838 | gint |
---|
1839 | html_object_get_parent_level (HTMLObject *self) |
---|
1840 | { |
---|
1841 | gint level = 0; |
---|
1842 | |
---|
1843 | while (self) { |
---|
1844 | level ++; |
---|
1845 | self = self->parent; |
---|
1846 | } |
---|
1847 | |
---|
1848 | return level; |
---|
1849 | } |
---|
1850 | |
---|
1851 | GList * |
---|
1852 | html_object_heads_list (HTMLObject *o) |
---|
1853 | { |
---|
1854 | GList *list = NULL; |
---|
1855 | |
---|
1856 | g_return_val_if_fail (o, NULL); |
---|
1857 | |
---|
1858 | while (o) { |
---|
1859 | list = g_list_append (list, o); |
---|
1860 | o = html_object_head (o); |
---|
1861 | } |
---|
1862 | |
---|
1863 | return list; |
---|
1864 | } |
---|
1865 | |
---|
1866 | GList * |
---|
1867 | html_object_tails_list (HTMLObject *o) |
---|
1868 | { |
---|
1869 | GList *list = NULL; |
---|
1870 | |
---|
1871 | g_return_val_if_fail (o, NULL); |
---|
1872 | |
---|
1873 | while (o) { |
---|
1874 | list = g_list_append (list, o); |
---|
1875 | o = html_object_tail_not_slave (o); |
---|
1876 | } |
---|
1877 | |
---|
1878 | return list; |
---|
1879 | } |
---|
1880 | |
---|
1881 | static void |
---|
1882 | merge_down (HTMLEngine *e, GList *left, GList *right) |
---|
1883 | { |
---|
1884 | HTMLObject *lo; |
---|
1885 | HTMLObject *ro; |
---|
1886 | |
---|
1887 | while (left && right) { |
---|
1888 | lo = HTML_OBJECT (left->data); |
---|
1889 | ro = HTML_OBJECT (right->data); |
---|
1890 | left = left->next; |
---|
1891 | right = right->next; |
---|
1892 | if (!html_object_merge (lo, ro, e, &left, &right, NULL)) |
---|
1893 | break; |
---|
1894 | } |
---|
1895 | } |
---|
1896 | |
---|
1897 | void |
---|
1898 | html_object_merge_down (HTMLObject *o, HTMLObject *w, HTMLEngine *e) |
---|
1899 | { |
---|
1900 | merge_down (e, html_object_tails_list (o), html_object_heads_list (w)); |
---|
1901 | } |
---|
1902 | |
---|
1903 | gboolean |
---|
1904 | html_object_is_parent (HTMLObject *parent, HTMLObject *child) |
---|
1905 | { |
---|
1906 | g_assert (parent && child); |
---|
1907 | |
---|
1908 | while (child) { |
---|
1909 | if (child->parent == parent) |
---|
1910 | return TRUE; |
---|
1911 | child = child->parent; |
---|
1912 | } |
---|
1913 | |
---|
1914 | return FALSE; |
---|
1915 | } |
---|
1916 | |
---|
1917 | gint |
---|
1918 | html_object_get_insert_level (HTMLObject *o) |
---|
1919 | { |
---|
1920 | switch (HTML_OBJECT_TYPE (o)) { |
---|
1921 | case HTML_TYPE_TABLECELL: |
---|
1922 | case HTML_TYPE_CLUEV: |
---|
1923 | return 3; |
---|
1924 | case HTML_TYPE_CLUEFLOW: |
---|
1925 | return 2; |
---|
1926 | default: |
---|
1927 | return 1; |
---|
1928 | } |
---|
1929 | } |
---|
1930 | |
---|
1931 | void |
---|
1932 | html_object_engine_translation (HTMLObject *o, HTMLEngine *e, gint *tx, gint *ty) |
---|
1933 | { |
---|
1934 | HTMLObject *p; |
---|
1935 | |
---|
1936 | *tx = 0; |
---|
1937 | *ty = 0; |
---|
1938 | |
---|
1939 | for (p = o->parent; p != NULL && HTML_OBJECT_TYPE (p) != HTML_TYPE_IFRAME; p = p->parent) { |
---|
1940 | *tx += p->x; |
---|
1941 | *ty += p->y - p->ascent; |
---|
1942 | } |
---|
1943 | |
---|
1944 | /* *tx += e->leftBorder; */ |
---|
1945 | /* *ty += e->topBorder; */ |
---|
1946 | } |
---|
1947 | |
---|
1948 | gboolean |
---|
1949 | html_object_engine_intersection (HTMLObject *o, HTMLEngine *e, gint tx, gint ty, gint *x1, gint *y1, gint *x2, gint *y2) |
---|
1950 | { |
---|
1951 | *x1 = o->x + tx; |
---|
1952 | *y1 = o->y - o->ascent + ty; |
---|
1953 | *x2 = o->x + o->width + tx; |
---|
1954 | *y2 = o->y + o->descent + ty; |
---|
1955 | |
---|
1956 | return html_engine_intersection (e, x1, y1, x2, y2); |
---|
1957 | } |
---|
1958 | |
---|
1959 | void |
---|
1960 | html_object_add_to_changed (GList **changed_objs, HTMLObject *o) |
---|
1961 | { |
---|
1962 | GList *l, *next; |
---|
1963 | |
---|
1964 | if (!changed_objs || (*changed_objs && (*changed_objs)->data == o)) |
---|
1965 | return; |
---|
1966 | |
---|
1967 | for (l = *changed_objs; l; l = next) { |
---|
1968 | if (l->data == NULL) { |
---|
1969 | l = l->next; |
---|
1970 | next = l->next; |
---|
1971 | continue; |
---|
1972 | } |
---|
1973 | next = l->next; |
---|
1974 | if (html_object_is_parent (o, HTML_OBJECT (l->data))) { |
---|
1975 | *changed_objs = g_list_remove_link (*changed_objs, l); |
---|
1976 | g_list_free (l); |
---|
1977 | } else |
---|
1978 | break; |
---|
1979 | } |
---|
1980 | |
---|
1981 | *changed_objs = g_list_prepend (*changed_objs, o); |
---|
1982 | } |
---|
1983 | |
---|
1984 | gint |
---|
1985 | html_object_get_n_children (HTMLObject *self) |
---|
1986 | { |
---|
1987 | return HO_CLASS (self)->get_n_children ? (* HO_CLASS (self)->get_n_children) (self) : 0; |
---|
1988 | } |
---|
1989 | |
---|
1990 | HTMLObject * |
---|
1991 | html_object_get_child (HTMLObject *self, gint index) |
---|
1992 | { |
---|
1993 | return HO_CLASS (self)->get_child ? (* HO_CLASS (self)->get_child) (self, index) : NULL; |
---|
1994 | } |
---|
1995 | |
---|
1996 | |
---|
1997 | gint |
---|
1998 | html_object_get_child_index (HTMLObject *self, HTMLObject *child) |
---|
1999 | { |
---|
2000 | return HO_CLASS (self)->get_child_index ? (* HO_CLASS (self)->get_child_index) (self, child) : -1; |
---|
2001 | } |
---|
2002 | |
---|
2003 | HTMLClearType |
---|
2004 | html_object_get_clear (HTMLObject *self) |
---|
2005 | { |
---|
2006 | return (* HO_CLASS (self)->get_clear) (self); |
---|
2007 | } |
---|
2008 | |
---|
2009 | static HTMLObject * |
---|
2010 | next_prev_cursor_object (HTMLObject *o, HTMLEngine *e, gint *offset, gboolean forward) |
---|
2011 | { |
---|
2012 | HTMLCursor cursor; |
---|
2013 | gboolean result; |
---|
2014 | |
---|
2015 | html_cursor_init (&cursor, o, html_object_is_container (o) ? *offset : (forward ? html_object_get_length (o) : 0)); |
---|
2016 | |
---|
2017 | result = forward ? html_cursor_forward (&cursor, e) : html_cursor_backward (&cursor, e); |
---|
2018 | *offset = cursor.offset; |
---|
2019 | |
---|
2020 | return result ? cursor.object : NULL; |
---|
2021 | } |
---|
2022 | |
---|
2023 | HTMLObject * |
---|
2024 | html_object_next_cursor_object (HTMLObject *o, HTMLEngine *e, gint *offset) |
---|
2025 | { |
---|
2026 | return next_prev_cursor_object (o, e, offset, TRUE); |
---|
2027 | } |
---|
2028 | |
---|
2029 | HTMLObject * |
---|
2030 | html_object_prev_cursor_object (HTMLObject *o, HTMLEngine *e, gint *offset) |
---|
2031 | { |
---|
2032 | return next_prev_cursor_object (o, e, offset, FALSE); |
---|
2033 | } |
---|
2034 | |
---|
2035 | HTMLObject * |
---|
2036 | html_object_next_cursor_leaf (HTMLObject *o, HTMLEngine *e) |
---|
2037 | { |
---|
2038 | gint offset = html_object_get_length (o); |
---|
2039 | |
---|
2040 | o = html_object_next_cursor_object (o, e, &offset); |
---|
2041 | while (o && html_object_is_container (o)) |
---|
2042 | o = html_object_next_cursor_object (o, e, &offset); |
---|
2043 | |
---|
2044 | return o; |
---|
2045 | } |
---|
2046 | |
---|
2047 | HTMLObject * |
---|
2048 | html_object_prev_cursor_leaf (HTMLObject *o, HTMLEngine *e) |
---|
2049 | { |
---|
2050 | gint offset = html_object_get_length (o); |
---|
2051 | |
---|
2052 | o = html_object_prev_cursor_object (o, e, &offset); |
---|
2053 | while (o && html_object_is_container (o)) |
---|
2054 | o = html_object_prev_cursor_object (o, e, &offset); |
---|
2055 | |
---|
2056 | return o; |
---|
2057 | } |
---|
2058 | |
---|
2059 | HTMLClueFlow * |
---|
2060 | html_object_get_flow (HTMLObject *o) |
---|
2061 | { |
---|
2062 | while (o && !HTML_IS_CLUEFLOW (o)) |
---|
2063 | o = o->parent; |
---|
2064 | |
---|
2065 | return HTML_CLUEFLOW (o); |
---|
2066 | } |
---|