Added "Ignore Packet" menu items to the main menu.
[metze/wireshark/wip.git] / gtk / main_packet_list.c
index 3f4868397f8cae5253b046303caa34ea092806fa..cf7ee439ebb9f5afae4ad49c99ead03987f56a1c 100644 (file)
@@ -58,6 +58,9 @@
 #include "gtk/main_packet_list.h"
 #include "gtk/main_statusbar.h"
 #include "gtk/packet_win.h"
+#include "gtk/prefs_column.h"
+#include "gtk/prefs_dlg.h"
+#include "gtk/dlg_utils.h"
 
 #include "image/clist_ascend.xpm"
 #include "image/clist_descend.xpm"
@@ -66,6 +69,7 @@
 
 typedef struct column_arrows {
   GtkWidget *table;
+  GtkWidget *label;
   GtkWidget *ascend_pm;
   GtkWidget *descend_pm;
 } column_arrows;
@@ -173,11 +177,139 @@ packet_list_compare(GtkCList *clist, gconstpointer  ptr1, gconstpointer  ptr2)
   }
 }
 
+static gboolean
+right_justify_column (gint col)
+{
+        header_field_info *hfi;
+        gboolean right_justify = FALSE;
+
+        switch (cfile.cinfo.col_fmt[col]) {
+
+        case COL_NUMBER:
+        case COL_PACKET_LENGTH:
+        case COL_CUMULATIVE_BYTES:
+        case COL_DCE_CALL:
+                right_justify = TRUE;
+                break;
+
+        case COL_CUSTOM:
+                hfi = proto_registrar_get_byname(cfile.cinfo.col_custom_field[col]);
+                /* Check if this is a valid field and we have no strings lookup table */
+                if ((hfi != NULL) && (hfi->strings == NULL)) {
+                        /* Check for bool, framenum and decimal/octal integer types */
+                        if ((hfi->type == FT_BOOLEAN) || (hfi->type == FT_FRAMENUM) ||
+                                (((hfi->display == BASE_DEC) || (hfi->display == BASE_OCT)) &&
+                                 (IS_FT_INT(hfi->type) || IS_FT_UINT(hfi->type)))) {
+                                right_justify = TRUE;
+                        }
+                }
+                break;
+
+        default:
+                break;
+        }
+
+        return right_justify;
+}
+
+static void
+col_title_change_ok (GtkWidget *w, gpointer parent_w)
+{
+      GtkWidget *column_lb = g_object_get_data (G_OBJECT(w), "column");
+      gint col_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(packet_list), E_MPACKET_LIST_COL_KEY));
+      GtkWidget *entry = g_object_get_data (G_OBJECT(w), "entry");
+      const gchar *title =  gtk_entry_get_text(GTK_ENTRY(entry));
+
+      gtk_label_set_text (GTK_LABEL(column_lb), title);
+      column_prefs_rename(col_id, title);
+
+      if (!prefs.gui_use_pref_save) {
+              prefs_main_write();
+      }
+
+      window_destroy(GTK_WIDGET(parent_w));
+}
+
+static void
+col_title_change_cancel (GtkWidget *w _U_, gpointer parent_w)
+{
+      window_destroy(GTK_WIDGET(parent_w));
+}
+
+static void
+col_title_edit_dlg (gint col_id, gpointer data)
+{
+      column_arrows *col_arrows = (column_arrows *) data;
+      const gchar *value = gtk_label_get_text (GTK_LABEL(col_arrows[col_id].label));
+
+      GtkWidget *win, *main_tb, *main_vb, *bbox, *cancel_bt, *ok_bt;
+      GtkWidget *entry, *label;
+
+      win = dlg_window_new("Column Title");
+
+      gtk_window_set_resizable(GTK_WINDOW(win),FALSE);
+      gtk_window_resize(GTK_WINDOW(win), 400, 100);
+
+      main_vb = gtk_vbox_new(FALSE, 5);
+      gtk_container_add(GTK_CONTAINER(win), main_vb);
+      gtk_container_set_border_width(GTK_CONTAINER(main_vb), 6);
+
+      main_tb = gtk_table_new(2, 2, FALSE);
+      gtk_box_pack_start(GTK_BOX(main_vb), main_tb, FALSE, FALSE, 0);
+      gtk_table_set_col_spacings(GTK_TABLE(main_tb), 10);
+
+      label = gtk_label_new(ep_strdup_printf("Title:"));
+      gtk_table_attach_defaults(GTK_TABLE(main_tb), label, 0, 1, 1, 2);
+      gtk_misc_set_alignment(GTK_MISC(label), 1.0f, 0.5f);
+
+      entry = gtk_entry_new();
+      gtk_table_attach_defaults(GTK_TABLE(main_tb), entry, 1, 2, 1, 2);
+      gtk_entry_set_text(GTK_ENTRY(entry), value);
+
+      bbox = dlg_button_row_new(GTK_STOCK_CANCEL,GTK_STOCK_OK, NULL);
+      gtk_box_pack_end(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
+
+      ok_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
+      g_object_set_data (G_OBJECT(ok_bt), "column", col_arrows[col_id].label);
+      g_object_set_data (G_OBJECT(ok_bt), "entry", entry);
+      g_signal_connect(ok_bt, "clicked", G_CALLBACK(col_title_change_ok), win);
+
+      dlg_set_activate(entry, ok_bt);
+
+      cancel_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
+      g_signal_connect(cancel_bt, "clicked", G_CALLBACK(col_title_change_cancel), win);
+      window_set_cancel_button(win, cancel_bt, NULL);
+
+      gtk_widget_grab_default(ok_bt);
+      gtk_widget_show_all(win);
+}
+
+
+static void
+packet_list_resize_column (gint col_id)
+{
+      gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), col_id, TRUE);
+      gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), col_id, TRUE);
+}
+
+static void
+packet_list_remove_column (gint col_id)
+{
+      column_prefs_remove(col_id);
+
+      if (!prefs.gui_use_pref_save) {
+              prefs_main_write();
+      }
+
+      packet_list_recreate();
+}
+
 /* What to do when a column is clicked */
 static void
