source: trunk/third/gtkhtml3/src/htmlframe.c @ 21116

Revision 21116, 15.8 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21115, which included commits to RCS files with non-trunk default branches.
Line 
1
2/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3/* This file is part of the GtkHTML library.
4   
5   Copyright (C) 2000 Helix Code, Inc.
6
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.
11   
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.
16   
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., 59 Temple Place - Suite 330,
20   Boston, MA 02111-1307, USA.
21*/
22
23#include <config.h>
24#include <gtk/gtk.h>
25#include <string.h>
26#include "gtkhtml.h"
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"
38
39HTMLFrameClass html_frame_class;
40static HTMLEmbeddedClass *parent_class = NULL;
41
42static void
43frame_url_requested (GtkHTML *html, const char *url, GtkHTMLStream *handle, gpointer data)
44{
45        HTMLFrame *frame = HTML_FRAME (data);
46        GtkHTML *parent = GTK_HTML (HTML_EMBEDDED(frame)->parent);
47
48        if (!html->engine->stopped)
49                g_signal_emit_by_name (parent->engine, "url_requested", url, handle);
50}
51
52static void
53frame_set_base (GtkHTML *html, const gchar *url, gpointer data)
54{
55        char *new_url = NULL;
56
57        new_url = gtk_html_get_url_base_relative (html, url);
58        gtk_html_set_base (html, new_url);
59        g_free (new_url);
60}
61
62static void
63frame_submit (GtkHTML *html,
64              const gchar *method,
65              const gchar *action,
66              const gchar *encoding,
67              gpointer data)
68{
69        HTMLFrame *frame = HTML_FRAME (data);
70        GtkHTML *parent = GTK_HTML (HTML_EMBEDDED(frame)->parent);
71
72        g_signal_emit_by_name (parent, "submit", method, action, encoding);
73}
74
75static void
76frame_size_changed (GtkHTML *html, gpointer data)
77{
78        HTMLFrame *frame = HTML_FRAME (data);
79        GtkHTML *parent = GTK_HTML (HTML_EMBEDDED(frame)->parent);
80       
81        html_engine_schedule_update (parent->engine);
82}
83
84static gboolean
85frame_object_requested (GtkHTML *html, GtkHTMLEmbedded *eb, gpointer data)
86{
87        HTMLFrame *frame = HTML_FRAME (data);
88        GtkHTML *parent = GTK_HTML (HTML_EMBEDDED(frame)->parent);
89        gboolean ret_val;
90
91        ret_val = FALSE;
92        g_signal_emit_by_name (parent, "object_requested", eb, &ret_val);
93        return ret_val;
94}
95
96static void
97frame_set_gdk_painter (HTMLFrame *frame, HTMLPainter *painter)
98{
99        if (painter)
100                g_object_ref (G_OBJECT (painter));
101       
102        if (frame->gdk_painter)
103                g_object_unref (G_OBJECT (frame->gdk_painter));
104
105        frame->gdk_painter = painter;
106}
107
108HTMLObject *
109html_frame_new (GtkWidget *parent,
110                 char *src,
111                 gint width,
112                 gint height,
113                 gboolean border)
114{
115        HTMLFrame *frame;
116       
117        frame = g_new (HTMLFrame, 1);
118       
119        html_frame_init (frame,
120                          &html_frame_class,
121                          parent,
122                          src,
123                          width,
124                          height,
125                          border);
126       
127        return HTML_OBJECT (frame);
128}
129
130static gboolean
131html_frame_grab_cursor(GtkWidget *frame, GdkEvent *event)
132{
133        /* Keep the focus! Fight the power */
134        return TRUE;
135}
136
137static gint
138calc_min_width (HTMLObject *o,
139                HTMLPainter *painter)
140{
141  int min_width;
142 
143  if (HTML_FRAME (o)->width < 0)
144          min_width =  html_engine_calc_min_width (GTK_HTML (HTML_FRAME (o)->html)->engine);
145  else
146          min_width = HTML_FRAME (o)->width;
147
148  return min_width;
149}
150
151static void
152set_max_width (HTMLObject *o, HTMLPainter *painter, gint max_width)
153{
154        HTMLEngine *e = GTK_HTML (HTML_FRAME (o)->html)->engine;
155
156        o->max_width = max_width;
157        html_object_set_max_width (e->clue, e->painter, max_width - (html_engine_get_left_border (e) + html_engine_get_right_border (e)));
158}
159
160static void
161draw (HTMLObject *o,
162      HTMLPainter *p,
163      gint x, gint y,
164      gint width, gint height,
165      gint tx, gint ty)
166{
167        HTMLFrame   *frame  = HTML_FRAME (o);
168        HTMLEngine   *e       = GTK_HTML (frame->html)->engine;
169        GdkRectangle paint;
170
171        if (GTK_OBJECT_TYPE (e->painter) == HTML_TYPE_PRINTER) {
172                gint pixel_size = html_painter_get_pixel_size (e->painter);
173
174                if (!html_object_intersect (o, &paint, x, y, width, height))
175                        return;
176
177                html_object_draw (e->clue, e->painter,
178                                  x, y,
179                                  width - pixel_size * (html_engine_get_left_border (e) + html_engine_get_right_border (e)),
180                                  height - pixel_size * (html_engine_get_top_border (e) + html_engine_get_bottom_border (e)),
181                                  tx + pixel_size * html_engine_get_left_border (e), ty + pixel_size * html_engine_get_top_border (e));
182        } else
183                (*HTML_OBJECT_CLASS (parent_class)->draw) (o, p, x, y, width, height, tx, ty);
184}
185
186static void
187set_painter (HTMLObject *o, HTMLPainter *painter)
188{
189        HTMLFrame *frame;
190
191        frame = HTML_FRAME (o);
192        if (G_OBJECT_TYPE (GTK_HTML (frame->html)->engine->painter) != HTML_TYPE_PRINTER) {
193                frame_set_gdk_painter (frame, GTK_HTML (frame->html)->engine->painter);
194        }
195       
196        html_engine_set_painter (GTK_HTML (frame->html)->engine,
197                                 GTK_OBJECT_TYPE (painter) != HTML_TYPE_PRINTER ? frame->gdk_painter : painter);
198}
199
200static void
201forall (HTMLObject *self,
202        HTMLEngine *e,
203        HTMLObjectForallFunc func,
204        gpointer data)
205{
206        HTMLFrame *frame;
207
208        frame = HTML_FRAME (self);
209        (* func) (self, html_object_get_engine (self, e), data);
210        html_object_forall (GTK_HTML (frame->html)->engine->clue, html_object_get_engine (self, e), func, data);
211}
212
213static gint
214check_page_split (HTMLObject *self, HTMLPainter *p, gint y)
215{
216        return html_object_check_page_split (GTK_HTML (HTML_FRAME (self)->html)->engine->clue, p, y);
217}
218
219static gboolean
220html_frame_real_calc_size (HTMLObject *o, HTMLPainter *painter, GList **changed_objs)
221{
222        HTMLFrame *frame;
223        HTMLEngine *e;
224        gint old_width, old_ascent, old_descent;
225       
226        old_width = o->width;
227        old_ascent = o->ascent;
228        old_descent = o->descent;
229
230        frame = HTML_FRAME (o);
231        e     = GTK_HTML (frame->html)->engine;
232
233        if ((frame->width < 0) && (frame->height < 0)) {
234                if (e->clue) {
235                        html_engine_calc_size (e, changed_objs);
236                        e->width = html_engine_get_doc_width (e);
237                        e->height = html_engine_get_doc_height (e);
238                }
239                html_frame_set_scrolling (frame, GTK_POLICY_NEVER);
240
241                o->width = e->width;
242                o->ascent = e->height;
243                o->descent = 0;
244        } else
245                return (* HTML_OBJECT_CLASS (parent_class)->calc_size) (o, painter, changed_objs);
246
247        if (o->descent != old_descent
248            || o->ascent != old_ascent
249            || o->width != old_width)
250                return TRUE;
251
252        return FALSE;
253}
254
255static gboolean
256search (HTMLObject *self, HTMLSearch *info)
257{
258        HTMLEngine *e = GTK_HTML (HTML_FRAME (self)->html)->engine;
259
260        /* printf ("search\n"); */
261
262        /* search_next? */
263        if (info->stack && HTML_OBJECT (info->stack->data) == e->clue) {
264                /* printf ("next\n"); */
265                info->engine = GTK_HTML (GTK_HTML (HTML_FRAME (self)->html)->iframe_parent)->engine;
266                html_search_pop (info);
267                html_engine_unselect_all (e);
268                return html_search_next_parent (info);
269        }
270
271        info->engine = e;
272        html_search_push (info, e->clue);
273        if (html_object_search (e->clue, info))
274                return TRUE;
275        html_search_pop (info);
276
277        info->engine = GTK_HTML (GTK_HTML (HTML_FRAME (self)->html)->iframe_parent)->engine;
278        /* printf ("FALSE\n"); */
279
280        return FALSE;
281}
282
283static HTMLObject *
284head (HTMLObject *self)
285{
286        return GTK_HTML (HTML_FRAME (self)->html)->engine->clue;
287}
288
289static HTMLObject *
290tail (HTMLObject *self)
291{
292        return GTK_HTML (HTML_FRAME (self)->html)->engine->clue;
293}
294
295static HTMLEngine *
296get_engine (HTMLObject *self, HTMLEngine *e)
297{
298        return GTK_HTML (HTML_FRAME (self)->html)->engine;
299}
300
301static HTMLObject*
302check_point (HTMLObject *self,
303             HTMLPainter *painter,
304             gint x, gint y,
305             guint *offset_return,
306             gboolean for_cursor)
307{
308        HTMLEngine *e = GTK_HTML (HTML_FRAME (self)->html)->engine;
309
310        if (x < self->x || x >= self->x + self->width
311            || y >= self->y + self->descent || y < self->y - self->ascent)
312                return NULL;
313
314        x -= self->x + html_engine_get_left_border (e) - e->x_offset;
315        y -= self->y - self->ascent + html_engine_get_top_border (e) - e->y_offset;
316
317        if (for_cursor && (x < 0 || y < e->clue->y - e->clue->ascent))
318                return html_object_check_point (e->clue, e->painter, 0, e->clue->y - e->clue->ascent,
319                                                offset_return, for_cursor);
320
321        if (for_cursor && (x > e->clue->width - 1 || y > e->clue->y + e->clue->descent - 1))
322                return html_object_check_point (e->clue, e->painter, e->clue->width - 1, e->clue->y + e->clue->descent - 1,
323                                                offset_return, for_cursor);
324
325        return html_object_check_point (e->clue, e->painter, x, y, offset_return, for_cursor);
326}
327
328static gboolean
329is_container (HTMLObject *self)
330{
331        return TRUE;
332}
333
334static void
335append_selection_string (HTMLObject *self,
336                         GString *buffer)
337{
338        html_object_append_selection_string (GTK_HTML (HTML_FRAME (self)->html)->engine->clue, buffer);
339}
340
341static void
342reparent (HTMLEmbedded *emb, GtkWidget *html)
343{
344        HTMLFrame *frame = HTML_FRAME (emb);
345
346        gtk_html_set_iframe_parent (GTK_HTML (frame->html),
347                                    html,
348                                    GTK_HTML (frame->html)->frame);
349        (* HTML_EMBEDDED_CLASS (parent_class)->reparent) (emb, html);
350}
351
352static gboolean
353select_range (HTMLObject *self,
354              HTMLEngine *engine,
355              guint start,
356              gint length,
357              gboolean queue_draw)
358{
359        return html_object_select_range (GTK_HTML (HTML_FRAME (self)->html)->engine->clue,
360                                         GTK_HTML (HTML_FRAME (self)->html)->engine,
361                                         start, length, queue_draw);
362}
363
364static void
365destroy (HTMLObject *o)
366{
367        HTMLFrame *frame = HTML_FRAME (o);
368
369        frame_set_gdk_painter (frame, NULL);
370
371        if (frame->html) {
372                g_signal_handlers_disconnect_matched (frame->html, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, o);
373                frame->html = NULL;
374        }
375        g_free ((frame)->url);
376
377        HTML_OBJECT_CLASS (parent_class)->destroy (o);
378}
379
380void
381html_frame_set_margin_width (HTMLFrame *frame, gint margin_width)
382{
383        HTMLEngine *e;
384
385        e = GTK_HTML (frame->html)->engine;
386
387        e->leftBorder = e->rightBorder = margin_width;
388        html_engine_schedule_redraw (e);
389}
390
391void
392html_frame_set_margin_height (HTMLFrame *frame, gint margin_height)
393{
394        HTMLEngine *e;
395
396        e = GTK_HTML (frame->html)->engine;
397
398        e->bottomBorder = e->topBorder = margin_height;
399        html_engine_schedule_redraw (e);
400}
401
402void
403html_frame_set_scrolling (HTMLFrame *frame, GtkPolicyType scroll)
404{
405
406        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (frame->scroll),
407                                        scroll, scroll);
408}
409
410void
411html_frame_set_size (HTMLFrame *frame, gint width, gint height)
412{
413        g_return_if_fail (frame != NULL);
414
415        if (width > 0)
416                frame->width = width;
417
418        if (height > 0)
419                frame->height = height;
420       
421        gtk_widget_set_size_request (frame->scroll, width, height);
422}
423
424void
425html_frame_init (HTMLFrame *frame,
426                  HTMLFrameClass *klass,
427                  GtkWidget *parent,
428                  char *src,
429                  gint width,
430                  gint height,
431                  gboolean border)
432{
433        HTMLEmbedded *em = HTML_EMBEDDED (frame);
434        HTMLTokenizer *new_tokenizer;
435        GtkWidget *new_widget;
436        GtkHTML   *new_html;
437        GtkHTML   *parent_html;
438        GtkWidget *scrolled_window;
439        gint depth;
440
441        g_assert (GTK_IS_HTML (parent));
442        parent_html = GTK_HTML (parent);
443
444        html_embedded_init (em, HTML_EMBEDDED_CLASS (klass),
445                            parent, NULL, NULL);
446       
447        scrolled_window = gtk_scrolled_window_new (NULL, NULL);
448        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
449                                             border ? GTK_SHADOW_IN : GTK_SHADOW_NONE);
450
451        new_widget = gtk_html_new ();
452        new_html = GTK_HTML (new_widget);
453
454        new_tokenizer = html_tokenizer_clone (parent_html->engine->ht);
455
456        html_engine_set_tokenizer (new_html->engine, new_tokenizer);
457        g_object_unref (G_OBJECT (new_tokenizer));
458        new_tokenizer = NULL;
459
460        gtk_html_set_default_content_type (new_html,
461                                           parent_html->priv->content_type);
462        frame->html = new_widget;
463        frame->url = g_strdup (src);
464        frame->width = width;
465        frame->height = height;
466        frame->gdk_painter = NULL;
467        gtk_html_set_base (new_html, src);
468        depth = gtk_html_set_iframe_parent (new_html, parent, HTML_OBJECT (frame));
469        gtk_container_add (GTK_CONTAINER (scrolled_window), new_widget);
470        gtk_widget_show (new_widget);
471
472        g_signal_connect (new_html, "url_requested", G_CALLBACK (frame_url_requested), frame);
473
474        if (parent_html->engine->stopped) {
475                gtk_html_stop (new_html);
476                gtk_html_load_empty (new_html);
477        } else {
478                GtkHTMLStream *handle;
479
480                handle = gtk_html_begin (new_html);
481                g_signal_emit_by_name (parent_html->engine, "url_requested", src, handle);
482        }
483
484        new_html->engine->clue->parent = HTML_OBJECT (frame);
485
486#if 0
487        /* NOTE: because of peculiarities of the frame/gtkhtml relationship
488         * on_url and link_clicked are emitted from the toplevel widget not
489         * proxied like url_requested is.
490         */
491        gtk_signal_connect (GTK_OBJECT (new_html), "on_url",
492                            GTK_SIGNAL_FUNC (frame_on_url),
493                            (gpointer)frame);
494        gtk_signal_connect (GTK_OBJECT (new_html), "link_clicked",
495                            GTK_SIGNAL_FUNC (frame_link_clicked),
496                            (gpointer)frame);   
497#endif
498        g_signal_connect (new_html, "size_changed", G_CALLBACK (frame_size_changed), frame);   
499        g_signal_connect (new_html, "object_requested", G_CALLBACK (frame_object_requested), frame);   
500        g_signal_connect (new_html, "submit", G_CALLBACK (frame_submit), frame);
501        g_signal_connect (new_html, "set_base", G_CALLBACK (frame_set_base), frame);
502
503        html_frame_set_margin_height (frame, 0);
504        html_frame_set_margin_width (frame, 0);
505
506        /*
507          gtk_signal_connect (GTK_OBJECT (html), "button_press_event",
508          GTK_SIGNAL_FUNC (frame_button_press_event), frame);
509        */
510
511        gtk_widget_set_size_request (scrolled_window, width, height);
512
513        gtk_widget_show (scrolled_window);     
514        frame->scroll = scrolled_window;
515        html_frame_set_scrolling (frame, GTK_POLICY_AUTOMATIC);
516
517        html_embedded_set_widget (em, scrolled_window);
518
519        g_signal_connect (scrolled_window, "button_press_event", G_CALLBACK (html_frame_grab_cursor), NULL);
520
521        /* inherit the current colors from our parent */
522        html_colorset_set_unchanged (new_html->engine->defaultSettings->color_set,
523                                     parent_html->engine->settings->color_set);
524        html_colorset_set_unchanged (new_html->engine->settings->color_set,
525                                     parent_html->engine->settings->color_set);
526        html_painter_set_focus (new_html->engine->painter, parent_html->engine->have_focus);
527        /*
528        g_signal_connect (html, "title_changed", G_CALLBACK (title_changed_cb), app);
529        g_signal_connect (html, "button_press_event", G_CALLBACK (on_button_press_event), popup_menu);
530        g_signal_connect (html, "redirect", G_CALLBACK (on_redirect), NULL);
531        g_signal_connect (html, "object_requested", G_CALLBACK (object_requested_cmd), NULL);
532        */
533}
534
535void
536html_frame_type_init (void)
537{
538        html_frame_class_init (&html_frame_class, HTML_TYPE_FRAME, sizeof (HTMLFrame));
539}
540
541void
542html_frame_class_init (HTMLFrameClass *klass,
543                        HTMLType type,
544                        guint size)
545{
546        HTMLEmbeddedClass *embedded_class;
547        HTMLObjectClass  *object_class;
548
549        g_return_if_fail (klass != NULL);
550       
551        embedded_class = HTML_EMBEDDED_CLASS (klass);
552        object_class = HTML_OBJECT_CLASS (klass);
553
554        html_embedded_class_init (embedded_class, type, size);
555        parent_class = &html_embedded_class;
556
557        object_class->destroy                 = destroy;
558        object_class->calc_size               = html_frame_real_calc_size;
559        object_class->calc_min_width          = calc_min_width;
560        object_class->set_painter             = set_painter;
561        /* object_class->reset                   = reset; */
562        object_class->draw                    = draw;
563        object_class->set_max_width           = set_max_width;
564        object_class->forall                  = forall;
565        object_class->check_page_split        = check_page_split;
566        object_class->search                  = search;
567        object_class->head                    = head;
568        object_class->tail                    = tail;
569        object_class->get_engine              = get_engine;
570        object_class->check_point             = check_point;
571        object_class->is_container            = is_container;
572        object_class->append_selection_string = append_selection_string;
573        object_class->select_range            = select_range;
574
575        embedded_class->reparent = reparent;
576}
577
578
579
Note: See TracBrowser for help on using the repository browser.