gtk: fix 32-bit build
[metze/wireshark/wip.git] / ui / gtk / packet_panes.c
index 7e760b6b037652a946116d84f7a94ab6dbd4ef15..a46f4ee7b97bdde4277a59776034e0c6d7eda25d 100644 (file)
@@ -1,8 +1,6 @@
 /* packet_panes.c
  * Routines for GTK+ packet display (packet details and hex dump panes)
  *
- * $Id$
- *
  * Wireshark - Network traffic analyzer
  * By Gerald Combs <gerald@wireshark.org>
  * Copyright 1998 Gerald Combs
 
 #include "config.h"
 
-#include <ctype.h>
-
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
 #include <gtk/gtk.h>
 #include <gdk/gdkkeysyms.h>
 #if GTK_CHECK_VERSION(3,0,0)
@@ -50,9 +38,7 @@
 #include <epan/packet.h>
 #include <epan/charsets.h>
 #include <epan/prefs.h>
-#include <epan/filesystem.h>
-
-#include "../isprint.h"
+#include <wsutil/filesystem.h>
 
 #include "ui/alert_box.h"
 #include "ui/last_open_dir.h"
@@ -62,6 +48,7 @@
 #include "ui/ui_util.h"
 
 #include <wsutil/file_util.h>
+#include <wsutil/str_util.h>
 
 #include "ui/gtk/keys.h"
 #include "ui/gtk/color_utils.h"
 #define E_BYTE_VIEW_TVBUFF_KEY    "byte_view_tvbuff"
 #define E_BYTE_VIEW_START_KEY     "byte_view_start"
 #define E_BYTE_VIEW_END_KEY       "byte_view_end"
-#define E_BYTE_VIEW_MASK_KEY      "byte_view_mask"
+#define E_BYTE_VIEW_MASK_LO_KEY   "byte_view_mask_lo"
+#define E_BYTE_VIEW_MASK_HI_KEY   "byte_view_mask_hi"
 #define E_BYTE_VIEW_MASKLE_KEY    "byte_view_mask_le"
 #define E_BYTE_VIEW_APP_START_KEY "byte_view_app_start"
 #define E_BYTE_VIEW_APP_END_KEY   "byte_view_app_end"
+#define E_BYTE_VIEW_PROTO_START_KEY "byte_view_proto_start"
+#define E_BYTE_VIEW_PROTO_END_KEY   "byte_view_proto_end"
 #define E_BYTE_VIEW_ENCODE_KEY    "byte_view_encode"
 
 /* Get the current text window for the notebook. */
@@ -124,7 +114,7 @@ get_byte_view_data_and_length(GtkWidget *byte_view, guint *data_len)
     if (byte_view_tvb == NULL)
         return NULL;
 
-    if ((*data_len = tvb_length(byte_view_tvb))) {
+    if ((*data_len = tvb_captured_length(byte_view_tvb))) {
         data_ptr = tvb_get_ptr(byte_view_tvb, 0, -1);
         return data_ptr;
     } else
@@ -191,9 +181,45 @@ redraw_packet_bytes_all(void)
     }
 }
 
