diff -pruN dillo-0.7.0/src/Makefile.am dillo-0.7.0-local/src/Makefile.am --- dillo-0.7.0/src/Makefile.am Sat Aug 3 16:22:22 2002 +++ dillo-0.7.0-local/src/Makefile.am Sat Nov 2 09:55:44 2002 @@ -101,6 +101,8 @@ dillo_SOURCES = \ cookies.c \ cookies.h \ list.h \ - pixmaps.h + pixmaps.h \ + offline.c \ + offline.h EXTRA_DIST = pixmaps_old.h chg srch diff -pruN dillo-0.7.0/src/browser.h dillo-0.7.0-local/src/browser.h --- dillo-0.7.0/src/browser.h Sat Aug 10 15:13:17 2002 +++ dillo-0.7.0-local/src/browser.h Sat Nov 2 09:55:44 2002 @@ -41,6 +41,7 @@ struct _BrowserWindow GtkWidget *save_button; GtkWidget *stop_button; GtkWidget *menubar; + GtkWidget *offline_menuitem; GtkWidget *clear_url_button; GtkWidget *location; GtkWidget *progress_box; diff -pruN dillo-0.7.0/src/commands.c dillo-0.7.0-local/src/commands.c --- dillo-0.7.0/src/commands.c Sat Aug 10 15:13:19 2002 +++ dillo-0.7.0-local/src/commands.c Sat Nov 2 09:56:10 2002 @@ -26,6 +26,7 @@ #include "prefs.h" #include "menu.h" #include "capi.h" +#include "offline.h" /* * Local data @@ -318,7 +319,15 @@ void a_Commands_save_link_callback(GtkWi a_Interface_save_link_dialog(widget, bw); } - +/* + * Toggle offline (local browsing only) mode on/off + */ +void a_Commands_offline_toggle_callback (GtkWidget *widget, gpointer client_data) +{ + a_Offline_toggle(); +} + + /* BOOKMARKS MENU */ /* diff -pruN dillo-0.7.0/src/commands.h dillo-0.7.0-local/src/commands.h --- dillo-0.7.0/src/commands.h Sat Aug 10 15:13:20 2002 +++ dillo-0.7.0-local/src/commands.h Sat Nov 2 09:55:44 2002 @@ -26,6 +26,7 @@ void a_Commands_home_callback (GtkWidget void a_Commands_save_callback (GtkWidget *widget, gpointer client_data); void a_Commands_save_link_callback (GtkWidget *widget, gpointer client_data); +void a_Commands_offline_toggle_callback (GtkWidget *widget, gpointer client_data); void a_Commands_addbm_callback (GtkWidget *widget, gpointer client_data); void a_Commands_viewbm_callback (GtkWidget *widget, gpointer client_data); diff -pruN dillo-0.7.0/src/dillo.c dillo-0.7.0-local/src/dillo.c --- dillo-0.7.0/src/dillo.c Sat Aug 24 02:29:49 2002 +++ dillo-0.7.0-local/src/dillo.c Sat Nov 2 09:55:44 2002 @@ -43,17 +43,39 @@ #include "IO/mime.h" #include "prefs.h" #include "interface.h" +#include "offline.h" #include "dw.h" #include "dw_widget.h" #include "cookies.h" /* + * Command line options structure + */ + +typedef struct { + char *sh_opt; /* must be non NULL */ + char *lg_opt; /* must be non NULL */ + int opt_argc; /* positive: mandatory, negative: optional */ + int opt_flg; /* 1 << n */ + char *help; /* can be NULL */ +} DilloCLIOptions; + +enum { + DILLO_CLI_LOCAL = 1 << 0, + DILLO_CLI_HELP = 1 << 29, + DILLO_CLI_VERSION = 1 << 30, + DILLO_CLI_ERROR = 1 << 31 +}; + +/* * Forward declarations */ static void Dillo_check_home_dir(char *dir); - - +static guint32 Dillo_get_opt(DilloCLIOptions *dillo_options, int argc, + char **argv, char ***opt_arg, gint *cli_idx); +static void Dillo_print_help(DilloCLIOptions *dillo_options); +static void Dillo_print_version(void); /* * ******************************** MAIN ************************************* @@ -63,13 +85,61 @@ gint main(int argc, char *argv[]) gchar *file; DilloUrl *start_url; BrowserWindow *bw; + guint32 cli_options = 0; + gint cli_idx; + guint opt_flg; + gboolean gui_state; + gint i; + char **opt_argv = NULL; + DilloCLIOptions dillo_options[] = { + {"-l", "--localonly", 0, DILLO_CLI_LOCAL, + " -l, --localonly Allow only local host browsing."}, + {"-v", "--version", 0, DILLO_CLI_VERSION, + " -v, --version Display version info and exit."}, + {"-h", "--help", 0, DILLO_CLI_HELP, + " -h, --help Display this help text and exit."}, + {NULL, NULL, 0, 0, NULL} + }; /* This lets threads in the file module end peacefully when aborted * todo: implement a cleaner mechanism (in file.c) */ signal(SIGPIPE, SIG_IGN); g_print("Setting locale to %s\n", gtk_set_locale()); - gtk_init(&argc, &argv); + + /* Initialize GUI when possible and parse GTK related args*/ + if (!(gui_state = gtk_init_check(&argc, &argv))) + /* GUI not initialized, args not parsed. Line from gtkmain.c */ + g_warning("cannot open display: %s", gdk_get_display()); + + /* Handle command line options */ + while ((opt_flg = Dillo_get_opt(dillo_options, argc, argv, &opt_argv, + &cli_idx))) + { + cli_options |= opt_flg; + switch (opt_flg) { + case DILLO_CLI_VERSION: + Dillo_print_version(); + return 0; + break; + case DILLO_CLI_HELP: + Dillo_print_help(dillo_options); + return 0; + break; + case DILLO_CLI_LOCAL: + a_Offline_set_mode(TRUE); + break; + default: + printf("Error in command line options.\n"); + return -1; + break; + } + } + + if (!gui_state) + /* Abort if GUI could not be initialized. */ + exit(1); + gdk_rgb_init(); /* check that ~/.dillo exists, create it if it doesn't */ @@ -98,22 +168,25 @@ gint main(int argc, char *argv[]) a_Nav_push(bw, start_url); a_Url_free(start_url); - if (argc == 2) { - if (access(argv[1], F_OK) == 0) { - GString *UrlStr = g_string_sized_new(128); + for (i = cli_idx; i < argc; i++) { + /* If more than one URL/FILE, open in new window */ + if (i > cli_idx) + bw = a_Interface_browser_window_new(prefs.width, prefs.height); + if (access(argv[i], F_OK) == 0) { + GString *UrlStr = g_string_sized_new(128); - if (argv[1][0] == '/') { - g_string_sprintf(UrlStr, "file:%s", argv[1]); + if (argv[i][0] == '/') { + g_string_sprintf(UrlStr, "file:%s", argv[i]); } else { g_string_sprintf(UrlStr, "file:%s", g_get_current_dir()); if (UrlStr->str[UrlStr->len - 1] != '/') g_string_append(UrlStr, "/"); - g_string_append(UrlStr, argv[1]); + g_string_append(UrlStr, argv[i]); } start_url = a_Url_new(UrlStr->str, NULL, 0, 0); g_string_free(UrlStr, TRUE); } else { - start_url = a_Url_new(argv[1], NULL, 0, 0); + start_url = a_Url_new(argv[i], NULL, 0, 0); } a_Nav_push(bw, start_url); a_Url_free(start_url); @@ -157,3 +230,105 @@ static void Dillo_check_home_dir(char *d } } +/* + * Get next command line option. + * Return value: + * opt_flg of the option + * 0 if no more options found + * -1 if an unrecognised option is found or if a mandatory option + * argument is not found. + */ +static guint32 Dillo_get_opt(DilloCLIOptions *dillo_options, int argc, + char **argv, char ***opt_argv, gint *cli_idx) +{ + static int idx = 1; + int opt_flg; + int opt_argc; + int i = 0; + guint32 ret_val = 0; + + if (idx >= argc) + goto done; + + /* Create a sufficiently large array to hold the maximum possible number of + * option arguments */ + if (*opt_argv == NULL) { + int max_argc = 0; + for (i = 0; dillo_options[i].sh_opt; i++) + if (abs(dillo_options[i].opt_argc) > max_argc) + max_argc = abs(dillo_options[i].opt_argc); + if (max_argc) + *opt_argv = (char **) calloc(max_argc + 1, sizeof(char *)); + } + + /* Find the option */ + for (i = 0; dillo_options[i].sh_opt; i++) { + if (strcmp(dillo_options[i].sh_opt, argv[idx]) == 0 + || strcmp(dillo_options[i].lg_opt, argv[idx]) == 0) { + opt_flg = dillo_options[i].opt_flg; + opt_argc = dillo_options[i].opt_argc; + idx++; + + if (opt_argc) { + /* Find the required/optional arguments of the option */ + for (i = 0; idx < argc && i < abs(opt_argc) && argv[idx][0] != '-'; + i++) + (*opt_argv)[i] = argv[idx++]; + + (*opt_argv)[i] = NULL; + /* Optional arguments have opt_argc < 0 */ + if (i < opt_argc) { + printf("Option %s requires %d argument(s)\n", argv[idx - i - 1], + opt_argc); + goto error; + } + } + *cli_idx = idx; + return opt_flg; + } + } + /* No known options found. We're done if there are no more options + * -- means: consider the rest of arguments as non options */ + if (strcmp(argv[idx], "--") == 0) { + idx++; + goto done; + } + if (argv[idx][0] != '-') + goto done; + +error: + /* Unknown option or insufficient mandatory option arguments */ + ret_val = DILLO_CLI_ERROR; +done: + if (*opt_argv) + free(*opt_argv); + *cli_idx = idx; + return ret_val; +} + +/* + * Print a short help text automatically generated from the options structure + */ +static void Dillo_print_help(DilloCLIOptions *dillo_options) +{ + printf("Usage: dillo [OPTIONS] [URL|FILE]...\n" + "Options:\n"); + + for (; dillo_options && dillo_options->sh_opt; dillo_options++) + if (dillo_options->help) + printf("%s\n", dillo_options->help); + else + printf(" %s, %s *Undocumented*\n", dillo_options->sh_opt, + dillo_options->lg_opt); + + printf(" URL URL to browse.\n" + " FILE Local FILE to view.\n"); +} + +/* + * Print version (TODO: and maybe a copyright notice) + */ +static void Dillo_print_version(void) +{ + printf("Dillo %s\n", VERSION); +} diff -pruN dillo-0.7.0/src/dns.c dillo-0.7.0-local/src/dns.c --- dillo-0.7.0/src/dns.c Sat Aug 10 15:13:22 2002 +++ dillo-0.7.0-local/src/dns.c Sat Nov 2 09:58:49 2002 @@ -29,6 +29,7 @@ #include "dns.h" #include "list.h" +#include "offline.h" #define DEBUG_LEVEL 5 #include "debug.h" @@ -44,6 +45,7 @@ */ /* #define LIBC5 */ +#define DNS_IP_IS_LOCAL(ip_addr) ((ip_addr & 0xff000000) == 0x7f000000) /* Maximum dns resolving threads */ #ifdef G_DNS_THREADED @@ -337,8 +339,12 @@ static void Dns_lookup(ChainLink *Info, /* if it hits already resolved, call the Callback inmediately. */ if (i < dns_cache_size) { - a_Dns_ccc(OpSend, 1, FWD, Info, &dns_cache[i].ip_addr, NULL); - a_Dns_ccc(OpEnd, 1, FWD, Info, NULL, NULL); + if (a_Offline_get_mode() && !DNS_IP_IS_LOCAL(dns_cache[i].ip_addr)) { + a_Dns_ccc(OpAbort, 1, FWD, Info, NULL, NULL); + } else { + a_Dns_ccc(OpSend, 1, FWD, Info, &dns_cache[i].ip_addr, NULL); + a_Dns_ccc(OpEnd, 1, FWD, Info, NULL, NULL); + } return; } if ((i = Dns_queue_find(hostname)) != -1) { @@ -374,7 +380,8 @@ static void Dns_serve_channel(gint chann for (i = 0; i < dns_queue_size; i++) { if (dns_queue[i].channel == channel) { Info = dns_queue[i].Info; - if ( srv->ip_addr == 0 ) { + if ( srv->ip_addr == 0 || + (a_Offline_get_mode() && !DNS_IP_IS_LOCAL(srv->ip_addr))) { a_Dns_ccc(OpAbort, 1, FWD, Info, NULL, NULL); } else { a_Dns_ccc(OpSend, 1, FWD, Info, &srv->ip_addr, NULL); diff -pruN dillo-0.7.0/src/menu.c dillo-0.7.0-local/src/menu.c --- dillo-0.7.0/src/menu.c Sat Aug 10 15:13:36 2002 +++ dillo-0.7.0-local/src/menu.c Sat Nov 2 09:55:44 2002 @@ -31,6 +31,7 @@ #include "dw_page.h" /* for a_Dw_page_add_anchor */ #include "bookmark.h" #include "interface.h" +#include "offline.h" /* * Forward declarations @@ -97,6 +98,39 @@ static GtkWidget * return menuitem; } +static GtkWidget * + Menu_toggle_add (GtkWidget *menu, const char *name, const char *accel, + BrowserWindow *bw, + void (*callback) (GtkWidget *widget, void *data), void *data, + int active) +{ + GtkWidget *menuitem; + GtkAccelGroup *menu_accels; + GdkModifierType accel_mods; + guint accel_key; + guint tmp_key; + + menuitem = gtk_check_menu_item_new_with_label((char *) name); + gtk_menu_append(GTK_MENU(menu), menuitem); + menu_accels = gtk_menu_ensure_uline_accel_group(GTK_MENU(menu)); + tmp_key = gtk_label_parse_uline(GTK_LABEL(GTK_BIN(menuitem)->child), name); + gtk_widget_add_accelerator(menuitem, "activate_item", + menu_accels, tmp_key, 0, 0); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), active); + + gtk_widget_show(menuitem); + + if (accel != NULL) { + gtk_accelerator_parse(accel, &accel_key, &accel_mods); + gtk_widget_add_accelerator(menuitem, "activate", bw->accel_group, + accel_key, (guint)accel_mods, GTK_ACCEL_VISIBLE); + } + if (callback != NULL) + gtk_signal_connect(GTK_OBJECT(menuitem), "activate", + (GtkSignalFunc) callback, data); + return menuitem; +} + /* * Add a separator into the menu. */ @@ -139,6 +173,11 @@ GtkWidget *a_Menu_mainbar_new(BrowserWin */ Menu_add(file_menu, "Close Window", "Q", bw, a_Commands_close_callback, bw); + Menu_sep(file_menu); + bw->offline_menuitem = Menu_toggle_add(file_menu, "Work off_line", + "L", bw, + a_Commands_offline_toggle_callback, + bw, a_Offline_get_mode()); Menu_sep(file_menu); Menu_add(file_menu, "Exit Dillo", "Q", bw, a_Commands_exit_callback, bw); diff -pruN dillo-0.7.0/src/offline.c dillo-0.7.0-local/src/offline.c --- dillo-0.7.0/src/offline.c Thu Jan 1 01:00:00 1970 +++ dillo-0.7.0-local/src/offline.c Sat Nov 2 09:55:44 2002 @@ -0,0 +1,50 @@ +/* + * File: offline.c + * + * Copyright (C) 1999, 2000, 2001 Jorge Arellano Cid + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include "browser.h" +#include "nav.h" +#include "offline.h" + +static void Offline_update_menu(BrowserWindow *bw); +static int offline_mode = FALSE; + +int a_Offline_get_mode() +{ + return offline_mode; +} + +void a_Offline_set_mode(int mode) +{ + offline_mode = mode; +} + +/* + * Toggle offline (local browsing only) mode on/off + */ +void a_Offline_toggle() +{ + int i; + offline_mode = (offline_mode == FALSE); + + for (i = 0; i < num_bw; i++) + Offline_update_menu(browser_window[i]); +} + +static void Offline_update_menu(BrowserWindow *bw) +{ + GtkWidget *menuitem = bw->offline_menuitem; + + gtk_signal_handler_block_by_data(GTK_OBJECT(menuitem), bw); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), offline_mode); + gtk_signal_handler_unblock_by_data(GTK_OBJECT(menuitem), bw); + a_Nav_cancel_expect(bw); +} diff -pruN dillo-0.7.0/src/offline.h dillo-0.7.0-local/src/offline.h --- dillo-0.7.0/src/offline.h Thu Jan 1 01:00:00 1970 +++ dillo-0.7.0-local/src/offline.h Sat Nov 2 09:55:44 2002 @@ -0,0 +1,8 @@ +#ifndef __OFFLINE_H__ +#define __OFFLINE_H__ + +void a_Offline_set_mode(int mode); +int a_Offline_get_mode(void); +void a_Offline_toggle(void); + +#endif /* __OFFLINE_H__ */