"main_menu.[ch]" -> "menus.[ch]"; it handles not only the main menu, but
[obnox/wireshark/wip.git] / gtk / main.c
index ed50229ae254dcb0de56b1837fa37ebe6b64f95c..bb4eab8891a468992ddc13b2e59916a8dac9fab7 100644 (file)
 #include "gtk/main.h"
 #include "gtk/main_airpcap_toolbar.h"
 #include "gtk/main_filter_toolbar.h"
-#include "gtk/main_menu.h"
+#include "gtk/menus.h"
 #include "gtk/main_packet_list.h"
 #include "gtk/main_statusbar.h"
 #include "gtk/main_statusbar_private.h"
 #include "airpcap_loader.h"
 #include "airpcap_dlg.h"
 #include "airpcap_gui_utils.h"
-
-#include "./image/toolbar/wep_closed_24.xpm"
 #endif
 
 #ifdef HAVE_AIRPDCAP
@@ -290,7 +288,7 @@ match_selected_cb_do(gpointer data, int action, gchar *text)
     /* Don't change the current display filter if we only want to copy the filter */
     if (action&MATCH_SELECTED_COPY_ONLY) {
         GString *gtk_text_str = g_string_new("");
-        g_string_append_printf(gtk_text_str, "%s", new_filter);
+        g_string_append(gtk_text_str, new_filter);
         copy_to_clipboard(gtk_text_str);
         g_string_free(gtk_text_str, TRUE);
     } else {
@@ -389,37 +387,71 @@ selected_ptree_info_cb(GtkWidget *widget _U_, gpointer data _U_)
 
         proto_abbrev = proto_registrar_get_abbrev(field_id);
 
-        /* ask the user if the wiki page really should be opened */
-        dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
+        if (!proto_is_private(field_id)) {
+            /* ask the user if the wiki page really should be opened */
+            dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
                     "%sOpen Wireshark Wiki page of protocol \"%s\"?%s\n"
                     "\n"
                     "This will open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
                     "\n"
-                    "The Wireshark Wiki is a collaborative approach to provide information\n"
+                    "The Wireshark Wiki is a collaborative approach to provide information "
                     "about Wireshark in several ways (not limited to protocol specifics).\n"
                     "\n"
-                    "This Wiki is new, so the page of the selected protocol\n"
+                    "This Wiki is new, so the page of the selected protocol "
                     "may not exist and/or may not contain valuable information.\n"
                     "\n"
-                    "As everyone can edit the Wiki and add new content (or extend existing),\n"
+                    "As everyone can edit the Wiki and add new content (or extend existing), "
                     "you are encouraged to add information if you can.\n"
                     "\n"
                     "Hint 1: If you are new to wiki editing, try out editing the Sandbox first!\n"
                     "\n"
-                    "Hint 2: If you want to add a new protocol page, you should use the ProtocolTemplate,\n"
+                    "Hint 2: If you want to add a new protocol page, you should use the ProtocolTemplate, "
                     "which will save you a lot of editing and will give a consistent look over the pages.",
                     simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
-        simple_dialog_set_cb(dialog, selected_ptree_info_answered_cb, (gpointer) proto_abbrev);
+            simple_dialog_set_cb(dialog, selected_ptree_info_answered_cb, (gpointer)proto_abbrev);
+        } else {
+            /* appologize to the user that the wiki page cannot be opened */
+            dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+                    "%sCan't open Wireshark Wiki page of protocol \"%s\"%s\n"
+                    "\n"
+                    "This would open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
+                    "\n"
+                    "Since this is a private protocol, such information is not available in "
+                    "a public wiki. Therefore this wiki entry is blocked.\n"
+                    "\n"
+                    "Sorry for the inconvenience.\n",
+                    simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
+        }
     }
 }
 
