source: trunk/third/gtkhtml/src/htmlframe.c @ 18136

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