-packet_list_click_column_cb(GtkCList *clist, gint column, gpointer data)
+packet_list_sort_column(gint column, gpointer data, GtkSortType order)
 {
   column_arrows *col_arrows = (column_arrows *) data;
+  GtkCList *clist = GTK_CLIST(packet_list);
   int i;
 
   gtk_clist_freeze(clist);
@@ -187,18 +319,13 @@ packet_list_click_column_cb(GtkCList *clist, gint column, gpointer data)
     gtk_widget_hide(col_arrows[i].descend_pm);
   }
 
-  if (column == clist->sort_column) {
-    if (clist->sort_type == GTK_SORT_ASCENDING) {
-      clist->sort_type = GTK_SORT_DESCENDING;
-      gtk_widget_show(col_arrows[column].descend_pm);
-    } else {
-      clist->sort_type = GTK_SORT_ASCENDING;
-      gtk_widget_show(col_arrows[column].ascend_pm);
-    }
+  clist->sort_type = order;
+  if (clist->sort_type == GTK_SORT_ASCENDING) {
+     gtk_widget_show(col_arrows[column].ascend_pm);
+  } else {
+     gtk_widget_show(col_arrows[column].descend_pm);
   }
-  else {
-    clist->sort_type = GTK_SORT_ASCENDING;
-    gtk_widget_show(col_arrows[column].ascend_pm);
+  if (column != clist->sort_column) {
     gtk_clist_set_sort_column(clist, column);
   }
   gtk_clist_thaw(clist);
@@ -206,6 +333,105 @@ packet_list_click_column_cb(GtkCList *clist, gint column, gpointer data)
   gtk_clist_sort(clist);
 }
 
+static GtkJustification
+get_xalign_value (gchar xalign, gboolean right_justify)
+{
+        GtkJustification value;
+
+        switch (xalign) {
+        case COLUMN_XALIGN_RIGHT:
+                value = GTK_JUSTIFY_RIGHT;
+                break;
+        case COLUMN_XALIGN_CENTER:
+                value = GTK_JUSTIFY_CENTER;
+                break;
+        case COLUMN_XALIGN_LEFT:
+                value = GTK_JUSTIFY_LEFT;
+                break;
+        case COLUMN_XALIGN_DEFAULT:
+        default:
+                if (right_justify) {
+                        value = GTK_JUSTIFY_RIGHT;
+                } else {
+                        value = GTK_JUSTIFY_LEFT;
+                }
+                break;
+        }
+
+        return value;
+}
+
+static void
+packet_list_xalign_column (gint col_id, gchar xalign)
+{
+        gboolean right_justify = right_justify_column(col_id);
+        GtkJustification justify = get_xalign_value (xalign, right_justify);
+
+        if ((xalign == COLUMN_XALIGN_LEFT && !right_justify) ||
+            (xalign == COLUMN_XALIGN_RIGHT && right_justify)) {
+                /* Default value selected, save default in the recent settings */
+                xalign = COLUMN_XALIGN_DEFAULT;
+        }
+
+       gtk_clist_set_column_justification (GTK_CLIST(packet_list), col_id, justify);
+        recent_set_column_xalign (col_id, xalign);
+}
+
+void
+packet_list_column_menu_cb (GtkWidget *w _U_, gpointer user_data _U_, COLUMN_SELECTED_E action)
+{
+      gint col_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(packet_list), E_MPACKET_LIST_COL_KEY));
+      gpointer data = g_object_get_data (G_OBJECT(packet_list), E_MPACKET_LIST_COL_ARROWS_KEY);
+
+      switch (action) {
+      case COLUMN_SELECTED_SORT_ASCENDING:
+              packet_list_sort_column (col_id, data, GTK_SORT_ASCENDING);
+              break;
+      case COLUMN_SELECTED_SORT_DESCENDING:
+              packet_list_sort_column (col_id, data, GTK_SORT_DESCENDING);
+              break;
+      case COLUMN_SELECTED_SORT_NONE:
+              packet_list_sort_column (0, data, GTK_SORT_ASCENDING);
+              break;
+      case COLUMN_SELECTED_ALIGN_LEFT:
+              packet_list_xalign_column (col_id, COLUMN_XALIGN_LEFT);
+              break;
+      case COLUMN_SELECTED_ALIGN_CENTER:
+              packet_list_xalign_column (col_id, COLUMN_XALIGN_CENTER);
+              break;
+      case COLUMN_SELECTED_ALIGN_RIGHT:
+              packet_list_xalign_column (col_id, COLUMN_XALIGN_RIGHT);
+              break;
+      case COLUMN_SELECTED_RESIZE:
+              packet_list_resize_column (col_id);
+              break;
+      case COLUMN_SELECTED_RENAME:
+              col_title_edit_dlg (col_id, data);
+              break;
+      case COLUMN_SELECTED_REMOVE:
+              packet_list_remove_column (col_id);
+              break;
+      default:
+              g_assert_not_reached();
+              break;
+      }
+}
+
+static void
+packet_list_click_column_cb (GtkCList *clist,  gint column, gpointer data)
+{
+      GtkWidget *menu;
+      gboolean   right_justify = right_justify_column (column);
+      menus_set_column_align_default (right_justify);
+
+      menu = g_object_get_data (G_OBJECT(popup_menu_object), PM_PACKET_LIST_COL_KEY);
+      g_object_set_data(G_OBJECT(clist), E_MPACKET_LIST_COL_KEY, GINT_TO_POINTER(column));
+      g_object_set_data(G_OBJECT(clist), E_MPACKET_LIST_COL_ARROWS_KEY, data);
+      gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, 1, gtk_get_current_event_time());
+}
+
+
 static void
 packet_list_resize_column_cb(GtkCList *clist _U_, gint column, gint width, gpointer data _U_)
 {
@@ -273,6 +499,37 @@ set_frame_mark(gboolean set, frame_data *frame, gint row)
   }
 }
 
