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

Revision 21116, 29.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/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2/*
3    This library is free software; you can redistribute it and/or
4    modify it under the terms of the GNU Library General Public
5    License as published by the Free Software Foundation; either
6    version 2 of the License, or (at your option) any later version.
7
8    This library is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11    Library General Public License for more details.
12
13    You should have received a copy of the GNU Library General Public License
14    along with this library; see the file COPYING.LIB.  If not, write to
15    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16    Boston, MA 02111-1307, USA.
17*/
18
19#include "config.h"
20#include <libgnome/gnome-i18n.h>
21#include <gnome.h>
22#include <bonobo.h>
23#include <sys/types.h>
24
25#include <glib.h>
26#include <sys/stat.h>
27#include <fcntl.h>
28 
29#include <gnome.h>
30#include <gtk/gtk.h>
31#include <gtk/gtkbutton.h>
32
33#include <libgnomeprint/gnome-print.h>
34#include <libgnomeprint/gnome-print-job.h>
35#include <libgnomeprintui/gnome-print-job-preview.h>
36
37#include <libsoup/soup.h>
38#include <sys/stat.h>
39#include <fcntl.h>
40#include <errno.h>
41#include <unistd.h>
42#include <string.h>
43
44#include "config.h"
45#include "gtkhtml.h"
46#include "htmlurl.h"
47#include "htmlengine.h"
48#include "gtkhtml-embedded.h"
49#include "gtkhtml-properties.h"
50
51#include "gtkhtmldebug.h"
52
53typedef struct {
54  FILE *fil;
55  GtkHTMLStream *handle;
56} FileInProgress;
57
58typedef struct {
59        gchar *url;
60        gchar *title;
61        GtkWidget *widget;
62} go_item;
63
64#define MAX_GO_ENTRIES 20
65
66static void exit_cb (GtkWidget *widget, gpointer data);
67static void print_preview_cb (GtkWidget *widget, gpointer data);
68static void test_cb (GtkWidget *widget, gpointer data);
69static void bug_cb (GtkWidget *widget, gpointer data);
70static void slow_cb (GtkWidget *widget, gpointer data);
71static void animate_cb (GtkWidget *widget, gpointer data);
72static void stop_cb (GtkWidget *widget, gpointer data);
73static void dump_cb (GtkWidget *widget, gpointer data);
74static void dump_simple_cb (GtkWidget *widget, gpointer data);
75static void forward_cb (GtkWidget *widget, gpointer data);
76static void back_cb (GtkWidget *widget, gpointer data);
77static void home_cb (GtkWidget *widget, gpointer data);
78static void reload_cb (GtkWidget *widget, gpointer data);
79static void redraw_cb (GtkWidget *widget, gpointer data);
80static void resize_cb (GtkWidget *widget, gpointer data);
81static void select_all_cb (GtkWidget *widget, gpointer data);
82static void title_changed_cb (GtkHTML *html, const gchar *title, gpointer data);
83static void url_requested (GtkHTML *html, const char *url, GtkHTMLStream *handle, gpointer data);
84static void entry_goto_url(GtkWidget *widget, gpointer data);
85static void goto_url(const char *url, int back_or_forward);
86static void on_set_base (GtkHTML *html, const gchar *url, gpointer data);
87
88static gchar *parse_href (const gchar *s);
89
90#ifdef HAVE_OLD_SOUP
91#define SOUP_STATUS_IS_SUCCESSFUL SOUP_ERROR_IS_SUCCESSFUL
92#define status_code errorcode
93#define reason_phrase errorphrase
94#else
95static SoupSession *session;
96#endif
97
98static GtkHTML *html;
99static GtkHTMLStream *html_stream_handle = NULL;
100/* static GtkWidget *animator; */
101static GtkWidget *entry;
102static GtkWidget *popup_menu, *popup_menu_back, *popup_menu_forward, *popup_menu_home;
103static GtkWidget *toolbar_back, *toolbar_forward;
104static HTMLURL *baseURL = NULL;
105
106static GList *go_list;
107static int go_position;
108
109static gboolean use_redirect_filter;
110
111static gboolean slow_loading = FALSE;
112
113static gint redirect_timerId = 0;
114static gchar *redirect_url = NULL;
115
116static GnomeUIInfo file_menu [] = {
117        { GNOME_APP_UI_ITEM, N_("Print pre_view"), N_("Print preview"),
118          print_preview_cb },
119        GNOMEUIINFO_SEPARATOR,
120        GNOMEUIINFO_MENU_EXIT_ITEM (exit_cb, NULL),
121        GNOMEUIINFO_END
122};
123
124static GnomeUIInfo test_menu[] = {
125        { GNOME_APP_UI_ITEM, "Test 1", "Run test 1",
126          test_cb, GINT_TO_POINTER (1), NULL, 0, 0, 0, 0},
127        { GNOME_APP_UI_ITEM, "Test 2", "Run test 2",
128          test_cb, GINT_TO_POINTER (2), NULL, 0, 0, 0, 0},
129        { GNOME_APP_UI_ITEM, "Test 3", "Run test 3",
130          test_cb, GINT_TO_POINTER (3), NULL, 0, 0, 0, 0},
131        { GNOME_APP_UI_ITEM, "Test 4", "Run test 4",
132          test_cb, GINT_TO_POINTER (4), NULL, 0, 0, 0, 0},
133        { GNOME_APP_UI_ITEM, "Test 5", "Run test 5",
134          test_cb, GINT_TO_POINTER (5), NULL, 0, 0, 0, 0},
135        { GNOME_APP_UI_ITEM, "Test 6", "Run test 6",
136          test_cb, GINT_TO_POINTER (6), NULL, 0, 0, 0, 0},
137        { GNOME_APP_UI_ITEM, "Test 7", "Run test 7 (FreshMeat)",
138          test_cb, GINT_TO_POINTER (7), NULL, 0, 0, 0, 0},
139        { GNOME_APP_UI_ITEM, "Test 8", "Run test 8 (local test)",
140          test_cb, GINT_TO_POINTER (8), NULL, 0, 0, 0, 0},
141        { GNOME_APP_UI_ITEM, "Test 9", "Run test 9 (Form Test)",
142          test_cb, GINT_TO_POINTER (9), NULL, 0, 0, 0, 0},
143        { GNOME_APP_UI_ITEM, "Test 10", "Run test 10 (Object Test)",
144          test_cb, GINT_TO_POINTER (10), NULL, 0, 0, 0, 0},
145        { GNOME_APP_UI_ITEM, "Test 11", "Run test 11 (Nowrap)",
146          test_cb, GINT_TO_POINTER (11), NULL, 0, 0, 0, 0},
147        GNOMEUIINFO_END
148};
149
150static GnomeUIInfo debug_menu[] = {
151        { GNOME_APP_UI_ITEM, "Show bug list", "Show the layout bug list",
152          bug_cb, NULL, NULL, 0, 0, 0, 0},
153        { GNOME_APP_UI_ITEM, "Dump Object tree", "Dump Object tree to stdout",
154          dump_cb, NULL, NULL, 0, 0, 0, 0},
155        { GNOME_APP_UI_ITEM, "Dump Object tree (simple)", "Dump Simple Object tree to stdout",
156          dump_simple_cb, NULL, NULL, 0, 0, 0, 0},
157        GNOMEUIINFO_TOGGLEITEM("Slow loading", "Load documents slowly", slow_cb, NULL),
158        { GNOME_APP_UI_ITEM, "Force resize", "Force a resize event",
159          resize_cb, NULL, NULL, 0, 0, 0 },
160        { GNOME_APP_UI_ITEM, "Force repaint", "Force a repaint event",
161          redraw_cb, NULL, NULL, 0, 0, 0 },
162        { GNOME_APP_UI_ITEM, "Select all", "Select all",
163          select_all_cb, NULL, NULL, 0, 0, 0 },
164        GNOMEUIINFO_TOGGLEITEM ("Disable Animations", "Disable Animated Images",  animate_cb, NULL),
165         
166        GNOMEUIINFO_END
167};
168
169static GnomeUIInfo go_menu[] = {
170        { GNOME_APP_UI_ITEM, "Back", "Return to the previous page in history list",
171          back_cb, NULL, NULL, 0, 0, 0, 0},
172        { GNOME_APP_UI_ITEM, "Forward", "Go to the next page in history list",
173          forward_cb, NULL, NULL, 0, 0, 0, 0},
174        { GNOME_APP_UI_ITEM, "Home", "Go to the homepage",
175          home_cb, NULL, NULL, 0, 0, 0 },
176        GNOMEUIINFO_SEPARATOR,
177        GNOMEUIINFO_END
178};
179
180static GnomeUIInfo main_menu[] = {
181        GNOMEUIINFO_MENU_FILE_TREE (file_menu),
182        GNOMEUIINFO_SUBTREE (("_Tests"), test_menu),
183        GNOMEUIINFO_SUBTREE (("_Debug"), debug_menu),
184        GNOMEUIINFO_SUBTREE (("_Go"), go_menu),
185        GNOMEUIINFO_END
186};
187
188static void
189create_toolbars (GtkWidget *app)
190{
191        GtkWidget *dock;
192        GtkWidget *hbox;
193        GtkWidget *frame;
194        GtkWidget *toolbar;
195        /* char *imgloc; */
196
197        dock = bonobo_dock_item_new ("testgtkhtml-toolbar1",
198                                    (BONOBO_DOCK_ITEM_BEH_EXCLUSIVE));
199        hbox = gtk_hbox_new (FALSE, 0);
200        gtk_container_add (GTK_CONTAINER (dock), hbox);
201        gtk_container_set_border_width (GTK_CONTAINER (dock), 2);
202       
203        toolbar = gtk_toolbar_new ();
204        gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_ICONS);
205        gtk_box_pack_start (GTK_BOX (hbox), toolbar, FALSE, FALSE, 0);
206
207        toolbar_back = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
208                                                NULL,
209                                                "Move back",
210                                                "Back",
211                                                gtk_image_new_from_stock ("gtk-go-back", GTK_ICON_SIZE_LARGE_TOOLBAR),
212                                                GTK_SIGNAL_FUNC (back_cb), NULL);
213        gtk_widget_set_sensitive(toolbar_back, FALSE);
214        toolbar_forward = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
215                                                   NULL,
216                                                   "Move forward",
217                                                   "Forward",
218                                                   gtk_image_new_from_stock ("gtk-go-forward", GTK_ICON_SIZE_LARGE_TOOLBAR),
219                                                   GTK_SIGNAL_FUNC (forward_cb), NULL);
220        gtk_widget_set_sensitive(toolbar_forward, FALSE);
221        gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
222        gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
223                                 NULL,
224                                 "Stop loading",
225                                 "Stop",
226                                 gtk_image_new_from_stock ("gtk-stop", GTK_ICON_SIZE_LARGE_TOOLBAR),
227                                 GTK_SIGNAL_FUNC (stop_cb),
228                                 NULL);
229        gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
230                                 NULL,
231                                 "Reload page",
232                                 "Reload",
233                                 gtk_image_new_from_stock ("gtk-refresh", GTK_ICON_SIZE_LARGE_TOOLBAR),
234                                 GTK_SIGNAL_FUNC (reload_cb), NULL);
235        gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
236                                 NULL,
237                                 "Home page",
238                                 "Home",
239                                 gtk_image_new_from_stock ("gtk-home", GTK_ICON_SIZE_LARGE_TOOLBAR),
240                                 GTK_SIGNAL_FUNC (home_cb), NULL);
241        gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
242
243        /* animator = gnome_animator_new_with_size (32, 32);
244
245        if (g_file_exists("32.png"))
246          imgloc = "32.png";
247        else if (g_file_exists(SRCDIR "/32.png"))
248          imgloc = SRCDIR "/32.png";
249        else
250          imgloc = "32.png";
251        gnome_animator_append_frames_from_file_at_size (GNOME_ANIMATOR (animator),
252                                                        imgloc,
253                                                        0, 0,
254                                                        25,
255                                                        32,
256                                                        32, 32); */
257
258        frame = gtk_frame_new (NULL);
259        /* TODO2 gtk_container_add (GTK_CONTAINER (frame), animator); */
260        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
261        gtk_box_pack_end (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
262        /* gnome_animator_set_loop_type (GNOME_ANIMATOR (animator),
263           GNOME_ANIMATOR_LOOP_RESTART); */
264        gtk_widget_show_all (dock);
265        bonobo_dock_add_item (BONOBO_DOCK (GNOME_APP (app)->dock),
266                              BONOBO_DOCK_ITEM (dock), BONOBO_DOCK_TOP, 1, 0, 0, FALSE);
267
268        /* Create the location bar */
269        dock = bonobo_dock_item_new ("testgtkhtml-toolbar2",
270                                     (BONOBO_DOCK_ITEM_BEH_EXCLUSIVE));
271        hbox = gtk_hbox_new (FALSE, 2);
272        gtk_container_add (GTK_CONTAINER (dock), hbox);
273        gtk_container_set_border_width (GTK_CONTAINER (dock), 2);
274        gtk_box_pack_start (GTK_BOX (hbox),
275                            gtk_label_new ("Location:"), FALSE, FALSE, 0);
276        entry = gtk_entry_new ();
277        g_signal_connect (entry, "activate", G_CALLBACK (entry_goto_url), NULL);
278        gtk_box_pack_start (GTK_BOX (hbox),
279                            entry, TRUE, TRUE, 0);
280        bonobo_dock_add_item (BONOBO_DOCK (GNOME_APP (app)->dock),
281                              BONOBO_DOCK_ITEM (dock), BONOBO_DOCK_TOP, 2, 0, 0, FALSE);
282
283}
284
285static gint page_num, pages;
286static GnomeFont *font;
287
288static void
289print_footer (GtkHTML *html, GnomePrintContext *context,
290              gdouble x, gdouble y, gdouble width, gdouble height, gpointer user_data)
291{
292        gchar *text = g_strdup_printf ("- %d of %d -", page_num, pages);
293        gdouble tw = gnome_font_get_width_utf8 (font, "text");
294
295        if (font) {
296                gnome_print_newpath     (context);
297                gnome_print_setrgbcolor (context, .0, .0, .0);
298                gnome_print_moveto      (context, x + (width - tw)/2, y - gnome_font_get_ascender (font));
299                gnome_print_setfont     (context, font);
300                gnome_print_show        (context, text);
301        }
302
303        g_free (text);
304        page_num++;
305}
306
307static void
308print_preview_cb (GtkWidget *widget,
309                  gpointer data)
310{
311        GnomePrintJob *print_master;
312        GnomePrintContext *print_context;
313        GtkWidget *preview;
314
315        print_master = gnome_print_job_new (NULL);
316        /* FIX2 gnome_print_master_set_paper (print_master, gnome_paper_with_name ("US-Letter")); */
317        gtk_html_print_set_master (html, print_master);
318
319        print_context = gnome_print_job_get_context (print_master);
320        font = gnome_font_find_closest ("Helvetica", 12);
321
322        page_num = 1;
323        pages = gtk_html_print_get_pages_num (html, print_context,
324                                              .0, gnome_font_get_ascender (font) - gnome_font_get_descender (font));
325        gtk_html_print_with_header_footer (html, print_context,
326                                           .0, gnome_font_get_ascender (font) - gnome_font_get_descender (font),
327                                           NULL, print_footer, NULL);
328        if (font)
329                g_object_unref (font);
330       
331        gnome_print_job_close (print_master);
332        preview = gnome_print_job_preview_new (print_master, "Print Preview");
333        gtk_widget_show (preview);
334
335        g_object_unref (print_master);
336}
337
338static void
339dump_cb (GtkWidget *widget, gpointer data)
340{
341        g_print ("Object Tree\n");
342        g_print ("-----------\n");
343
344        gtk_html_debug_dump_tree (html->engine->clue, 0);
345}
346
347static void
348dump_simple_cb (GtkWidget *widget, gpointer data)
349{
350        g_print ("Simple Object Tree\n");
351        g_print ("-----------\n");
352
353        gtk_html_debug_dump_tree_simple (html->engine->clue, 0);
354}
355
356static void
357resize_cb (GtkWidget *widget, gpointer data)
358{
359        g_print ("forcing resize\n");
360        html_engine_calc_size (html->engine, FALSE);
361}
362
363static void
364select_all_cb (GtkWidget *widget, gpointer data)
365{
366        g_print ("select all\n");
367        gtk_html_select_all (html);
368}
369
370static void
371redraw_cb (GtkWidget *widget, gpointer data)
372{
373        g_print ("forcing redraw\n");
374        gtk_widget_queue_draw (GTK_WIDGET (html));
375}
376
377static void
378slow_cb (GtkWidget *widget, gpointer data)
379{
380        slow_loading = !slow_loading;
381}
382
383static void
384animate_cb (GtkWidget *widget, gpointer data)
385{
386        /* gtk_html_set_animate (html, !gtk_html_get_animate (html)); */
387}
388
389static void
390title_changed_cb (GtkHTML *html, const gchar *title, gpointer data)
391{
392        gchar *s;
393
394        s = g_strconcat ("GtkHTML: ", title, NULL);
395        gtk_window_set_title (GTK_WINDOW (data), s);
396        g_free (s);
397}
398
399static void
400entry_goto_url(GtkWidget *widget, gpointer data)
401{
402        gchar *tmpurl;
403
404        tmpurl = g_strdup (gtk_entry_get_text (GTK_ENTRY (widget)));
405
406        /* Add "http://" if no protocol is specified */
407        if(strchr(tmpurl, ':')) {
408                on_set_base (NULL, tmpurl, NULL);
409                goto_url (tmpurl, 0);
410        } else {
411                gchar *url;
412
413                url = g_strdup_printf("http://%s", tmpurl);
414                on_set_base (NULL, url, NULL);
415                goto_url (url, 0);
416                g_free(url);
417        }
418        g_free (tmpurl);
419}
420
421static void
422home_cb (GtkWidget *widget, gpointer data)
423{
424        goto_url("http://www.gnome.org", 0);
425}
426
427static void
428back_cb (GtkWidget *widget, gpointer data)
429{
430        go_item *item;
431
432        go_position++;
433
434        if((item = g_list_nth_data(go_list, go_position))) {
435
436                goto_url(item->url, 1);
437                gtk_widget_set_sensitive(popup_menu_forward, TRUE);
438                gtk_widget_set_sensitive(toolbar_forward, TRUE);
439                gtk_widget_set_sensitive(go_menu[1].widget, TRUE);
440
441                if(go_position == (g_list_length(go_list) - 1)) {
442
443                        gtk_widget_set_sensitive(popup_menu_back, FALSE);
444                        gtk_widget_set_sensitive(toolbar_back, FALSE);
445                        gtk_widget_set_sensitive(go_menu[0].widget, FALSE);
446                }
447
448        } else
449                go_position--;
450}
451
452static void
453forward_cb (GtkWidget *widget, gpointer data)
454{
455        go_item *item;
456
457        go_position--;
458
459        if((go_position >= 0) && (item = g_list_nth_data(go_list, go_position))) {
460
461                goto_url(item->url, 1);
462
463                gtk_widget_set_sensitive(popup_menu_back, TRUE);
464                gtk_widget_set_sensitive(toolbar_back, TRUE);
465                gtk_widget_set_sensitive(go_menu[0].widget, TRUE);
466
467                if(go_position == 0) {
468                        gtk_widget_set_sensitive(popup_menu_forward, FALSE);
469                        gtk_widget_set_sensitive(toolbar_forward, FALSE);
470                        gtk_widget_set_sensitive(go_menu[1].widget, FALSE);
471                }
472        } else
473                go_position++;
474}
475
476static void
477reload_cb (GtkWidget *widget, gpointer data)
478{
479        go_item *item;
480
481        if((item = g_list_nth_data(go_list, go_position))) {
482
483                goto_url(item->url, 1);
484        }
485}
486
487static void
488stop_cb (GtkWidget *widget, gpointer data)
489{
490        /* Kill all requests */
491#ifdef HAVE_OLD_SOUP
492        soup_shutdown ();
493#else
494        soup_session_abort (session);
495#endif
496        html_stream_handle = NULL;
497}
498
499static void
500load_done (GtkHTML *html)
501{
502        /* TODO2 gnome_animator_stop (GNOME_ANIMATOR (animator));
503        gnome_animator_goto_frame (GNOME_ANIMATOR (animator), 1);
504
505        if (exit_when_done)
506        gtk_main_quit(); */
507}
508
509static int
510on_button_press_event (GtkWidget *widget, GdkEventButton *event)
511{
512        GtkMenu *menu;
513       
514        g_return_val_if_fail (widget != NULL, FALSE);
515        g_return_val_if_fail (event != NULL, FALSE);
516       
517        /* The "widget" is the menu that was supplied when
518         * gtk_signal_connect_object was called.
519         */
520        menu = GTK_MENU (popup_menu);
521       
522        if (event->type == GDK_BUTTON_PRESS) {
523
524                if (event->button == 3) {
525                        gtk_menu_popup (menu, NULL, NULL, NULL, NULL,
526                                        event->button, event->time);
527                        return TRUE;
528                }
529        }
530               
531        return FALSE;
532}
533
534static void
535on_set_base (GtkHTML *html, const gchar *url, gpointer data)
536{
537        gtk_entry_set_text (GTK_ENTRY (entry), url);
538        if (baseURL)
539                html_url_destroy (baseURL);
540
541        if (html) {
542                gtk_html_set_base (html, url);
543        }
544               
545        baseURL = html_url_new (url);
546}
547
548static gboolean
549redirect_timer_event (gpointer data) {
550        g_print("Redirecting to '%s' NOW\n", redirect_url);
551        goto_url(redirect_url, 0);
552
553        /*      OBS: redirect_url is freed in goto_url */
554
555        return FALSE;
556}
557
558static void
559on_redirect (GtkHTML *html, const gchar *url, int delay, gpointer data) {
560        g_print("Redirecting to '%s' in %d seconds\n", url, delay);
561
562        if(redirect_timerId == 0) {
563
564                redirect_url = g_strdup(url);
565               
566                redirect_timerId = gtk_timeout_add (delay * 1000,(GtkFunction) redirect_timer_event, NULL);
567        }
568}
569
570static void
571on_submit (GtkHTML *html, const gchar *method, const gchar *action, const gchar *encoding, gpointer data) {
572        GString *tmpstr = g_string_new (action);
573
574        g_print("submitting '%s' to '%s' using method '%s'\n", encoding, action, method);
575
576        if(strcasecmp(method, "GET") == 0) {
577
578                tmpstr = g_string_append_c (tmpstr, '?');
579                tmpstr = g_string_append (tmpstr, encoding);
580               
581                goto_url(tmpstr->str, 0);
582               
583                g_string_free (tmpstr, TRUE);
584        } else {
585                g_warning ("Unsupported submit method '%s'\n", method);
586        }
587
588}
589
590static void
591on_url (GtkHTML *html, const gchar *url, gpointer data)
592{
593        GnomeApp *app;
594
595        app = GNOME_APP (data);
596
597        if (url == NULL)
598                gnome_appbar_set_status (GNOME_APPBAR (app->statusbar), "");
599        else
600                gnome_appbar_set_status (GNOME_APPBAR (app->statusbar), url);
601}
602
603static void
604on_link_clicked (GtkHTML *html, const gchar *url, gpointer data)
605{
606        goto_url (url, 0);
607}
608
609/* simulate an async object isntantiation */
610static int
611object_timeout(GtkHTMLEmbedded *eb)
612{
613        GtkWidget *w;
614
615        w = gtk_check_button_new();
616        gtk_widget_show(w);
617
618        printf("inserting custom widget after a delay ...\n");
619        gtk_html_embedded_set_descent(eb, rand()%8);
620        gtk_container_add (GTK_CONTAINER(eb), w);
621        gtk_widget_unref (GTK_WIDGET (eb));
622
623        return FALSE;
624}
625
626static gboolean
627object_requested_cmd (GtkHTML *html, GtkHTMLEmbedded *eb, void *data)
628{
629        /* printf("object requested, wiaint a bit before creating it ...\n"); */
630
631        if (eb->classid && strcmp (eb->classid, "mine:NULL") == 0)
632                return FALSE;
633
634        gtk_widget_ref (GTK_WIDGET (eb));
635        gtk_timeout_add(rand() % 5000 + 1000, (GtkFunction) object_timeout, eb);
636        /* object_timeout (eb); */
637
638        return TRUE;
639}
640
641static void
642got_data (SoupMessage *msg, gpointer user_data)
643{
644        GtkHTMLStream *handle = user_data;
645
646        if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
647                g_warning ("%d - %s", msg->status_code, msg->reason_phrase);
648                gtk_html_end (html, handle, GTK_HTML_STREAM_ERROR);
649                return;
650        }
651
652        gtk_html_write (html, handle, msg->response.body, msg->response.length);
653        gtk_html_end (html, handle, GTK_HTML_STREAM_OK);
654}
655
656static void
657url_requested (GtkHTML *html, const char *url, GtkHTMLStream *handle, gpointer data)
658{
659        gchar *full_url = NULL;
660
661        full_url = parse_href (url);
662
663        if (full_url && !strncmp (full_url, "http", 4)) {
664                SoupMessage *msg;
665#ifdef HAVE_OLD_SOUP
666                SoupContext *ctx;
667
668                ctx = soup_context_get (full_url);
669                msg = soup_message_new (ctx, SOUP_METHOD_GET);
670
671                soup_message_queue (msg, got_data, handle);
672#else
673                msg = soup_message_new (SOUP_METHOD_GET, full_url);
674                soup_session_queue_message (session, msg, got_data, handle);
675#endif
676        } else if (full_url && !strncmp (full_url, "file:", 5)) {
677                struct stat st;
678                char *buf;
679                int fd, nread, total;
680
681                fd = open (full_url + 5, O_RDONLY);
682                if (fd != -1 && fstat (fd, &st) != -1) {
683                        buf = g_malloc (st.st_size);
684                        for (nread = total = 0; total < st.st_size; total += nread) {
685                                nread = read (fd, buf + total, st.st_size - total);
686                                if (nread == -1) {
687                                        if (errno == EINTR)
688                                                continue;
689
690                                        g_warning ("read error: %s", g_strerror (errno));
691                                        gtk_html_end (html, handle, GTK_HTML_STREAM_ERROR);
692                                        break;
693                                }
694                                gtk_html_write (html, handle, buf + total, nread);
695                        }
696                        g_free (buf);
697                        if (nread != -1)
698                                gtk_html_end (html, handle, GTK_HTML_STREAM_OK);
699                } else
700                        gtk_html_end (html, handle, GTK_HTML_STREAM_OK);
701                if (fd != -1)
702                        close (fd);
703        } else
704                g_warning ("Unrecognized URL %s", full_url);
705
706        g_free (full_url);
707}
708
709static gchar *
710parse_href (const gchar *s)
711{
712        gchar *retval;
713        gchar *tmp;
714        HTMLURL *tmpurl;
715
716        if(s == NULL || *s == 0)
717                return g_strdup ("");
718
719        if (s[0] == '#') {
720                tmpurl = html_url_dup (baseURL, HTML_URL_DUP_NOREFERENCE);
721                html_url_set_reference (tmpurl, s + 1);
722
723                tmp = html_url_to_string (tmpurl);
724                html_url_destroy (tmpurl);
725
726                return tmp;
727        }
728
729        tmpurl = html_url_new (s);
730        if (html_url_get_protocol (tmpurl) == NULL) {
731                if (s[0] == '/') {
732                        if (s[1] == '/') {
733                                gchar *t;
734
735                                /* Double slash at the beginning.  */
736
737                                /* FIXME?  This is a bit sucky.  */
738                                t = g_strconcat (html_url_get_protocol (baseURL),
739                                                 ":", s, NULL);
740                                html_url_destroy (tmpurl);
741                                tmpurl = html_url_new (t);
742                                retval = html_url_to_string (tmpurl);
743                                html_url_destroy (tmpurl);
744                                g_free (t);
745                        } else {
746                                /* Single slash at the beginning.  */
747
748                                html_url_destroy (tmpurl);
749                                tmpurl = html_url_dup (baseURL,
750                                                       HTML_URL_DUP_NOPATH);
751                                html_url_set_path (tmpurl, s);
752                                retval = html_url_to_string (tmpurl);
753                                html_url_destroy (tmpurl);
754                        }
755                } else {
756                        html_url_destroy (tmpurl);
757                        tmpurl = html_url_append_path (baseURL, s);
758                        retval = html_url_to_string (tmpurl);
759                        html_url_destroy (tmpurl);
760                }
761        } else {
762                retval = html_url_to_string (tmpurl);
763                html_url_destroy (tmpurl);
764        }
765
766        return retval;
767}
768
769static void
770go_list_cb (GtkWidget *widget, gpointer data)
771{
772        go_item *item;
773        int num;
774        /* Only if the item was selected, not deselected */
775        if(GTK_CHECK_MENU_ITEM(widget)->active) {
776               
777                go_position = GPOINTER_TO_INT(data);
778               
779                if((item = g_list_nth_data(go_list, go_position))) {
780                       
781                        goto_url(item->url, 1);
782                        num = g_list_length(go_list);
783
784                        if(go_position == 0 || num < 2) {
785                                gtk_widget_set_sensitive(popup_menu_forward, FALSE);
786                                gtk_widget_set_sensitive(toolbar_forward, FALSE);
787                                gtk_widget_set_sensitive(go_menu[1].widget, FALSE);
788                        } else {
789                                gtk_widget_set_sensitive(popup_menu_forward, TRUE);
790                                gtk_widget_set_sensitive(toolbar_forward, TRUE);
791                                gtk_widget_set_sensitive(go_menu[1].widget, TRUE);
792                        }
793                        if(go_position == (num - 1) || num < 2) {
794                                gtk_widget_set_sensitive(popup_menu_back, FALSE);
795                                gtk_widget_set_sensitive(toolbar_back, FALSE);
796                                gtk_widget_set_sensitive(go_menu[0].widget, FALSE);
797                        } else {
798                                gtk_widget_set_sensitive(popup_menu_back, TRUE);
799                                gtk_widget_set_sensitive(toolbar_back, TRUE);
800                                gtk_widget_set_sensitive(go_menu[0].widget, TRUE);
801                        }
802                }
803        }
804}
805
806static void remove_go_list(gpointer data, gpointer user_data) {
807        go_item *item = (go_item *)data;
808       
809        if(item->widget)
810                gtk_widget_destroy(item->widget);
811       
812        item->widget = NULL;
813}
814
815static void
816goto_url(const char *url, int back_or_forward)
817{
818        int tmp, i;
819        go_item *item;
820        GSList *group = NULL;
821        gchar *full_url;
822
823        /* Kill all requests */
824#ifdef HAVE_OLD_SOUP
825        soup_shutdown ();
826#else
827        soup_session_abort (session);
828#endif
829
830        /* Remove any pending redirection */
831        if(redirect_timerId) {
832                gtk_timeout_remove(redirect_timerId);
833
834                redirect_timerId = 0;
835        }
836
837        /* TODO2 gnome_animator_start (GNOME_ANIMATOR (animator)); */
838
839        use_redirect_filter = TRUE;
840
841        html_stream_handle = gtk_html_begin_content (html, "text/html; charset=utf-8");
842
843        /* Yuck yuck yuck.  Well this code is butt-ugly already
844        anyway.  */
845
846        full_url = parse_href (url);
847        on_set_base (NULL, full_url, NULL);
848        url_requested (html, url, html_stream_handle, NULL);
849
850        if(!back_or_forward) {
851                if(go_position) {
852                        /* Removes "Forward entries"*/
853                        tmp = go_position;
854                        while(tmp) {
855                                item = g_list_nth_data(go_list, --tmp);
856                                go_list = g_list_remove(go_list, item);
857                                if(item->url)
858                                        g_free(item->url);
859                                if(item->title)
860                                        g_free(item->title);
861                                if(item->url)
862                                        gtk_widget_destroy(item->widget);
863                                g_free(item);
864                        }
865                        go_position = 0;
866                }
867
868                /* Removes old entries if the list is to big */
869                tmp = g_list_length(go_list);
870                while(tmp > MAX_GO_ENTRIES) {
871                        item = g_list_nth_data(go_list, MAX_GO_ENTRIES);
872
873                        if(item->url)
874                                g_free(item->url);
875                        if(item->title)
876                                g_free(item->title);
877                        if(item->url)
878                                gtk_widget_destroy(item->widget);
879                        g_free(item);
880
881                        go_list = g_list_remove(go_list, item);
882                        tmp--;
883                }
884                gtk_widget_set_sensitive(popup_menu_forward, FALSE);
885                gtk_widget_set_sensitive(toolbar_forward, FALSE);
886                gtk_widget_set_sensitive(go_menu[1].widget, FALSE);
887               
888                item = g_malloc0(sizeof(go_item));
889                item->url = g_strdup(full_url);
890
891                /* Remove old go list */
892                g_list_foreach(go_list, remove_go_list, NULL);
893
894                /* Add new url to go list */
895                go_list = g_list_prepend(go_list, item);
896
897                /* Create a new go list menu */
898                tmp = g_list_length(go_list);
899                group = NULL;
900
901                for(i=0;i<tmp;i++) {
902                        item = g_list_nth_data(go_list, i);
903                        item->widget = gtk_radio_menu_item_new_with_label(group, item->url);
904
905                        g_signal_connect (item->widget, "activate",
906                                          G_CALLBACK (go_list_cb), GINT_TO_POINTER (i));
907
908                        group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item->widget));
909
910                        if(i == 0)
911                                gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item->widget), TRUE);
912
913                        gtk_menu_shell_append (GTK_MENU_SHELL (GTK_MENU_ITEM(main_menu[3].widget)->submenu), item->widget);
914                        gtk_widget_show(item->widget);
915                       
916                }
917                /* Enable the "Back" button if there are more then one url in the list */
918                if(g_list_length(go_list) > 1) {
919
920                        gtk_widget_set_sensitive(popup_menu_back, TRUE);
921                        gtk_widget_set_sensitive(toolbar_back, TRUE);
922                        gtk_widget_set_sensitive(go_menu[0].widget, TRUE);
923                }
924        } else {
925                /* Update current link in the go list */
926                item = g_list_nth_data(go_list, go_position);
927                gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item->widget), TRUE);
928        }
929
930        if(redirect_url) {
931
932                g_free(redirect_url);
933                redirect_url = NULL;
934        }
935        g_free (full_url);
936}
937
938static void
939bug_cb (GtkWidget *widget, gpointer data)
940{
941        gchar cwd[PATH_MAX], *filename;
942
943        getcwd(cwd, sizeof (cwd));
944        filename = g_strdup_printf("file:%s/bugs.html", cwd);
945        goto_url(filename, 0);
946        g_free(filename);
947}
948
949static void
950test_cb (GtkWidget *widget, gpointer data)
951{
952        gchar cwd[PATH_MAX], *filename;
953
954        getcwd(cwd, sizeof (cwd));
955        filename = g_strdup_printf ("file:%s/tests/test%d.html", cwd,
956                                    GPOINTER_TO_INT (data));
957        goto_url(filename, 0);
958        g_free(filename);
959}
960
961static void
962exit_cb (GtkWidget *widget, gpointer data)
963{
964        gtk_main_quit ();
965}
966
967/* static struct poptOption options[] = {
968  {"slow-loading", '\0', POPT_ARG_NONE, &slow_loading, 0, "Load the document as slowly as possible", NULL},
969  {"exit-when-done", '\0', POPT_ARG_NONE, &exit_when_done, 0, "Exit the program as soon as the document is loaded", NULL},
970  {NULL}
971  }; */
972
973gint
974main (gint argc, gchar *argv[])
975{
976        GtkWidget *app, *bar;
977        GtkWidget *html_widget;
978        GtkWidget *scrolled_window;
979
980#ifdef MEMDEBUG
981        void *p = malloc (1024);        /* to make linker happy with ccmalloc */
982#endif
983        /* gnome_init_with_popt_table (PACKAGE, VERSION,
984           argc, argv, options, 0, &ctx); */
985        gnome_program_init ("testgtkhtml", VERSION, LIBGNOMEUI_MODULE, argc, argv,
986
987                            GNOME_PARAM_HUMAN_READABLE_NAME, _("GtkHTML Test Application"),
988                            NULL);
989
990        app = gnome_app_new ("testgtkhtml", "GtkHTML: testbed application");
991
992        g_signal_connect (app, "delete_event", G_CALLBACK (exit_cb), NULL);
993
994        create_toolbars (app);
995        bar = gnome_appbar_new (FALSE, TRUE, GNOME_PREFERENCES_USER);
996        gnome_app_set_statusbar (GNOME_APP (app), bar);
997        gnome_app_create_menus (GNOME_APP (app), main_menu);
998
999        /* Disable back and forward on the Go menu */
1000        gtk_widget_set_sensitive(go_menu[0].widget, FALSE);
1001        gtk_widget_set_sensitive(go_menu[1].widget, FALSE);
1002
1003        gnome_app_install_menu_hints (GNOME_APP (app), main_menu);
1004
1005        scrolled_window = gtk_scrolled_window_new (NULL, NULL);
1006
1007        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
1008                                        GTK_POLICY_AUTOMATIC,
1009                                        GTK_POLICY_AUTOMATIC);
1010
1011        gnome_app_set_contents (GNOME_APP (app), scrolled_window);
1012
1013#ifndef HAVE_OLD_SOUP
1014        session = soup_session_async_new ();
1015#endif
1016
1017        html_widget = gtk_html_new ();
1018        html = GTK_HTML (html_widget);
1019        gtk_html_set_allow_frameset (html, TRUE);
1020        gtk_html_load_empty (html);
1021        /* gtk_html_set_default_background_color (GTK_HTML (html_widget), &bgColor); */
1022        /* gtk_html_set_editable (GTK_HTML (html_widget), TRUE); */
1023       
1024        gtk_container_add (GTK_CONTAINER (scrolled_window), html_widget);
1025
1026        /* Create a popup menu with disabled back and forward items */
1027        popup_menu = gtk_menu_new();
1028
1029        popup_menu_back = gtk_menu_item_new_with_label ("Back");
1030        gtk_widget_set_sensitive (popup_menu_back, FALSE);
1031        gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), popup_menu_back);
1032        gtk_widget_show (popup_menu_back);
1033        g_signal_connect (popup_menu_back, "activate", G_CALLBACK (back_cb), NULL);
1034
1035        popup_menu_forward = gtk_menu_item_new_with_label ("Forward");
1036        gtk_widget_set_sensitive (popup_menu_forward, FALSE);
1037        gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), popup_menu_forward);
1038        gtk_widget_show (popup_menu_forward);
1039        g_signal_connect (popup_menu_forward, "activate", G_CALLBACK (forward_cb), NULL);
1040
1041        popup_menu_home = gtk_menu_item_new_with_label ("Home");
1042        gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), popup_menu_home);
1043        gtk_widget_show (popup_menu_home);
1044        g_signal_connect (popup_menu_home, "activate", G_CALLBACK (home_cb), NULL);
1045
1046        /* End of menu creation */
1047
1048        gtk_widget_set_events (html_widget, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
1049
1050        g_signal_connect (html, "title_changed", G_CALLBACK (title_changed_cb), (gpointer)app);
1051        g_signal_connect (html, "url_requested", G_CALLBACK (url_requested), (gpointer)app);
1052        g_signal_connect (html, "load_done", G_CALLBACK (load_done), (gpointer)app);
1053        g_signal_connect (html, "on_url", G_CALLBACK (on_url), (gpointer)app);
1054        g_signal_connect (html, "set_base", G_CALLBACK (on_set_base), (gpointer)app);
1055        g_signal_connect (html, "button_press_event", G_CALLBACK (on_button_press_event), popup_menu);
1056        g_signal_connect (html, "link_clicked", G_CALLBACK (on_link_clicked), NULL);
1057        g_signal_connect (html, "redirect", G_CALLBACK (on_redirect), NULL);
1058        g_signal_connect (html, "submit", G_CALLBACK (on_submit), NULL);
1059        g_signal_connect (html, "object_requested", G_CALLBACK (object_requested_cmd), NULL);
1060
1061#if 0
1062        gtk_box_pack_start_defaults (GTK_BOX (hbox), GTK_WIDGET (html));
1063        vscrollbar = gtk_vscrollbar_new (GTK_LAYOUT (html)->vadjustment);
1064        gtk_box_pack_start (GTK_BOX (hbox), vscrollbar, FALSE, TRUE, 0);
1065       
1066#endif
1067        gtk_widget_realize (GTK_WIDGET (html));
1068
1069        gtk_window_set_default_size (GTK_WINDOW (app), 540, 400);
1070        gtk_window_set_focus (GTK_WINDOW (app), GTK_WIDGET (html));
1071
1072        gtk_widget_show_all (app);
1073
1074        if (argc > 1 && *argv [argc - 1] != '-')
1075                goto_url (argv [argc - 1], 0);
1076
1077        gtk_main ();
1078
1079#ifdef MEMDEBUG
1080
1081        /* gtk_widget_unref (html_widget); */
1082        free (p);
1083#endif
1084
1085        return 0;
1086}
Note: See TracBrowser for help on using the repository browser.