Introduce experimental new feature: GTK2 tree view based packet list
authorsfisher <sfisher@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 30 Jun 2009 18:05:04 +0000 (18:05 +0000)
committersfisher <sfisher@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 30 Jun 2009 18:05:04 +0000 (18:05 +0000)
To use the GTK2 based packet list, define NEW_PACKET_LIST when compiling.
To do this with gcc, set the environment variable CPPFLAGS to
"-DNEW_PACKET_LIST" and re-run configure.

Many features do not yet work.  This work began with prototypes by Ulf
quite a while back.  I've put quite a bit of work into this so far and
as discussed with a few of the core team members at Sharkfest09 and it was
decided that it would be best to commit what I have so far to allow others to
help work on this.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@28892 f5534014-38df-0310-8fa8-9805f1628bb7

24 files changed:
color_filters.c
file.c
gtk/Makefile.common
gtk/capture_file_dlg.c
gtk/color_dlg.c
gtk/drag_and_drop.c
gtk/font_utils.c
gtk/gtkglobals.h
gtk/main.c
gtk/main.h
gtk/main_packet_list.c
gtk/main_packet_list.h
gtk/main_proto_draw.c
gtk/main_toolbar.c
gtk/menus.c
gtk/new_packet_list.c [new file with mode: 0644]
gtk/new_packet_list.h [new file with mode: 0644]
gtk/packet_list_store.c [new file with mode: 0644]
gtk/packet_list_store.h [new file with mode: 0644]
gtk/prefs_column.c
gtk/prefs_gui.c
gtk/prefs_stream.c
gtk/recent.c
ui_util.h

index 6d72c1928eee162cc7870648b0a1deea0b0e4ec3..4076e22203353453b846ffdbc80336848e7dd9aa 100644 (file)
@@ -431,6 +431,7 @@ color_filters_prime_edt(epan_dissect_t *edt)
        g_slist_foreach(color_filter_list, prime_edt, edt);
 }
 
+#ifndef NEW_PACKET_LIST
 /* Colorize a single packet of the packet list */
 color_filter_t *
 color_filters_colorize_packet(gint row, epan_dissect_t *edt)
@@ -448,7 +449,9 @@ color_filters_colorize_packet(gint row, epan_dissect_t *edt)
                  (colorf->c_colorfilter != NULL) &&
                  dfilter_apply_edt(colorf->c_colorfilter, edt)) {
                     /* this is the filter to use, apply it to the packet list */
+#ifndef NEW_PACKET_LIST
                     packet_list_set_colors(row, &(colorf->fg_color), &(colorf->bg_color));
+#endif
                     return colorf;
             }
             curr = g_slist_next(curr);
@@ -457,6 +460,7 @@ color_filters_colorize_packet(gint row, epan_dissect_t *edt)
 
     return NULL;
 }
+#endif /* NEW_PACKET_LIST */
 
 /* read filters from the given file */
 /* XXX - Would it make more sense to use GStrings here instead of reallocing
diff --git a/file.c b/file.c
index 1ed059c7615889c65e9a832097d688988bf1a28b..b85931e9a9d8f8655af40d31edd31e768acf7979 100644 (file)
--- a/file.c
+++ b/file.c
 #include <epan/column-utils.h>
 #include <epan/strutil.h>
 
+#ifdef NEW_PACKET_LIST
+#include "gtk/new_packet_list.h"
+#endif
+
 #ifdef HAVE_LIBPCAP
 gboolean auto_scroll_live;
 #endif
@@ -354,9 +358,14 @@ cf_reset_state(capture_file *cf)
   cf->finfo_selected = NULL;
 
   /* Clear the packet list. */
+#ifdef NEW_PACKET_LIST
+  new_packet_list_freeze();
+  new_packet_list_thaw();
+#else
   packet_list_freeze();
   packet_list_clear();
   packet_list_thaw();
+#endif
 
   cf->f_datalen = 0;
   cf->count = 0;
@@ -456,7 +465,11 @@ cf_read(capture_file *cf)
   /* Progress so far. */
   progbar_val = 0.0f;
 
+#ifdef NEW_PACKET_LIST
+  new_packet_list_freeze();
+#else
   packet_list_freeze();
+#endif
 
   stop_flag = FALSE;
   g_get_current_time(&start_time);
@@ -501,14 +514,18 @@ cf_read(capture_file *cf)
               if (progbar_quantum > 500000 || displayed_once == 0) {
                   if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->plist_end != NULL) {
                       displayed_once = 1;
+#ifdef NEW_PACKET_LIST
+                     /* XXX - Add move to end function call.  Freeze/thaw if
+                     * necessary. */
+#else
                       packet_list_thaw();
                       if (auto_scroll_live)
                           packet_list_moveto_end();
                       packet_list_freeze();
+#endif /* NEW_PACKET_LIST */
                   }
-              }
-#endif
-
+             }
+#endif /* HAVE_LIBPCAP */
             g_snprintf(status_str, sizeof(status_str),
                        "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
                        file_pos / 1024, size / 1024);
@@ -581,14 +598,20 @@ cf_read(capture_file *cf)
   cf->current_frame = cf->first_displayed;
   cf->current_row = 0;
 
+#ifdef NEW_PACKET_LIST
+  new_packet_list_thaw();
+#else
   packet_list_thaw();
+#endif
 
   cf_callback_invoke(cf_cb_file_read_finished, cf);
 
+#ifndef NEW_PACKET_LIST
   /* If we have any displayed packets to select, select the first of those
      packets by making the first row the selected row. */
   if (cf->first_displayed != NULL)
     packet_list_select_row(0);
+#endif /* NEW_PACKET_LIST */
 
   if(stop_flag) {
     simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
@@ -684,8 +707,12 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
 
   *err = 0;
 
+#ifdef NEW_PACKET_LIST
+  new_packet_list_freeze();
+#else
   packet_list_check_end();
   packet_list_freeze();
+#endif
 
   /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
 
@@ -723,7 +750,11 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
             /* XXX - how to avoid a busy wait? */
             /* Sleep(100); */
         };
-        packet_list_thaw();
+#ifdef NEW_PACKET_LIST
+        new_packet_list_thaw();
+#else
+       packet_list_thaw();
+#endif
         return CF_READ_ABORTED;
     }
     ENDTRY;
@@ -738,9 +769,14 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
   /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
          cf->count, cf->state, *err);*/
 
+#ifdef NEW_PACKET_LIST
+  new_packet_list_thaw();
+#else
   /* XXX - this causes "flickering" of the list */
   packet_list_thaw();
+#endif
 
+#ifndef NEW_PACKET_LIST
   /* moving to the end of the packet list - if the user requested so and
      we have some new packets.
      this doesn't seem to work well with a frozen GTK_Clist, so do this after
@@ -749,6 +785,7 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
      row number. */
   if (newly_displayed_packets && auto_scroll_live && cf->plist_end != NULL)
     packet_list_moveto_end();
+#endif /* NEW_PACKET_LIST */
 
   if (cf->state == FILE_READ_ABORTED) {
     /* Well, the user decided to exit Wireshark.  Return CF_READ_ABORTED
@@ -797,8 +834,12 @@ cf_finish_tail(capture_file *cf, int *err)
     return CF_READ_ERROR;
   }
 
+#ifdef NEW_PACKET_LIST
+  new_packet_list_freeze();
+#else
   packet_list_check_end();
   packet_list_freeze();
+#endif
 
   while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
     if (cf->state == FILE_READ_ABORTED) {
@@ -815,7 +856,11 @@ cf_finish_tail(capture_file *cf, int *err)
     dfilter_free(dfcode);
   }
 
+#ifdef NEW_PACKET_LIST
+  new_packet_list_thaw();
+#else
   packet_list_thaw();
+#endif
 
   if (cf->state == FILE_READ_ABORTED) {
     /* Well, the user decided to abort the read.  We're only called
@@ -827,10 +872,12 @@ cf_finish_tail(capture_file *cf, int *err)
     return CF_READ_ABORTED;
   }
 
+#ifndef NEW_PACKET_LIST
   if (auto_scroll_live && cf->plist_end != NULL)
     /* XXX - this cheats and looks inside the packet list to find the final
        row number. */
     packet_list_moveto_end();
+#endif
 
   /* We're done reading sequentially through the file. */
   cf->state = FILE_READ_DONE;
@@ -1085,8 +1132,14 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
       }
     }
 #endif
+
+#ifdef NEW_PACKET_LIST
+    row = new_packet_list_append(cf->cinfo, fdata);
+#else
     row = packet_list_append(cf->cinfo.col_data, fdata);
+#endif
 
+#ifndef NEW_PACKET_LIST
     /* colorize packet: first apply color filters
      * then if packet is marked, use preferences to overwrite color
      * we do both to make sure that when a packet gets un-marked, the
@@ -1096,6 +1149,7 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
      if (fdata->flags.marked) {
        packet_list_set_colors(row, &prefs.gui_marked_fg, &prefs.gui_marked_bg);
      }
+#endif /* NEW_PACKET_LIST */
 
     /* Set the time of the previous displayed frame to the time of this
        frame. */
@@ -1587,10 +1641,14 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
 
   /* Freeze the packet list while we redo it, so we don't get any
      screen updates while it happens. */
+#ifdef NEW_PACKET_LIST
+  new_packet_list_freeze();
+#else
   packet_list_freeze();
 
   /* Clear it out. */
   packet_list_clear();
+#endif
 
   /* We don't yet know which will be the first and last frames displayed. */
   cf->first_displayed = NULL;
@@ -1731,8 +1789,10 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
   /* We are done redissecting the packet list. */
   cf->redissecting = FALSE;
 
+#ifndef NEW_PACKET_LIST
   /* Re-sort the list using the previously selected order */
   packet_list_set_sort_column();
+#endif
 
   if (redissect) {
     /* Clear out what remains of the visited flags and per-frame data
@@ -1759,7 +1819,11 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
     destroy_progress_dlg(progbar);
 
   /* Unfreeze the packet list. */
+#ifdef NEW_PACKET_LIST
+  new_packet_list_thaw();
+#else
   packet_list_thaw();
+#endif
 
   if (selected_row == -1) {
     /* The selected frame didn't pass the filter. */
@@ -1798,6 +1862,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
     /* There are no frames displayed at all. */
     cf_unselect_packet(cf);
   } else {
+#ifndef NEW_PACKET_LIST
     /* Either the frame that was selected passed the filter, or we've
        found the nearest displayed frame to that frame.  Select it, make
        it the focus row, and make it visible. */
@@ -1806,6 +1871,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
       cf->current_row = -1;
     }
     packet_list_set_selected_row(selected_row);
+#endif /* NEW_PACKET_LIST */
   }
 
   /* Cleanup and release all dfilter resources */