+static void selected_ptree_ref_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
+{
+    gchar *selected_proto_url;
+    gchar *proto_abbrev = data;
+
+    switch(btn) {
+    case(ESD_BTN_OK):
+        if (cfile.finfo_selected) {
+            /* open reference page using the protocol abbreviation */
+            selected_proto_url = g_strdup_printf("http://www.wireshark.org/docs/dfref/%c/%s", proto_abbrev[0], proto_abbrev);
+            browser_open_url(selected_proto_url);
+            g_free(selected_proto_url);
+        }
+        break;
+    case(ESD_BTN_CANCEL):
+        break;
+    default:
+        g_assert_not_reached();
+    }
+}
 
 void
 selected_ptree_ref_cb(GtkWidget *widget _U_, gpointer data _U_)
 {
     int field_id;
     const gchar *proto_abbrev;
-    gchar *selected_proto_url;
+    gpointer  dialog;
 
 
     if (cfile.finfo_selected) {
@@ -433,15 +465,33 @@ selected_ptree_ref_cb(GtkWidget *widget _U_, gpointer data _U_)
 
         proto_abbrev = proto_registrar_get_abbrev(field_id);
 
-        /* open reference page using the protocol abbreviation */
-        selected_proto_url = g_strdup_printf("http://www.wireshark.org/docs/dfref/%c/%s.html", proto_abbrev[0], proto_abbrev);
-        browser_open_url(selected_proto_url);
-        g_free(selected_proto_url);
+        if (!proto_is_private(field_id)) {
+            /* ask the user if the wiki page really should be opened */
+            dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
+                    "%sOpen Wireshark filter reference page of protocol \"%s\"?%s\n"
+                    "\n"
+                    "This will open the \"%s\" related Wireshark filter reference page in your Web browser.\n"
+                    "\n",
+                    simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
+            simple_dialog_set_cb(dialog, selected_ptree_ref_answered_cb, (gpointer)proto_abbrev);
+        } else {
+            /* appologize to the user that the wiki page cannot be opened */
+            dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+                    "%sCan't open Wireshark filter reference page of protocol \"%s\"%s\n"
+                    "\n"
+                    "This would open the \"%s\" related Wireshark filter reference page in your Web browser.\n"
+                    "\n"
+                    "Since this is a private protocol, such information is not available on "
+                    "a public website. Therefore this filter entry is blocked.\n"
+                    "\n"
+                    "Sorry for the inconvenience.\n",
+                    simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
+        }
     }
 }
 
 static gchar *
-get_text_from_packet_list(gpointer data)
+get_filter_from_packet_list_row_and_column(gpointer data)
 {
     gint       row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_ROW_KEY));
     gint       column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY));
@@ -461,7 +511,7 @@ match_selected_plist_cb(GtkWidget *w _U_, gpointer data, MATCH_SELECTED_E action
 {
     match_selected_cb_do(data,
         action,
-        get_text_from_packet_list(data));
+        get_filter_from_packet_list_row_and_column(data));
 }
 
 /* This function allows users to right click in the details window and copy the text
@@ -472,25 +522,46 @@ match_selected_plist_cb(GtkWidget *w _U_, gpointer data, MATCH_SELECTED_E action
  * fails we display a message to the user to indicate the copy could not be completed.
  */
 void
-copy_selected_plist_cb(GtkWidget *w _U_, gpointer data _U_)
+copy_selected_plist_cb(GtkWidget *w _U_, gpointer data _U_, COPY_SELECTED_E action)
 {
     GString *gtk_text_str = g_string_new("");
     char labelstring[256];
     char *stringpointer = labelstring;
 
-    if (cfile.finfo_selected->rep->representation != 0) {
-        g_string_append_printf(gtk_text_str, "%s", cfile.finfo_selected->rep->representation);   /* Get the represented data */
+    switch(action)
+    {
+    case COPY_SELECTED_DESCRIPTION:
+        if (cfile.finfo_selected->rep->representation != 0) {
+            g_string_append(gtk_text_str, cfile.finfo_selected->rep->representation);
+        }
+        break;
+    case COPY_SELECTED_FIELDNAME:
+        if (cfile.finfo_selected->hfinfo->abbrev != 0) {
+            g_string_append(gtk_text_str, cfile.finfo_selected->hfinfo->abbrev);
+        }
+        break;
+    case COPY_SELECTED_VALUE:
+        if (cfile.edt !=0 ) {
+            g_string_append(gtk_text_str, 
+                    get_node_field_value(cfile.finfo_selected, cfile.edt));
+        }
+        break;
+    default:
+        break;
     }
-    if (gtk_text_str->len == 0) {                                                           /* If no representation then... */
-        proto_item_fill_label(cfile.finfo_selected, stringpointer);                         /* Try to read the value */
-        g_string_append_printf(gtk_text_str, "%s", stringpointer);
+
+    if (gtk_text_str->len == 0) {
+        /* If no representation then... Try to read the value */
+        proto_item_fill_label(cfile.finfo_selected, stringpointer);
+        g_string_append(gtk_text_str, stringpointer);
     }
-    if (gtk_text_str->len == 0) {                                                           /* Could not get item so display error msg */
+
+    if (gtk_text_str->len == 0) {
+        /* Could not get item so display error msg */
         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to copy, try expanding or choosing another item");
-    }
-    else
-    {
-        copy_to_clipboard(gtk_text_str);                     /* Copy string to clipboard */
+    } else {
+        /* Copy string to clipboard */
+        copy_to_clipboard(gtk_text_str);
     }
     g_string_free(gtk_text_str, TRUE);                       /* Free the memory */
 }
@@ -624,9 +695,9 @@ tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data _U_)
         if (finfo->hfinfo->blurb != NULL &&
             finfo->hfinfo->blurb[0] != '\0') {
             has_blurb = TRUE;
-            length = strlen(finfo->hfinfo->blurb);
+            length = (guint) strlen(finfo->hfinfo->blurb);
         } else {
-            length = strlen(finfo->hfinfo->name);
+            length = (guint) strlen(finfo->hfinfo->name);
         }
         finfo_length = finfo->length + finfo->appendix_length;
 
@@ -687,8 +758,8 @@ void expand_tree_cb(GtkWidget *widget _U_, gpointer data _U_) {
   path = tree_find_by_field_info(GTK_TREE_VIEW(tree_view), cfile.finfo_selected);
   if(path) {
     /* the mouse position is at an entry, expand that one */
-  gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view), path, TRUE);
-  gtk_tree_path_free(path);
+    gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view), path, TRUE);
+    gtk_tree_path_free(path);
   }
 }
 
