2 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 /* This file is part of the GtkHTML library.
5 * Copyright (C) 2000 Helix Code, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
27 #include "gtkhtml-stream.h"
28 #include "htmltokenizer.h"
29 #include "gtkhtml-private.h"
30 #include "htmlcolorset.h"
31 #include "htmlgdkpainter.h"
32 #include "htmlprinter.h"
33 #include "htmlframe.h"
34 #include "htmlengine-search.h"
35 #include "htmlsearch.h"
36 #include "htmlselection.h"
37 #include "htmlsettings.h"
39 HTMLFrameClass html_frame_class
;
40 static HTMLEmbeddedClass
*parent_class
= NULL
;
43 frame_url_requested (GtkHTML
*html
,
45 GtkHTMLStream
*handle
,
48 HTMLFrame
*frame
= HTML_FRAME (data
);
49 GtkHTML
*parent
= GTK_HTML (HTML_EMBEDDED (frame
)->parent
);
51 if (!html
->engine
->stopped
)
52 g_signal_emit_by_name (parent
->engine
, "url_requested", url
, handle
);
56 frame_set_base (GtkHTML
*html
,
60 gchar
*new_url
= NULL
;
62 new_url
= gtk_html_get_url_base_relative (html
, url
);
63 gtk_html_set_base (html
, new_url
);
68 frame_submit (GtkHTML
*html
,
71 const gchar
*encoding
,
74 HTMLFrame
*frame
= HTML_FRAME (data
);
75 GtkHTML
*parent
= GTK_HTML (HTML_EMBEDDED (frame
)->parent
);
77 g_signal_emit_by_name (parent
, "submit", method
, action
, encoding
);
81 frame_size_changed (GtkHTML
*html
,
84 HTMLFrame
*frame
= HTML_FRAME (data
);
85 GtkHTML
*parent
= GTK_HTML (HTML_EMBEDDED (frame
)->parent
);
87 html_engine_schedule_update (parent
->engine
);
91 frame_object_requested (GtkHTML
*html
,
95 HTMLFrame
*frame
= HTML_FRAME (data
);
96 GtkHTML
*parent
= GTK_HTML (HTML_EMBEDDED (frame
)->parent
);
100 g_signal_emit_by_name (parent
, "object_requested", eb
, &ret_val
);
105 frame_set_gdk_painter (HTMLFrame
*frame
,
106 HTMLPainter
*painter
)
109 g_object_ref (G_OBJECT (painter
));
111 if (frame
->gdk_painter
)
112 g_object_unref (G_OBJECT (frame
->gdk_painter
));
114 frame
->gdk_painter
= painter
;
118 html_frame_new (GtkWidget
*parent
,
126 frame
= g_new (HTMLFrame
, 1);
128 html_frame_init (frame
,
136 return HTML_OBJECT (frame
);
140 html_frame_grab_cursor (GtkWidget
*frame
,
143 /* Keep the focus! Fight the power */
148 calc_min_width (HTMLObject
*o
,
149 HTMLPainter
*painter
)
153 if (HTML_FRAME (o
)->width
< 0)
154 min_width
= html_engine_calc_min_width (GTK_HTML (HTML_FRAME (o
)->html
)->engine
);
156 min_width
= HTML_FRAME (o
)->width
;
162 set_max_width (HTMLObject
*o
,
163 HTMLPainter
*painter
,
166 HTMLEngine
*e
= GTK_HTML (HTML_FRAME (o
)->html
)->engine
;
168 o
->max_width
= max_width
;
169 html_object_set_max_width (e
->clue
, e
->painter
, max_width
- (html_engine_get_left_border (e
) + html_engine_get_right_border (e
)));
182 HTMLFrame
*frame
= HTML_FRAME (o
);
183 HTMLEngine
*e
= GTK_HTML (frame
->html
)->engine
;
186 if (G_OBJECT_TYPE (e
->painter
) == HTML_TYPE_PRINTER
) {
187 gint pixel_size
= html_painter_get_pixel_size (e
->painter
);
189 if (!html_object_intersect (o
, &paint
, x
, y
, width
, height
))
192 html_object_draw (e
->clue
, e
->painter
,
194 width
- pixel_size
* (html_engine_get_left_border (e
) + html_engine_get_right_border (e
)),
195 height
- pixel_size
* (html_engine_get_top_border (e
) + html_engine_get_bottom_border (e
)),
196 tx
+ pixel_size
* html_engine_get_left_border (e
), ty
+ pixel_size
* html_engine_get_top_border (e
));
198 (*HTML_OBJECT_CLASS (parent_class
)->draw
) (o
, p
, x
, y
, width
, height
, tx
, ty
);
202 set_painter (HTMLObject
*o
,
203 HTMLPainter
*painter
)
207 frame
= HTML_FRAME (o
);
208 if (G_OBJECT_TYPE (GTK_HTML (frame
->html
)->engine
->painter
) != HTML_TYPE_PRINTER
) {
209 frame_set_gdk_painter (frame
, GTK_HTML (frame
->html
)->engine
->painter
);
212 html_engine_set_painter (GTK_HTML (frame
->html
)->engine
,
213 G_OBJECT_TYPE (painter
) != HTML_TYPE_PRINTER
? frame
->gdk_painter
: painter
);
217 forall (HTMLObject
*self
,
219 HTMLObjectForallFunc func
,
224 frame
= HTML_FRAME (self
);
225 (* func
) (self
, html_object_get_engine (self
, e
), data
);
226 html_object_forall (GTK_HTML (frame
->html
)->engine
->clue
, html_object_get_engine (self
, e
), func
, data
);
230 check_page_split (HTMLObject
*self
,
234 return html_object_check_page_split (GTK_HTML (HTML_FRAME (self
)->html
)->engine
->clue
, p
, y
);
238 html_frame_real_calc_size (HTMLObject
*o
,
239 HTMLPainter
*painter
,
240 GList
**changed_objs
)
244 gint old_width
, old_ascent
, old_descent
;
246 old_width
= o
->width
;
247 old_ascent
= o
->ascent
;
248 old_descent
= o
->descent
;
250 frame
= HTML_FRAME (o
);
251 e
= GTK_HTML (frame
->html
)->engine
;
253 if ((frame
->width
< 0) && (frame
->height
< 0)) {
255 html_engine_calc_size (e
, changed_objs
);
256 e
->width
= html_engine_get_doc_width (e
);
257 e
->height
= html_engine_get_doc_height (e
);
259 html_frame_set_scrolling (frame
, GTK_POLICY_NEVER
);
262 o
->ascent
= e
->height
;
265 if (G_OBJECT_TYPE (painter
) == HTML_TYPE_PRINTER
) {
266 o
->ascent
+= html_painter_get_pixel_size (painter
) * (html_engine_get_top_border (e
) + html_engine_get_bottom_border (e
));
269 return (* HTML_OBJECT_CLASS (parent_class
)->calc_size
) (o
, painter
, changed_objs
);
271 if (o
->descent
!= old_descent
272 || o
->ascent
!= old_ascent
273 || o
->width
!= old_width
)
280 search (HTMLObject
*self
,
283 HTMLEngine
*e
= GTK_HTML (HTML_FRAME (self
)->html
)->engine
;
285 /* printf ("search\n"); */
288 if (info
->stack
&& HTML_OBJECT (info
->stack
->data
) == e
->clue
) {
289 /* printf ("next\n"); */
290 info
->engine
= GTK_HTML (GTK_HTML (HTML_FRAME (self
)->html
)->iframe_parent
)->engine
;
291 html_search_pop (info
);
292 html_engine_unselect_all (e
);
293 return html_search_next_parent (info
);
297 html_search_push (info
, e
->clue
);
298 if (html_object_search (e
->clue
, info
))
300 html_search_pop (info
);
302 info
->engine
= GTK_HTML (GTK_HTML (HTML_FRAME (self
)->html
)->iframe_parent
)->engine
;
303 /* printf ("FALSE\n"); */
309 head (HTMLObject
*self
)
311 return GTK_HTML (HTML_FRAME (self
)->html
)->engine
->clue
;
315 tail (HTMLObject
*self
)
317 return GTK_HTML (HTML_FRAME (self
)->html
)->engine
->clue
;
321 get_engine (HTMLObject
*self
,
324 return GTK_HTML (HTML_FRAME (self
)->html
)->engine
;
328 check_point (HTMLObject
*self
,
329 HTMLPainter
*painter
,
332 guint
*offset_return
,
335 HTMLEngine
*e
= GTK_HTML (HTML_FRAME (self
)->html
)->engine
;
337 if (x
< self
->x
|| x
>= self
->x
+ self
->width
338 || y
>= self
->y
+ self
->descent
|| y
< self
->y
- self
->ascent
)
341 x
-= self
->x
+ html_engine_get_left_border (e
) - e
->x_offset
;
342 y
-= self
->y
- self
->ascent
+ html_engine_get_top_border (e
) - e
->y_offset
;
344 if (for_cursor
&& (x
< 0 || y
< e
->clue
->y
- e
->clue
->ascent
))
345 return html_object_check_point (e
->clue
, e
->painter
, 0, e
->clue
->y
- e
->clue
->ascent
,
346 offset_return
, for_cursor
);
348 if (for_cursor
&& (x
> e
->clue
->width
- 1 || y
> e
->clue
->y
+ e
->clue
->descent
- 1))
349 return html_object_check_point (e
->clue
, e
->painter
, e
->clue
->width
- 1, e
->clue
->y
+ e
->clue
->descent
- 1,
350 offset_return
, for_cursor
);
352 return html_object_check_point (e
->clue
, e
->painter
, x
, y
, offset_return
, for_cursor
);
356 is_container (HTMLObject
*self
)
362 append_selection_string (HTMLObject
*self
,
365 html_object_append_selection_string (GTK_HTML (HTML_FRAME (self
)->html
)->engine
->clue
, buffer
);
369 reparent (HTMLEmbedded
*emb
,
372 HTMLFrame
*frame
= HTML_FRAME (emb
);
374 gtk_html_set_iframe_parent (GTK_HTML (frame
->html
),
376 GTK_HTML (frame
->html
)->frame
);
377 (* HTML_EMBEDDED_CLASS (parent_class
)->reparent
) (emb
, html
);
381 select_range (HTMLObject
*self
,
387 return html_object_select_range (GTK_HTML (HTML_FRAME (self
)->html
)->engine
->clue
,
388 GTK_HTML (HTML_FRAME (self
)->html
)->engine
,
389 start
, length
, queue_draw
);
393 destroy (HTMLObject
*o
)
395 HTMLFrame
*frame
= HTML_FRAME (o
);
397 frame_set_gdk_painter (frame
, NULL
);
400 g_signal_handlers_disconnect_matched (frame
->html
, G_SIGNAL_MATCH_DATA
, 0, 0, NULL
, NULL
, o
);
403 g_free ((frame
)->url
);
405 HTML_OBJECT_CLASS (parent_class
)->destroy (o
);
409 find_anchor (HTMLObject
*self
,
417 g_return_val_if_fail (HTML_IS_FRAME (self
), NULL
);
419 frame
= HTML_FRAME (self
);
421 if (!frame
|| !frame
->html
|| !GTK_IS_HTML (frame
->html
) || !GTK_HTML (frame
->html
)->engine
|| !GTK_HTML (frame
->html
)->engine
->clue
)
424 anchor
= html_object_find_anchor (GTK_HTML (frame
->html
)->engine
->clue
, name
, x
, y
);
428 *y
+= self
->y
- self
->ascent
;
435 html_frame_set_margin_width (HTMLFrame
*frame
,
440 e
= GTK_HTML (frame
->html
)->engine
;
442 e
->leftBorder
= e
->rightBorder
= margin_width
;
443 html_engine_schedule_redraw (e
);
447 html_frame_set_margin_height (HTMLFrame
*frame
,
452 e
= GTK_HTML (frame
->html
)->engine
;
454 e
->bottomBorder
= e
->topBorder
= margin_height
;
455 html_engine_schedule_redraw (e
);
459 html_frame_set_scrolling (HTMLFrame
*frame
,
460 GtkPolicyType scroll
)
463 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (frame
->scroll
),
468 html_frame_set_size (HTMLFrame
*frame
,
472 g_return_if_fail (frame
!= NULL
);
475 frame
->width
= width
;
478 frame
->height
= height
;
480 gtk_widget_set_size_request (frame
->scroll
, width
, height
);
484 html_frame_init (HTMLFrame
*frame
,
485 HTMLFrameClass
*klass
,
492 HTMLEmbedded
*em
= HTML_EMBEDDED (frame
);
493 HTMLTokenizer
*new_tokenizer
;
494 GtkWidget
*new_widget
;
496 GtkHTML
*parent_html
;
497 GtkWidget
*scrolled_window
;
499 g_assert (GTK_IS_HTML (parent
));
500 parent_html
= GTK_HTML (parent
);
502 html_embedded_init (em
, HTML_EMBEDDED_CLASS (klass
),
505 scrolled_window
= gtk_scrolled_window_new (NULL
, NULL
);
506 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window
),
507 border
? GTK_SHADOW_IN
: GTK_SHADOW_NONE
);
509 new_widget
= gtk_html_new ();
510 new_html
= GTK_HTML (new_widget
);
512 new_tokenizer
= html_tokenizer_clone (parent_html
->engine
->ht
);
514 html_engine_set_tokenizer (new_html
->engine
, new_tokenizer
);
515 g_object_unref (G_OBJECT (new_tokenizer
));
516 new_tokenizer
= NULL
;
518 gtk_html_set_default_content_type (new_html
,
519 gtk_html_get_default_content_type (parent_html
));
521 gtk_html_set_default_engine (new_html
,
522 gtk_html_get_default_engine (parent_html
));
524 frame
->html
= new_widget
;
525 frame
->url
= g_strdup (src
);
526 frame
->width
= width
;
527 frame
->height
= height
;
528 frame
->gdk_painter
= NULL
;
529 gtk_html_set_base (new_html
, src
);
530 gtk_html_set_iframe_parent (new_html
, parent
, HTML_OBJECT (frame
));
531 gtk_container_add (GTK_CONTAINER (scrolled_window
), new_widget
);
532 gtk_widget_show (new_widget
);
534 g_signal_connect (new_html
, "url_requested", G_CALLBACK (frame_url_requested
), frame
);
536 if (parent_html
->engine
->stopped
) {
537 gtk_html_stop (new_html
);
538 gtk_html_load_empty (new_html
);
540 GtkHTMLStream
*handle
;
542 handle
= gtk_html_begin (new_html
);
543 g_signal_emit_by_name (parent_html
->engine
, "url_requested", src
, handle
);
546 new_html
->engine
->clue
->parent
= HTML_OBJECT (frame
);
549 /* NOTE: because of peculiarities of the frame/gtkhtml relationship
550 * on_url and link_clicked are emitted from the toplevel widget not
551 * proxied like url_requested is.
553 g_signal_connect (new_html
, "on_url", G_CALLBACK (frame_on_url
), frame
);
554 g_signal_connect (new_html
, "link_clicked", G_CALLBACK (frame_link_clicked
), frame
);
556 g_signal_connect (new_html
, "size_changed", G_CALLBACK (frame_size_changed
), frame
);
557 g_signal_connect (new_html
, "object_requested", G_CALLBACK (frame_object_requested
), frame
);
558 g_signal_connect (new_html
, "submit", G_CALLBACK (frame_submit
), frame
);
559 g_signal_connect (new_html
, "set_base", G_CALLBACK (frame_set_base
), frame
);
561 html_frame_set_margin_height (frame
, 0);
562 html_frame_set_margin_width (frame
, 0);
565 g_signal_connect (html, "button_press_event", G_CALLBACK (frame_button_press_event), frame);
568 gtk_widget_set_size_request (scrolled_window
, width
, height
);
570 gtk_widget_show (scrolled_window
);
571 frame
->scroll
= scrolled_window
;
572 html_frame_set_scrolling (frame
, GTK_POLICY_AUTOMATIC
);
574 html_embedded_set_widget (em
, scrolled_window
);
576 g_signal_connect (scrolled_window
, "button_press_event", G_CALLBACK (html_frame_grab_cursor
), NULL
);
578 /* inherit the current colors from our parent */
579 html_colorset_set_unchanged (new_html
->engine
->defaultSettings
->color_set
,
580 parent_html
->engine
->settings
->color_set
);
581 html_colorset_set_unchanged (new_html
->engine
->settings
->color_set
,
582 parent_html
->engine
->settings
->color_set
);
583 html_painter_set_focus (new_html
->engine
->painter
, parent_html
->engine
->have_focus
);
585 g_signal_connect (html, "title_changed", G_CALLBACK (title_changed_cb), app);
586 g_signal_connect (html, "button_press_event", G_CALLBACK (on_button_press_event), popup_menu);
587 g_signal_connect (html, "redirect", G_CALLBACK (on_redirect), NULL);
588 g_signal_connect (html, "object_requested", G_CALLBACK (object_requested_cmd), NULL);
593 html_frame_type_init (void)
595 html_frame_class_init (&html_frame_class
, HTML_TYPE_FRAME
, sizeof (HTMLFrame
));
599 html_frame_class_init (HTMLFrameClass
*klass
,
603 HTMLEmbeddedClass
*embedded_class
;
604 HTMLObjectClass
*object_class
;
606 g_return_if_fail (klass
!= NULL
);
608 embedded_class
= HTML_EMBEDDED_CLASS (klass
);
609 object_class
= HTML_OBJECT_CLASS (klass
);
611 html_embedded_class_init (embedded_class
, type
, size
);
612 parent_class
= &html_embedded_class
;
614 object_class
->destroy
= destroy
;
615 object_class
->calc_size
= html_frame_real_calc_size
;
616 object_class
->calc_min_width
= calc_min_width
;
617 object_class
->set_painter
= set_painter
;
618 /* object_class->reset = reset; */
619 object_class
->draw
= draw
;
620 object_class
->set_max_width
= set_max_width
;
621 object_class
->forall
= forall
;
622 object_class
->check_page_split
= check_page_split
;
623 object_class
->search
= search
;
624 object_class
->head
= head
;
625 object_class
->tail
= tail
;
626 object_class
->get_engine
= get_engine
;
627 object_class
->check_point
= check_point
;
628 object_class
->is_container
= is_container
;
629 object_class
->append_selection_string
= append_selection_string
;
630 object_class
->select_range
= select_range
;
631 object_class
->find_anchor
= find_anchor
;
633 embedded_class
->reparent
= reparent
;