@@ -2617,7 +2683,11 @@ cf_change_time_formats(capture_file *cf)
 
   /* Freeze the packet list while we redo it, so we don't get any
      screen updates while it happens. */
+#ifdef NEW_PACKET_LIST
+  new_packet_list_freeze();
+#else
   packet_list_freeze();
+#endif
 
   /* Update the progress bar when it gets to this value. */
   progbar_nextstep = 0;
@@ -2645,7 +2715,9 @@ cf_change_time_formats(capture_file *cf)
   for (i = 0; i < cf->cinfo.num_cols; i++) {
     if (cf->cinfo.col_fmt[i] == COL_NUMBER)
     {
+#ifndef NEW_PACKET_LIST
       sorted_by_frame_column = (i == packet_list_get_sort_column());
+#endif
       break;
     }
   }
@@ -2703,7 +2775,9 @@ cf_change_time_formats(capture_file *cf)
     /* Find what row this packet is in. */
     if (!sorted_by_frame_column) {
       /* This function is O(N), so we try to avoid using it... */
+#ifndef NEW_PACKET_LIST
       row = packet_list_find_row_from_data(fdata);
+#endif
     } else {
       /* ...which we do by maintaining a count of packets that are
          being displayed (i.e., that have passed the display filter),
@@ -2725,7 +2799,9 @@ cf_change_time_formats(capture_file *cf)
              "command-line-specified" format; update it. */
           cf->cinfo.col_buf[i][0] = '\0';
           col_set_fmt_time(fdata, &cf->cinfo, cf->cinfo.col_fmt[i], i);
+#ifndef NEW_PACKET_LIST
           packet_list_set_text(row, i, cf->cinfo.col_data[i]);
+#endif
         }
       }
     }
@@ -2740,12 +2816,18 @@ cf_change_time_formats(capture_file *cf)
      "command-line-specified" format. */
   for (i = 0; i < cf->cinfo.num_cols; i++) {
     if (col_has_time_fmt(&cf->cinfo, i)) {
+#ifndef NEW_PACKET_LIST
       packet_list_set_time_width(cf->cinfo.col_fmt[i], i);
+#endif
     }
   }
 
   /* Unfreeze the packet list. */
+#ifdef NEW_PACKET_LIST
+  new_packet_list_thaw();
+#else
   packet_list_thaw();
+#endif
 }
 
 typedef struct {
@@ -3091,7 +3173,9 @@ find_packet(capture_file *cf,
   int         count;
   int         err;
   gchar      *err_info;
+#ifndef NEW_PACKET_LIST
   int         row;
+#endif
   float       progbar_val;
   GTimeVal    start_time;
   gchar       status_str[100];
@@ -3248,6 +3332,7 @@ find_packet(capture_file *cf,
   }
 
   if (new_fd != NULL) {
+#ifndef NEW_PACKET_LIST
     /* We found a frame.  Find what row it's in. */
     row = packet_list_find_row_from_data(new_fd);
     if (row == -1) {
@@ -3263,6 +3348,7 @@ find_packet(capture_file *cf,
 
     /* Select that row, make it the focus row, and make it visible. */
     packet_list_set_selected_row(row);
+#endif /* NEW_PACKET_LIST */
     return TRUE;       /* success */
   } else
     return FALSE;      /* failure */
@@ -3272,7 +3358,9 @@ gboolean
 cf_goto_frame(capture_file *cf, guint fnumber)
 {
   frame_data *fdata;
+#ifndef NEW_PACKET_LIST
   int row;
+#endif
 
   for (fdata = cf->plist; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
     ;
@@ -3291,6 +3379,7 @@ cf_goto_frame(capture_file *cf, guint fnumber)
     return FALSE;      /* we failed to go to that packet */
   }
 
+#ifndef NEW_PACKET_LIST
   /* We found that packet, and it's currently being displayed.
      Find what row it's in. */
   row = packet_list_find_row_from_data(fdata);
@@ -3298,6 +3387,7 @@ cf_goto_frame(capture_file *cf, guint fnumber)
 
   /* Select that row, make it the focus row, and make it visible. */
   packet_list_set_selected_row(row);
+#endif /* NEW_PACKET_LIST */
   return TRUE; /* we got to that packet */
 }
 
@@ -3305,7 +3395,9 @@ gboolean
 cf_goto_top_frame(capture_file *cf)
 {
   frame_data *fdata;
+#ifndef NEW_PACKET_LIST
   int row;
+#endif
   frame_data *lowest_fdata = NULL;
 
   for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
@@ -3319,6 +3411,7 @@ cf_goto_top_frame(capture_file *cf)
       return FALSE;
   }
 
+#ifndef NEW_PACKET_LIST
   /* We found that packet, and it's currently being displayed.
      Find what row it's in. */
   row = packet_list_find_row_from_data(lowest_fdata);
@@ -3326,6 +3419,7 @@ cf_goto_top_frame(capture_file *cf)
 
   /* Select that row, make it the focus row, and make it visible. */
   packet_list_set_selected_row(row);
+#endif /* NEW_PACKET_LIST */
   return TRUE; /* we got to that packet */
 }
 
@@ -3333,7 +3427,9 @@ gboolean
 cf_goto_bottom_frame(capture_file *cf)
 {
   frame_data *fdata;
+#ifndef NEW_PACKET_LIST
   int row;
+#endif
   frame_data *highest_fdata = NULL;
 
   for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
@@ -3346,6 +3442,7 @@ cf_goto_bottom_frame(capture_file *cf)
       return FALSE;
   }
 
+#ifndef NEW_PACKET_LIST
   /* We found that packet, and it's currently being displayed.
      Find what row it's in. */
   row = packet_list_find_row_from_data(highest_fdata);
@@ -3353,6 +3450,7 @@ cf_goto_bottom_frame(capture_file *cf)
 
   /* Select that row, make it the focus row, and make it visible. */
   packet_list_set_selected_row(row);
+#endif /* NEW_PACKET_LIST */
   return TRUE; /* we got to that packet */
 }
 
@@ -3387,7 +3485,11 @@ cf_select_packet(capture_file *cf, int row)
   gchar *err_info;
 
   /* Get the frame data struct pointer for this frame */
+#ifdef NEW_PACKET_LIST
+  fdata = new_packet_list_get_row_data(row);
+#else
   fdata = (frame_data *)packet_list_get_row_data(row);
+#endif
 
   if (fdata == NULL) {
     /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
index 4ff9b3c291bf56d0e4d5fbc56e771e1476cd6bbc..e0f31df051b37469102270209ee742dbf7d37fd7 100644 (file)
@@ -87,7 +87,9 @@ WIRESHARK_GTK_SRC = \
        main_toolbar.c  \
        main_welcome.c          \
        mcast_stream.c  \
+       new_packet_list.c       \
        packet_history.c        \
+       packet_list_store.c     \
        packet_win.c    \
        pixmap_save.c   \
        plugins_dlg.c   \
@@ -267,7 +269,9 @@ noinst_HEADERS = \
        mcast_stream.h  \
        mcast_stream_dlg.h \
        mtp3_stat.h     \
+       new_packet_list.h \
        packet_history.h        \
+       packet_list_store.h     \
        packet_win.h    \
        pixmap_save.h   \
        plugins_dlg.h   \
index b4b472ecffaecce7c278f7dc0e2f169224ac8d9f..787a2c6614ab339ec4b30bc3134b8ac8becce0fd 100644 (file)
@@ -690,7 +690,9 @@ file_open_ok_cb(GtkWidget *w, gpointer fs) {
      "get_dirname()" does write over its argument. */
   s = get_dirname(cf_name);
   set_last_open_dir(s);
+#ifndef NEW_PACKET_LIST
   gtk_widget_grab_focus(packet_list);
+#endif
 
   g_free(cf_name);
 }
@@ -716,8 +718,13 @@ file_merge_cmd(GtkWidget *w)
 {
 #if _WIN32
   win32_merge_file(GDK_WINDOW_HWND(top_level->window));
+#ifdef NEW_PACKET_LIST
+  new_packet_list_freeze();
+  new_packet_list_thaw();
+#else
   packet_list_freeze();
   packet_list_thaw();
+#endif /* NEW_PACKET_LIST */
 #else /* _WIN32 */
   GtkWidget    *main_hb, *main_vb, *ft_hb, *ft_lb, *filter_hbox,
                *filter_bt, *filter_te, *prepend_rb, *chrono_rb,
@@ -1020,7 +1027,9 @@ file_merge_ok_cb(GtkWidget *w, gpointer fs) {
      "get_dirname()" does write over its argument. */
   s = get_dirname(tmpname);
   set_last_open_dir(s);
+#ifndef NEW_PACKET_LIST
   gtk_widget_grab_focus(packet_list);
+#endif
 }
 
 static void
@@ -1586,7 +1595,9 @@ file_color_import_ok_cb(GtkWidget *w, gpointer color_filters) {
      "get_dirname()" does write over its argument. */
   s = get_dirname(cf_name);
   set_last_open_dir(s);
+#ifndef NEW_PACKET_LIST
   gtk_widget_grab_focus(packet_list);
+#endif
 
   g_free(cf_name);
 }
index e2bb740cefcc67b8f71b4dd0dce62d77fed8bbd4..6f6b212529d429c491effa1b1efe64aeedad8c85 100644 (file)
@@ -64,8 +64,10 @@ static void color_filter_down_cb(GtkButton *button, gpointer user_data);
 static void remember_selected_row(GtkTreeSelection *sel, gpointer list);
 static void color_destroy_cb(GtkButton *button, gpointer user_data);
 static void destroy_edit_dialog_cb(gpointer filter_arg, gpointer dummy);
+#ifndef NEW_PACKET_LIST
 static void create_new_color_filter(GtkButton *button, const char *filter);
 static void color_new_cb(GtkButton *button, gpointer user_data);
+#endif
 static void color_edit_cb(GtkButton *button, gpointer user_data);
 static gint color_filters_button_cb(GtkWidget *, GdkEventButton *, gpointer);
 static void color_disable_cb(GtkWidget *widget, gboolean user_data);
@@ -400,7 +402,9 @@ colorize_dialog_new (char *filter)
   g_object_set_data(G_OBJECT(color_filters), COLOR_DISABLE_LB, color_disable);
   g_object_set_data(G_OBJECT(color_filters), COLOR_DELETE_LB, color_delete);
   g_object_set_data(G_OBJECT(color_new), COLOR_FILTERS_CL, color_filters);
+#ifndef NEW_PACKET_LIST
   g_signal_connect(color_new, "clicked", G_CALLBACK(color_new_cb), NULL);
+#endif
   g_object_set_data(G_OBJECT(color_edit), COLOR_FILTERS_CL, color_filters);
   g_signal_connect(color_edit, "clicked", G_CALLBACK(color_edit_cb), NULL);
   g_object_set_data(G_OBJECT(color_enable), COLOR_FILTERS_CL, color_filters);
@@ -439,7 +443,9 @@ colorize_dialog_new (char *filter)
   if(filter){
     /* if we specified a preset filter string, open the new dialog and
        set the filter */
+#ifndef NEW_PACKET_LIST
     create_new_color_filter(GTK_BUTTON(color_new), filter);
+#endif
   }
 
   return color_win;
@@ -698,6 +704,7 @@ color_destroy_cb                       (GtkButton       *button _U_,
 }
 
 
+#ifndef NEW_PACKET_LIST
 static void
 select_row(GtkWidget *color_filters, int row)
 {
@@ -713,7 +720,7 @@ select_row(GtkWidget *color_filters, int row)
   sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(color_filters));
   gtk_tree_selection_select_iter(sel, &iter);
 }
-
+#endif
 
 
 /* add a single color filter to the list */
@@ -760,6 +767,7 @@ color_filter_add_cb(color_filter_t *colorf, gpointer user_data)
   gtk_widget_grab_focus(color_filters);
 }
 
+#ifndef NEW_PACKET_LIST
 /* Create a new filter, add it to the list, and pop up an
    "Edit color filter" dialog box to edit it. */
 static void
@@ -791,7 +799,9 @@ create_new_color_filter(GtkButton *button, const char *filter)
 
   gtk_widget_grab_focus(color_filters);
 }
+#endif /* NEW_PACKET_LIST */
 
+#ifndef NEW_PACKET_LIST
 /* User pressed the "New" button: Create a new filter in the list,
    and pop up an "Edit color filter" dialog box to edit it. */
 static void
@@ -799,6 +809,7 @@ color_new_cb(GtkButton *button, gpointer user_data _U_)
 {
   create_new_color_filter(button, "filter");
 }
+#endif
 
 /* User pressed the "Edit" button: Pop up an "Edit color filter" dialog box
  * to edit an existing filter. */
index 1e43326aa330fa1ce86b34be2a7854bb9e8c2d94..f5bd0db1eeb5cfd46d5fee36cabc9dd50168f754 100644 (file)
@@ -194,7 +194,9 @@ dnd_merge_files(int in_file_count, char **in_filenames)
        return;
     }
 