@@ -794,7 +865,7 @@ main_window_delete_event_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer
   if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
     gtk_window_present(GTK_WINDOW(top_level));
     /* user didn't saved his current file, ask him */
-    dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
+    dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL,
                 "%sSave capture file before program quit?%s\n\n"
                 "If you quit the program without saving, your capture data will be discarded.",
                 simple_dialog_primary_start(), simple_dialog_primary_end());
@@ -883,7 +954,7 @@ static void file_quit_answered_cb(gpointer dialog _U_, gint btn, gpointer data _
         /* save file first */
         file_save_as_cmd(after_save_exit, NULL);
         break;
-    case(ESD_BTN_DONT_SAVE):
+    case(ESD_BTN_QUIT_DONT_SAVE):
         main_do_quit();
         break;
     case(ESD_BTN_CANCEL):
@@ -900,7 +971,7 @@ file_quit_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
 
   if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
     /* user didn't saved his current file, ask him */
-    dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
+    dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL,
                 "%sSave capture file before program quit?%s\n\n"
                 "If you quit the program without saving, your capture data will be discarded.",
                 simple_dialog_primary_start(), simple_dialog_primary_end());
@@ -1175,7 +1246,7 @@ main_cf_cb_file_closing(capture_file *cf)
 {
 
     /* if we have more than 10000 packets, show a splash screen while closing */
-    /* XXX - don't know a better way to decide wether to show or not,
+    /* XXX - don't know a better way to decide whether to show or not,
      * as most of the time is spend in a single eth_clist_clear function,
      * so we can't use a progress bar here! */
     if(cf->count > 10000) {
@@ -1702,6 +1773,9 @@ main(int argc, char *argv[])
   extern char         *optarg;
   gboolean             arg_error = FALSE;
 
+  extern int           splash_register_freq;  /* Found in about_dlg.c */
+  const gchar         *filter;
+
 #ifdef _WIN32
   WSADATA             wsaData;
 #endif  /* _WIN32 */
@@ -1730,9 +1804,11 @@ main(int argc, char *argv[])
   int                  status;
   gchar               *cur_user, *cur_group;
 
+#ifdef _WIN32
 #ifdef HAVE_AIRPCAP
   char                 *err_str;
 #endif
+#endif
 
 #define OPTSTRING_INIT "a:b:c:C:Df:g:Hhi:kK:lLm:nN:o:P:pQr:R:Ss:t:vw:X:y:z:"
 
@@ -1756,7 +1832,7 @@ main(int argc, char *argv[])
   /*
    * Attempt to get the pathname of the executable file.
    */
-  init_progfile_dir_error = init_progfile_dir(argv[0]);
+  init_progfile_dir_error = init_progfile_dir(argv[0], main);
 
   /* initialize the funnel mini-api */
   initialize_funnel_ops();
@@ -1837,6 +1913,14 @@ main(int argc, char *argv[])
   runtime_info_str = g_string_new("Running ");
   get_runtime_version_info(runtime_info_str, get_gui_runtime_info);
 
+  /* Read the profile independent recent file.  We have to do this here so we can */
+  /* set the profile before it can be set from the command line parameterts */
+  recent_read_static(&rf_path, &rf_open_errno);
+  if (rf_path != NULL && rf_open_errno != 0) {
+    simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+                 "Could not open common recent file\n\"%s\": %s.",
+                 rf_path, strerror(rf_open_errno));
+  }
 
   /* "pre-scan" the command line parameters, if we have "console only"
      parameters.  We do this so we don't start GTK+ if we're only showing
@@ -1997,6 +2081,11 @@ main(int argc, char *argv[])
   /* Initialize whatever we need to allocate colors for GTK+ */
   colors_init();
 
+  /* Non-blank filter means we're remote. Throttle splash screen updates. */
+  filter = get_conn_cfilter();
+  if ( *filter != '\0' )
+    splash_register_freq = 1000;  /* Milliseconds */
+
   /* We won't come till here, if we had a "console only" command line parameter. */
   splash_win = splash_new("Loading Wireshark ...");
   if (init_progfile_dir_error != NULL) {
@@ -2016,7 +2105,8 @@ main(int argc, char *argv[])
      case any dissectors register preferences. */
   epan_init(register_all_protocols,register_all_protocol_handoffs,
            splash_update, (gpointer) splash_win,
-            failure_alert_box,open_failure_alert_box,read_failure_alert_box);
+            failure_alert_box,open_failure_alert_box,read_failure_alert_box,
+            write_failure_alert_box);
 
   splash_update(RA_LISTENERS, NULL, (gpointer)splash_win);
 
@@ -2055,22 +2145,17 @@ main(int argc, char *argv[])
   tap_update_timer_id = g_timeout_add(prefs->tap_update_interval, update_cb, NULL);
 #endif /* !_WIN32 && G_THREADS_ENABLED && USE_THREADS */
 
-#if HAVE_GNU_ADNS
+#if HAVE_GNU_ADNS || HAVE_C_ARES
   g_timeout_add(750, host_name_lookup_process, NULL);
 #endif
 
   splash_update(RA_CONFIGURATION, NULL, (gpointer)splash_win);
 
 
-  /* Read the (static part) of the recent file. Only the static part of it will be read, */
-  /* as we don't have the gui now to fill the recent lists which is done in the dynamic part. */
+  /* Read the profile dependent (static part) of the recent file. */
+  /* Only the static part of it will be read, as we don't have the gui now to fill the */
+  /* recent lists which is done in the dynamic part. */
   /* We have to do this already here, so command line parameters can overwrite these values. */
-  recent_read_static(&rf_path, &rf_open_errno);
-  if (rf_path != NULL && rf_open_errno != 0) {
-    simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
-                 "Could not open common recent file\n\"%s\": %s.",
-                 rf_path, strerror(rf_open_errno));
-  }
   recent_read_profile_static(&rf_path, &rf_open_errno);
   if (rf_path != NULL && rf_open_errno != 0) {
     simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
@@ -2154,8 +2239,7 @@ main(int argc, char *argv[])
 #endif
         break;
       case 'm':        /* Fixed-width font for the display */
-        if (prefs->gui_font_name != NULL)
-          g_free(prefs->gui_font_name);
+        g_free(prefs->gui_font_name);
         prefs->gui_font_name = g_strdup(optarg);
         break;
       case 'n':        /* No name resolution */
@@ -2544,7 +2628,7 @@ main(int argc, char *argv[])
 
         case CF_READ_ABORTED:
           /* Exit now. */
-          gtk_exit(0);
+          exit(0);
           break;
         }
         /* Save the name of the containing directory specified in the
@@ -2635,14 +2719,7 @@ main(int argc, char *argv[])
   destroy_console();
 #endif
 
-  gtk_exit(0);
-
-  /* This isn't reached, but we need it to keep GCC from complaining
-     that "main()" returns without returning a value - it knows that
-     "exit()" never returns, but it doesn't know that "gtk_exit()"
-     doesn't, as GTK+ doesn't declare it with the attribute
-     "noreturn". */
-  return 0;    /* not reached */
+  exit(0);
 }
 
 #ifdef _WIN32