+/* Expand trees (and any subtrees they may have) whose ett_ shows them as
+ * expanded.
+ * Callers should block calls to expand_tree() to avoid useless recursion.
+ */
+static void
+check_expand_trees(GtkTreeView *tree_view, GtkTreeModel *model, GtkTreePath *path,
+                   GtkTreeIter *iter, gboolean scroll_it, gboolean expand_parent)
+{
+    /* code inspired by gtk_tree_model_foreach_helper */
+
+    field_info *fi;
+
+    do {
+        GtkTreeIter child;
+
+        if (gtk_tree_model_iter_children(model, &child, iter)) {
+            gtk_tree_model_get(model, iter, 1, &fi, -1);
+
+            if (tree_expanded(fi->tree_type)) {
+                if (expand_parent)
+                    gtk_tree_view_expand_row(tree_view, path, FALSE);
+
+                if (scroll_it)
+                     gtk_tree_view_scroll_to_cell(tree_view, path, NULL, TRUE, (prefs.gui_auto_scroll_percentage/100.0f), 0.0f);
+
+                /* try to expand children only when parent is expanded */
+                gtk_tree_path_down(path);
+                check_expand_trees(tree_view, model, path, &child, scroll_it, TRUE);
+                gtk_tree_path_up(path);
+            }
+        }
+
+        gtk_tree_path_next(path);
+    } while (gtk_tree_model_iter_next(model, iter));
+}
+
 static void
 expand_tree(GtkTreeView *tree_view, GtkTreeIter *iter,
-            GtkTreePath *path _U_, gpointer user_data _U_)
+            GtkTreePath *path, gpointer user_data _U_)
 {
     field_info   *finfo;
     GtkTreeModel *model;
@@ -212,10 +238,14 @@ expand_tree(GtkTreeView *tree_view, GtkTreeIter *iter,
      * Nodes with "finfo->tree_type" of -1 have no ett_ value, and
      * are thus presumably leaf nodes and cannot be expanded.
      */
-    if (finfo->tree_type != -1) {
-        g_assert(finfo->tree_type >= 0 &&
-                 finfo->tree_type < num_tree_types);
-        tree_is_expanded[finfo->tree_type] = TRUE;
+    if (finfo->tree_type != -1)
+        tree_expanded_set(finfo->tree_type, TRUE);
+
+    if (finfo->tree_type != -1 && path) {
+        /* Expand any subtrees that the user had left open */
+        g_signal_handlers_block_by_func(tree_view, expand_tree, NULL);
+        check_expand_trees(tree_view, model, path, iter, FALSE, FALSE);
+        g_signal_handlers_unblock_by_func(tree_view, expand_tree, NULL);
     }
 }
 
@@ -234,11 +264,8 @@ collapse_tree(GtkTreeView *tree_view, GtkTreeIter *iter,
      * Nodes with "finfo->tree_type" of -1 have no ett_ value, and
      * are thus presumably leaf nodes and cannot be collapsed.
      */
-    if (finfo->tree_type != -1) {
-        g_assert(finfo->tree_type >= 0 &&
-                 finfo->tree_type < num_tree_types);
-        tree_is_expanded[finfo->tree_type] = FALSE;
-    }
+    if (finfo->tree_type != -1)
+        tree_expanded_set(finfo->tree_type, FALSE);
 }
 
 struct field_lookup_info {
@@ -356,9 +383,6 @@ highlight_field(tvbuff_t *tvb, gint byte, GtkTreeView *tree_view,
         gtk_tree_path_free(path);
     }
 
-    /* Refresh the display so that the expanded trees are visible */
-    proto_tree_draw(tree, GTK_WIDGET(tree_view));
-
     /* select our field's row */
     gtk_tree_selection_select_path(gtk_tree_view_get_selection(tree_view),
                                    first_path);
@@ -500,6 +524,7 @@ add_byte_views(epan_dissect_t *edt, GtkWidget *tree_view,
 {
     GSList *src_le;
     struct data_source *src;
+    char* src_name;
 
     /*
      * Get rid of all the old notebook tabs.
@@ -513,8 +538,10 @@ add_byte_views(epan_dissect_t *edt, GtkWidget *tree_view,
      */
     for (src_le = edt->pi.data_src; src_le != NULL; src_le = src_le->next) {
         src = (struct data_source *)src_le->data;
-        add_byte_tab(byte_nb_ptr, get_data_source_name(src), get_data_source_tvb(src), edt->tree,
+        src_name = get_data_source_name(src);
+        add_byte_tab(byte_nb_ptr, src_name, get_data_source_tvb(src), edt->tree,
                      tree_view);
+        wmem_free(NULL, src_name);
     }
 
     /*
@@ -546,7 +573,7 @@ copy_hex_all_info(GString* copy_buffer, const guint8* data_p, int data_len, gboo
 
         g_string_append_printf(hex_str," %02x",*data_p);
         if(append_text) {
-            g_string_append_printf(char_str,"%c",isprint(*data_p) ? *data_p : '.');
+            g_string_append_printf(char_str,"%c",g_ascii_isprint(*data_p) ? *data_p : '.');
         }
 
         ++data_p;
@@ -592,7 +619,7 @@ copy_hex_bytes_text_only(GString* copy_buffer, const guint8* data_p, int data_le
     gchar to_append;
 
     /* Copy printable characters, newlines, and (horizontal) tabs. */
-    if(isprint(*data_p)) {
+    if(g_ascii_isprint(*data_p)) {
         to_append = *data_p;
     } else if(*data_p==0x0a) {
         to_append = '\n';
@@ -722,7 +749,7 @@ savehex_save_clicked_cb(gchar *file, int start, int end, const guint8 *data_p)
 void
 savehex_cb(GtkWidget * w _U_, gpointer data _U_)
 {
-    win32_export_raw_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level)));
+    win32_export_raw_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level)), &cfile);
     return;
 }
 #else
@@ -806,21 +833,57 @@ savehex_cb(GtkWidget * w _U_, gpointer data _U_)
 
 static void
 packet_hex_update(GtkWidget *bv, const guint8 *pd, int len, int bstart,
-                  int bend, guint32 bmask, int bmask_le,
-                  int astart, int aend, int encoding)
+                  int bend, guint64 bmask, int bmask_le,
+                  int astart, int aend,
+                  int pstart, int pend,
+                  packet_char_enc encoding)
+{
+        bytes_view_set_encoding(BYTES_VIEW(bv), encoding);
+        bytes_view_set_format(BYTES_VIEW(bv), recent.gui_bytes_view);
+        bytes_view_set_data(BYTES_VIEW(bv), pd, len);
+
+        bytes_view_set_highlight_style(BYTES_VIEW(bv), prefs.gui_hex_dump_highlight_style);
+
+        bytes_view_set_highlight(BYTES_VIEW(bv), bstart, bend, bmask, bmask_le);
+        bytes_view_set_highlight_extra(BYTES_VIEW(bv), BYTE_VIEW_HIGHLIGHT_APPENDIX, astart, aend);
+        bytes_view_set_highlight_extra(BYTES_VIEW(bv), BYTE_VIEW_HIGHLIGHT_PROTOCOL, pstart, pend);
+
+        if (bstart != -1 && bend != -1)
+                bytes_view_scroll_to_byte(BYTES_VIEW(bv), bstart);
+        bytes_view_refresh(BYTES_VIEW(bv));
+}
+
+static field_info *
+get_top_finfo(proto_node *node, field_info *finfo)
 {
-       bytes_view_set_encoding(BYTES_VIEW(bv), encoding);
-       bytes_view_set_format(BYTES_VIEW(bv), recent.gui_bytes_view);
-       bytes_view_set_data(BYTES_VIEW(bv), pd, len);
+        proto_node *child;
+        field_info *top;
+
+        if (node == NULL)
+            return NULL;
+        if (PNODE_FINFO(node) == finfo) {
+                top = finfo;
 
-       bytes_view_set_highlight_style(BYTES_VIEW(bv), prefs.gui_hex_dump_highlight_style);
+                while (node && node->parent) {
+                        field_info *fi;
 
-       bytes_view_set_highlight(BYTES_VIEW(bv), bstart, bend, bmask, bmask_le);
-       bytes_view_set_highlight_appendix(BYTES_VIEW(bv), astart, aend);
+                        node = node->parent;
+
+                        fi = PNODE_FINFO(node);
+                        if (fi && fi->ds_tvb == finfo->ds_tvb)
+                                top = fi;
+                }
+
+                return top;
+        }
+
+        for (child = node->first_child; child; child = child->next) {
+                top = get_top_finfo(child, finfo);
+                if (top)
+                        return top;
+        }
 
-       if (bstart != -1 && bend != -1)
-               bytes_view_scroll_to_byte(BYTES_VIEW(bv), bstart);
-       bytes_view_refresh(BYTES_VIEW(bv));
+        return NULL;
 }
 
 void
@@ -831,11 +894,13 @@ packet_hex_print(GtkWidget *bv, const guint8 *pd, frame_data *fd,
     /* to redraw the display if preferences change.             */
 
     int bstart = -1, bend = -1, blen = -1;
-    guint32 bmask = 0x00; int bmask_le = 0;
+    guint64 bmask = 0x00; int bmask_le = 0;
     int astart = -1, aend = -1, alen = -1;
-
+    int pstart = -1, pend = -1, plen = -1;
 
     if (finfo != NULL) {
+        proto_tree *tree = (proto_tree *)g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_TREE_PTR);
+        field_info *top_finfo;
 
         if (cfile.search_in_progress && (cfile.hex || (cfile.string && cfile.packet_data))) {
             /* In the hex view, only highlight the target bytes or string. The entire
@@ -859,11 +924,18 @@ packet_hex_print(GtkWidget *bv, const guint8 *pd, frame_data *fd,
             bstart = finfo->start;
         }
 
-        /* bmask = finfo->hfinfo->bitmask << finfo->hfinfo->bitshift; */ /* (value & mask) >> shift */
+        /* bmask = finfo->hfinfo->bitmask << hfinfo_bitshift(finfo->hfinfo); */ /* (value & mask) >> shift */
         if (finfo->hfinfo) bmask = finfo->hfinfo->bitmask;
         astart = finfo->appendix_start;
         alen = finfo->appendix_length;
 
+        top_finfo = get_top_finfo(tree, finfo);
+        /* it's possible to have top_finfo == finfo, no problem right now */
+        if (top_finfo) {
+            pstart = top_finfo->start;
+            plen = top_finfo->length;
+        }
+
         if (FI_GET_FLAG(finfo, FI_LITTLE_ENDIAN))
             bmask_le = 1;
         else if (FI_GET_FLAG(finfo, FI_BIG_ENDIAN))
@@ -883,18 +955,20 @@ packet_hex_print(GtkWidget *bv, const guint8 *pd, frame_data *fd,
             /* XXX, mask has only 32 bit, later we can store bito&bitc, and use them (which should be faster) */
             if (bitt > 0 && bitt < 32) {
 
-                bmask = ((1 << bitc) - 1) << ((8-bitt) & 7);
+                bmask = ((G_GUINT64_CONSTANT(1) << bitc) - 1) << ((8-bitt) & 7);
                 bmask_le = 0; /* ? */
             }
         }
     }
 
-    if (bstart >= 0 && blen > 0 && (guint)bstart < len) {
+    if (pstart >= 0 && plen > 0 && (guint)pstart < len)
+        pend = pstart + plen;
+
+    if (bstart >= 0 && blen > 0 && (guint)bstart < len)
         bend = bstart + blen;
-    }
-    if (astart >= 0 && alen > 0 && (guint)astart < len) {
+
+    if (astart >= 0 && alen > 0 && (guint)astart < len)
         aend = astart + alen;
-    }
 
     if (bend == -1 && aend != -1) {
         bstart = astart;
@@ -906,22 +980,26 @@ packet_hex_print(GtkWidget *bv, const guint8 *pd, frame_data *fd,
     /* don't exceed the end of available data */
     if (aend != -1 && (guint)aend > len) aend = len;
     if (bend != -1 && (guint)bend > len) bend = len;
+    if (pend != -1 && (guint)pend > len) pend = len;
 
     /* save the information needed to redraw the text */
     /* should we save the fd & finfo pointers instead ?? */
     g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_START_KEY, GINT_TO_POINTER(bstart));
     g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_END_KEY, GINT_TO_POINTER(bend));
-    g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_MASK_KEY, GINT_TO_POINTER(bmask));
+    g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_MASK_LO_KEY, GINT_TO_POINTER((guint32) bmask));
+    g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_MASK_HI_KEY, GINT_TO_POINTER((guint32)(bmask >> 32)));
     g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_MASKLE_KEY, GINT_TO_POINTER(bmask_le));
     g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_APP_START_KEY, GINT_TO_POINTER(astart));
     g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_APP_END_KEY, GINT_TO_POINTER(aend));
