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

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