@@ -2848,21 +2925,21 @@ void main_widgets_rearrange(void) {
     gtk_widget_hide(main_vbox);
 
     /* be sure we don't lose a widget while rearranging */
-    gtk_widget_ref(menubar);
-    gtk_widget_ref(main_tb);
-    gtk_widget_ref(filter_tb);
+    g_object_ref(G_OBJECT(menubar));
+    g_object_ref(G_OBJECT(main_tb));
+    g_object_ref(G_OBJECT(filter_tb));
 #ifdef HAVE_AIRPCAP
-    gtk_widget_ref(airpcap_tb);
-#endif
-    gtk_widget_ref(pkt_scrollw);
-    gtk_widget_ref(tv_scrollw);
-    gtk_widget_ref(byte_nb_ptr);
-    gtk_widget_ref(statusbar);
-    gtk_widget_ref(main_pane_v1);
-    gtk_widget_ref(main_pane_v2);
-    gtk_widget_ref(main_pane_h1);
-    gtk_widget_ref(main_pane_h2);
-    gtk_widget_ref(welcome_pane);
+    g_object_ref(G_OBJECT(airpcap_tb));
+#endif
+    g_object_ref(G_OBJECT(pkt_scrollw));
+    g_object_ref(G_OBJECT(tv_scrollw));
+    g_object_ref(G_OBJECT(byte_nb_ptr));
+    g_object_ref(G_OBJECT(statusbar));
+    g_object_ref(G_OBJECT(main_pane_v1));
+    g_object_ref(G_OBJECT(main_pane_v2));
+    g_object_ref(G_OBJECT(main_pane_h1));
+    g_object_ref(G_OBJECT(main_pane_h2));
+    g_object_ref(G_OBJECT(welcome_pane));
 
     /* empty all containers participating */
     gtk_container_foreach(GTK_CONTAINER(main_vbox),     foreach_remove_a_child, main_vbox);
@@ -3086,7 +3163,7 @@ window_state_event_cb (GtkWidget *widget _U_,
 
 #define NO_SHIFT_MOD_MASK (GDK_MODIFIER_MASK & ~(GDK_SHIFT_MASK|GDK_MOD2_MASK|GDK_LOCK_MASK))
 static int
-top_level_key_pressed_cb(GtkCTree *ctree _U_, GdkEventKey *event, gpointer user_data _U_)
+top_level_key_pressed_cb(GtkWidget *w _U_, GdkEventKey *event, gpointer user_data _U_)
 {
     if (event->keyval == GDK_F8) {
        packet_list_next();
@@ -3245,6 +3322,7 @@ prefs_to_capture_opts(void)
   /* Set promiscuous mode from the preferences setting. */
   /* the same applies to other preferences settings as well. */
     global_capture_opts.promisc_mode   = prefs.capture_prom_mode;
+    global_capture_opts.use_pcapng     = prefs.capture_pcap_ng;
     global_capture_opts.show_info      = prefs.capture_show_info;
     global_capture_opts.real_time_mode = prefs.capture_real_time;
     auto_scroll_live             = prefs.capture_auto_scroll;
@@ -3270,8 +3348,10 @@ void change_configuration_profile (const gchar *profile_name)
    /* Get the current geometry, before writing it to disk */
    main_save_window_geometry(top_level);
 
-   /* Write recent file for profile we are leaving */
-   write_profile_recent();
+   if (profile_exists(get_profile_name())) {
+     /* Write recent file for profile we are leaving, if it still exists */
+     write_profile_recent();
+   }
 
    /* Set profile name and update the status bar */
    set_profile_name (profile_name);
@@ -3279,6 +3359,8 @@ void change_configuration_profile (const gchar *profile_name)
 
    /* Reset current preferences and apply the new */
    prefs_reset();
+   menu_prefs_reset();
+   
    (void) read_configuration_files (&gdp_path, &dp_path);
 
    recent_read_profile_static(&rf_path, &rf_open_errno);
@@ -3314,7 +3396,13 @@ void change_configuration_profile (const gchar *profile_name)
 
    /* Recreate the packet list according to new preferences */
    packet_list_recreate ();
-   status_expert_update();
    cfile.cinfo.columns_changed = FALSE; /* Reset value */
    user_font_apply();
 }
+
+/** redissect packets and update UI */
+void redissect_packets(void)
+{
+    cf_redissect_packets(&cfile);
+    status_expert_update();
+}