+    g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_PROTO_START_KEY, GINT_TO_POINTER(pstart));
+    g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_PROTO_END_KEY, GINT_TO_POINTER(pend));
     g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_ENCODE_KEY,
                       GUINT_TO_POINTER((guint)fd->flags.encoding));
 
     /* stig: it should be done only for bitview... */
     if (recent.gui_bytes_view != BYTES_BITS)
         bmask = 0x00;
-    packet_hex_update(bv, pd, len, bstart, bend, bmask, bmask_le, astart, aend, fd->flags.encoding);
+    packet_hex_update(bv, pd, len, bstart, bend, bmask, bmask_le, astart, aend, pstart, pend, (packet_char_enc)fd->flags.encoding);
 }
 
 void
@@ -931,8 +1009,9 @@ packet_hex_editor_print(GtkWidget *bv, const guint8 *pd, frame_data *fd, int off
     /* to redraw the display if preferences change.             */
 
     int bstart = offset, bend = (bstart != -1) ? offset+1 : -1;
-    guint32 bmask=0; int bmask_le = 0;
+    guint64 bmask=0; int bmask_le = 0;
     int astart = -1, aend = -1;
+    int pstart = -1, pend = -1;
 
     switch (recent.gui_bytes_view) {
     case BYTES_HEX:
@@ -940,7 +1019,7 @@ packet_hex_editor_print(GtkWidget *bv, const guint8 *pd, frame_data *fd, int off
         break;
 
     case BYTES_BITS:
-        bmask = (1 << (7-bitoffset));
+        bmask = (G_GUINT64_CONSTANT(1) << (7-bitoffset));
         break;
 
     default:
@@ -951,14 +1030,17 @@ packet_hex_editor_print(GtkWidget *bv, const guint8 *pd, frame_data *fd, int off
     /* save the information needed to redraw the text */
     g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_START_KEY, GINT_TO_POINTER(bstart));
     g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_END_KEY, GINT_TO_POINTER(bend));
-    g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_MASK_KEY, GINT_TO_POINTER(bmask));
+    g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_MASK_LO_KEY, GINT_TO_POINTER((guint32) bmask));
+    g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_MASK_HI_KEY, GINT_TO_POINTER((guint32)(bmask >> 32)));
     g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_MASKLE_KEY, GINT_TO_POINTER(bmask_le));
     g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_APP_START_KEY, GINT_TO_POINTER(astart));
     g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_APP_END_KEY, GINT_TO_POINTER(aend));
     g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_ENCODE_KEY,
                       GUINT_TO_POINTER((guint)fd->flags.encoding));