+#ifndef NEW_PACKET_LIST
     gtk_widget_grab_focus(packet_list);
+#endif
 }
 
 /* open/merge the dnd file */
index 456af0b9d0b1078f3a065186a96b8accacbd54bd..e9799aa09aee00cd989a01393d67c206df5972ee 100644 (file)
@@ -274,7 +274,9 @@ user_font_apply(void) {
     }
 
     /* the font(s) seem to be ok */
+#ifndef NEW_PACKET_LIST
     packet_list_set_font(new_r_font);
+#endif
     set_ptree_font_all(new_r_font);
     old_r_font = m_r_font;
     old_b_font = m_b_font;
index 3099a069743218be1030a7787942e168842f28f2..f233d2c9d315fb9ac6f4938902eb0ed98d1304a4 100644 (file)
 /** Application window. */
 extern GtkWidget *top_level;
 
+#ifndef NEW_PACKET_LIST
 /** Packet list pane. */
 extern GtkWidget *packet_list;
+#endif
 
 /** Tree view (packet details) pane. */
 extern GtkWidget *tree_view;
index 44f4eee6dc9e520a355b3c73ad93020b51d04453..35adcdd5b0772cceb0e5d96756397000e8e61796 100644 (file)
 #include <epan/crypt/airpdcap_ws.h>
 #endif
 
+#ifdef NEW_PACKET_LIST
+#include "gtk/new_packet_list.h"
+#endif
+
 /*
  * Files under personal and global preferences directories in which
  * GTK settings for Wireshark are stored.
@@ -490,6 +494,7 @@ selected_ptree_ref_cb(GtkWidget *widget _U_, gpointer data _U_)
     }
 }
 
+#ifndef NEW_PACKET_LIST
 static gchar *
 get_filter_from_packet_list_row_and_column(gpointer data)
 {
@@ -513,6 +518,7 @@ match_selected_plist_cb(GtkWidget *w _U_, gpointer data, MATCH_SELECTED_E action
         action,
         get_filter_from_packet_list_row_and_column(data));
 }
+#endif /* NEW_PACKET_LIST */
 
 /* This function allows users to right click in the details window and copy the text
  * information to the operating systems clipboard.
@@ -2524,13 +2530,16 @@ main(int argc, char *argv[])
      is displayed.
 
      XXX - is that still true, with fixed-width columns? */
+#ifndef NEW_PACKET_LIST
   packet_list_set_column_titles();
+#endif
 
   menu_recent_read_finished();
 #ifdef HAVE_LIBPCAP
   menu_auto_scroll_live_changed(auto_scroll_live);
 #endif
 
+#ifndef NEW_PACKET_LIST
   switch (user_font_apply()) {
   case FA_SUCCESS:
       break;
@@ -2549,6 +2558,7 @@ main(int argc, char *argv[])
       recent.gui_zoom_level = 0;
       /* XXX: would it be a good idea to disable zooming (insensitive GUI)? */
   }
+#endif /* NEW_PACKET_LIST */
 
   dnd_init(top_level);
 
@@ -3136,8 +3146,10 @@ main_widgets_show_or_hide(void)
     }
 
     /* workaround for bug in GtkCList to ensure packet list scrollbar is updated */
+#ifndef NEW_PACKET_LIST
     packet_list_freeze ();
-    packet_list_thaw ();
+    packet_list_thaw (); 
+#endif
 }
 
 
@@ -3166,10 +3178,14 @@ static int
 top_level_key_pressed_cb(GtkWidget *w _U_, GdkEventKey *event, gpointer user_data _U_)
 {
     if (event->keyval == GDK_F8) {
+#ifndef NEW_PACKET_LIST
        packet_list_next();
+#endif
        return TRUE;
     } else if (event->keyval == GDK_F7) {
+#ifndef NEW_PACKET_LIST
        packet_list_prev();
+#endif
        return TRUE;
     } else if (event->state & NO_SHIFT_MOD_MASK) {
         return FALSE; /* Skip control, alt, and other modifiers */
@@ -3243,9 +3259,15 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
     filter_tb = filter_toolbar_new();
 
     /* Packet list */
+#ifdef NEW_PACKET_LIST
+    pkt_scrollw = new_packet_list_create();
+    gtk_widget_set_size_request(pkt_scrollw, -1, pl_size);
+    gtk_widget_show_all(pkt_scrollw);
+#else
     pkt_scrollw = packet_list_new(prefs);
     gtk_widget_set_size_request(packet_list, -1, pl_size);
     gtk_widget_show(pkt_scrollw);
+#endif
 
     /* Tree view */
     tv_scrollw = main_tree_view_new(prefs, &tree_view);
@@ -3254,8 +3276,10 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
 
     g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view)),
                    "changed", G_CALLBACK(tree_view_selection_changed_cb), NULL);
+#ifndef NEW_PACKET_LIST
     g_signal_connect(tree_view, "button_press_event", G_CALLBACK(popup_menu_handler),
                    g_object_get_data(G_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY));
+#endif /* NEW_PACKET_LIST */
     gtk_widget_show(tree_view);
 
     /* Byte view. */
@@ -3263,9 +3287,10 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
     gtk_widget_set_size_request(byte_nb_ptr, -1, bv_size);
     gtk_widget_show(byte_nb_ptr);
 
+#ifndef NEW_PACKET_LIST
     g_signal_connect(byte_nb_ptr, "button_press_event", G_CALLBACK(popup_menu_handler),
                    g_object_get_data(G_OBJECT(popup_menu_object), PM_HEXDUMP_KEY));
-
+#endif /* NEW_PACKET_LIST */
 
     /* Panes for the packet list, tree, and byte view */
     main_pane_v1 = gtk_vpaned_new();
@@ -3394,10 +3419,12 @@ void change_configuration_profile (const gchar *profile_name)
    /* Reload list of interfaces on welcome page */
    welcome_if_panel_reload();
 
+#ifndef NEW_PACKET_LIST
    /* Recreate the packet list according to new preferences */
    packet_list_recreate ();
    cfile.cinfo.columns_changed = FALSE; /* Reset value */
    user_font_apply();
+#endif
 }
 
 /** redissect packets and update UI */
