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