+    g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_PROTO_START_KEY, GINT_TO_POINTER(pstart));
+    g_object_set_data(G_OBJECT(bv), E_BYTE_VIEW_PROTO_END_KEY, GINT_TO_POINTER(pend));
 
-    packet_hex_update(bv, pd, len, bstart, bend, bmask, bmask_le, astart, aend, fd->flags.encoding);
+    packet_hex_update(bv, pd, len, bstart, bend, bmask, bmask_le, astart, aend, pstart, pend, (packet_char_enc)fd->flags.encoding);
 }
 
 /*
@@ -968,25 +1050,31 @@ packet_hex_editor_print(GtkWidget *bv, const guint8 *pd, frame_data *fd, int off
 void
 packet_hex_reprint(GtkWidget *bv)
 {
-    int start, end, mask, mask_le, encoding;
+    int start, end, mask_le;
+    packet_char_enc encoding;
     int astart, aend;
+    int pstart, pend;
+    guint64 mask;
     const guint8 *data;
     guint len = 0;
 
     start = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_START_KEY));
     end = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_END_KEY));
-    mask = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_MASK_KEY));
+    mask = (guint64) GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_MASK_HI_KEY)) << 32 |
+                     GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_MASK_LO_KEY));
     mask_le = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_MASKLE_KEY));
     astart = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_APP_START_KEY));
     aend = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_APP_END_KEY));
+    pstart = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_PROTO_START_KEY));
+    pend = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_PROTO_END_KEY));
     data = get_byte_view_data_and_length(bv, &len);
     g_assert(data != NULL);
-    encoding = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_ENCODE_KEY));
+    encoding = (packet_char_enc) GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(bv), E_BYTE_VIEW_ENCODE_KEY));
 
     /* stig: it should be done only for bitview... */
     if (recent.gui_bytes_view != BYTES_BITS)
         mask = 0x00;