index 5dafbf2e195fdcd3f250967153d6f378cb82f1f6..acd5a221f890d7b6ed763cdc35744b5815da8c78 100644 (file)
@@ -159,6 +159,7 @@ extern void copy_selected_plist_cb(GtkWidget *w _U_, gpointer data, COPY_SELECTE
  */
 extern void colorize_selected_ptree_cb(GtkWidget *w, gpointer data, guint8 filt_nr);
 
+#ifndef NEW_PACKET_LIST
 /** User requested one of "Apply as Filter" or "Prepare a Filter" functions
  *  by context menu of packet list.
  *
@@ -167,6 +168,7 @@ extern void colorize_selected_ptree_cb(GtkWidget *w, gpointer data, guint8 filt_
  * @param action the function to use
  */
 extern void match_selected_plist_cb(GtkWidget *widget, gpointer data, MATCH_SELECTED_E action);
+#endif /* NEW_PACKET_LIST */
 
 /** User requested "Quit" by menu or toolbar.
  *
index ab41c902f0bb78809564b050bcac8fc986d099de..9ec04716a1fbcd41af2a695d0d422ca467b628e3 100644 (file)
@@ -26,6 +26,8 @@
 # include "config.h"
 #endif
 
+#ifndef NEW_PACKET_LIST
+
 #include <gtk/gtk.h>
 #include <string.h>
 
@@ -378,6 +380,7 @@ void packet_list_unmark_all_frames_cb(GtkWidget *w _U_, gpointer data _U_)
   mark_all_frames(FALSE);
 }
 
+#ifndef NEW_PACKET_LIST */
 gboolean
 packet_list_get_event_row_column(GtkWidget *w, GdkEventButton *event_button,
                                  gint *row, gint *column)
@@ -386,6 +389,7 @@ 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_)
@@ -988,3 +992,5 @@ packet_list_recent_write_all(FILE *rf)
    }
    fprintf (rf, "\n");
 }
+
+#endif /* NEW_PACKET_LIST */
index 49f2d7e302e9d84df54329ce1121d4b85dec5a20..cc6d1eca9c50531517684bf9d76c7c6c92b86924 100644 (file)
@@ -25,6 +25,8 @@
 #ifndef __PACKET_LIST_H__
 #define __PACKET_LIST_H__
 
+#ifndef NEW_PACKET_LIST
+
 #define RECENT_KEY_COL_WIDTH                "column.width"
 
 /** @file
@@ -140,4 +142,6 @@ extern void packet_list_copy_summary_cb(GtkWidget * w _U_, gpointer data _U_, co
  */
 extern void packet_list_recent_write_all(FILE *rf);
 
+#endif /* NEW_PACKET_LIST */
+
 #endif /* __PACKET_LIST_H__ */
index 83f29145c5ea47b82ab8bc6fdf07d81a84391fe9..4a0b3d9d469438baba1873d81bfaf46f5a734bdf 100644 (file)
@@ -518,8 +518,10 @@ byte_view_button_press_cb(GtkWidget *widget, GdkEvent *event, gpointer data)
 
                case 1:
                        return byte_view_select(widget, event_button);
+#ifndef NEW_PACKET_LIST
                case 3:
                        return popup_menu_handler(widget, event, data);
+#endif
                default:
                        return FALSE;
                }
@@ -588,13 +590,19 @@ add_byte_tab(GtkWidget *byte_nb, const char *name, tvbuff_t *tvb,
   gtk_text_view_set_editable(GTK_TEXT_VIEW(byte_view), FALSE);
   gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(byte_view), FALSE);
   buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(byte_view));
+
+#ifdef NEW_PACKET_LIST
+  style = gtk_widget_get_style(GTK_WIDGET(top_level));
+#else
   style = gtk_widget_get_style(GTK_WIDGET(packet_list));
+ #endif
   gtk_text_buffer_create_tag(buf, "plain", "font-desc", user_font_get_regular(), NULL);
   gtk_text_buffer_create_tag(buf, "reverse",
                              "font-desc", user_font_get_regular(),
                              "foreground-gdk", &style->text[GTK_STATE_SELECTED],
                              "background-gdk", &style->base[GTK_STATE_SELECTED],
                              NULL);
+
   gtk_text_buffer_create_tag(buf, "bold", "font-desc", user_font_get_bold(), NULL);
   g_object_set_data(G_OBJECT(byte_view), E_BYTE_VIEW_TVBUFF_KEY, tvb);
   gtk_container_add(GTK_CONTAINER(byte_scrollw), byte_view);
index 0994171995f3872fb33a7c1428d8be634c5c94f1..a32f004558b8507f4b06e4b06a00043150592f53 100644 (file)
@@ -76,7 +76,10 @@ static GtkToolItem *open_button, *save_button, *close_button, *reload_button;
 static GtkToolItem *print_button, *find_button, *history_forward_button, *history_back_button;
 static GtkToolItem *go_to_button, *go_to_top_button, *go_to_bottom_button;
 static GtkToolItem *display_filter_button;
-static GtkToolItem *zoom_in_button, *zoom_out_button, *zoom_100_button, *colorize_button, *resize_columns_button;
+static GtkToolItem *zoom_in_button, *zoom_out_button, *zoom_100_button, *colorize_button;
+#ifndef NEW_PACKET_LIST
+static GtkToolItem *resize_columns_button;
+#endif
 static GtkToolItem *color_display_button, *prefs_button, *help_button;
 
 #define SAVE_BUTTON_TOOLTIP_TEXT "Save this capture file..."
@@ -202,8 +205,10 @@ void set_toolbar_for_captured_packets(gboolean have_captured_packets) {
                                 have_captured_packets);
         gtk_widget_set_sensitive(GTK_WIDGET(zoom_100_button),
                                 have_captured_packets);        
+#ifndef NEW_PACKET_LIST
         gtk_widget_set_sensitive(GTK_WIDGET(resize_columns_button),
                                 have_captured_packets);
+#endif
         /* XXX - I don't see a reason why this should be done (as it is in the
          * menus) */
         /* gtk_widget_set_sensitive(GTK_WIDGET(color_display_button),
@@ -381,8 +386,10 @@ toolbar_new(void)
     toolbar_item(zoom_100_button, main_tb, 
        GTK_STOCK_ZOOM_100, tooltips, "Zoom 100%", view_zoom_100_cb, NULL);
 
+#ifndef NEW_PACKET_LIST
     toolbar_item(resize_columns_button, main_tb, 
        WIRESHARK_STOCK_RESIZE_COLUMNS, tooltips, "Resize All Columns", packet_list_resize_columns_cb, NULL);
+#endif
 
     toolbar_append_separator(main_tb);
     
index 4cdb10c9a786de3c089bbd93ba089ca47e220d6e..6413d0cabc569975046492de660f2fb5a3ce8eeb 100644 (file)
@@ -492,6 +492,7 @@ static GtkItemFactoryEntry menu_items[] =
     {"/Edit/Find Ne_xt", "<control>N", GTK_MENU_FUNC(find_next_cb), 0, NULL, NULL,},
     {"/Edit/Find Pre_vious", "<control>B", GTK_MENU_FUNC(find_previous_cb), 0, NULL, NULL,},
     {"/Edit/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
+#ifndef NEW_PACKET_LIST
     {"/Edit/_Mark Packet (toggle)", "<control>M", GTK_MENU_FUNC(packet_list_mark_frame_cb),
                        0, NULL, NULL,},
     {"/Edit/Find Next Mark", "<shift><control>N", GTK_MENU_FUNC(find_next_mark_cb),
@@ -503,6 +504,7 @@ static GtkItemFactoryEntry menu_items[] =
     {"/Edit/_Unmark All Packets", "<control>D", GTK_MENU_FUNC(packet_list_unmark_all_frames_cb),
                        0, NULL, NULL,},
     {"/Edit/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
+#endif /* NEW_PACKET_LIST */
     {"/Edit/Set Time Reference (toggle)", "<control>T", GTK_MENU_FUNC(reftime_frame_cb),
                         REFTIME_TOGGLE, "<StockItem>", WIRESHARK_STOCK_TIME,},
     {"/Edit/Find Next Reference", "<alt><shift><control>N", GTK_MENU_FUNC(reftime_frame_cb), REFTIME_FIND_NEXT, NULL, NULL,},
@@ -568,8 +570,10 @@ static GtkItemFactoryEntry menu_items[] =
                              0, "<StockItem>", GTK_STOCK_ZOOM_OUT,},
     {"/View/_Normal Size", "<control>equal", GTK_MENU_FUNC(view_zoom_100_cb),
                              0, "<StockItem>", GTK_STOCK_ZOOM_100,},
+#ifndef NEW_PACKET_LIST
     {"/View/Resize All Columns", "<shift><control>R", GTK_MENU_FUNC(packet_list_resize_columns_cb),
                        0, "<StockItem>", WIRESHARK_STOCK_RESIZE_COLUMNS,},