+/* ignore packet */
+static void
+set_frame_ignore(gboolean set, frame_data *frame, gint row)
+{
+  GdkColor fg, bg;
+
+  if (row == -1)
+    return;
+  if (set) {
+    cf_ignore_frame(&cfile, frame);
+    color_t_to_gdkcolor(&fg, &prefs.gui_ignored_fg);
+    color_t_to_gdkcolor(&bg, &prefs.gui_ignored_bg);
+    gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &fg);
+    gtk_clist_set_background(GTK_CLIST(packet_list), row, &bg);
+  } else {
+    const color_filter_t *cfilter = frame->color_filter;
+
+    cf_unignore_frame(&cfile, frame);
+    /* Restore the color from the matching color filter if any */
+    if (cfilter) { /* The packet matches a color filter */
+      color_t_to_gdkcolor(&fg, &cfilter->fg_color);
+      color_t_to_gdkcolor(&bg, &cfilter->bg_color);
+      gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &fg);
+      gtk_clist_set_background(GTK_CLIST(packet_list), row, &bg);
+    } else { /* No color filter match */
+      gtk_clist_set_foreground(GTK_CLIST(packet_list), row, NULL);
+      gtk_clist_set_background(GTK_CLIST(packet_list), row, NULL);
+    }
+  }
+}
+
 /* call this after last set_frame_mark is done */
 static void mark_frames_ready(void)
 {
@@ -328,7 +585,43 @@ void packet_list_unmark_all_frames_cb(GtkWidget *w _U_, gpointer data _U_)
   mark_all_frames(FALSE);
 }
 
-#ifndef NEW_PACKET_LIST
+void packet_list_ignore_frame_cb(GtkWidget *w _U_, gpointer data _U_)
+{
+  if (cfile.current_frame) {
+    set_frame_ignore(!cfile.current_frame->flags.ignored,
+                   cfile.current_frame, cfile.current_row);
+    redissect_packets();
+  }
+}
+
+void packet_list_unignore_all_frames_cb(GtkWidget *w _U_, gpointer data _U_)
+{
+  frame_data *fdata;
+
+  /* XXX: we might need a progressbar here */
+  for (fdata = cfile.plist_start; fdata != NULL; fdata = fdata->next) {
+    set_frame_ignore(FALSE,
+                   fdata,
+                   gtk_clist_find_row_from_data(GTK_CLIST(packet_list), fdata));
+  }
+  redissect_packets();
+}
+
+void packet_list_update_ignored_frames(void)
+{
+  frame_data *fdata;
+
+  if (cfile.plist_start == NULL) return;
+
+  /* XXX: we might need a progressbar here */
+  for (fdata = cfile.plist_start; fdata != NULL; fdata = fdata->next) {
+    if (fdata->flags.ignored)
+      set_frame_ignore(TRUE, fdata,
+                     gtk_clist_find_row_from_data(GTK_CLIST(packet_list),
+                                                  fdata));
+  }
+}
+
 gboolean
 packet_list_get_event_row_column(GtkWidget *w, GdkEventButton *event_button,
                                  gint *row, gint *column)
@@ -337,7 +630,6 @@ packet_list_get_event_row_column(GtkWidget *w, GdkEventButton *event_button,
                                  (gint) event_button->x, (gint) event_button->y,
                                   row, column);
 }
-#endif /* NEW_PACKET_LIST */
 
 static gint
 packet_list_button_pressed_cb(GtkWidget *w, GdkEvent *event, gpointer data _U_)
@@ -437,8 +729,7 @@ GtkWidget *
 packet_list_new(e_prefs *prefs)
 {
     GtkWidget *pkt_scrollw;
-    header_field_info *hfi;
-    gboolean custom_right_justify;
+    GtkJustification justify;
     int      i;
 
     /* Packet list */
@@ -471,26 +762,10 @@ packet_list_new(e_prefs *prefs)
         gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
         gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
 
-        custom_right_justify = FALSE;
-        if (cfile.cinfo.col_fmt[i] == COL_CUSTOM) {
-          hfi = proto_registrar_get_byname(cfile.cinfo.col_custom_field[i]);
-          if ((hfi != NULL) && (hfi->strings == NULL) &&
-              ((hfi->type == FT_BOOLEAN) || (hfi->type == FT_FRAMENUM) ||
-               (((hfi->display == BASE_DEC) || (hfi->display == BASE_OCT)) &&
-                (IS_FT_INT(hfi->type) || IS_FT_UINT(hfi->type)  ||
-                 (hfi->type == FT_INT64) || (hfi->type == FT_UINT64))))) {
-            custom_right_justify = TRUE;
-          }
-        }
-
-        /* Right-justify some special columns. */
-        if (cfile.cinfo.col_fmt[i] == COL_NUMBER ||
-            cfile.cinfo.col_fmt[i] == COL_PACKET_LENGTH ||
-            cfile.cinfo.col_fmt[i] == COL_CUMULATIVE_BYTES ||
-            cfile.cinfo.col_fmt[i] == COL_DCE_CALL ||
-            custom_right_justify)
-            gtk_clist_set_column_justification(GTK_CLIST(packet_list), i,
-                                               GTK_JUSTIFY_RIGHT);
+        /* Justify columns. */
+       justify = get_xalign_value (recent_get_column_xalign(i), right_justify_column(i));
+       if (justify != GTK_JUSTIFY_LEFT)
+            gtk_clist_set_column_justification(GTK_CLIST(packet_list), i, justify);
     }
     g_signal_connect(packet_list, "button_press_event", G_CALLBACK(popup_menu_handler),
                    g_object_get_data(G_OBJECT(popup_menu_object), PM_PACKET_LIST_KEY));
@@ -530,8 +805,10 @@ packet_list_set_column_titles(void)
     GdkPixmap     *ascend_pm, *descend_pm;
     GdkBitmap     *ascend_bm, *descend_bm;
     column_arrows *col_arrows;
+    gchar         *tooltip_text;
+    header_field_info *hfi;
+    GtkTooltips   *tooltips = gtk_tooltips_new ();
     int            i;
-    GtkWidget     *column_lb;
 
     win_style = gtk_widget_get_style(top_level);
     ascend_pm = gdk_pixmap_create_from_xpm_d(top_level->window, &ascend_bm,
@@ -546,10 +823,23 @@ packet_list_set_column_titles(void)
     for (i = 0; i < cfile.cinfo.num_cols; i++) {
         col_arrows[i].table = gtk_table_new(2, 2, FALSE);
         gtk_table_set_col_spacings(GTK_TABLE(col_arrows[i].table), 5);
-        column_lb = gtk_label_new(cfile.cinfo.col_title[i]);
-        gtk_table_attach(GTK_TABLE(col_arrows[i].table), column_lb, 0, 1, 0, 2,
+        col_arrows[i].label = gtk_label_new(cfile.cinfo.col_title[i]);
+        gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].label, 0, 1, 0, 2,
                          GTK_SHRINK, GTK_SHRINK, 0, 0);
-        gtk_widget_show(column_lb);
+        if (cfile.cinfo.col_fmt[i] == COL_CUSTOM) {
+            hfi = proto_registrar_get_byname(cfile.cinfo.col_custom_field[i]);
+           if (hfi->parent != -1) {
+               /* Prefix with protocol name */
+               tooltip_text = g_strdup_printf("%s\n%s (%s)", proto_get_protocol_name(hfi->parent), hfi->name, hfi->abbrev);
+           } else {
+               tooltip_text = g_strdup_printf("%s (%s)", hfi->name, hfi->abbrev);
+           }
+        } else {
+            tooltip_text = g_strdup(col_format_desc(cfile.cinfo.col_fmt[i]));
+        }
+        gtk_tooltips_set_tip(tooltips, col_arrows[i].label, tooltip_text, NULL);
+        g_free(tooltip_text);
+        gtk_widget_show(col_arrows[i].label);
         col_arrows[i].ascend_pm = gtk_image_new_from_pixmap(ascend_pm, ascend_bm);
         gtk_table_attach(GTK_TABLE(col_arrows[i].table),
                          col_arrows[i].ascend_pm,
@@ -924,6 +1214,7 @@ void
 packet_list_recent_write_all(FILE *rf)
 {
   gint col;
+  gchar xalign;
 
   fprintf (rf, "%s:", RECENT_KEY_COL_WIDTH);
   for (col = 0; col < cfile.cinfo.num_cols; col++) {
@@ -933,6 +1224,10 @@ packet_list_recent_write_all(FILE *rf)
        fprintf (rf, " %s,", col_format_to_string(cfile.cinfo.col_fmt[col]));
      }
      fprintf (rf, " %d", GTK_CLIST(packet_list)->column[col].width);
+     xalign = recent_get_column_xalign (col);
+     if (xalign != COLUMN_XALIGN_DEFAULT) {
+       fprintf (rf, ":%c", xalign);
+     }
      if (col != cfile.cinfo.num_cols-1) {
        fprintf (rf, ",");
      }