-    packet_hex_update(bv, data, len, start, end, mask, mask_le, astart, aend, encoding);
+    packet_hex_update(bv, data, len, start, end, mask, mask_le, astart, aend, pstart, pend, encoding);
 }
 
 /* List of all protocol tree widgets, so we can globally set the selection
@@ -1058,14 +1146,6 @@ void proto_draw_colors_init(void)
     if(colors_ok) {
         return;
     }
-#if 0
-    /* Allocating collor isn't necessary? */
-    get_color(&expert_color_chat);
-    get_color(&expert_color_note);
-    get_color(&expert_color_warn);
-    get_color(&expert_color_error);
-    get_color(&expert_color_foreground);
-#endif
     expert_color_comment_str = gdk_color_to_string(&expert_color_comment);
     expert_color_chat_str = gdk_color_to_string(&expert_color_chat);
     expert_color_note_str = gdk_color_to_string(&expert_color_note);
@@ -1073,9 +1153,6 @@ void proto_draw_colors_init(void)
     expert_color_error_str = gdk_color_to_string(&expert_color_error);
     expert_color_foreground_str = gdk_color_to_string(&expert_color_foreground);
 
-#if 0
-    get_color(&hidden_proto_item);
-#endif
     colors_ok = TRUE;
 }
 
@@ -1230,9 +1307,10 @@ void
 expand_all_tree(proto_tree *protocol_tree _U_, GtkWidget *tree_view)
 {
     int i;
-    for(i=0; i < num_tree_types; i++) {
-        tree_is_expanded[i] = TRUE;
-    }
+
+    for(i=0; i < num_tree_types; i++)
+        tree_expanded_set(i, TRUE);
+
     gtk_tree_view_expand_all(GTK_TREE_VIEW(tree_view));
 }
 