+#endif /* NEW_PACKET_LIST */
     {"/View/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
     {"/View/E_xpand Subtrees", "<shift>Right", GTK_MENU_FUNC(expand_tree_cb), 0, NULL, NULL,},
     {"/View/_Expand All", "<control>Right", GTK_MENU_FUNC(expand_all_cb),
@@ -623,6 +627,7 @@ static GtkItemFactoryEntry menu_items[] =
     {"/Go/Go to _Corresponding Packet", NULL, GTK_MENU_FUNC(goto_framenum_cb),
                        0, NULL, NULL,},
     {"/Go/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
+ #ifndef NEW_PACKET_LIST
     {"/Go/Previous Packet", "<control>Up",
                              GTK_MENU_FUNC(packet_list_prev), 0, "<StockItem>", GTK_STOCK_GO_UP,},
     {"/Go/Next Packet", "<control>Down",
@@ -631,6 +636,7 @@ static GtkItemFactoryEntry menu_items[] =
                              GTK_MENU_FUNC(goto_top_frame_cb), 0, "<StockItem>", GTK_STOCK_GOTO_TOP,},
     {"/Go/_Last Packet", "<control>End",
                              GTK_MENU_FUNC(goto_bottom_frame_cb), 0, "<StockItem>", GTK_STOCK_GOTO_BOTTOM,},
+#endif /* NEW_PACKET_LIST */
 #ifdef HAVE_LIBPCAP
     {"/_Capture", NULL, NULL, 0, "<Branch>", NULL,},
     {"/Capture/_Interfaces...", "<control>I",
@@ -735,12 +741,15 @@ static int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
 /* packet list popup */
 static GtkItemFactoryEntry packet_list_menu_items[] =
 {
+#ifndef NEW_PACKET_LIST
     {"/Mark Packet (toggle)", NULL, GTK_MENU_FUNC(packet_list_mark_frame_cb), 0, NULL, NULL,},
+#endif /* NEW_PACKET_LIST */
     {"/Set Time Reference (toggle)", NULL, GTK_MENU_FUNC(reftime_frame_cb), REFTIME_TOGGLE, "<StockItem>", WIRESHARK_STOCK_TIME,},
 
     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
 
     {"/Apply as Filter", NULL, NULL, 0, "<Branch>", NULL,},
+#ifndef NEW_PACKET_LIST */
     {"/Apply as Filter/_Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
                        MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
     {"/Apply as Filter/_Not Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
@@ -753,7 +762,6 @@ static GtkItemFactoryEntry packet_list_menu_items[] =
                        MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
     {"/Apply as Filter/... o_r not Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
                        MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
-
     {"/Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL,},
     {"/Prepare a Filter/_Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
                        MATCH_SELECTED_REPLACE, NULL, NULL,},
@@ -767,7 +775,7 @@ static GtkItemFactoryEntry packet_list_menu_items[] =
                        MATCH_SELECTED_AND_NOT, NULL, NULL,},
     {"/Prepare a Filter/... o_r not Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
                        MATCH_SELECTED_OR_NOT, NULL, NULL,},
-
+#endif /* NEW_PACKET_LIST */
     {"/Conversation Filter", NULL, NULL, 0, "<Branch>",NULL,},
     {"/Conversation Filter/Ethernet", NULL, GTK_MENU_FUNC(conversation_cb),
                        CONV_ETHER, NULL, NULL,},
@@ -921,13 +929,14 @@ static GtkItemFactoryEntry packet_list_menu_items[] =
                        0, NULL, NULL,},
 
     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
-
+#ifndef NEW_PACKET_LIST
     {"/Copy", NULL, NULL, 0, "<Branch>", NULL,},
     {"/Copy/Summary (Text)", NULL, GTK_MENU_FUNC(packet_list_copy_summary_cb), CS_TEXT, NULL, NULL,},
     {"/Copy/Summary (CSV)", NULL, GTK_MENU_FUNC(packet_list_copy_summary_cb), CS_CSV, NULL, NULL,},
     {"/Copy/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
     {"/Copy/As Filter", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
                        MATCH_SELECTED_REPLACE|MATCH_SELECTED_COPY_ONLY, NULL, NULL,},
+#endif /* NEW_PACKET_LIST */
     {"/Copy/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
     {"/Copy/Bytes (Offset Hex Text)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_ALLINFO, NULL, NULL,},
     {"/Copy/Bytes (Offset Hex)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_HEXCOLUMNS, NULL, NULL,},
@@ -1594,8 +1603,10 @@ set_menu_sensitivity(GtkItemFactory *ifactory, const gchar *path, gint val)
             }
             gtk_widget_set_sensitive(menu_item, val);
         } else{
+#ifndef NEW_PACKET_LIST
             /* be sure this menu item *is* existing */
             g_assert_not_reached();
+#endif
         }
     }
 
@@ -2254,6 +2265,7 @@ menu_recent_read_finished(void) {
 }
 
 
+#ifndef NEW_PACKET_LIST
 gint
 popup_menu_handler(GtkWidget *widget, GdkEvent *event, gpointer data)
 {
@@ -2332,6 +2344,7 @@ popup_menu_handler(GtkWidget *widget, GdkEvent *event, gpointer data)
     }
     return FALSE;
 }
+#endif /* NEW_PACKET_LIST */
 
 /* Enable or disable menu items based on whether you have a capture file
    you've finished reading and, if you have one, whether it's been saved
diff --git a/gtk/new_packet_list.c b/gtk/new_packet_list.c
new file mode 100644 (file)
index 0000000..a89bc14
--- /dev/null
@@ -0,0 +1,231 @@
+/* new_packet_list.c
+ * Routines to implement a new GTK2 packet list using our custom model
+ * Copyright 2008-2009, Stephen Fisher <stephentfisher@yahoo.com>
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ */
+
+#ifdef NEW_PACKET_LIST
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_STRING_H
+#include "string.h"
+#endif
+
+#include <gtk/gtk.h>
+#include <glib.h>
+
+#include "gui_utils.h"
+#include "packet_list_store.h"
+#include "epan/column_info.h"
+#include "epan/emem.h"
+#include "globals.h"
+#include "gtk/gtkglobals.h"
+#include "gtk/font_utils.h"
+#include "epan/column.h"
+#include "gtk/recent.h"
+#include "gtk/keys.h"
+#include "gtk/menus.h"
+
+static PacketList *packetlist;
+
+static GtkWidget *create_view_and_model(void);
+static guint row_from_iter(GtkTreeIter *iter);
+static void new_packet_list_select_cb(GtkTreeView *tree_view, gpointer data _U_);
+
+GtkWidget *
+new_packet_list_create(void)
+{
+       GtkWidget *view, *scrollwin;
+
+       scrollwin = scrolled_window_new(NULL, NULL);
+
+       view = create_view_and_model();
+
+       gtk_container_add(GTK_CONTAINER(scrollwin), view);
+
+       /* XXX - Implement me
+       g_signal_connect(view, "row-activated",
+                        G_CALLBACK(popup_menu_handler),
+                        g_object_get_data(G_OBJECT(popup_menu_object),
+                                          PM_PACKET_LIST_KEY));
+       g_signal_connect(view, "button_press_event",
+                        G_CALLBACK(new_packet_list_button_pressed_cb), NULL);
+       */
+
+       g_object_set_data(G_OBJECT(popup_menu_object), E_MPACKET_LIST_KEY, view);
+
+       return scrollwin;
+}
+
+guint
+new_packet_list_append(column_info cinfo, frame_data *fdata)
+{
+       gint i;
+       row_data_t *row_data;
+
+       row_data = g_new0(row_data_t, NUM_COL_FMTS+1);
+
+       for(i = 0; i < cfile.cinfo.num_cols; i++) {
+               row_data->col_text[cinfo.col_fmt[i]] =
+                       se_strdup(cinfo.col_data[i]);
+       }
+
+       row_data->fdata = fdata;
+
+       packet_list_append_record(packetlist, row_data);
+
+       g_free(row_data);
+
+       return packetlist->num_rows; /* XXX - Check that this is the right # */
+}
+
+static GtkWidget *
+create_view_and_model(void)
+{
+       GtkTreeViewColumn *col;
+       GtkCellRenderer *renderer;
+       PangoLayout *layout;
+       gint i, col_width;
+
+       packetlist = new_packet_list_new();
+
+       packetlist->view = tree_view_new(GTK_TREE_MODEL(packetlist));
+
+       gtk_tree_view_set_fixed_height_mode(GTK_TREE_VIEW(packetlist->view),
+                                           TRUE);
+
+       g_signal_connect(packetlist->view, "cursor-changed",
+                        G_CALLBACK(new_packet_list_select_cb), NULL);
+
+       /*      g_object_unref(packetlist); */ /* Destroy automatically with view for now */ /* XXX - Messes up freezing & thawing */
+
+       renderer = gtk_cell_renderer_text_new();
+       g_object_set(renderer, "ypad", 0, "font-desc", user_font_get_regular(),
+                    NULL);                  
+
+       for(i = 0; i < cfile.cinfo.num_cols; i++) {
+               col = gtk_tree_view_column_new();
+               gtk_tree_view_column_pack_start(col, renderer, TRUE);
+               gtk_tree_view_column_add_attribute(col, renderer, "text",
+                                                  cfile.cinfo.col_fmt[i]);
+               gtk_tree_view_column_set_title(col, cfile.cinfo.col_title[i]);
+               gtk_tree_view_column_set_sort_column_id(col, i);
+               gtk_tree_view_column_set_resizable(col, TRUE);
+               gtk_tree_view_column_set_sizing(col,GTK_TREE_VIEW_COLUMN_FIXED);
+
+               col_width = recent_get_column_width(i);
+               if(col_width == -1) {
+                       layout = gtk_widget_create_pango_layout(packetlist->view, get_column_width_string(get_column_format(i), i));
+                       pango_layout_get_pixel_size(layout, &col_width, NULL);
+                       gtk_tree_view_column_set_min_width(col, col_width);
+                       g_object_unref(G_OBJECT(layout));
+               }
+
+               gtk_tree_view_append_column(GTK_TREE_VIEW(packetlist->view), col);
+       }
+
+       return packetlist->view;
+}
+
+void
+new_packet_list_freeze(void)
+{
+       /* So we don't lose the model by the time we want to thaw it */
+       g_object_ref(packetlist);
+
+       /* Detach view from model */
+       gtk_tree_view_set_model(GTK_TREE_VIEW(packetlist->view), NULL);
+}
+
+void
+new_packet_list_thaw(void)
+{
+       /* Remove extra reference added by new_packet_list_freeze() */
+       g_object_unref(packetlist);
+
+       /* Re-attach view to the model */
+       gtk_tree_view_set_model(GTK_TREE_VIEW(packetlist->view),
+                               GTK_TREE_MODEL(packetlist));
+}
+
+void
+new_packet_list_resize_columns_cb(GtkWidget *widget _U_, gpointer data _U_)
+{
+       g_warning("*** new_packet_list_resize_columns_cb() not yet implemented.");
+}
+
+void
+new_packet_list_next(void)
+{
+       g_warning("*** new_packet_list_next() not yet implemented.");
+}
+
+void
+new_packet_list_prev(void)
+{
+       g_warning("*** new_packet_list_prev() not yet implemented.");
+}
+
+static void
+new_packet_list_select_cb(GtkTreeView *tree_view, gpointer data _U_)
+{
+       GtkTreeSelection *selection;
+       GtkTreeIter iter;
+       guint row;
+
+       selection = gtk_tree_view_get_selection(tree_view);
+       gtk_tree_selection_get_selected(selection, NULL, &iter);
+
+       /* Remove the hex display tab pages */
+       while(gtk_notebook_get_nth_page(GTK_NOTEBOOK(byte_nb_ptr), 0))
+               gtk_notebook_remove_page(GTK_NOTEBOOK(byte_nb_ptr), 0);
+
+       row = row_from_iter(&iter);
+
+       cf_select_packet(&cfile, row);
+}
+
+frame_data *
+new_packet_list_get_row_data(gint row)
+{
+       PacketListRecord *record;
+
+       record = packetlist->rows[row];
+
+       return record->fdata;
+}
+
+static guint
+row_from_iter(GtkTreeIter *iter)
+{
+       PacketListRecord *record;
+
+       record = iter->user_data;
+
+       return record->pos;
+}
+
+#endif /* NEW_PACKET_LIST */
diff --git a/gtk/new_packet_list.h b/gtk/new_packet_list.h
new file mode 100644 (file)
index 0000000..7f748a9
--- /dev/null
@@ -0,0 +1,43 @@
+/* new_packet_list.h
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ */
+
+#ifndef __NEW_PACKET_LIST_H__
+#define __NEW_PACKET_LIST_H__
+
+#ifdef NEW_PACKET_LIST
+
+#include <gtk/gtk.h>
+
+GtkWidget *new_packet_list_create(void);
+guint new_packet_list_append(column_info cinfo, gpointer fdata);
+void new_packet_list_freeze(void);
+void new_packet_list_thaw(void);
+void new_packet_list_next(void);
+void new_packet_list_prev(void);
+void new_packet_list_resize_columns_cb(GtkWidget *widget _U_, gpointer data _U_);
+gpointer new_packet_list_get_row_data(gint row);
+
+#endif /* NEW_PACKET_LIST */
+
+#endif /* __NEW_PACKET_LIST_H__ */
diff --git a/gtk/packet_list_store.c b/gtk/packet_list_store.c
new file mode 100644 (file)
index 0000000..0263348
--- /dev/null
@@ -0,0 +1,674 @@
+/* packet_list_store.c
+ * Routines to implement a custom GTK+ list model for Wireshark's packet list
+ * Copyright 2008-2009, Stephen Fisher <stephentfisher@yahoo.com>
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ */
+
+/* This code is based on the GTK+ Tree View tutorial at http://scentric.net */
+
+#ifdef NEW_PACKET_LIST
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include <glib.h>
+
+#include "packet_list_store.h"
+#include "globals.h"
+
+static void packet_list_init(PacketList *pkg_tree);
+static void packet_list_class_init(PacketListClass *klass);
+static void packet_list_tree_model_init(GtkTreeModelIface *iface);
+static void packet_list_finalize(GObject *object);
+static GtkTreeModelFlags packet_list_get_flags(GtkTreeModel *tree_model);
+static gint packet_list_get_n_columns(GtkTreeModel *tree_model);
+static GType packet_list_get_column_type(GtkTreeModel *tree_model, gint index);
+static gboolean packet_list_get_iter(GtkTreeModel *tree_model,
+                                    GtkTreeIter *iter, GtkTreePath *path);
+static GtkTreePath *packet_list_get_path(GtkTreeModel *tree_model,
+                                        GtkTreeIter *iter);
+static void packet_list_get_value(GtkTreeModel *tree_model, GtkTreeIter *iter,
+                                 gint column, GValue *value);
+static gboolean packet_list_iter_next(GtkTreeModel *tree_model,
+                                     GtkTreeIter *iter);
+static gboolean packet_list_iter_children(GtkTreeModel *tree_model,
+                                         GtkTreeIter *iter,
+                                         GtkTreeIter *parent);
+static gboolean packet_list_iter_has_child(GtkTreeModel *tree_model _U_,
+                                          GtkTreeIter *iter _U_);
+static gint packet_list_iter_n_children(GtkTreeModel *tree_model,
+                                       GtkTreeIter *iter);
+static gboolean packet_list_iter_nth_child(GtkTreeModel *tree_model,
+                                          GtkTreeIter *iter,
+                                          GtkTreeIter *parent,
+                                          gint n);
+static gboolean packet_list_iter_parent(GtkTreeModel *tree_model _U_,
+                                       GtkTreeIter *iter _U_,
+                                       GtkTreeIter *child _U_);
+
+static gboolean packet_list_sortable_get_sort_column_id(GtkTreeSortable
+                                                       *sortable,
+                                                       gint *sort_col_id,
+                                                       GtkSortType *order);
+static void packet_list_sortable_set_sort_column_id(GtkTreeSortable *sortable,
+                                                   gint sort_col_id,
+                                                   GtkSortType order);
+static void packet_list_sortable_set_sort_func(GtkTreeSortable *sortable,
+                                              gint sort_col_id,
+                                              GtkTreeIterCompareFunc sort_func,
+                                              gpointer user_data,
+                                              GtkDestroyNotify destroy_func);
+static void packet_list_sortable_set_default_sort_func(GtkTreeSortable
+                                                      *sortable,
+                                                      GtkTreeIterCompareFunc
+                                                      sort_func,
+                                                      gpointer user_data,
+                                                      GtkDestroyNotify
+                                                      destroy_func);
+static gboolean packet_list_sortable_has_default_sort_func(GtkTreeSortable
+                                                          *sortable);
+static void packet_list_sortable_init(GtkTreeSortableIface *iface);
+static gint packet_list_compare_records(gint sort_id _U_, PacketListRecord *a,
+                                       PacketListRecord *b);
+static gint packet_list_qsort_compare_func(PacketListRecord **a,
+                                          PacketListRecord **b,
+                                          PacketList *packet_list);
+static void packet_list_resort(PacketList *packet_list);
+
+static GObjectClass *parent_class = NULL;
+
+
+GType
+packet_list_get_type(void)
+{
+       static GType packet_list_type = 0;
+
+       if(packet_list_type == 0) {
+               static const GTypeInfo packet_list_info = {
+                       sizeof(PacketListClass),
+                       NULL, /* base_init */
+                       NULL, /* base_finalize */
+                       (GClassInitFunc) packet_list_class_init,
+                       NULL, /* class finalize */
+                       NULL, /* class_data */
+                       sizeof(PacketList),
+                       0, /* n_preallocs */
+                       (GInstanceInitFunc) packet_list_init,
+                       NULL /* value_table */
+               };
+
+               static const GInterfaceInfo tree_model_info = {
+                       (GInterfaceInitFunc) packet_list_tree_model_init,
+                       NULL,
+                       NULL
+               };
+
+               static const GInterfaceInfo tree_sortable_info = {
+                               (GInterfaceInitFunc) packet_list_sortable_init,
+                               NULL,
+                               NULL
+               };
+
+               /* Register the new derived type with the GObject type system */
+               packet_list_type = g_type_register_static(G_TYPE_OBJECT,
+                                                         "PacketList",
+                                                         &packet_list_info,
+                                                         (GTypeFlags)0);
+
+               g_type_add_interface_static(packet_list_type,
+                                           GTK_TYPE_TREE_MODEL,
+                                           &tree_model_info);
+                                                         
+
+               /* Register our GtkTreeModel interface with the type system */
+               g_type_add_interface_static(packet_list_type,
+                                           GTK_TYPE_TREE_SORTABLE,
+                                           &tree_sortable_info);
+       }
+
+       return packet_list_type;
+}
+
+static void
+packet_list_sortable_init(GtkTreeSortableIface *iface)
+{
+       iface->get_sort_column_id = packet_list_sortable_get_sort_column_id;
+       iface->set_sort_column_id = packet_list_sortable_set_sort_column_id;
+       /* The following three functions are not implemented */
+       iface->set_sort_func = packet_list_sortable_set_sort_func;
+       iface->set_default_sort_func =
+               packet_list_sortable_set_default_sort_func;
+       iface->has_default_sort_func =
+               packet_list_sortable_has_default_sort_func;
+}
+
+static void
+packet_list_class_init(PacketListClass *klass)
+{
+       GObjectClass *object_class;
+
+       parent_class = (GObjectClass*) g_type_class_peek_parent(klass);
+       object_class = (GObjectClass*) klass;
+
+       object_class->finalize = packet_list_finalize;
+}
+
+static void
+packet_list_tree_model_init(GtkTreeModelIface *iface)
+{
+       iface->get_flags = packet_list_get_flags;
+       iface->get_n_columns = packet_list_get_n_columns;
+       iface->get_column_type = packet_list_get_column_type;
+       iface->get_iter = packet_list_get_iter;
+       iface->get_path = packet_list_get_path;
+       iface->get_value = packet_list_get_value;
+       iface->iter_next = packet_list_iter_next;
+       iface->iter_children = packet_list_iter_children;
+       iface->iter_has_child = packet_list_iter_has_child;
+       iface->iter_n_children = packet_list_iter_n_children;
+       iface->iter_nth_child = packet_list_iter_nth_child;
+       iface->iter_parent = packet_list_iter_parent;
+}
+
+/* This is called every time a new packet list object instance is created in
+ * packet_list_new.  Initialize the list structure's fields here. */
+static void
+packet_list_init(PacketList *packet_list)
+{
+       guint i;
+
+       for(i = 0; i <= NUM_COL_FMTS; i++) { /* XXX - Temporary? */
+               packet_list->column_types[i] = G_TYPE_STRING;
+       }
+       
+
+       packet_list->n_columns = NUM_COL_FMTS;
+       packet_list->num_rows = 0;
+       packet_list->rows = NULL;
+
+       packet_list->sort_id = 0; /* defaults to first column for now */
+       packet_list->sort_order = GTK_SORT_ASCENDING;
+
+       packet_list->stamp = g_random_int(); /* To check whether an iter belongs
+                                             * to our model. */
+}
+
+/* This function is called just before a packet list is destroyed.  Free
+ * dynamically allocated memory here. */
+static void
+packet_list_finalize(GObject *object)
+{
+       /* PacketList *packet_list = PACKET_LIST(object); */
+
+       /* XXX - Free all records and free all memory used by the list */
+
+       /* must chain up - finalize parent */
+       (* parent_class->finalize) (object);
+}
+
+static GtkTreeModelFlags
+packet_list_get_flags(GtkTreeModel *tree_model)
+{
+       g_return_val_if_fail(PACKETLIST_IS_LIST(tree_model),
+                            (GtkTreeModelFlags)0);
+
+       return (GTK_TREE_MODEL_LIST_ONLY | GTK_TREE_MODEL_ITERS_PERSIST);
+}
+
+static gint
+packet_list_get_n_columns(GtkTreeModel *tree_model)
+{
+       g_return_val_if_fail(PACKETLIST_IS_LIST(tree_model), 0);
+
+       return PACKET_LIST(tree_model)->n_columns;
+}
+
+static GType
+packet_list_get_column_type(GtkTreeModel *tree_model, gint index)
+{
+       g_return_val_if_fail(PACKETLIST_IS_LIST(tree_model), G_TYPE_INVALID);
+       g_return_val_if_fail(index < PACKET_LIST(tree_model)->n_columns &&
+                            index >= 0, G_TYPE_INVALID);
+
+       return PACKET_LIST(tree_model)->column_types[index];
+}
+
+static gboolean
+packet_list_get_iter(GtkTreeModel *tree_model, GtkTreeIter *iter,
+                    GtkTreePath *path)
+{
+       PacketList *packet_list;
+       PacketListRecord *record;
+       gint *indices, depth;
+       guint n;
+
+       g_assert(PACKETLIST_IS_LIST(tree_model));
+       g_assert(path != NULL);
+
+       packet_list = PACKET_LIST(tree_model);
+
+       indices = gtk_tree_path_get_indices(path);
+       depth = gtk_tree_path_get_depth(path);
+
+       /* we do not allow children since it's just a list */
+       g_assert(depth == 1);
+
+       n = indices[0]; /* the n-th top level row */
+
+       if(n >= packet_list->num_rows)
+               return FALSE;
+
+       record = packet_list->rows[n];
+
+       g_assert(record != NULL);
+       g_assert(record->pos == n);
+
+       /* We simply store a pointer to our custom record in the iter */
+       iter->stamp = packet_list->stamp;
+       iter->user_data = record;
+       iter->user_data2 = NULL;
+       iter->user_data3 = NULL;
+
+       return TRUE;
+}
+
+static GtkTreePath *
+packet_list_get_path(GtkTreeModel *tree_model, GtkTreeIter *iter)
+{
+       GtkTreePath *path;
+       PacketListRecord *record;
+       PacketList *packet_list;
+
+       g_return_val_if_fail(PACKETLIST_IS_LIST(tree_model), NULL);
+       g_return_val_if_fail(iter != NULL, NULL);
+       g_return_val_if_fail(iter->user_data != NULL, NULL);
+
+       packet_list = PACKET_LIST(tree_model);
+
+       record = (PacketListRecord*) iter->user_data;
+
+       path = gtk_tree_path_new();
+       gtk_tree_path_append_index(path, record->pos);
+
+       return path;
+}
+
+static void
+packet_list_get_value(GtkTreeModel *tree_model, GtkTreeIter *iter, gint column,
+                     GValue *value)
+{
+       PacketListRecord *record;
+       PacketList *packet_list;
+
+       g_return_if_fail(PACKETLIST_IS_LIST(tree_model));
+       g_return_if_fail(iter != NULL);
+       g_return_if_fail(column < PACKET_LIST(tree_model)->n_columns);
+
+       g_value_init(value, PACKET_LIST(tree_model)->column_types[column]);
+
+       packet_list = PACKET_LIST(tree_model);
+
+       record = (PacketListRecord*) iter->user_data;
+
+       if(record->pos >= packet_list->num_rows)
+               g_return_if_reached();
+
+       g_value_set_string(value, record->col_text[column]);
+}
+
+/* Takes an iter structure and sets it to point to the next row. */
+static gboolean
+packet_list_iter_next(GtkTreeModel *tree_model, GtkTreeIter *iter)
+{
+       PacketListRecord *record, *nextrecord;
+       PacketList *packet_list;
+
+       g_return_val_if_fail(PACKETLIST_IS_LIST(tree_model), FALSE);
+
+       if(iter == NULL || iter->user_data == NULL)
+               return FALSE;
+
+       packet_list = PACKET_LIST(tree_model);
+
+       record = (PacketListRecord*) iter->user_data;
+
+       /* Is this the last record in the list? */
+       if((record->pos + 1) >= packet_list->num_rows)
+               return FALSE;
+
+       nextrecord = packet_list->rows[(record->pos + 1)];
+
+       g_assert(nextrecord != NULL);
+       g_assert(nextrecord->pos == (record->pos + 1));
+
+       iter->stamp = packet_list->stamp;
+       iter->user_data = nextrecord;
+
+       return TRUE;
+}
+
+static gboolean
+packet_list_iter_children(GtkTreeModel *tree_model, GtkTreeIter *iter,
+                         GtkTreeIter *parent)
+{
+       PacketList *packet_list;
+
+       g_return_val_if_fail(parent == NULL || parent->user_data != NULL,
+                            FALSE);
+
+       /* This is a list, nodes have no children. */
+       if(parent)
+               return FALSE;
+
+       /* parent == NULL is a special case; we need to return the first top-
+        * level row */
+
+       g_return_val_if_fail(PACKETLIST_IS_LIST(tree_model), FALSE);
+
+       packet_list = PACKET_LIST(tree_model);
+
+       /* No rows => no first row */
+       if(packet_list->num_rows == 0)
+               return FALSE;
+
+       /* Set iter to first item in list */
+       iter->stamp = packet_list->stamp;
+       iter->user_data = packet_list->rows[0];
+
+       return TRUE;
+}
+
+static gboolean
+packet_list_iter_has_child(GtkTreeModel *tree_model _U_, GtkTreeIter *iter _U_)
+{
+       return FALSE; /* Lists have no children */
+}
+
+static gint
+packet_list_iter_n_children(GtkTreeModel *tree_model, GtkTreeIter *iter)
+{
+       PacketList *packet_list;
+
+       g_return_val_if_fail(PACKETLIST_IS_LIST(tree_model), -1);
+       g_return_val_if_fail(iter == NULL || iter->user_data != NULL, FALSE);
+
+       packet_list = PACKET_LIST(tree_model);
+
+       /* special case: if iter == NULL, return number of top-level rows */
+       if(!iter)
+               return packet_list->num_rows;
+
+       return 0; /* Lists have zero children */
+}
+
+static gboolean
+packet_list_iter_nth_child(GtkTreeModel *tree_model, GtkTreeIter *iter,
+                          GtkTreeIter *parent, gint n)
+{
+       PacketListRecord *record;
+       PacketList *packet_list;
+
+       g_return_val_if_fail(PACKETLIST_IS_LIST(tree_model), FALSE);
+
+       packet_list = PACKET_LIST(tree_model);
+
+       /* A list only has top-level rows */
+       if(parent)
+               return FALSE;
+
+       /* Special case: if parent == NULL, set iter to n-th
+        * top-level row. */
+       if((guint)n >= packet_list->num_rows)
+               return FALSE;
+
+       record = packet_list->rows[n];
+
+       g_assert(record != NULL);
+       g_assert(record->pos == (guint)n);
+
+       iter->stamp = packet_list->stamp;
+       iter->user_data = record;
+
+       return TRUE;
+}
+
+static gboolean
+packet_list_iter_parent(GtkTreeModel *tree_model _U_, GtkTreeIter *iter _U_,
+                       GtkTreeIter *child _U_)
+{
+       return FALSE; /* No parents since no children in a list */
+}
+
+PacketList *
+new_packet_list_new(void)
+{
+       PacketList *newpacketlist;
+
+       newpacketlist = (PacketList*) g_object_new(PACKETLIST_TYPE_LIST, NULL);
+
+       g_assert(newpacketlist != NULL);
+
+       return newpacketlist;
+}
+
+void
+packet_list_append_record(PacketList *packet_list, row_data_t *row_data)
+{
+       GtkTreeIter iter;
+       GtkTreePath *path;
+       PacketListRecord *newrecord;
+       guint pos;
+       gint i;
+
+       g_return_if_fail(PACKETLIST_IS_LIST(packet_list));
+
+       pos = packet_list->num_rows;
+
+       packet_list->num_rows++;
+
+       packet_list->rows = g_renew(PacketListRecord*, packet_list->rows,
+                                   packet_list->num_rows);
+
+       newrecord = se_alloc0(sizeof(PacketListRecord));
+
+       for(i = 0; i < NUM_COL_FMTS; i++)
+               newrecord->col_text[i] = row_data->col_text[i];
+
+       newrecord->fdata = row_data->fdata;
+
+       packet_list->rows[pos] = newrecord;
+       newrecord->pos = pos;
+
+       /* Inform the tree view and other interested objects (such as tree row
+        * references) that we have inserted a new row and where it was
+        * inserted. */
+       path = gtk_tree_path_new();
+       gtk_tree_path_append_index(path, newrecord->pos);
+
+       packet_list_get_iter(GTK_TREE_MODEL(packet_list), &iter, path);
+
+       gtk_tree_model_row_inserted(GTK_TREE_MODEL(packet_list), path, &iter);
+
+       gtk_tree_path_free(path);
+
+       packet_list_resort(packet_list);
+}
+
+static gboolean
+packet_list_sortable_get_sort_column_id(GtkTreeSortable *sortable,
+                                       gint *sort_col_id,
+                                       GtkSortType *order)
+{
+       PacketList *packet_list;
+
+       g_return_val_if_fail(sortable != NULL, FALSE);
+       g_return_val_if_fail(PACKETLIST_IS_LIST(sortable), FALSE);
+
+       packet_list = PACKET_LIST(sortable);
+
+       if(sort_col_id)
+               *sort_col_id = packet_list->sort_id;
+
+       if(order)
+               *order = packet_list->sort_order;
+
+       return TRUE;
+}
+
+static void
+packet_list_sortable_set_sort_column_id(GtkTreeSortable *sortable,
+                                       gint sort_col_id,
+                                       GtkSortType order)
+{
+       PacketList *packet_list;
+
+       g_return_if_fail(sortable != NULL);
+       g_return_if_fail(PACKETLIST_IS_LIST(sortable));
+
+       packet_list = PACKET_LIST(sortable);
+
+       if(packet_list->sort_id == sort_col_id &&
+          packet_list->sort_order == order)
+               return;
+
+       packet_list->sort_id = sort_col_id;
+       packet_list->sort_order = order;
+
+       packet_list_resort(packet_list);
+
+       /* emit "sort-column-changed" signal to tell any tree views
+        * that the sort column has changed (so the little arrow
+        * in the column header of the sort column is drawn
+        * in the right column) */
+
+       gtk_tree_sortable_sort_column_changed(sortable);
+}
+
+static void
+packet_list_sortable_set_sort_func(GtkTreeSortable *sortable _U_,
+                                  gint sort_col_id _U_,
+                                  GtkTreeIterCompareFunc sort_func _U_,
+                                  gpointer user_data _U_,
+                                  GtkDestroyNotify destroy_func _U_)
+{
+       g_warning("%s is not supported by the PacketList model.\n",
+                 __FUNCTION__);
+}
+
+static void
+packet_list_sortable_set_default_sort_func(GtkTreeSortable *sortable _U_,
+                                          GtkTreeIterCompareFunc sort_func _U_,
+                                          gpointer user_data _U_,
+                                          GtkDestroyNotify destroy_func _U_)
+{
+       g_warning("%s is not supported by the PacketList model.\n",
+                 __FUNCTION__);
+}
+
+static gboolean
+packet_list_sortable_has_default_sort_func(GtkTreeSortable *sortable _U_)
+{
+       return FALSE; /* Since packet_list_sortable_set_sort_func and
+                        set_default_sort_func are not implemented. */
+}
+
+static gint
+packet_list_compare_records(gint sort_id, PacketListRecord *a,
+                           PacketListRecord *b)
+{
+       /* The following is necessary because sort_id is a column number as
+        * seen by the user, whereas the col_text array from a and b is a
+        * column format number. This matches them to each other to get
+        * the right column text. */
+       gchar *a_col_text = a->col_text[cfile.cinfo.col_fmt[sort_id]];
+       gchar *b_col_text = b->col_text[cfile.cinfo.col_fmt[sort_id]];
+
+       if((a_col_text) && (b_col_text))
+               return strcmp(a_col_text, b_col_text);
+
+       if(a_col_text == b_col_text)
+               return 0; /* both are NULL */
+       else
+               return (a_col_text == NULL) ? -1 : 1;
+
+       g_return_val_if_reached(0);
+}
+               
+static gint
+packet_list_qsort_compare_func(PacketListRecord **a, PacketListRecord **b,
+                              PacketList *packet_list)
+{
+       gint ret;
+
+       g_assert((a) && (b) && (packet_list));
+
+       ret = packet_list_compare_records(packet_list->sort_id, *a, *b);
+
+       /* Swap -1 and 1 if sort order is reverse */
+       if(ret != 0 && packet_list->sort_order == GTK_SORT_DESCENDING)
+               ret = (ret < 0) ? 1 : -1;
+
+       return ret;
+}
+
+static void
+packet_list_resort(PacketList *packet_list)
+{
+       GtkTreePath *path;
+       gint *neworder;
+       guint i;
+
+       g_return_if_fail(packet_list != NULL);
+       g_return_if_fail(PACKETLIST_IS_LIST(packet_list));
+
+       if(packet_list->num_rows == 0)
+               return;
+
+       /* resort */
+       g_qsort_with_data(packet_list->rows, packet_list->num_rows,
+                         sizeof(PacketListRecord*),
+                         (GCompareDataFunc) packet_list_qsort_compare_func,
+                         packet_list);
+
+       /* let other objects know about the new order */
+       neworder = g_new0(gint, packet_list->num_rows);
+
+       for(i = 0; i < packet_list->num_rows; ++i) {
+               neworder[i] = (packet_list->rows[i])->pos;
+               (packet_list->rows[i])->pos = i;
+       }
+
+       path = gtk_tree_path_new();
+
+       gtk_tree_model_rows_reordered(GTK_TREE_MODEL(packet_list), path, NULL,
+                                     neworder);
+
+       gtk_tree_path_free(path);
+       g_free(neworder);
+}
+
+#endif /* NEW_PACKET_LIST */
diff --git a/gtk/packet_list_store.h b/gtk/packet_list_store.h
new file mode 100644 (file)
index 0000000..9fa7429
--- /dev/null
@@ -0,0 +1,94 @@
+/* packet_list_store.h
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
+ * USA.
+ */
+
+#ifndef __NEW_PACKET_LIST_H__
+#define __NEW_PACKET_LIST_H__
+
+#ifdef NEW_PACKET_LIST
+
+#include "epan/column_info.h"
+#include "epan/frame_data.h"
+
+#define PACKETLIST_TYPE_LIST (packet_list_get_type())
+#define PACKET_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PACKETLIST_TYPE_LIST, PacketList))
+#define PACKETLIST_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CART((klass), PACKETLIST_TYPE_LIST))
+#define PACKETLIST_IS_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PACKETLIST_TYPE_LIST))
+#define PACKETLIST_IS_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE(klass), PACKETLIST_TYPE_LIST)
+#define PACKETLIST_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PACKETLIST_TYPE_LIST, PacketListClass))
+
+typedef struct {
+       gchar *col_text[NUM_COL_FMTS], *col_filter[NUM_COL_FMTS];
+       frame_data *fdata;
+} row_data_t;
+
+typedef struct _PacketListRecord PacketListRecord;
+typedef struct _PacketList PacketList;
+typedef struct _PacketListClass PacketListClass;
+
+/* PacketListRecord: represents a row */
+struct _PacketListRecord
+
+{
+       frame_data *fdata;
+       gchar *col_text[NUM_COL_FMTS];
+
+       /* admin stuff used by the custom list model */
+       guint pos; /* position within the array */
+};
+
+/* PacketListRecord: Everything for our model implementation. */
+struct _PacketList
+{
+       GObject parent; /* MUST be first */
+
+       guint num_rows;
+       PacketListRecord **rows; /* Dynamically allocated array of pointers to
+                                 * the PacketListRecord structure for each
+                                 * row. */
+
+       gint n_columns;
+       GType column_types[NUM_COL_FMTS];
+       GtkWidget *view; /* XXX - Does this really belong here?? */
+
+       gint sort_id;
+       GtkSortType sort_order;
+
+       gint stamp; /* Random integer to check whether an iter belongs to our
+                    * model. */
+};
+
+
+/* PacketListClass: more boilerplate GObject stuff */
+struct _PacketListClass
+{
+       GObjectClass parent_class;
+};
+
+GType packet_list_list_get_type(void);
+PacketList *new_packet_list_new(void);
+void packet_list_append_record(PacketList *packet_list, row_data_t *row_data);
+
+#endif /* NEW_PACKET_LIST */
+
+#endif /* __NEW_PACKET_LIST_H__ */
index 86f38e811412c39ce42fea0d900ea3dc745c453e..4527008f31fa9d968f8105ef2fb812960a5374f7 100644 (file)
@@ -602,7 +602,9 @@ column_prefs_apply(GtkWidget *w _U_)
 {
     /* Redraw the packet list if the columns were changed */
     if(cfile.cinfo.columns_changed) {
+#ifndef NEW_PACKET_LIST
         packet_list_recreate();
+#endif
         cfile.cinfo.columns_changed = FALSE; /* Reset value */
     }
 }
index f90a8739bd905a4647877d2eb8e60a543c4f98e7..3de2fdd90453ec0fbbc3f1dd10563c97fc11534b 100644 (file)
@@ -502,7 +502,9 @@ gui_prefs_apply(GtkWidget *w _U_ , gboolean redissect)
        toolbar_redraw_all();
 
        set_scrollbar_placement_all();
+#ifndef NEW_PACKET_LIST
        packet_list_set_sel_browse(prefs.gui_plist_sel_browse, FALSE);
+#endif
        set_ptree_sel_browse_all(prefs.gui_ptree_sel_browse);
        set_tree_styles_all();
        main_widgets_rearrange();
index 5368ea4434f1e645f4e31fd149fb979c33d77ffb..8f8a56a0429a08273273ebb716d09b56ca375d1a 100644 (file)
@@ -203,7 +203,9 @@ stream_prefs_apply(GtkWidget *w _U_)
 {
        follow_tcp_redraw_all();
 
+#ifndef NEW_PACKET_LIST
        packet_list_update_marked_frames();
+#endif
 }
 
 void
index 1ac34d5fbe61e566e948136f2b454a68e5ee43d2..47af8b86285e208b6baa432cc7d731e61215c885 100644 (file)
@@ -373,7 +373,9 @@ write_profile_recent(void)
 
   fprintf(rf, "\n# Packet list column pixel widths.\n");
   fprintf(rf, "# Each pair of strings consists of a column format and its pixel width.\n");
+#ifndef NEW_PACKET_LIST
   packet_list_recent_write_all(rf);
+#endif
 
   if (get_last_open_dir() != NULL) {
     fprintf(rf, "\n# Last directory navigated to in File Open dialog.\n");
@@ -515,10 +517,12 @@ read_set_recent_pair_static(gchar *key, gchar *value, void *private_data _U_)
 {
   long num;
   char *p;
+#ifndef NEW_PACKET_LIST
   GList *col_l, *col_l_elt;
   col_width_data *cfmt;
   const gchar *cust_format = col_format_to_string(COL_CUSTOM);
   int cust_format_len = (int) strlen(cust_format);
+#endif
 
   if (strcmp(key, RECENT_KEY_MAIN_TOOLBAR_SHOW) == 0) {
     if (g_ascii_strcasecmp(value, "true") == 0) {
@@ -618,7 +622,9 @@ read_set_recent_pair_static(gchar *key, gchar *value, void *private_data _U_)
       return PREFS_SET_SYNTAX_ERR;     /* number must be positive */
     recent.gui_geometry_main_lower_pane = num;
     recent.has_gui_geometry_main_lower_pane = TRUE;
-  } else if (strcmp(key, RECENT_KEY_COL_WIDTH) == 0) {
+  }
+#ifndef NEW_PACKET_LIST
+  else if (strcmp(key, RECENT_KEY_COL_WIDTH) == 0) {
     col_l = prefs_get_string_list(value);
     if (col_l == NULL)
       return PREFS_SET_SYNTAX_ERR;
@@ -679,6 +685,7 @@ read_set_recent_pair_static(gchar *key, gchar *value, void *private_data _U_)
     }
     prefs_clear_string_list(col_l);
   }
+#endif /* NEW_PACKET_LIST */
 
   return PREFS_SET_OK;
 }
index ac85a65d1bcc4cfc0be7427ed2cde41c552ea2b3..5509dd3110a55f6d8e1af06590c33d736a0cdd96 100644 (file)
--- a/ui_util.h
+++ b/ui_util.h
@@ -54,6 +54,8 @@ extern void pipe_input_set_handler(gint source, gpointer user_data, int *child_p
 
 /* packet_list.c */
 
+#ifndef NEW_PACKET_LIST
+
 /* packet list related functions */
 void packet_list_clear(void);
 void packet_list_freeze(void);
@@ -71,6 +73,7 @@ gint packet_list_get_sort_column(void);
 void packet_list_set_sort_column(void);
 gboolean packet_list_check_end(void);
 
+#endif /* NEW_PACKET_LIST */
 
 #ifdef __cplusplus
 }