Added "Ignore Packet" menu items to the main menu.
[metze/wireshark/wip.git] / gtk / main_packet_list.c
index c503859b03025b5f43aed071f9296ba165017df6..cf7ee439ebb9f5afae4ad49c99ead03987f56a1c 100644 (file)
 # include "config.h"
 #endif
 
+#ifndef NEW_PACKET_LIST
+
 #include <gtk/gtk.h>
+
+#include <stdio.h>
 #include <string.h>
 
 #include <epan/epan.h>
 #include "gtk/packet_history.h"
 #include "gtk/recent.h"
 #include "gtk/main.h"
-#include "gtk/main_menu.h"
+#include "gtk/menus.h"
 #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"
@@ -61,6 +69,7 @@
 
 typedef struct column_arrows {
   GtkWidget *table;
+  GtkWidget *label;
   GtkWidget *ascend_pm;
   GtkWidget *descend_pm;
 } column_arrows;
@@ -70,27 +79,6 @@ static gboolean last_at_end = FALSE;
 
 /* GtkClist compare routine, overrides default to allow numeric comparison */
 
-#define COMPARE_FRAME_NUM()    ((fdata1->num < fdata2->num) ? -1 : \
-                                (fdata1->num > fdata2->num) ? 1 : \
-                                0)
-
-#define COMPARE_NUM(f) ((fdata1->f < fdata2->f) ? -1 : \
-                        (fdata1->f > fdata2->f) ? 1 : \
-                        COMPARE_FRAME_NUM())
-
-/* Compare time stamps.
-   A packet whose time is a reference time is considered to have
-   a lower time stamp than any frame with a non-reference time;
-   if both packets' times are reference times, we compare the
-   times of the packets. */
-#define COMPARE_TS(ts) \
-               ((fdata1->flags.ref_time && !fdata2->flags.ref_time) ? -1 : \
-                (!fdata1->flags.ref_time && fdata2->flags.ref_time) ? 1 : \
-                (fdata1->ts.secs < fdata2->ts.secs) ? -1 : \
-                (fdata1->ts.secs > fdata2->ts.secs) ? 1 : \
-                (fdata1->ts.nsecs < fdata2->ts.nsecs) ? -1 :\
-                (fdata1->ts.nsecs > fdata2->ts.nsecs) ? 1 : \
-                COMPARE_FRAME_NUM())
 static gint
 packet_list_compare(GtkCList *clist, gconstpointer  ptr1, gconstpointer  ptr2)
 {
@@ -121,53 +109,20 @@ packet_list_compare(GtkCList *clist, gconstpointer  ptr1, gconstpointer  ptr2)
   switch (col_fmt) {
 
   case COL_NUMBER:
-    return COMPARE_FRAME_NUM();
-
   case COL_CLS_TIME:
-    switch (timestamp_get_type()) {
-
-    case TS_ABSOLUTE:
-    case TS_ABSOLUTE_WITH_DATE:
-    case TS_EPOCH:
-      return COMPARE_TS(abs_ts);
-
-    case TS_RELATIVE:
-      return COMPARE_TS(rel_ts);
-
-    case TS_DELTA:
-      return COMPARE_TS(del_cap_ts);
-
-    case TS_DELTA_DIS:
-      return COMPARE_TS(del_dis_ts);
-
-    case TS_NOT_SET:
-      return 0;
-    }
-    return 0;
-
   case COL_ABS_TIME:
   case COL_ABS_DATE_TIME:
-    return COMPARE_TS(abs_ts);
-
   case COL_REL_TIME:
-    return COMPARE_TS(rel_ts);
-
   case COL_DELTA_TIME:
-    return COMPARE_TS(del_cap_ts);
-
   case COL_DELTA_TIME_DIS:
-    return COMPARE_TS(del_dis_ts);
-
   case COL_PACKET_LENGTH:
-    return COMPARE_NUM(pkt_len);
-
   case COL_CUMULATIVE_BYTES:
-    return COMPARE_NUM(cum_bytes);
+    return frame_data_compare(fdata1, fdata2, col_fmt);
 
   case COL_CUSTOM:
     hfi = proto_registrar_get_byname(cfile.cinfo.col_custom_field[clist->sort_column]);
     if (hfi == NULL) {
-        return COMPARE_FRAME_NUM();
+        return frame_data_compare(fdata1, fdata2, COL_NUMBER);
     } else if ((hfi->strings == NULL) &&
                (((IS_FT_INT(hfi->type) || IS_FT_UINT(hfi->type)) &&
                  ((hfi->display == BASE_DEC) || (hfi->display == BASE_DEC_HEX) ||
@@ -175,7 +130,7 @@ packet_list_compare(GtkCList *clist, gconstpointer  ptr1, gconstpointer  ptr2)
                 (hfi->type == FT_DOUBLE) || (hfi->type == FT_FLOAT) ||
                 (hfi->type == FT_BOOLEAN) || (hfi->type == FT_FRAMENUM) ||
                 (hfi->type == FT_RELATIVE_TIME))) {
-      
+
       /* Compare numeric column */
       custom_numeric = TRUE;
     }
@@ -184,9 +139,9 @@ packet_list_compare(GtkCList *clist, gconstpointer  ptr1, gconstpointer  ptr2)
     num1 = atof(text1);
     num2 = atof(text2);
     if ((col_fmt == COL_UNRES_SRC_PORT) || (col_fmt == COL_UNRES_DST_PORT) ||
-       (custom_numeric) || 
+        (custom_numeric) ||
         ((num1 != 0) && (num2 != 0) && ((col_fmt == COL_DEF_SRC_PORT) ||
-                                        (col_fmt == COL_RES_SRC_PORT) || 
+                                        (col_fmt == COL_RES_SRC_PORT) ||
                                         (col_fmt == COL_DEF_DST_PORT) ||
                                         (col_fmt == COL_RES_DST_PORT)))) {
 
@@ -197,7 +152,7 @@ packet_list_compare(GtkCList *clist, gconstpointer  ptr1, gconstpointer  ptr2)
       else if (num1 > num2)
         return 1;
       else
-        return COMPARE_FRAME_NUM();
+        return frame_data_compare(fdata1, fdata2, COL_NUMBER);
     }
 
     else {
@@ -207,7 +162,7 @@ packet_list_compare(GtkCList *clist, gconstpointer  ptr1, gconstpointer  ptr2)
         if (text1)
           return 1;
         else
-          return COMPARE_FRAME_NUM();
+          return frame_data_compare(fdata1, fdata2, COL_NUMBER);
       }
 
       if (!text1)
@@ -215,18 +170,146 @@ packet_list_compare(GtkCList *clist, gconstpointer  ptr1, gconstpointer  ptr2)
 
       ret = strcmp(text1, text2);
       if (ret == 0)
-        return COMPARE_FRAME_NUM();
+        return frame_data_compare(fdata1, fdata2, COL_NUMBER);
       else
         return ret;
     }
   }
 }
 
+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);
@@ -236,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);
@@ -255,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_)
 {
@@ -263,9 +440,14 @@ packet_list_resize_column_cb(GtkCList *clist _U_, gint column, gint width, gpoin
 
 /* What to do when a list item is selected/unselected */
 static void
-packet_list_select_cb(GtkWidget *w _U_, gint row, gint col _U_, GdkEventButton *event _U_, gpointer evt _U_) {
+packet_list_select_cb(GtkWidget *w _U_, gint row, gint col _U_, GdkEventButton *event _U_, gpointer evt _U_)
+{
   frame_data *fdata;
 
+  /* Check if already selected */
+  if (cfile.current_frame && cfile.current_row == row)
+    return;
+
   /* Remove the hex display tabbed pages */
   while( (gtk_notebook_get_nth_page( GTK_NOTEBOOK(byte_nb_ptr), 0)))
     gtk_notebook_remove_page( GTK_NOTEBOOK(byte_nb_ptr), 0);
@@ -281,14 +463,15 @@ packet_list_select_cb(GtkWidget *w _U_, gint row, gint col _U_, GdkEventButton *
 }
 
 static void
-packet_list_unselect_cb(GtkWidget *w _U_, gint row _U_, gint col _U_, GdkEventButton *event _U_, gpointer evt _U_) {
-
+packet_list_unselect_cb(GtkWidget *w _U_, gint row _U_, gint col _U_, GdkEventButton *event _U_, gpointer evt _U_)
+{
   cf_unselect_packet(&cfile);
 }
 
 /* mark packets */
 static void
-set_frame_mark(gboolean set, frame_data *frame, gint row) {
+set_frame_mark(gboolean set, frame_data *frame, gint row)
+{
   GdkColor fg, bg;
 
   if (row == -1)
@@ -300,7 +483,7 @@ set_frame_mark(gboolean set, frame_data *frame, gint row) {
     gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &fg);
     gtk_clist_set_background(GTK_CLIST(packet_list), row, &bg);
   } else {
-    color_filter_t *cfilter = frame->color_filter;
+    const color_filter_t *cfilter = frame->color_filter;
 
     cf_unmark_frame(&cfile, frame);
     /* Restore the color from the matching color filter if any */
@@ -316,62 +499,132 @@ 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) {
+static void mark_frames_ready(void)
+{
   file_save_update_dynamics();
   packets_bar_update();
 }
 
-void packet_list_mark_frame_cb(GtkWidget *w _U_, gpointer data _U_) {
+void packet_list_mark_frame_cb(GtkWidget *w _U_, gpointer data _U_)
+{
   if (cfile.current_frame) {
-    /* XXX hum, should better have a "cfile->current_row" here ... */
     set_frame_mark(!cfile.current_frame->flags.marked,
-                  cfile.current_frame,
-                  gtk_clist_find_row_from_data(GTK_CLIST(packet_list),
-                                               cfile.current_frame));
+                   cfile.current_frame, cfile.current_row);
     mark_frames_ready();
   }
 }
 
-static void mark_all_frames(gboolean set) {
+static void mark_all_frames(gboolean set)
+{
   frame_data *fdata;
 
   /* XXX: we might need a progressbar here */
-  for (fdata = cfile.plist; fdata != NULL; fdata = fdata->next) {
+  for (fdata = cfile.plist_start; fdata != NULL; fdata = fdata->next) {
     set_frame_mark(set,
-                  fdata,
-                  gtk_clist_find_row_from_data(GTK_CLIST(packet_list), fdata));
+                   fdata,
+                   gtk_clist_find_row_from_data(GTK_CLIST(packet_list), fdata));
   }
   mark_frames_ready();
 }
 
-void packet_list_update_marked_frames(void) {
+void packet_list_update_marked_frames(void)
+{
   frame_data *fdata;
 
-  if (cfile.plist == NULL) return;
+  if (cfile.plist_start == NULL) return;
 
   /* XXX: we might need a progressbar here */
-  for (fdata = cfile.plist; fdata != NULL; fdata = fdata->next) {
+  for (fdata = cfile.plist_start; fdata != NULL; fdata = fdata->next) {
     if (fdata->flags.marked)
-      set_frame_mark(TRUE,
-                    fdata,
-                    gtk_clist_find_row_from_data(GTK_CLIST(packet_list),
-                                                 fdata));
+      set_frame_mark(TRUE, fdata,
+                     gtk_clist_find_row_from_data(GTK_CLIST(packet_list),
+                                                  fdata));
   }
   mark_frames_ready();
 }
 
-void packet_list_mark_all_frames_cb(GtkWidget *w _U_, gpointer data _U_) {
+void packet_list_mark_all_frames_cb(GtkWidget *w _U_, gpointer data _U_)
+{
   mark_all_frames(TRUE);
 }
 
-void packet_list_unmark_all_frames_cb(GtkWidget *w _U_, gpointer data _U_) {
+void packet_list_unmark_all_frames_cb(GtkWidget *w _U_, gpointer data _U_)
+{
   mark_all_frames(FALSE);
 }
 
+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)
+                                 gint *row, gint *column)
 {
     return gtk_clist_get_selection_info(GTK_CLIST(w),
                                  (gint) event_button->x, (gint) event_button->y,
@@ -391,12 +644,19 @@ packet_list_button_pressed_cb(GtkWidget *w, GdkEvent *event, gpointer data _U_)
         event_button->window == GTK_CLIST(w)->clist_window &&
         gtk_clist_get_selection_info(GTK_CLIST(w), (gint) event_button->x,
                                      (gint) event_button->y, &row, &column)) {
-        frame_data *fdata = (frame_data *)gtk_clist_get_row_data(GTK_CLIST(w),
-                                                                 row);
+        frame_data *fdata = (frame_data *)gtk_clist_get_row_data(GTK_CLIST(w), row);
         set_frame_mark(!fdata->flags.marked, fdata, row);
         mark_frames_ready();
         return TRUE;
     }
+
+    if (event->type == GDK_2BUTTON_PRESS && event_button->button == 1 &&
+        event_button->window == GTK_CLIST(w)->clist_window ) {
+
+        new_window_cb(w);
+        return TRUE;
+    }
+
     return FALSE;
 }
 
@@ -404,79 +664,73 @@ packet_list_button_pressed_cb(GtkWidget *w, GdkEvent *event, gpointer data _U_)
 void
 packet_list_set_sel_browse(gboolean val, gboolean force_set)
 {
-        GtkSelectionMode new_mode;
-        /* initialize with a mode we don't use, so that the mode == new_mode
-         * test will fail the first time */
-        static GtkSelectionMode mode = GTK_SELECTION_MULTIPLE;
-
-        /* Yeah, GTK uses "browse" in the case where we do not, but oh well. I
-         * think "browse" in Wireshark makes more sense than "SINGLE" in GTK+ */
-        new_mode = val ? GTK_SELECTION_SINGLE : GTK_SELECTION_BROWSE;
-
-       if ((mode == new_mode) && !force_set) {
-               /*
-                * The mode isn't changing, so don't do anything.
-                * In particular, don't gratuitiously unselect the
-                * current packet.
-                *
-                * XXX - why do we have to unselect the current packet
-                * ourselves?  The documentation for the GtkCList at
-                *
-                *      http://developer.gnome.org/doc/API/gtk/gtkclist.html
-                *
-                * says "Note that setting the widget's selection mode to
-                * one of GTK_SELECTION_BROWSE or GTK_SELECTION_SINGLE will
-                * cause all the items in the GtkCList to become deselected."
-                */
-               return;
-       }
-
-       if (cfile.finfo_selected)
-               cf_unselect_field(&cfile);
-
-        mode = new_mode;
-        gtk_clist_set_selection_mode(GTK_CLIST(packet_list), mode);
+    GtkSelectionMode new_mode;
+    /* initialize with a mode we don't use, so that the mode == new_mode
+     * test will fail the first time */
+    static GtkSelectionMode mode = GTK_SELECTION_MULTIPLE;
+
+    /* Yeah, GTK uses "browse" in the case where we do not, but oh well. I
+     * think "browse" in Wireshark makes more sense than "SINGLE" in GTK+ */
+    new_mode = val ? GTK_SELECTION_SINGLE : GTK_SELECTION_BROWSE;
+
+    if ((mode == new_mode) && !force_set) {
+        /*
+         * The mode isn't changing, so don't do anything.
+         * In particular, don't gratuitiously unselect the
+         * current packet.
+         *
+         * XXX - why do we have to unselect the current packet
+         * ourselves?  The documentation for the GtkCList at
+         *
+         *      http://developer.gnome.org/doc/API/gtk/gtkclist.html
+         *
+         * says "Note that setting the widget's selection mode to
+         * one of GTK_SELECTION_BROWSE or GTK_SELECTION_SINGLE will
+         * cause all the items in the GtkCList to become deselected."
+         */
+      return;
+    }
+
+    if (cfile.finfo_selected)
+        cf_unselect_field(&cfile);
+
+    mode = new_mode;
+    gtk_clist_set_selection_mode(GTK_CLIST(packet_list), mode);
 }
 
 /* Set the font of the packet list window. */
 void
-packet_list_set_font(PangoFontDescription *font, gboolean saved_column_width)
-{
-       int i;
-       gint col_width;
-        PangoLayout *layout;
-
-       /* Manually set the font so it can be used right away in the
-        * pango_layout_get_pixel_size call below.  The gtk_widget_modify_font
-        * function only takes effect after the widget is displayed. */
-       packet_list->style->font_desc = pango_font_description_copy(font);
-
-        gtk_widget_modify_font(packet_list, font);
-
-       /* Compute default column sizes. */
-       for (i = 0; i < cfile.cinfo.num_cols; i++) {
-               col_width = -1;
-               if (saved_column_width) {
-                       col_width = recent_get_column_width(i);
-               }
-               if (col_width == -1) {
-                       layout = gtk_widget_create_pango_layout(packet_list,
-                          get_column_width_string(get_column_format(i), i));
-                       pango_layout_get_pixel_size(layout, &col_width, NULL);
-                       g_object_unref(G_OBJECT(layout));
-               }
-               gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
-                                          col_width);
-       }
+packet_list_set_font(PangoFontDescription *font)
+{
+    int i;
+    gint col_width;
+    PangoLayout *layout;
+
+    /* Manually set the font so it can be used right away in the
+     * pango_layout_get_pixel_size call below.  The gtk_widget_modify_font
+     * function only takes effect after the widget is displayed. */
+    packet_list->style->font_desc = pango_font_description_copy(font);
+
+    gtk_widget_modify_font(packet_list, font);
+
+    /* Compute default column sizes. */
+    for (i = 0; i < cfile.cinfo.num_cols; i++) {
+        col_width = recent_get_column_width(i);
+        if (col_width == -1) {
+            layout = gtk_widget_create_pango_layout(packet_list, get_column_width_string(get_column_format(i), i));
+            pango_layout_get_pixel_size(layout, &col_width, NULL);
+            g_object_unref(G_OBJECT(layout));
+        }
+        gtk_clist_set_column_width(GTK_CLIST(packet_list), i, col_width);
+    }
 }
 
 GtkWidget *
 packet_list_new(e_prefs *prefs)
 {
     GtkWidget *pkt_scrollw;
-    header_field_info *hfi;
-    gboolean custom_right_justify;
-    int            i;
+    GtkJustification justify;
+    int      i;
 
     /* Packet list */
     pkt_scrollw = scrolled_window_new(NULL, NULL);
@@ -498,7 +752,7 @@ packet_list_new(e_prefs *prefs)
     gtk_container_add(GTK_CONTAINER(pkt_scrollw), packet_list);
 
     packet_list_set_sel_browse(prefs->gui_plist_sel_browse, FALSE);
-    packet_list_set_font(user_font_get_regular(), prefs->gui_geometry_save_column_width);
+    packet_list_set_font(user_font_get_regular());
     gtk_widget_set_name(packet_list, "packet list");
     g_signal_connect(packet_list, "select-row", G_CALLBACK(packet_list_select_cb), NULL);
     g_signal_connect(packet_list, "unselect-row", G_CALLBACK(packet_list_unselect_cb), NULL);
@@ -508,27 +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 ||
-            cfile.cinfo.col_fmt[i] == COL_DCE_CTX ||
-            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));
@@ -548,7 +785,7 @@ packet_list_recreate(void)
 
     prefs.num_cols = g_list_length(prefs.col_list);
 
-    build_column_format_array(&cfile.cinfo, FALSE);
+    build_column_format_array(&cfile.cinfo, prefs.num_cols, FALSE);
 
     pkt_scrollw = packet_list_new(&prefs);
     gtk_widget_show(pkt_scrollw);
@@ -558,7 +795,7 @@ packet_list_recreate(void)
     main_widgets_rearrange();
 
     if(cfile.state != FILE_CLOSED)
-        cf_redissect_packets(&cfile);
+       redissect_packets();
 }
 
 void
@@ -568,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,
@@ -584,18 +823,31 @@ 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);
-        col_arrows[i].ascend_pm = gtk_pixmap_new(ascend_pm, ascend_bm);
+        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,
                          1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
         if (i == 0) {
             gtk_widget_show(col_arrows[i].ascend_pm);
         }
-        col_arrows[i].descend_pm = gtk_pixmap_new(descend_pm, descend_bm);
+        col_arrows[i].descend_pm = gtk_image_new_from_pixmap(descend_pm, descend_bm);
         gtk_table_attach(GTK_TABLE(col_arrows[i].table),
                          col_arrows[i].descend_pm,
                          1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
@@ -604,10 +856,8 @@ packet_list_set_column_titles(void)
         gtk_widget_show(col_arrows[i].table);
     }
     gtk_clist_column_titles_show(GTK_CLIST(packet_list));
-    g_signal_connect(packet_list, "click-column", G_CALLBACK(packet_list_click_column_cb),
-                    col_arrows);
-    g_signal_connect(packet_list, "resize-column", G_CALLBACK(packet_list_resize_column_cb),
-                    NULL);
+    g_signal_connect(packet_list, "click-column", G_CALLBACK(packet_list_click_column_cb), col_arrows);
+    g_signal_connect(packet_list, "resize-column", G_CALLBACK(packet_list_resize_column_cb), NULL);
 }
 
 void
@@ -626,7 +876,8 @@ packet_list_freeze(void)
 }
 
 static void
-packet_list_resize_columns(void) {
+packet_list_resize_columns(void)
+{
     int         i;
     int         progbar_nextstep;
     int         progbar_quantum;
@@ -642,7 +893,7 @@ packet_list_resize_columns(void) {
        bump that value by this amount. */
     progbar_quantum = cfile.cinfo.num_cols/N_PROGBAR_UPDATES;
     /* Progress so far. */
-    progbar_val = 0.0;
+    progbar_val = 0.0f;
 
     progbar_stop_flag = FALSE;
     g_get_current_time(&progbar_start_time);
@@ -742,7 +993,7 @@ void
 packet_list_moveto_end(void)
 {
     gtk_clist_moveto(GTK_CLIST(packet_list),
-                     GTK_CLIST(packet_list)->rows - 1, -1, 1.0, 1.0);
+                     GTK_CLIST(packet_list)->rows - 1, -1, 1.0f, 1.0f);
 }
 
 gboolean
@@ -814,14 +1065,12 @@ packet_list_set_time_width(gint col_fmt, gint column)
     gint      width = -1;
     PangoLayout  *layout;
 
-    if (prefs.gui_geometry_save_column_width) {
-      width = recent_get_column_width(column);
-    }
+    width = recent_get_column_width(column);
     if (width == -1) {
         layout = gtk_widget_create_pango_layout(packet_list,
                      get_column_longest_string(col_fmt));
-       pango_layout_get_pixel_size(layout, &width, NULL);
-       g_object_unref(G_OBJECT(layout));
+        pango_layout_get_pixel_size(layout, &width, NULL);
+        g_object_unref(G_OBJECT(layout));
     }
     gtk_clist_set_column_width(GTK_CLIST(packet_list), column, width);
 }
@@ -835,32 +1084,28 @@ packet_list_get_row_data(gint row)
 
 /* get the first fully visible row number, given row MUST be visible */
 static gint
-packet_list_first_full_visible_row(gint row) {
-
-       g_assert(gtk_clist_row_is_visible(GTK_CLIST(packet_list), row) ==
-        GTK_VISIBILITY_FULL);
+packet_list_first_full_visible_row(gint row)
+{
+        g_assert(gtk_clist_row_is_visible(GTK_CLIST(packet_list), row) == GTK_VISIBILITY_FULL);
 
-       while(gtk_clist_row_is_visible(GTK_CLIST(packet_list), row) ==
-        GTK_VISIBILITY_FULL) {
-               row--;
-       }
+        while(gtk_clist_row_is_visible(GTK_CLIST(packet_list), row) == GTK_VISIBILITY_FULL) {
+                row--;
+        }
 
-       return ++row;
+        return ++row;
 }
 
 /* get the last fully visible row number, given row MUST be visible */
 static gint
-packet_list_last_full_visible_row(gint row) {
-
-       g_assert(gtk_clist_row_is_visible(GTK_CLIST(packet_list), row) ==
-        GTK_VISIBILITY_FULL);
+packet_list_last_full_visible_row(gint row)
+{
+        g_assert(gtk_clist_row_is_visible(GTK_CLIST(packet_list), row) == GTK_VISIBILITY_FULL);
 
-       while(gtk_clist_row_is_visible(GTK_CLIST(packet_list), row) ==
-        GTK_VISIBILITY_FULL) {
-               row++;
-       }
+        while(gtk_clist_row_is_visible(GTK_CLIST(packet_list), row) == GTK_VISIBILITY_FULL) {
+                row++;
+        }
 
-       return --row;
+        return --row;
 }
 
 /* Set the selected row and the focus row of the packet list to the specified
@@ -868,13 +1113,11 @@ packet_list_last_full_visible_row(gint row) {
 void
 packet_list_set_selected_row(gint row)
 {
-       gint visible_rows;
-       gint first_row;
-       gboolean full_visible;
-
+    gint visible_rows;
+    gint first_row;
+    gboolean full_visible;
 
-       full_visible = gtk_clist_row_is_visible(GTK_CLIST(packet_list), row) ==
-        GTK_VISIBILITY_FULL;
+    full_visible = gtk_clist_row_is_visible(GTK_CLIST(packet_list), row) ==  GTK_VISIBILITY_FULL;
 
     /* XXX - why is there no "gtk_clist_set_focus_row()", so that we
      * can make the row for the frame we found the focus row?
@@ -886,34 +1129,32 @@ packet_list_set_selected_row(gint row)
     gtk_clist_select_row(GTK_CLIST(packet_list), row, -1);
 
     if (!full_visible) {
-
         gtk_clist_freeze(GTK_CLIST(packet_list));
 
-        gtk_clist_moveto(GTK_CLIST(packet_list), row, -1, 0.0, 0.0);
-
-               /* even after move still invisible (happens with empty list) -> give up */
-               if(gtk_clist_row_is_visible(GTK_CLIST(packet_list), row) !=
-                       GTK_VISIBILITY_FULL) {
-                       gtk_clist_thaw(GTK_CLIST(packet_list));
-                       return;
-               }
-
-               /* The now selected row will be the first visible row in the list.
-                * This is inconvenient, as the user is usually interested in some
-                * packets *before* the currently selected one too.
-                *
-                * Try to adjust the visible rows, so the currently selected row will
-                * be shown around the first third of the list screen.
-                *
-                * (This won't even do any harm if the current row is the first or the
-                * last in the list) */
-               visible_rows = packet_list_last_full_visible_row(row) - packet_list_first_full_visible_row(row);
-               first_row = row - visible_rows / 3;
+        gtk_clist_moveto(GTK_CLIST(packet_list), row, -1, 0.0f, 0.0f);
 
-               gtk_clist_moveto(GTK_CLIST(packet_list), first_row >= 0 ? first_row : 0, -1, 0.0, 0.0);
+        /* even after move still invisible (happens with empty list) -> give up */
+        if(gtk_clist_row_is_visible(GTK_CLIST(packet_list), row) != GTK_VISIBILITY_FULL) {
+            gtk_clist_thaw(GTK_CLIST(packet_list));
+            return;
+        }
 
-               gtk_clist_thaw(GTK_CLIST(packet_list));
-       }
+        /* The now selected row will be the first visible row in the list.
+         * This is inconvenient, as the user is usually interested in some
+         * packets *before* the currently selected one too.
+         *
+         * Try to adjust the visible rows, so the currently selected row will
+         * be shown around the first third of the list screen.
+         *
+         * (This won't even do any harm if the current row is the first or the
+         * last in the list) */
+        visible_rows = packet_list_last_full_visible_row(row) - packet_list_first_full_visible_row(row);
+        first_row = row - visible_rows / 3;
+
+        gtk_clist_moveto(GTK_CLIST(packet_list), first_row >= 0 ? first_row : 0, -1, 0.0f, 0.0f);
+
+        gtk_clist_thaw(GTK_CLIST(packet_list));
+    }
 }
 
 /* Return the column number that the clist is currently sorted by */
@@ -925,36 +1166,32 @@ packet_list_get_sort_column(void)
 
 void packet_list_copy_summary_cb(GtkWidget * w _U_, gpointer data _U_, copy_summary_type copy_type)
 {
-    gint row;
     gint col;
     gchar* celltext = NULL;
     GString* text;
 
-       if(CS_CSV == copy_type) {
-               text = g_string_new("\"");
-       } else {
-               text = g_string_new("");
-       }
+    if(CS_CSV == copy_type) {
+        text = g_string_new("\"");
+    } else {
+        text = g_string_new("");
+    }
 
     if (cfile.current_frame) {
-        /* XXX hum, should better have a "cfile->current_row" here ... */
-        row = gtk_clist_find_row_from_data(GTK_CLIST(packet_list),
-                               cfile.current_frame);
         for(col = 0; col < cfile.cinfo.num_cols; ++col) {
             if(col != 0) {
-                               if(CS_CSV == copy_type) {
-                                       g_string_append(text,"\",\"");
-                               } else {
-                                       g_string_append_c(text, '\t');
-                               }
+                if(CS_CSV == copy_type) {
+                    g_string_append(text,"\",\"");
+                } else {
+                    g_string_append_c(text, '\t');
+                }
             }
-            if(0 != gtk_clist_get_text(GTK_CLIST(packet_list),row,col,&celltext)) {
+            if(0 != gtk_clist_get_text(GTK_CLIST(packet_list),cfile.current_row,col,&celltext)) {
                 g_string_append(text,celltext);
             }
         }
-               if(CS_CSV == copy_type) {
-                       g_string_append_c(text,'"');
-               }
+        if(CS_CSV == copy_type) {
+            g_string_append_c(text,'"');
+        }
         copy_to_clipboard(text);
     }
     g_string_free(text,TRUE);
@@ -977,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++) {
@@ -986,9 +1224,15 @@ 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, ",");
      }
    }
    fprintf (rf, "\n");
 }
+
+#endif /* NEW_PACKET_LIST */