@@ -1240,9 +1318,10 @@ void
 collapse_all_tree(proto_tree *protocol_tree _U_, GtkWidget *tree_view)
 {
     int i;
-    for(i=0; i < num_tree_types; i++) {
-        tree_is_expanded[i] = FALSE;
-    }
+
+    for(i=0; i < num_tree_types; i++)
+        tree_expanded_set(i, FALSE);
+
     gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree_view));
 }
 
@@ -1255,10 +1334,10 @@ tree_view_follow_link(field_info   *fi)
         cf_goto_frame(&cfile, fi->value.value.uinteger);
     }
     if(FI_GET_FLAG(fi, FI_URL) && IS_FT_STRING(fi->hfinfo->type)) {
-        url = fvalue_to_string_repr(&fi->value, FTREPR_DISPLAY, NULL);
+        url = fvalue_to_string_repr(NULL, &fi->value, FTREPR_DISPLAY, fi->hfinfo->display);
         if(url){
             browser_open_url(url);
-            g_free(url);
+            wmem_free(NULL, url);
         }
     }
 }
@@ -1306,37 +1385,29 @@ tree_view_select(GtkWidget *widget, GdkEventButton *event)
     return TRUE;
 }
 
-static gboolean
-expand_finfos(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
-{
-    GtkTreeView *tree_view = (GtkTreeView *) data;
-    field_info *fi;
-
-    if (!gtk_tree_model_iter_has_child(model, iter))
-        return FALSE;
-
-    gtk_tree_model_get(model, iter, 1, &fi, -1);
-
-    g_assert(fi->tree_type >= 0 && fi->tree_type < num_tree_types);
-
-    if (tree_is_expanded[fi->tree_type])
-        gtk_tree_view_expand_to_path(tree_view, path);
-    else
-        gtk_tree_view_collapse_row(tree_view, path);
-    return FALSE;
-}
-
 void
 proto_tree_draw_resolve(proto_tree *protocol_tree, GtkWidget *tree_view, const e_addr_resolve *resolv)
 {
     ProtoTreeModel *model;
+    GtkTreePath *path;
+    GtkTreeIter iter;
 
     model = proto_tree_model_new(protocol_tree, prefs.display_hidden_proto_items);
     if (resolv)
         proto_tree_model_force_resolv(PROTO_TREE_MODEL(model), resolv);
     gtk_tree_view_set_model(GTK_TREE_VIEW(tree_view), GTK_TREE_MODEL(model));
 
-    gtk_tree_model_foreach(GTK_TREE_MODEL(model), expand_finfos, GTK_TREE_VIEW(tree_view));
+    g_signal_handlers_block_by_func(tree_view, expand_tree, NULL);
+
+    /* modified version of gtk_tree_model_foreach */
+    path = gtk_tree_path_new_first();
+    if (gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path))
+        check_expand_trees(GTK_TREE_VIEW(tree_view), GTK_TREE_MODEL(model),
+                              path, &iter, prefs.gui_auto_scroll_on_expand, TRUE);
+    gtk_tree_path_free(path);
+
+    g_signal_handlers_unblock_by_func(tree_view, expand_tree, NULL);
+
     g_object_unref(G_OBJECT(model));
 }
 
@@ -1348,10 +1419,23 @@ proto_tree_draw(proto_tree *protocol_tree, GtkWidget *tree_view)
 }
 
 void
-select_bytes_view (GtkWidget *w _U_, gpointer data _U_, gint view)
+select_bytes_view (GtkWidget *w _U_, gpointer data _U_, bytes_view_type view)
 {
     if (recent.gui_bytes_view != view) {
         recent.gui_bytes_view = view;
         redraw_packet_bytes_all();
     }
 }
+
+/*
+ * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */