merge_all_tap_menus() has been moved to menus.c.
[obnox/wireshark/wip.git] / gtk / tcp_graph.c
index 030932df630085ad14a2500b72d99d7eabbf6951..d89d90b71cc5244d5307c0ac6da9eca64d5dfb81 100644 (file)
 # include "config.h"
 #endif
 
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+
+#if defined(GDK_DISABLE_DEPRECATED)
+# undef GDK_DISABLE_DEPRECATED
+#endif
+
 #include <gtk/gtk.h>
 #include <gdk/gdkkeysyms.h>
-#include <math.h>              /* rint() */
-#include <string.h>
+#if GTK_CHECK_VERSION(3,0,0)
+# include <gdk/gdkkeysyms-compat.h>
+#endif
 
+#include <epan/packet.h>
 #include <epan/ipproto.h>
-#include "globals.h"           /* cfile */
-#include <epan/packet.h>       /* frame_data */
-#include <epan/emem.h>
-#include "simple_dialog.h"
-#include "gui_utils.h"
-#include "color.h"
-#include "compat_macros.h"
 #include <epan/etypes.h>
 #include <epan/ppptypes.h>
-#include "dlg_utils.h"
 #include <epan/epan_dissect.h>
-#include "../stat_menu.h"
-#include "gui_stat_menu.h"
 #include <epan/dissectors/packet-tcp.h>
 #include <epan/address.h>
 #include <epan/tap.h>
 
+#include "../globals.h"
+#include "../simple_dialog.h"
+#include "../stat_menu.h"
+
+#include "gtk/gui_utils.h"
+#include "gtk/dlg_utils.h"
+#include "gtk/gui_stat_menu.h"
+
+#include "gtk/old-gtk-compat.h"
+
 #define TH_FIN    0x01
 #define TH_SYN    0x02
 #define TH_RST    0x04
 #define AXIS_HORIZONTAL                0
 #define AXIS_VERTICAL          1
 
+#define WINDOW_TITLE_LENGTH 256
+
+#define MOUSE_BUTTON_LEFT      1
+#define MOUSE_BUTTON_MIDDLE    2
+#define MOUSE_BUTTON_RIGHT     3
 
 struct segment {
        struct segment *next;
@@ -85,7 +100,7 @@ struct segment {
 
        guint32 th_seq;
        guint32 th_ack;
-       guint th_flags;
+       guint16 th_flags;
        guint32 th_win;   /* make it 32 bits so we can handle some scaling */
        guint32 th_seglen;
        guint16 th_sport;
@@ -114,7 +129,7 @@ typedef enum {
        ELMT_NONE=0,
        ELMT_RECT=1,
        ELMT_LINE=2,
-       ELMT_ARC=3
+       ELMT_ELLIPSE=3
 } ElementType;
 
 struct rect_params {
@@ -126,18 +141,16 @@ struct line_params {
        struct line dim;
 };
 
-struct arc_params {
+struct ellipse_params {
        struct rect dim;
-       gint filled;
-       gint angle1, angle2;
 };
 
 struct element {
        ElementType type;
-       GdkGC *gc;
+       GdkColor *elment_color_p;
        struct segment *parent;
        union {
-               struct arc_params arc;
+               struct ellipse_params ellipse;
                struct rect_params rect;
                struct line_params line;
        } p;
@@ -151,7 +164,11 @@ struct element_list {
 struct axis {
        struct graph *g;                        /* which graph we belong to */
        GtkWidget *drawing_area;
+#if GTK_CHECK_VERSION(2,22,0)
+       cairo_surface_t *surface[2];
+#else
        GdkPixmap *pixmap[2];
+#endif
        int displayed;
 #define AXIS_ORIENTATION       1 << 0
        int flags;
@@ -170,8 +187,8 @@ struct axis {
 #define RMARGIN_WIDTH  30
 
 struct style_tseq_tcptrace {
-       GdkGC *gc_seq;
-       GdkGC *gc_ack[2];
+       GdkColor seq_color;
+       GdkColor ack_color[2];
        int flags;
 };
 
@@ -192,6 +209,12 @@ struct style_rtt {
        int flags;
 };
 
+struct style_wscale {
+       int win_width;
+       int win_height;
+       int flags;
+};
+
 /* style flags */
 #define SEQ_ORIGIN                     0x1
 /* show absolute sequence numbers (not differences from isn) */
@@ -260,10 +283,10 @@ struct magnify {
        int width, height;
        struct zoom zoom;
        struct graph *g;
-#define MAGZOOMS_SAME          (1 << 0)
-#define MAGZOOMS_SAME_RATIO    (1 << 1)
-#define MAGZOOMS_IGNORE                (1 << 31)
-       int flags;
+#define MAGZOOMS_SAME          (1U << 0)
+#define MAGZOOMS_SAME_RATIO    (1U << 1)
+#define MAGZOOMS_IGNORE                (1U << 31)
+       guint flags;
        struct {
                GtkSpinButton *h_zoom, *v_zoom;
        } widget;
@@ -275,19 +298,28 @@ struct graph {
 #define GRAPH_TSEQ_TCPTRACE    1
 #define GRAPH_THROUGHPUT       2
 #define GRAPH_RTT                      3
+#define GRAPH_WSCALE           4
        int type;
 #define GRAPH_DESTROYED                                (1 << 0)
 #define GRAPH_INIT_ON_TYPE_CHANGE      (1 << 1)
        int flags;
        GtkWidget *toplevel;    /* keypress handler needs this */
        GtkWidget *drawing_area;
-        GtkWidget *text;       /* text widget for seg list - probably
-                                 * temporary */
+       GtkWidget *text;        /* text widget for seg list - probably
+                                                * temporary
+                                                */
        PangoFontDescription *font;     /* font used for annotations etc. */
+#if GTK_CHECK_VERSION(3,0,0)
+#else
        GdkGC *fg_gc;
-       GdkGC *bg_gc;
+#endif
+#if GTK_CHECK_VERSION(2,22,0)
+       cairo_surface_t *title_surface;
+       cairo_surface_t *surface[2];
+#else
        GdkPixmap *title_pixmap;
        GdkPixmap *pixmap[2];
+#endif
        int displayed;                  /* which of both pixmaps is on screen right now */
        struct {
                GtkWidget *control_panel;
@@ -325,10 +357,19 @@ struct graph {
                struct style_tseq_tcptrace tseq_tcptrace;
                struct style_tput tput;
                struct style_rtt rtt;
+               struct style_wscale wscale;
        } s;
+       /* This allows keyboard to set the radio button */
+       struct {
+               GtkToggleButton *graph_rtt, *graph_tput, *graph_tseqstevens, *graph_tseqttrace;
+               GtkToggleButton *graph_wscale;
+       } gt;
 };
 
+#if GTK_CHECK_VERSION(3,0,0)
+#else
 static GdkGC *xor_gc = NULL;
+#endif
 static int refnum=0;
 
 #define debug(section) if (debugging & section)
@@ -393,7 +434,7 @@ static void graph_destroy (struct graph * );
 static void graph_initialize_values (struct graph * );
 static void graph_init_sequence (struct graph * );
 static void draw_element_line (struct graph * , struct element * );
-static void draw_element_arc (struct graph * , struct element * );
+static void draw_element_ellipse (struct graph * , struct element * );
 static void graph_display (struct graph * );
 static void graph_pixmaps_create (struct graph * );
 static void graph_pixmaps_switch (struct graph * );
@@ -409,7 +450,7 @@ static void graph_segment_list_get (struct graph * );
 static void graph_segment_list_free (struct graph * );
 static void graph_select_segment (struct graph * , int , int );
 static int line_detect_collision (struct element * , int , int );
-static int arc_detect_collision (struct element * , int , int );
+static int ellipse_detect_collision (struct element * , int , int );
 static void axis_pixmaps_create (struct axis * );
 static void axis_pixmaps_switch (struct axis * );
 static void axis_display (struct axis * );
@@ -422,8 +463,10 @@ static void axis_ticks_up (int * , int * );
 static void axis_ticks_down (int * , int * );
 static void axis_destroy (struct axis * );
 static int get_label_dim (struct axis * , int , double );
+static void toggle_crosshairs (struct graph *g);
 static void toggle_time_origin (struct graph * );
 static void toggle_seq_origin (struct graph * );
+static void restore_initial_graph_view (struct graph *g);
 static void cross_xor (struct graph * , int , int );
 static void cross_draw (struct graph * , int , int );
 static void cross_erase (struct graph * );
@@ -432,15 +475,15 @@ static void magnify_move (struct graph * , int , int );
 static void magnify_destroy (struct graph * );
 static void magnify_draw (struct graph * );
 static void magnify_get_geom (struct graph * , int , int );
-static gint configure_event (GtkWidget * , GdkEventConfigure * );
-static gint expose_event (GtkWidget * , GdkEventExpose * );
-static gint button_press_event (GtkWidget * , GdkEventButton * );
-static gint button_release_event (GtkWidget * , GdkEventButton * );
-static gint motion_notify_event (GtkWidget * , GdkEventMotion * );
-static gint key_press_event (GtkWidget * , GdkEventKey * );
-static gint key_release_event (GtkWidget * , GdkEventKey * );
-static gint leave_notify_event (GtkWidget * , GdkEventCrossing * );
-static gint enter_notify_event (GtkWidget * , GdkEventCrossing * );
+static gboolean configure_event (GtkWidget * , GdkEventConfigure * , gpointer );
+static gboolean expose_event (GtkWidget * , GdkEventExpose * , gpointer );
+static gboolean button_press_event (GtkWidget * , GdkEventButton * , gpointer );
+static gboolean button_release_event (GtkWidget * , GdkEventButton * , gpointer );
+static gboolean motion_notify_event (GtkWidget * , GdkEventMotion * , gpointer );
+static gboolean key_press_event (GtkWidget * , GdkEventKey * , gpointer );
+static gboolean key_release_event (GtkWidget * , GdkEventKey * , gpointer );
+static gboolean leave_notify_event (GtkWidget * , GdkEventCrossing * , gpointer );
+static gboolean enter_notify_event (GtkWidget * , GdkEventCrossing * , gpointer );
 static void tseq_initialize (struct graph * );
 static void tseq_get_bounds (struct graph * );
 static void tseq_stevens_read_config (struct graph * );
@@ -463,42 +506,156 @@ static void rtt_put_unack_on_list (struct unack ** , struct unack * );
 static void rtt_delete_unack_from_list (struct unack ** , struct unack * );
 static void rtt_make_elmtlist (struct graph * );
 static void rtt_toggle_seq_origin (struct graph * );
+static void wscale_initialize(struct graph *);
+static void wscale_read_config(struct graph *);
+static void wscale_make_elmtlist(struct graph *);
 #if defined(_WIN32) && !defined(__MINGW32__)
 static int rint (double );     /* compiler template for Windows */
 #endif
 
+/*
+ * Uncomment the following define to revert WIN32 to
+ * use original mouse button controls
+ */
+
+/* #define ORIGINAL_WIN32_BUTTONS 1 */
+
 /* XXX - what about OS X? */
 static char helptext[] =
-#ifndef _WIN32
-"Here's what you can do:\n\
-- Left Mouse Button selects segment in Wireshark's packet list\n\
-- Middle Mouse Button zooms in\n\
-- <shift>-Middle Button zooms out\n\
-- Right Mouse Button moves the graph (if zoomed in)\n\
-- <ctrl>-Right Mouse Button displays a portion of graph magnified\n\
-- Space toggles crosshairs\n\
-- 's' toggles relative/absolute sequence numbers\n\
-- 't' toggles time origin\n\
-";
-#else /* _WIN32 */
-"Here's what you can do:\n\
-- <ctrl>-Left  Mouse Button selects segment in Wireshark's packet list\n\
-- Left         Mouse Button zooms in\n\
-- <shift>-Left Mouse Button zooms out\n\
-- Right        Mouse Button moves the graph (if zoomed in)\n\
-- <ctrl>-Right Mouse Button displays a portion of graph magnified\n\
-\n\
-- Space bar toggles crosshairs\n\
-- 's' - Toggles relative/absolute sequence numbers\n\
-- 't' - Toggles time origin\n\
-";
+       "Here's what you can do:\n"
+       "\n"
+#ifdef ORIGINAL_WIN32_BUTTONS
+       "   <Ctrl>-Left Mouse Button            selects segment under cursor in Wireshark's packet list\n"
+       "\n"
+       "   Left Mouse Button                   zooms in (towards area under mouse pointer)\n"
+       "   <Shift>-Left Mouse Button           zooms out\n"
+       "\n"
+       "   Right Mouse Button                  moves the graph (if zoomed in)\n"
+       "   <Ctrl>-Right Mouse Button           displays a portion of graph under cursor magnified\n"
+#else /* !ORIGINAL_WIN32_BUTTONS */
+       "   Left Mouse Button                   selects segment under cursor in Wireshark's packet list\n"
+       "\n"
+       "   Middle Mouse Button                 zooms in (towards area under cursor)\n"
+       "   <Shift>-Middle Mouse Button zooms out\n"
+       "\n"
+       "   Right Mouse Button                  moves the graph (if zoomed in)\n"
+       "   <Ctrl>-Right Mouse Button           displays a portion of graph under cursor magnified\n"
+#endif
+       "\n"
+       "\n"
+       "   '1'                         display Round Trip Time Graph\n"
+       "   '2'                         display Throughput Graph\n"
+       "   '3'                         display Time/Sequence Graph (Stevens)\n"
+       "   '4'                         display Time/Sequence Graph (tcptrace)\n"
+       "   '5'                         display Window Scaling Graph\n"
+       "\n"
+       "   <Space bar> toggles crosshairs on/off\n"
+       "\n"
+       "   'i' or '+'                  zoom in (towards area under mouse pointer)\n"
+       "   'o' or '-'                  zoom out\n"
+       "   'r' or <Home>       restore graph to initial state (zoom out max)\n"
+       "   's'                         toggles relative/absolute sequence numbers\n"
+       "   't'                         toggles time origin\n"
+       "   'g'                         go to frame under cursor in Wireshark's packet list (if possible)\n"
+       "\n"
+       "   <Left>                      move view left by 100 pixels (if zoomed in)\n"
+       "   <Right>             move view right 100 pixels (if zoomed in)\n"
+       "   <Up>                        move view up by 100 pixels (if zoomed in)\n"
+       "   <Down>              move view down by 100 pixels (if zoomed in)\n"
+       "\n"
+       "   <Shift><Left>       move view left by 10 pixels (if zoomed in)\n"
+       "   <Shift><Right>      move view right 10 pixels (if zoomed in)\n"
+       "   <Shift><Up> move view up by 10 pixels (if zoomed in)\n"
+       "   <Shift><Down>       move view down by 10 pixels (if zoomed in)\n"
+       "\n"
+       "   <Ctrl><Left>        move view left by 1 pixel (if zoomed in)\n"
+       "   <Ctrl><Right>       move view right 1 pixel (if zoomed in)\n"
+       "   <Ctrl><Up>  move view up by 1 pixel (if zoomed in)\n"
+       "   <Ctrl><Down>        move view down by 1 pixel (if zoomed in)\n"
+;
+
+#if 0
+static void debug_coord (struct graph *g, const char *c)
+{
+       static unsigned count = 0;
+
+       count++;
+       printf("%u: %s\n", count, c);
+       printf("%u:  g->geom.width %d\n", count, g->geom.width);
+       printf("%u: g->geom.height %d\n", count, g->geom.height);
+       printf("%u:      g->geom.x %d\n", count, g->geom.x);
+       printf("%u:      g->geom.y %d\n", count, g->geom.y);
+
+       printf("%u:    g->wp.width %d\n", count, g->wp.width);
+       printf("%u:   g->wp.height %d\n", count, g->wp.height);
+       printf("%u:        g->wp.x %d\n", count, g->wp.x);
+       printf("%u:        g->wp.y %d\n", count, g->wp.y);
+       printf("---------------\n");
+}
 #endif
 
+static void set_busy_cursor(GdkWindow *w)
+{
+       GdkCursor* cursor;
+
+       cursor = gdk_cursor_new(GDK_WATCH);
+       gdk_window_set_cursor(w, cursor);
+       gdk_flush();
+       gdk_cursor_unref(cursor);
+}
+
+static void unset_busy_cursor(GdkWindow *w)
+{
+       gdk_window_set_cursor(w, NULL);
+       gdk_flush();
+}
+#ifdef MAIN_MENU_USE_UIMANAGER
+void tcp_graph_cb (GtkAction *action, gpointer user_data _U_)
+{
+       struct segment current;
+       struct graph *g;
+       const gchar *name;
+       guint graph_type;
+
+       name = gtk_action_get_name (action);
+       if(strcmp(name, "Analyze/StatisticsMenu/TCPStreamGraphMenu/Time-Sequence-Graph-Stevens") == 0){
+               graph_type = GRAPH_TSEQ_STEVENS;
+       }else if(strcmp(name, "/Analyze/StatisticsMenu/TCPStreamGraphMenu/Time-Sequence-Graph-tcptrace") == 0){
+               graph_type = GRAPH_TSEQ_TCPTRACE;
+       }else if(strcmp(name, "StatisticsMenu/TCPStreamGraphMenu/Throughput-Graph") == 0){
+               graph_type = GRAPH_THROUGHPUT;
+       }else if(strcmp(name, "/Analyze/StatisticsMenu/TCPStreamGraphMenu/RTT-Graph") == 0){
+               graph_type = GRAPH_RTT;
+       }else if(strcmp(name, "/Analyze/StatisticsMenu/TCPStreamGraphMenu/Window-Scaling-Graph") == 0){
+               graph_type = GRAPH_WSCALE;
+       }else{
+               return;
+       }
+
+       debug(DBS_FENTRY) puts ("tcp_graph_cb()");
+
+       if (! (g = graph_new()))
+               return;
+
+       refnum++;
+       graph_initialize_values (g);
+
+       g->type = graph_type;
+       if (!select_tcpip_session (&cfile, &current)) {
+               return;
+       }
+
+       graph_segment_list_get(g);
+       create_gui(g);
+       /* display_text(g); */
+       graph_init_sequence(g);
+
+}
+#else
 static void tcp_graph_cb (GtkWidget *w _U_, gpointer data, guint callback_action /*graph_type*/ _U_)
 {
        struct segment current;
        struct graph *g;
-       struct tcpheader *thdr;
 
        guint graph_type = GPOINTER_TO_INT(data);
 
@@ -511,7 +668,7 @@ static void tcp_graph_cb (GtkWidget *w _U_, gpointer data, guint callback_action
        graph_initialize_values (g);
 
        g->type = graph_type;
-       if (!(thdr=select_tcpip_session (&cfile, &current))) {
+       if (!select_tcpip_session (&cfile, &current)) {
                return;
        }
 
@@ -520,7 +677,7 @@ static void tcp_graph_cb (GtkWidget *w _U_, gpointer data, guint callback_action
        /* display_text(g); */
        graph_init_sequence(g);
 }
-
+#endif
 static void create_gui (struct graph *g)
 {
        debug(DBS_FENTRY) puts ("create_gui()");
@@ -529,161 +686,70 @@ static void create_gui (struct graph *g)
        create_drawing_area(g);
 }
 
-#if 0
-static void create_text_widget (struct graph *g)
-{
-       GtkWidget *streamwindow, *txt_scrollw, *box;
-
-       debug(DBS_FENTRY) puts ("create_text_widget()");
-       streamwindow = dlg_window_new ("Wireshark: Packet chain");
-       gtk_widget_set_name (streamwindow, "Packet chain");
-       WIDGET_SET_SIZE(streamwindow, TXT_WIDTH, TXT_HEIGHT);
-       gtk_container_border_width (GTK_CONTAINER(streamwindow), 2);
-
-       box = gtk_vbox_new (FALSE, 0);
-       gtk_container_add (GTK_CONTAINER (streamwindow), box);
-       gtk_widget_show (box);
-
-       txt_scrollw = scrolled_window_new (NULL, NULL);
-    gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(txt_scrollw),
-                                   GTK_SHADOW_IN);
-       gtk_box_pack_start (GTK_BOX (box), txt_scrollw, TRUE, TRUE, 0);
-       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (txt_scrollw),
-                                       GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
-       gtk_widget_show (txt_scrollw);
-
-       g->text = gtk_text_view_new();
-       gtk_text_view_set_editable(GTK_TEXT_VIEW(g->text), FALSE);
-       gtk_container_add (GTK_CONTAINER (txt_scrollw), g->text);
-       gtk_widget_show (g->text);
-       gtk_widget_show (streamwindow);
-}
-static void display_text (struct graph *g)
-{
-       char *line[256];
-       struct segment *ptr;
-       double first_time, prev_time;
-       unsigned int isn_this=0, isn_opposite=0, seq_this_prev, seq_opposite_prev;
-       GdkColor color, *c;
-        GtkTextBuffer *buf;
-        GtkTextIter    iter;
 
-       debug(DBS_FENTRY) puts ("display_text()");
-       if (!gdk_color_parse ("SlateGray", &color)) {
-               /*
-                * XXX - do more than just warn.
-                */
-               simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
-                   "Could not parse color SlateGray.");
-       }
-       g_snprintf ((char * )line, 256, "%10s%15s%15s%15s%15s%15s%15s%10s\n",
-                                       "pkt num", "time", "delta first", "delta prev",
-                                       "seqno", "delta first", "delta prev", "data (B)");
-       gtk_text_insert (GTK_TEXT (g->text), g->font, NULL, NULL,
-                                                       (const char *)line, -1);
-
-       first_time = g->segments->rel_secs + g->segments->rel_usecs/1000000.0;
-       prev_time = first_time;
-       /* we have to find Initial Sequence Number for both ends of connection */
-       for (ptr=g->segments; ptr; ptr=ptr->next) {
-               if (compare_headers (g->current, ptr, COMPARE_CURR_DIR)) {
-                       isn_this = ptr->th_seq;
-                       break;
-               }
-       }
-       for (ptr=g->segments; ptr; ptr=ptr->next) {
-               if (!compare_headers (g->current, ptr, COMPARE_CURR_DIR)) {
-                       isn_opposite = ptr->th_seq;
-                       break;
-               }
-       }
-       seq_this_prev = isn_this;
-       seq_opposite_prev = isn_opposite;
-       for (ptr=g->segments; ptr; ptr=ptr->next) {
-               double time=ptr->rel_secs + ptr->rel_usecs/1000000.0;
-               unsigned int seq = ptr->th_seq;
-               int seq_delta_isn, seq_delta_prev;
-
-               if (compare_headers (g->current, ptr, COMPARE_CURR_DIR)) {
-                       seq_delta_isn = seq - isn_this;
-                       seq_delta_prev = seq - seq_this_prev;
-                       seq_this_prev = seq;
-                       c = NULL;
-               } else {
-                       seq_delta_isn = seq - isn_opposite;
-                       seq_delta_prev = seq - seq_opposite_prev;
-                       seq_opposite_prev = seq;
-                       c = &color;
-               }
-               g_snprintf ((char *)line, 256, "%10d%15.6f%15.6f%15.6f%15u%15d%15d%10u\n",
-                                               ptr->num, time, time-first_time, time-prev_time,
-                                               seq, seq_delta_isn, seq_delta_prev,
-                                               ptr->th_seglen);
-                gtk_text_buffer_insert(buf, &iter, (const char *)line, -1);
-               prev_time = time;
-       }
-}
-#endif
 
 static void create_drawing_area (struct graph *g)
 {
+#if GTK_CHECK_VERSION(3,0,0)
+       GtkStyleContext *context;
+#else
        GdkColormap *colormap;
        GdkColor color;
-#define WINDOW_TITLE_LENGTH 64
+#endif
        char window_title[WINDOW_TITLE_LENGTH];
        struct segment current;
        struct tcpheader *thdr;
-
-       debug(DBS_FENTRY) puts ("create_drawing_area()");
+       GtkAllocation widget_alloc;
 #if 0
-       g->font = gdk_font_load ("-sony-fixed-medium-r-normal--16-150-75-75"
-                                                       "-c-80-iso8859-2");
-       g->font = gdk_font_load ("-biznet-fotinostypewriter-medium-r-normal-*-*-120"
-                                                       "-*-*-m-*-iso8859-2");
+       /* Prep. to include the controls in the graph window */
+       GtkWidget *frame;
+       GtkWidget *vbox;
+       GtkWidget *hbox;
 #endif
+       debug(DBS_FENTRY) puts ("create_drawing_area()");
        thdr=select_tcpip_session (&cfile, &current);
        g_snprintf (window_title, WINDOW_TITLE_LENGTH, "TCP Graph %d: %s %s:%d -> %s:%d",
                        refnum,
                        cf_get_display_name(&cfile),
-                       address_to_str(&(thdr->ip_src)),
+                       ep_address_to_str(&(thdr->ip_src)),
                        thdr->th_sport,
-                       address_to_str(&(thdr->ip_dst)),
+                       ep_address_to_str(&(thdr->ip_dst)),
                        thdr->th_dport
        );
        g->toplevel = dlg_window_new ("Tcp Graph");
        gtk_window_set_title(GTK_WINDOW(g->toplevel), window_title);
        gtk_widget_set_name (g->toplevel, "Test Graph");
-       OBJECT_SET_DATA(g->toplevel, "graph", g);
+       g_object_set_data(G_OBJECT(g->toplevel), "graph", g);
 
        /* Create the drawing area */
        g->drawing_area = gtk_drawing_area_new ();
-       OBJECT_SET_DATA(g->drawing_area, "graph", g);
+       g_object_set_data(G_OBJECT(g->drawing_area), "graph", g);
        g->x_axis->drawing_area = g->y_axis->drawing_area = g->drawing_area;
-       gtk_drawing_area_size (GTK_DRAWING_AREA (g->drawing_area),
+       gtk_widget_set_size_request (g->drawing_area,
                                        g->wp.width + g->wp.x + RMARGIN_WIDTH,
                                        g->wp.height + g->wp.y + g->x_axis->s.height);
        gtk_widget_show (g->drawing_area);
 
-       SIGNAL_CONNECT(g->drawing_area, "expose_event", expose_event, NULL);
+       g_signal_connect(g->drawing_area, "expose_event", G_CALLBACK(expose_event), NULL);
        /* this has to be done later, after the widget has been shown */
        /*
-       SIGNAL_CONNECT(g->drawing_area,"configure_event", configure_event,
+       g_signal_connect(g->drawing_area,"configure_event", G_CALLBACK(configure_event),
         NULL);
         */
-       SIGNAL_CONNECT(g->drawing_area, "motion_notify_event",
-                       motion_notify_event, NULL);
-       SIGNAL_CONNECT(g->drawing_area, "button_press_event",
-                       button_press_event, NULL);
-       SIGNAL_CONNECT(g->drawing_area, "button_release_event",
-                       button_release_event, NULL);
-       SIGNAL_CONNECT(g->drawing_area, "leave_notify_event",
-                       leave_notify_event, NULL);
-       SIGNAL_CONNECT(g->drawing_area, "enter_notify_event",
-                       enter_notify_event, NULL);
-       SIGNAL_CONNECT(g->toplevel, "destroy", callback_toplevel_destroy, g);
+       g_signal_connect(g->drawing_area, "motion_notify_event",
+                       G_CALLBACK(motion_notify_event), NULL);
+       g_signal_connect(g->drawing_area, "button_press_event",
+                       G_CALLBACK(button_press_event), NULL);
+       g_signal_connect(g->drawing_area, "button_release_event",
+                       G_CALLBACK(button_release_event), NULL);
+       g_signal_connect(g->drawing_area, "leave_notify_event",
+                       G_CALLBACK(leave_notify_event), NULL);
+       g_signal_connect(g->drawing_area, "enter_notify_event",
+                       G_CALLBACK(enter_notify_event), NULL);
+       g_signal_connect(g->toplevel, "destroy", G_CALLBACK(callback_toplevel_destroy), g);
        /* why doesn't drawing area send key_press_signals? */
-       SIGNAL_CONNECT(g->toplevel, "key_press_event", key_press_event, NULL);
-       SIGNAL_CONNECT(g->toplevel, "key_release_event", key_release_event,
+       g_signal_connect(g->toplevel, "key_press_event", G_CALLBACK(key_press_event), NULL);
+       g_signal_connect(g->toplevel, "key_release_event", G_CALLBACK(key_release_event),
                        NULL);
        gtk_widget_set_events(g->toplevel,
                               GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK);
@@ -698,33 +764,53 @@ static void create_drawing_area (struct graph *g)
                                | GDK_POINTER_MOTION_HINT_MASK);
 
 #if 0
+       /* Prep. to include the controls in the graph window */
+
+       vbox = gtk_vbox_new (FALSE, 0);
+       gtk_container_add (GTK_CONTAINER (g->toplevel), vbox);
+       gtk_container_set_border_width (GTK_CONTAINER (g->toplevel), 5);
+       gtk_widget_show (vbox);
+
        frame = gtk_frame_new (NULL);
        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
        gtk_container_add (GTK_CONTAINER (frame), g->drawing_area);
-
-       box = gtk_hbox_new (FALSE, 0);
-       gtk_box_pack_start (GTK_BOX (box), g->gui.control_panel, FALSE, FALSE, 0);
-       gtk_box_pack_start (GTK_BOX (box), frame, TRUE, TRUE, 0);
-       gtk_container_add (GTK_CONTAINER (g->toplevel), box);
-       gtk_container_set_border_width (GTK_CONTAINER (g->toplevel), 5);
+       gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
        gtk_widget_show (frame);
-       gtk_widget_show (box);
+
+
+       /*gtk_box_pack_start (GTK_BOX (vbox), g->gui.control_panel, FALSE, FALSE, 0);*/
+
+       hbox=gtk_hbox_new(FALSE, 3);
+       gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
+       gtk_container_set_border_width(GTK_CONTAINER(hbox), 3);
+       gtk_box_set_child_packing(GTK_BOX(vbox), hbox, FALSE, FALSE, 0, GTK_PACK_START);
+       gtk_widget_show(hbox);
+
+       create_ctrl_area(g, hbox);
+
 #endif
 
        gtk_container_add (GTK_CONTAINER (g->toplevel), g->drawing_area);
        gtk_widget_show (g->toplevel);
 
        /* in case we didn't get what we asked for */
-       g->wp.width = GTK_WIDGET (g->drawing_area)->allocation.width -
-                                               g->wp.x - RMARGIN_WIDTH;
-       g->wp.height = GTK_WIDGET (g->drawing_area)->allocation.height -
-                                               g->wp.y - g->x_axis->s.height;
-
-        g->font = g->drawing_area->style->font_desc;
-
-       colormap = gdk_window_get_colormap (g->drawing_area->window);
+       gtk_widget_get_allocation(GTK_WIDGET (g->drawing_area), &widget_alloc);
+       g->wp.width = widget_alloc.width - g->wp.x - RMARGIN_WIDTH;
+       g->wp.height = widget_alloc.height - g->wp.y - g->x_axis->s.height;
+
+#if GTK_CHECK_VERSION(3,0,0)
+       context = gtk_widget_get_style_context (g->drawing_area);
+       gtk_style_context_get (context, GTK_STATE_NORMAL,
+                                          "font", &g->font,
+                                          NULL);
+#else
+       g->font = gtk_widget_get_style(g->drawing_area)->font_desc;
+#endif
+#if GTK_CHECK_VERSION(3,0,0)
+#else
+       colormap = gtk_widget_get_colormap(GTK_WIDGET(g->drawing_area));
        if (!xor_gc) {
-               xor_gc = gdk_gc_new (g->drawing_area->window);
+               xor_gc = gdk_gc_new (gtk_widget_get_window(g->drawing_area));
                gdk_gc_set_function (xor_gc, GDK_XOR);
                if (!gdk_color_parse ("gray15", &color)) {
                        /*
@@ -742,23 +828,7 @@ static void create_drawing_area (struct graph *g)
                }
                gdk_gc_set_foreground (xor_gc, &color);
        }
-       g->fg_gc = gdk_gc_new (g->drawing_area->window);
-       g->bg_gc = gdk_gc_new (g->drawing_area->window);
-       if (!gdk_color_parse ("white", &color)) {
-               /*
-                * XXX - do more than just warn.
-                */
-               simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
-                   "Could not parse color white.");
-       }
-       if (!gdk_colormap_alloc_color (colormap, &color, FALSE, TRUE)) {
-               /*
-                * XXX - do more than just warn.
-                */
-               simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
-                   "Could not allocate color white.");
-       }
-       gdk_gc_set_foreground (g->bg_gc, &color);
+       g->fg_gc = gdk_gc_new (gtk_widget_get_window(g->drawing_area));
 
        /* this is probably quite an ugly way to get rid of the first configure
         * event
@@ -770,10 +840,11 @@ static void create_drawing_area (struct graph *g)
         * and we don't have the GC's at all. so we just postpone installation
         * of configure handler until we're ready to deal with it.
         *
-        * !!! NEMÌLO BY TO BÝT NA KONCI graph_init_sequence()? !!!
+        * !!! NEMLLO BY TO BYT NA KONCI graph_init_sequence()? !!!
         *
         */
-       SIGNAL_CONNECT(g->drawing_area,"configure_event", configure_event,
+#endif
+       g_signal_connect(g->drawing_area, "configure_event", G_CALLBACK(configure_event),
                        NULL);
 
        /* puts ("exiting create_drawing_area()"); */
@@ -794,7 +865,6 @@ static void control_panel_create (struct graph *g)
     GtkWidget *toplevel, *notebook;
     GtkWidget *table;
     GtkWidget *help_bt, *close_bt, *bbox;
-#define WINDOW_TITLE_LENGTH 64
     char window_title[WINDOW_TITLE_LENGTH];
 
     debug(DBS_FENTRY) puts ("control_panel_create()");
@@ -822,15 +892,15 @@ static void control_panel_create (struct graph *g)
     gtk_table_attach (GTK_TABLE (table), bbox, 0, 1, 1, 2,
                       GTK_FILL|GTK_EXPAND, GTK_FILL, 5, 5);
 
-    help_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_HELP);
-    SIGNAL_CONNECT(help_bt, "clicked", callback_create_help, g);
+    help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
+    g_signal_connect(help_bt, "clicked", G_CALLBACK(callback_create_help), g);
 
-    close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE);
+    close_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLOSE);
     window_set_cancel_button(toplevel, close_bt, NULL);
-    SIGNAL_CONNECT(close_bt, "clicked", callback_close, g);
+    g_signal_connect(close_bt, "clicked", G_CALLBACK(callback_close), g);
 
-    SIGNAL_CONNECT(toplevel, "delete_event", callback_delete_event, g);
-    SIGNAL_CONNECT(toplevel, "destroy", callback_toplevel_destroy, g);
+    g_signal_connect(toplevel, "delete_event", G_CALLBACK(callback_delete_event), g);
+    g_signal_connect(toplevel, "destroy", G_CALLBACK(callback_toplevel_destroy), g);
 
     /* gtk_widget_show_all (table); */
     /* g->gui.control_panel = table; */
@@ -879,7 +949,7 @@ static void control_panel_add_origin_page (struct graph *g, GtkWidget *n)
        time_orig_cap =
                        gtk_radio_button_new_with_label (NULL, "beginning of capture");
        time_orig_conn = gtk_radio_button_new_with_label (
-                       gtk_radio_button_group (GTK_RADIO_BUTTON (time_orig_cap)),
+                       gtk_radio_button_get_group (GTK_RADIO_BUTTON (time_orig_cap)),
                        "beginning of this TCP connection");
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (time_orig_conn), TRUE);
        time_orig_box = gtk_vbox_new (TRUE, 0);
@@ -892,7 +962,7 @@ static void control_panel_add_origin_page (struct graph *g, GtkWidget *n)
        /* sequence number origin group */
        seq_orig_isn =
                        gtk_radio_button_new_with_label (NULL, "initial sequence number");
-       seq_orig_zero = gtk_radio_button_new_with_label (gtk_radio_button_group (
+       seq_orig_zero = gtk_radio_button_new_with_label (gtk_radio_button_get_group (
                        GTK_RADIO_BUTTON (seq_orig_isn)), "0 (=absolute)");
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (seq_orig_isn), TRUE);
        seq_orig_box = gtk_vbox_new (TRUE, 0);
@@ -905,8 +975,8 @@ static void control_panel_add_origin_page (struct graph *g, GtkWidget *n)
        g->gui.time_orig_conn = (GtkToggleButton * )time_orig_conn;
        g->gui.seq_orig_isn = (GtkToggleButton * )seq_orig_isn;
 
-       SIGNAL_CONNECT(time_orig_conn, "toggled", callback_time_origin, g);
-       SIGNAL_CONNECT(seq_orig_isn, "toggled", callback_seq_origin, g);
+       g_signal_connect(time_orig_conn, "toggled", G_CALLBACK(callback_time_origin), g);
+       g_signal_connect(seq_orig_isn, "toggled", G_CALLBACK(callback_seq_origin), g);
 
        box = gtk_vbox_new (FALSE, 0);
        gtk_container_set_border_width (GTK_CONTAINER (box), 5);
@@ -965,11 +1035,11 @@ static void callback_create_help(GtkWidget *widget _U_, gpointer data _U_)
        gtk_window_set_default_size(GTK_WINDOW(toplevel), 500, 400);
 
        vbox = gtk_vbox_new (FALSE, 3);
-    gtk_container_border_width(GTK_CONTAINER(vbox), 12);
+       gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
        gtk_container_add (GTK_CONTAINER (toplevel), vbox);
 
        scroll = scrolled_window_new (NULL, NULL);
-    gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll),
+       gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll),
                                    GTK_SHADOW_IN);
        gtk_box_pack_start (GTK_BOX (vbox), scroll, TRUE, TRUE, 0);
         text = gtk_text_view_new();
@@ -979,17 +1049,17 @@ static void callback_create_help(GtkWidget *widget _U_, gpointer data _U_)
        gtk_container_add (GTK_CONTAINER (scroll), text);
 
        /* Button row. */
-    bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
+       bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
        gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, FALSE, 0);
-    gtk_widget_show(bbox);
+       gtk_widget_show(bbox);
 
-    close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE);
-    window_set_cancel_button(toplevel, close_bt, window_cancel_button_cb);
+       close_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLOSE);
+       window_set_cancel_button(toplevel, close_bt, window_cancel_button_cb);
 
-    SIGNAL_CONNECT(toplevel, "delete_event", window_delete_event_cb, NULL);
+       g_signal_connect(toplevel, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
 
        gtk_widget_show_all (toplevel);
-    window_present(toplevel);
+       window_present(toplevel);
 }
 
 static void callback_time_origin (GtkWidget *toggle _U_, gpointer data)
@@ -1015,7 +1085,7 @@ static GtkWidget *control_panel_create_zoom_group (struct graph *g)
 
        zoom_in = gtk_radio_button_new_with_label (NULL, "in");
        zoom_out = gtk_radio_button_new_with_label (
-                                       gtk_radio_button_group (GTK_RADIO_BUTTON (zoom_in)), "out");
+                                       gtk_radio_button_get_group (GTK_RADIO_BUTTON (zoom_in)), "out");
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (zoom_in), TRUE);
        zoom_inout_box = gtk_hbox_new (FALSE, 0);
        gtk_box_pack_start (GTK_BOX (zoom_inout_box), zoom_in, FALSE, FALSE, 10);
@@ -1063,11 +1133,11 @@ static GtkWidget *control_panel_create_zoom_group (struct graph *g)
 
        zoom_same_toggle = gtk_check_button_new_with_label("Keep them the same");
        zoom_ratio_toggle = gtk_check_button_new_with_label("Preserve their ratio");
-       OBJECT_SET_DATA(zoom_same_toggle, "flag", (gpointer)ZOOM_STEPS_SAME);
-       OBJECT_SET_DATA(zoom_ratio_toggle, "flag",
+       g_object_set_data(G_OBJECT(zoom_same_toggle), "flag", (gpointer)ZOOM_STEPS_SAME);
+       g_object_set_data(G_OBJECT(zoom_ratio_toggle), "flag",
                         (gpointer)ZOOM_STEPS_KEEP_RATIO);
-       SIGNAL_CONNECT(zoom_same_toggle, "clicked", callback_zoom_flags, g);
-       SIGNAL_CONNECT(zoom_ratio_toggle, "clicked", callback_zoom_flags, g);
+       g_signal_connect(zoom_same_toggle, "clicked", G_CALLBACK(callback_zoom_flags), g);
+       g_signal_connect(zoom_ratio_toggle, "clicked", G_CALLBACK(callback_zoom_flags), g);
 
        zoom_step_table = gtk_table_new (4, 2,  FALSE);
        gtk_table_attach (GTK_TABLE (zoom_step_table), zoom_h_step_label, 0,1,0,1,
@@ -1092,12 +1162,12 @@ static GtkWidget *control_panel_create_zoom_group (struct graph *g)
        zoom_frame = gtk_frame_new ("Zoom");
        gtk_container_add (GTK_CONTAINER (zoom_frame), zoom_box);
 
-       OBJECT_SET_DATA(zoom_h_step, "direction", GINT_TO_POINTER(0));
-       OBJECT_SET_DATA(zoom_v_step, "direction", GINT_TO_POINTER(1));
+       g_object_set_data(G_OBJECT(zoom_h_step), "direction", GINT_TO_POINTER(0));
+       g_object_set_data(G_OBJECT(zoom_v_step), "direction", GINT_TO_POINTER(1));
 
-       SIGNAL_CONNECT(zoom_in, "toggled", callback_zoom_inout, g);
-       SIGNAL_CONNECT(zoom_h_step, "changed", callback_zoom_step, g);
-        SIGNAL_CONNECT(zoom_v_step, "changed", callback_zoom_step, g);
+       g_signal_connect(zoom_in, "toggled", G_CALLBACK(callback_zoom_inout), g);
+       g_signal_connect(zoom_h_step, "changed", G_CALLBACK(callback_zoom_step), g);
+        g_signal_connect(zoom_v_step, "changed", G_CALLBACK(callback_zoom_step), g);
 
        g->zoom.widget.in_toggle = (GtkToggleButton * )zoom_in;
        g->zoom.widget.out_toggle = (GtkToggleButton * )zoom_out;
@@ -1108,7 +1178,7 @@ static void callback_zoom_inout (GtkWidget *toggle, gpointer data)
 {
        struct graph *g = (struct graph * )data;
 
-       if (GTK_TOGGLE_BUTTON (toggle)->active)
+       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (toggle)))
                g->zoom.flags &= ~ZOOM_OUT;
        else
                g->zoom.flags |= ZOOM_OUT;
@@ -1123,8 +1193,8 @@ static void callback_zoom_step (GtkWidget *spin, gpointer data)
        GtkSpinButton *widget_this, *widget_other;
        double old_this;
 
-       direction = (long)OBJECT_GET_DATA(spin, "direction");
-       value = gtk_spin_button_get_value_as_float (GTK_SPIN_BUTTON (spin));
+       direction = (long)g_object_get_data(G_OBJECT(spin), "direction");
+       value = gtk_spin_button_get_value (GTK_SPIN_BUTTON (spin));
 
        if (direction) {
                zoom_this = &g->zoom.step_y;
@@ -1162,9 +1232,9 @@ static void callback_zoom_step (GtkWidget *spin, gpointer data)
 static void callback_zoom_flags (GtkWidget *toggle, gpointer data)
 {
        struct graph *g = (struct graph * )data;
-       int flag = (long)OBJECT_GET_DATA(toggle, "flag");
+       int flag = (long)g_object_get_data(G_OBJECT(toggle), "flag");
 
-       if (GTK_TOGGLE_BUTTON (toggle)->active)
+       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (toggle)))
                g->zoom.flags |= flag;
        else
                g->zoom.flags &= ~flag;
@@ -1174,9 +1244,9 @@ static void update_zoom_spins (struct graph *g)
 {
        char s[32];
 
-       g_snprintf (s, 32, "%.3f", g->zoom.x / g->zoom.initial.x);
+       g_snprintf (s, sizeof(s), "%.3f", g->zoom.x / g->zoom.initial.x);
        gtk_entry_set_text (g->zoom.widget.h_zoom, s);
-       g_snprintf (s, 32, "%.3f", g->zoom.y / g->zoom.initial.y);
+       g_snprintf (s, sizeof(s), "%.3f", g->zoom.y / g->zoom.initial.y);
        gtk_entry_set_text (g->zoom.widget.v_zoom, s);
 }
 
@@ -1265,19 +1335,19 @@ static GtkWidget *control_panel_create_magnify_group (struct graph *g)
 
        g->magnify.widget.h_zoom = (GtkSpinButton * )mag_h_zoom;
        g->magnify.widget.v_zoom = (GtkSpinButton * )mag_v_zoom;
-       OBJECT_SET_DATA(mag_h_zoom, "direction", GINT_TO_POINTER(0));
-       OBJECT_SET_DATA(mag_v_zoom, "direction", GINT_TO_POINTER(1));
-       OBJECT_SET_DATA(mag_zoom_same, "flag", (gpointer)MAGZOOMS_SAME);
-       OBJECT_SET_DATA(mag_zoom_ratio, "flag", (gpointer)MAGZOOMS_SAME_RATIO);
-
-       SIGNAL_CONNECT(mag_width, "changed", callback_mag_width, g);
-       SIGNAL_CONNECT(mag_height, "changed", callback_mag_height, g);
-       SIGNAL_CONNECT(mag_x, "changed", callback_mag_x, g);
-       SIGNAL_CONNECT(mag_y, "changed", callback_mag_y, g);
-       SIGNAL_CONNECT(mag_h_zoom, "changed", callback_mag_zoom, g);
-       SIGNAL_CONNECT(mag_v_zoom, "changed", callback_mag_zoom, g);
-       SIGNAL_CONNECT(mag_zoom_same, "clicked", callback_mag_flags, g);
-       SIGNAL_CONNECT(mag_zoom_ratio, "clicked", callback_mag_flags, g);
+       g_object_set_data(G_OBJECT(mag_h_zoom), "direction", GINT_TO_POINTER(0));
+       g_object_set_data(G_OBJECT(mag_v_zoom), "direction", GINT_TO_POINTER(1));
+       g_object_set_data(G_OBJECT(mag_zoom_same), "flag", (gpointer)MAGZOOMS_SAME);
+       g_object_set_data(G_OBJECT(mag_zoom_ratio), "flag", (gpointer)MAGZOOMS_SAME_RATIO);
+
+       g_signal_connect(mag_width, "changed", G_CALLBACK(callback_mag_width), g);
+       g_signal_connect(mag_height, "changed", G_CALLBACK(callback_mag_height), g);
+       g_signal_connect(mag_x, "changed", G_CALLBACK(callback_mag_x), g);
+       g_signal_connect(mag_y, "changed", G_CALLBACK(callback_mag_y), g);
+       g_signal_connect(mag_h_zoom, "changed", G_CALLBACK(callback_mag_zoom), g);
+       g_signal_connect(mag_v_zoom, "changed", G_CALLBACK(callback_mag_zoom), g);
+       g_signal_connect(mag_zoom_same, "clicked", G_CALLBACK(callback_mag_flags), g);
+       g_signal_connect(mag_zoom_ratio, "clicked", G_CALLBACK(callback_mag_flags), g);
 
        return mag_frame;
 }
@@ -1324,8 +1394,8 @@ static void callback_mag_zoom (GtkWidget *spin, gpointer data)
                g->magnify.flags &= ~MAGZOOMS_IGNORE;
                return;
        }
-       direction = (long)OBJECT_GET_DATA(spin, "direction");
-       value = gtk_spin_button_get_value_as_float (GTK_SPIN_BUTTON (spin));
+       direction = (long)g_object_get_data(G_OBJECT(spin), "direction");
+       value = gtk_spin_button_get_value (GTK_SPIN_BUTTON (spin));
 
        if (direction) {
                zoom_this = &g->magnify.zoom.y;
@@ -1367,9 +1437,9 @@ static void callback_mag_zoom (GtkWidget *spin, gpointer data)
 static void callback_mag_flags (GtkWidget *toggle, gpointer data)
 {
        struct graph *g = (struct graph * )data;
-       int flag = (long)OBJECT_GET_DATA(toggle, "flag");
+       int flag = (long)g_object_get_data(G_OBJECT(toggle), "flag");
 
-       if (GTK_TOGGLE_BUTTON (toggle)->active)
+       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (toggle)))
                g->magnify.flags |= flag;
        else
                g->magnify.flags &= ~flag;
@@ -1382,10 +1452,10 @@ static GtkWidget *control_panel_create_zoomlock_group (struct graph *g)
 
        zoom_lock_none = gtk_radio_button_new_with_label (NULL, "none");
        zoom_lock_h = gtk_radio_button_new_with_label (
-                                       gtk_radio_button_group (GTK_RADIO_BUTTON (zoom_lock_none)),
+                                       gtk_radio_button_get_group (GTK_RADIO_BUTTON (zoom_lock_none)),
                                        "horizontal");
        zoom_lock_v = gtk_radio_button_new_with_label (
-                                       gtk_radio_button_group (GTK_RADIO_BUTTON (zoom_lock_none)),
+                                       gtk_radio_button_get_group (GTK_RADIO_BUTTON (zoom_lock_none)),
                                        "vertical");
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (zoom_lock_none), TRUE);
        zoom_lock_box = gtk_hbox_new (FALSE, 0);
@@ -1396,8 +1466,8 @@ static GtkWidget *control_panel_create_zoomlock_group (struct graph *g)
        zoom_lock_frame = gtk_frame_new ("Zoom lock:");
        gtk_container_add (GTK_CONTAINER (zoom_lock_frame), zoom_lock_box);
 
-       SIGNAL_CONNECT(zoom_lock_h, "toggled", callback_zoomlock_h, g);
-       SIGNAL_CONNECT(zoom_lock_v, "toggled", callback_zoomlock_v, g);
+       g_signal_connect(zoom_lock_h, "toggled", G_CALLBACK(callback_zoomlock_h), g);
+       g_signal_connect(zoom_lock_v, "toggled", G_CALLBACK(callback_zoomlock_v), g);
 
        return zoom_lock_frame;
 }
@@ -1406,7 +1476,7 @@ static void callback_zoomlock_h (GtkWidget *toggle, gpointer data)
 {
        struct graph *g = (struct graph * )data;
 
-       if (GTK_TOGGLE_BUTTON (toggle)->active)
+       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (toggle)))
                g->zoom.flags |= ZOOM_HLOCK;
        else
                g->zoom.flags &= ~ZOOM_HLOCK;
@@ -1416,7 +1486,7 @@ static void callback_zoomlock_v (GtkWidget *toggle, gpointer data)
 {
        struct graph *g = (struct graph * )data;
 
-       if (GTK_TOGGLE_BUTTON (toggle)->active)
+       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (toggle)))
                g->zoom.flags |= ZOOM_VLOCK;
        else
                g->zoom.flags &= ~ZOOM_VLOCK;
@@ -1429,7 +1499,7 @@ static GtkWidget *control_panel_create_cross_group (struct graph *g)
        label = gtk_label_new ("Crosshairs:");
        off = gtk_radio_button_new_with_label (NULL, "off");
        on = gtk_radio_button_new_with_label (
-                               gtk_radio_button_group (GTK_RADIO_BUTTON (off)), "on");
+                               gtk_radio_button_get_group (GTK_RADIO_BUTTON (off)), "on");
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (off), TRUE);
        box = gtk_hbox_new (FALSE, 0);
        gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 10);
@@ -1441,7 +1511,7 @@ static GtkWidget *control_panel_create_cross_group (struct graph *g)
        frame = gtk_frame_new (NULL);
        gtk_container_add (GTK_CONTAINER (frame), vbox);
 
-       SIGNAL_CONNECT(on, "toggled", callback_cross_on_off, g);
+       g_signal_connect(on, "toggled", G_CALLBACK(callback_cross_on_off), g);
 
        g->cross.on_toggle = (GtkToggleButton * )on;
        g->cross.off_toggle = (GtkToggleButton * )off;
@@ -1453,10 +1523,10 @@ static void callback_cross_on_off (GtkWidget *toggle, gpointer data)
 {
        struct graph *g = (struct graph * )data;
 
-       if (GTK_TOGGLE_BUTTON (toggle)->active) {
+       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (toggle))) {
                int x, y;
                g->cross.draw = TRUE;
-               gdk_window_get_pointer (g->drawing_area->window, &x, &y, 0);
+               gdk_window_get_pointer (gtk_widget_get_window(g->drawing_area), &x, &y, 0);
                cross_draw (g, x, y);
        } else {
                g->cross.draw = FALSE;
@@ -1469,17 +1539,22 @@ static GtkWidget *control_panel_create_graph_type_group (struct graph *g)
        GtkWidget *graph_tseqttrace, *graph_tseqstevens;
        GtkWidget *graph_tput, *graph_rtt, *graph_sep, *graph_init, *graph_box;
        GtkWidget *graph_frame;
+       GtkWidget *graph_wscale;
 
        graph_tput = gtk_radio_button_new_with_label (NULL, "Throughput");
        graph_tseqttrace = gtk_radio_button_new_with_label (
-                                       gtk_radio_button_group (GTK_RADIO_BUTTON (graph_tput)),
+                                       gtk_radio_button_get_group (GTK_RADIO_BUTTON (graph_tput)),
                                        "Time/Sequence (tcptrace-style)");
        graph_tseqstevens = gtk_radio_button_new_with_label (
-                                       gtk_radio_button_group (GTK_RADIO_BUTTON (graph_tput)),
+                                       gtk_radio_button_get_group (GTK_RADIO_BUTTON (graph_tput)),
                                        "Time/Sequence (Stevens'-style)");
        graph_rtt = gtk_radio_button_new_with_label (
-                                       gtk_radio_button_group (GTK_RADIO_BUTTON (graph_tput)),
+                                       gtk_radio_button_get_group (GTK_RADIO_BUTTON (graph_tput)),
                                        "Round-trip Time");
+       graph_wscale = gtk_radio_button_new_with_label (
+                       gtk_radio_button_get_group (GTK_RADIO_BUTTON (graph_tput)),
+                       "Window Scaling");
+
        switch (g->type) {
        case GRAPH_TSEQ_STEVENS:
                gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(graph_tseqstevens),TRUE);
@@ -1493,31 +1568,42 @@ static GtkWidget *control_panel_create_graph_type_group (struct graph *g)
        case GRAPH_RTT:
                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (graph_rtt), TRUE);
                break;
+       case GRAPH_WSCALE:
+               gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (graph_wscale), TRUE);
+               break;
        }
        graph_init = gtk_check_button_new_with_label ("Init on change");
        graph_sep = gtk_hseparator_new ();
        graph_box = gtk_vbox_new (FALSE, 0);
-       gtk_box_pack_start (GTK_BOX (graph_box), graph_tseqttrace, TRUE, TRUE, 0);
-       gtk_box_pack_start (GTK_BOX (graph_box), graph_tseqstevens, TRUE, TRUE, 0);
-       gtk_box_pack_start (GTK_BOX (graph_box), graph_tput, TRUE, TRUE, 0);
        gtk_box_pack_start (GTK_BOX (graph_box), graph_rtt, TRUE, TRUE, 0);
+       gtk_box_pack_start (GTK_BOX (graph_box), graph_tput, TRUE, TRUE, 0);
+       gtk_box_pack_start (GTK_BOX (graph_box), graph_tseqstevens, TRUE, TRUE, 0);
+       gtk_box_pack_start (GTK_BOX (graph_box), graph_tseqttrace, TRUE, TRUE, 0);
+       gtk_box_pack_start (GTK_BOX (graph_box), graph_wscale, TRUE, TRUE, 0);
        gtk_box_pack_start (GTK_BOX (graph_box), graph_sep, TRUE, TRUE, 0);
        gtk_box_pack_start (GTK_BOX (graph_box), graph_init, TRUE, TRUE, 0);
        graph_frame = gtk_frame_new ("Graph type:");
        gtk_container_add (GTK_CONTAINER (graph_frame), graph_box);
 
-       OBJECT_SET_DATA(graph_tseqstevens, "new-graph-type",
+       g_object_set_data(G_OBJECT(graph_tseqstevens), "new-graph-type",
                         GINT_TO_POINTER(0));
-       OBJECT_SET_DATA(graph_tseqttrace, "new-graph-type", GINT_TO_POINTER(1));
-       OBJECT_SET_DATA(graph_tput, "new-graph-type", GINT_TO_POINTER(2));
-       OBJECT_SET_DATA(graph_rtt, "new-graph-type", GINT_TO_POINTER(3));
-
-        SIGNAL_CONNECT(graph_tseqttrace, "toggled", callback_graph_type, g);
-        SIGNAL_CONNECT(graph_tseqstevens, "toggled", callback_graph_type, g);
-        SIGNAL_CONNECT(graph_tput, "toggled", callback_graph_type, g);
-        SIGNAL_CONNECT(graph_rtt, "toggled", callback_graph_type, g);
-        SIGNAL_CONNECT(graph_init, "toggled", callback_graph_init_on_typechg,
-                       g);
+       g_object_set_data(G_OBJECT(graph_tseqttrace), "new-graph-type", GINT_TO_POINTER(1));
+       g_object_set_data(G_OBJECT(graph_tput), "new-graph-type", GINT_TO_POINTER(2));
+       g_object_set_data(G_OBJECT(graph_rtt), "new-graph-type", GINT_TO_POINTER(3));
+       g_object_set_data(G_OBJECT(graph_wscale), "new-graph-type", GINT_TO_POINTER(GRAPH_WSCALE));
+
+       g->gt.graph_wscale = (GtkToggleButton *)graph_wscale;
+       g->gt.graph_rtt = (GtkToggleButton * )graph_rtt;
+       g->gt.graph_tput = (GtkToggleButton * )graph_tput;
+       g->gt.graph_tseqstevens = (GtkToggleButton * )graph_tseqstevens;
+       g->gt.graph_tseqttrace = (GtkToggleButton * )graph_tseqttrace;
+
+        g_signal_connect(graph_tseqttrace, "toggled", G_CALLBACK(callback_graph_type), g);
+        g_signal_connect(graph_tseqstevens, "toggled", G_CALLBACK(callback_graph_type), g);
+        g_signal_connect(graph_tput, "toggled", G_CALLBACK(callback_graph_type), g);
+        g_signal_connect(graph_rtt, "toggled", G_CALLBACK(callback_graph_type), g);
+        g_signal_connect(graph_wscale, "toggled", G_CALLBACK(callback_graph_type), g);
+        g_signal_connect(graph_init, "toggled", G_CALLBACK(callback_graph_init_on_typechg), g);
 
        return graph_frame;
 }
@@ -1527,9 +1613,9 @@ static void callback_graph_type (GtkWidget *toggle, gpointer data)
        int old_type, new_type;
        struct graph *g = (struct graph * )data;
 
-       new_type = (long)OBJECT_GET_DATA(toggle,"new-graph-type");
+       new_type = (long)g_object_get_data(G_OBJECT(toggle),"new-graph-type");
 
-       if (!GTK_TOGGLE_BUTTON (toggle)->active)
+       if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (toggle)))
                return;
 
        old_type = g->type;
@@ -1647,6 +1733,9 @@ static void graph_type_dependent_initialize (struct graph *g)
        case GRAPH_RTT:
                rtt_initialize (g);
                break;
+       case GRAPH_WSCALE:
+               wscale_initialize (g);
+               break;
        default:
                break;
        }
@@ -1662,10 +1751,20 @@ static void graph_destroy (struct graph *g)
        window_destroy (g->gui.control_panel);
        window_destroy (g->toplevel);
        /* window_destroy (g->text); */
-       gdk_gc_unref (g->fg_gc);
-       gdk_gc_unref (g->bg_gc);
-       gdk_pixmap_unref (g->pixmap[0]);
-       gdk_pixmap_unref (g->pixmap[1]);
+#if GTK_CHECK_VERSION(2,22,0)
+       if(g->title_surface){
+                cairo_surface_destroy (g->title_surface);
+       }
+       if(g->surface[0]){
+                cairo_surface_destroy (g->surface[0]);
+       }
+       if(g->surface[1]){
+                cairo_surface_destroy (g->surface[1]);
+       }
+#else
+       g_object_unref (g->pixmap[0]);
+       g_object_unref (g->pixmap[1]);
+#endif /* GTK_CHECK_VERSION(2,22,0) */
        g_free (g->x_axis);
        g_free (g->y_axis);
        g_free ( (gpointer) (g->title) );
@@ -1692,9 +1791,6 @@ tapall_tcpip_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, cons
 
        if(!segment){
                segment=g_malloc(sizeof (struct segment));
-               if(!segment){
-                       perror ("malloc failed");
-               }
        }
 
 
@@ -1758,14 +1854,14 @@ static void graph_segment_list_get (struct graph *g)
        ts.current=&current;
        ts.g=g;
        ts.last=NULL;
-       error_string=register_tap_listener("tcp", &ts, "tcp", NULL, tapall_tcpip_packet, NULL);
+       error_string=register_tap_listener("tcp", &ts, "tcp", 0, NULL, tapall_tcpip_packet, NULL);
        if(error_string){
                fprintf(stderr, "wireshark: Couldn't register tcp_graph tap: %s\n",
                    error_string->str);
                g_string_free(error_string, TRUE);
                exit(1);
        }
-       cf_retap_packets(&cfile, FALSE);
+       cf_retap_packets(&cfile);
        remove_tap_listener(&ts);
 }
 
@@ -1795,9 +1891,7 @@ tap_tcpip_packet(void *pct, packet_info *pinfo _U_, epan_dissect_t *edt _U_, con
 static struct tcpheader *select_tcpip_session (capture_file *cf, struct segment *hdrs)
 {
        frame_data *fdata;
-       gint err;
-       gchar *err_info;
-       epan_dissect_t *edt;
+       epan_dissect_t edt;
        dfilter_t *sfcode;
        GString *error_string;
        th_t th = {0, NULL};
@@ -1806,20 +1900,16 @@ static struct tcpheader *select_tcpip_session (capture_file *cf, struct segment
 
        /* no real filter yet */
        if (!dfilter_compile("tcp", &sfcode)) {
-               simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, dfilter_error_msg);
+               simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", dfilter_error_msg);
                return NULL;
        }
 
        /* dissect the current frame */
-       if (!wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
-           cf->pd, fdata->cap_len, &err, &err_info)) {
-               simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                       cf_read_error_message(err, err_info), cf->filename);
-               return NULL;
-       }
+       if (!cf_read_frame(cf, fdata))
+               return NULL;    /* error reading the frame */
 
 
-       error_string=register_tap_listener("tcp", &th, NULL, NULL, tap_tcpip_packet, NULL);
+       error_string=register_tap_listener("tcp", &th, NULL, 0, NULL, tap_tcpip_packet, NULL);
        if(error_string){
                fprintf(stderr, "wireshark: Couldn't register tcp_graph tap: %s\n",
                    error_string->str);
@@ -1827,12 +1917,12 @@ static struct tcpheader *select_tcpip_session (capture_file *cf, struct segment
                exit(1);
        }
 
-       edt = epan_dissect_new(TRUE, FALSE);
-       epan_dissect_prime_dfilter(edt, sfcode);
-       tap_queue_init(edt);
-       epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
-       tap_push_tapped_queue(edt);
-       epan_dissect_free(edt);
+       epan_dissect_init(&edt, TRUE, FALSE);
+       epan_dissect_prime_dfilter(&edt, sfcode);
+       tap_queue_init(&edt);
+       epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
+       tap_push_tapped_queue(&edt);
+       epan_dissect_cleanup(&edt);
        remove_tap_listener(&th);
 
        if(th.num_hdrs==0){
@@ -1927,6 +2017,9 @@ static void graph_element_lists_make (struct graph *g)
        case GRAPH_RTT:
                rtt_make_elmtlist (g);
                break;
+       case GRAPH_WSCALE:
+               wscale_make_elmtlist (g);
+               break;
        default:
                printf ("graph_element_lists_make: unknown graph type: %d\n", g->type);
                break;
@@ -1957,66 +2050,138 @@ static void graph_element_lists_free (struct graph *g)
 
 static void graph_title_pixmap_create (struct graph *g)
 {
+#if GTK_CHECK_VERSION(2,22,0)
+       if(g->title_surface){
+               cairo_surface_destroy (g->title_surface);
+               g->title_surface = NULL;
+       }
+
+       g->title_surface = gdk_window_create_similar_surface (gtk_widget_get_window(g->drawing_area),
+                       CAIRO_CONTENT_COLOR,
+                       g->x_axis->p.width,
+                       g->wp.y);
+
+#else
        if (g->title_pixmap)
-               gdk_pixmap_unref (g->title_pixmap);
+               g_object_unref (g->title_pixmap);
 
-       g->title_pixmap = gdk_pixmap_new (g->drawing_area->window,
+       g->title_pixmap = gdk_pixmap_new (gtk_widget_get_window(g->drawing_area),
                                                        g->x_axis->p.width, g->wp.y, -1);
+#endif
 }
 
 static void graph_title_pixmap_draw (struct graph *g)
 {
        int i;
+       cairo_t *cr;
+
+#if GTK_CHECK_VERSION(2,22,0)
+       cr = cairo_create (g->title_surface);
+#else
+       cr = gdk_cairo_create (g->title_pixmap);
+#endif
+       cairo_set_source_rgb (cr, 1, 1, 1);
+       cairo_rectangle (cr, 0, 0,  g->x_axis->p.width, g->wp.y);
+       cairo_fill (cr);
+       cairo_destroy (cr);
+       cr = NULL;
 
-       gdk_draw_rectangle(g->title_pixmap, g->bg_gc, TRUE, 0, 0,
-                           g->x_axis->p.width, g->wp.y);
        for (i=0; g->title[i]; i++) {
                gint w, h;
-                PangoLayout *layout;
-                layout = gtk_widget_create_pango_layout(g->drawing_area,
-                                                        g->title[i]);
-                pango_layout_get_pixel_size(layout, &w, &h);
-                gdk_draw_layout(g->title_pixmap, g->fg_gc,
-                                g->wp.width/2 - w/2, 20 + i*(h+3), layout);
-                g_object_unref(G_OBJECT(layout));
+        PangoLayout *layout;
+        layout = gtk_widget_create_pango_layout(g->drawing_area,
+                                                g->title[i]);
+        pango_layout_get_pixel_size(layout, &w, &h);
+#if GTK_CHECK_VERSION(2,22,0)
+               cr = cairo_create (g->title_surface);
+#else
+               cr = gdk_cairo_create (g->title_pixmap);
+#endif
+               cairo_move_to (cr, g->wp.width/2 - w/2, 20 + i*(h+3));
+               pango_cairo_show_layout (cr, layout);
+               cairo_destroy (cr);
+        g_object_unref(G_OBJECT(layout));
        }
 }
 
 static void graph_title_pixmap_display (struct graph *g)
 {
-       gdk_draw_pixmap (g->drawing_area->window, g->fg_gc, g->title_pixmap,
-                         0, 0, g->wp.x, 0, g->x_axis->p.width, g->wp.y);
+       cairo_t *cr;
+
+       cr = gdk_cairo_create (gtk_widget_get_window(g->drawing_area));
+#if GTK_CHECK_VERSION(2,22,0)
+       cairo_set_source_surface (cr, g->title_surface, g->wp.x, 0);
+#else
+       gdk_cairo_set_source_pixmap (cr, g->title_pixmap, g->wp.x, 0);
+#endif
+       cairo_rectangle (cr, g->wp.x, 0, g->x_axis->p.width, g->wp.y);
+       cairo_fill (cr);
+       cairo_destroy (cr);
 }
 
 static void graph_pixmaps_create (struct graph *g)
 {
        debug(DBS_FENTRY) puts ("graph_pixmaps_create()");
+#if GTK_CHECK_VERSION(2,22,0)
+       if(g->surface[0]){
+               cairo_surface_destroy (g->surface[0]);
+               g->surface[0] = NULL;
+       }
+
+       if(g->surface[1]){
+               cairo_surface_destroy (g->surface[1]);
+               g->surface[1] = NULL;
+       }
+
+       g->surface[0] = gdk_window_create_similar_surface (gtk_widget_get_window(g->drawing_area),
+                       CAIRO_CONTENT_COLOR,
+                       g->wp.width,
+                       g->wp.height);
 
+       g->surface[1] = gdk_window_create_similar_surface (gtk_widget_get_window(g->drawing_area),
+                       CAIRO_CONTENT_COLOR,
+                       g->wp.width,
+                       g->wp.height);
+
+       g->displayed = 0;
+#else
        if (g->pixmap[0])
-               gdk_pixmap_unref (g->pixmap[0]);
+               g_object_unref (g->pixmap[0]);
        if (g->pixmap[1])
-               gdk_pixmap_unref (g->pixmap[1]);
+               g_object_unref (g->pixmap[1]);
 
-       g->pixmap[0] = gdk_pixmap_new (g->drawing_area->window,
+       g->pixmap[0] = gdk_pixmap_new (gtk_widget_get_window(g->drawing_area),
                                                                        g->wp.width, g->wp.height, -1);
-       g->pixmap[1] = gdk_pixmap_new (g->drawing_area->window,
+       g->pixmap[1] = gdk_pixmap_new (gtk_widget_get_window(g->drawing_area),
                                                                        g->wp.width, g->wp.height, -1);
 
        g->displayed = 0;
+#endif /* GTK_CHECK_VERSION(2,22,0) */
 }
 
 static void graph_display (struct graph *g)
 {
+       set_busy_cursor (gtk_widget_get_window(g->drawing_area));
        graph_pixmap_draw (g);
+       unset_busy_cursor (gtk_widget_get_window(g->drawing_area));
        graph_pixmaps_switch (g);
        graph_pixmap_display (g);
 }
 
 static void graph_pixmap_display (struct graph *g)
 {
-    gdk_draw_pixmap (g->drawing_area->window, g->fg_gc,
-                                       g->pixmap[g->displayed], 0, 0, g->wp.x, g->wp.y,
-                                       g->wp.width, g->wp.height);
+       cairo_t *cr;
+
+       cr = gdk_cairo_create (gtk_widget_get_window(g->drawing_area));
+#if GTK_CHECK_VERSION(2,22,0)
+       cairo_set_source_surface (cr, g->surface[g->displayed], g->wp.x, g->wp.y);
+#else
+       gdk_cairo_set_source_pixmap (cr, g->pixmap[g->displayed], g->wp.x, g->wp.y);
+#endif /* GTK_CHECK_VERSION(2,22,0) */
+       cairo_rectangle (cr, g->wp.x, g->wp.y, g->wp.width, g->wp.height);
+       cairo_fill (cr);
+       cairo_destroy (cr);
+
     if (g->cross.erase_needed) {
        cross_xor(g, g->cross.x, g->cross.y);
     }
@@ -2032,12 +2197,21 @@ static void graph_pixmap_draw (struct graph *g)
        struct element_list *list;
        struct element *e;
        int not_disp;
+       cairo_t *cr;
 
        debug(DBS_FENTRY) puts ("graph_display()");
        not_disp = 1 ^ g->displayed;
 
-       gdk_draw_rectangle (g->pixmap[not_disp], g->bg_gc, TRUE,
-                                                       0, 0, g->wp.width, g->wp.height);
+#if GTK_CHECK_VERSION(2,22,0)
+       cr = cairo_create (g->surface[not_disp]);
+#else
+       cr = gdk_cairo_create (g->pixmap[not_disp]);
+#endif /* GTK_CHECK_VERSION(2,22,0) */
+       cairo_set_source_rgb (cr, 1, 1, 1);
+       cairo_rectangle (cr, 0, 0, g->wp.width, g->wp.height);
+       cairo_fill (cr);
+       cairo_destroy (cr);
+       cr = NULL;
 
        for (list=g->elists; list; list=list->next)
                for (e=list->elements; e->type != ELMT_NONE; e++) {
@@ -2047,8 +2221,8 @@ static void graph_pixmap_draw (struct graph *g)
                        case ELMT_LINE:
                                draw_element_line (g, e);
                                break;
-                       case ELMT_ARC:
-                               draw_element_arc (g, e);
+                       case ELMT_ELLIPSE:
+                               draw_element_ellipse (g, e);
                                break;
                        default:
                                break;
@@ -2058,78 +2232,146 @@ static void graph_pixmap_draw (struct graph *g)
 
 static void draw_element_line (struct graph *g, struct element *e)
 {
-       int x1, x2, y1, y2;
+       int xx1, xx2, yy1, yy2;
+       cairo_t *cr;
 
        debug(DBS_GRAPH_DRAWING) printf ("line element: (%.2f,%.2f)->(%.2f,%.2f), "
                                "seg %d ... ", e->p.line.dim.x1, e->p.line.dim.y1,
                                e->p.line.dim.x2, e->p.line.dim.y2, e->parent->num);
-       x1 = (int )rint (e->p.line.dim.x1 + g->geom.x - g->wp.x);
-       x2 = (int )rint (e->p.line.dim.x2 + g->geom.x - g->wp.x);
-       y1 = (int )rint ((g->geom.height-1-e->p.line.dim.y1) + g->geom.y-g->wp.y);
-       y2 = (int )rint ((g->geom.height-1-e->p.line.dim.y2) + g->geom.y-g->wp.y);
-       if (x1 > x2) {
-               int tmp=x2;
-               x2=x1;
-               x1=tmp;
-       }
-       if (y1 > y2) {
-               int tmp=y2;
-               y2=y1;
-               y1=tmp;
-       }
-       if ((x1<0 && x2<0) || (x1>=g->wp.width && x2>=g->wp.width) ||
-                               (y1<0 && y2<0) || (y1>=g->wp.height && y2>=g->wp.height)) {
+       xx1 = (int )rint (e->p.line.dim.x1 + g->geom.x - g->wp.x);
+       xx2 = (int )rint (e->p.line.dim.x2 + g->geom.x - g->wp.x);
+       yy1 = (int )rint ((g->geom.height-1-e->p.line.dim.y1) + g->geom.y-g->wp.y);
+       yy2 = (int )rint ((g->geom.height-1-e->p.line.dim.y2) + g->geom.y-g->wp.y);
+       if (xx1 > xx2) {
+               int tmp=xx2;
+               xx2=xx1;
+               xx1=tmp;
+       }
+       if (yy1 > yy2) {
+               int tmp=yy2;
+               yy2=yy1;
+               yy1=tmp;
+       }
+       if ((xx1<0 && xx2<0) || (xx1>=g->wp.width && xx2>=g->wp.width) ||
+                               (yy1<0 && yy2<0) || (yy1>=g->wp.height && yy2>=g->wp.height)) {
                debug(DBS_GRAPH_DRAWING) printf (" refusing: (%d,%d)->(%d,%d)\n",
-                                                                       x1, y1, x2, y2);
+                                                                       xx1, yy1, xx2, yy2);
                return;
        }
-       if (x2 > g->wp.width-1)
-               x2 = g->wp.width-1;
-       if (x1 < 0)
-               x1 = 0;
-       if (y2 > g->wp.height-1)
-               y2 = g->wp.height-1;
-       if (y1 < 0)
-               y1 = 0;
-       debug(DBS_GRAPH_DRAWING) printf ("line: (%d,%d)->(%d,%d)\n", x1, y1, x2,y2);
-       gdk_draw_line (g->pixmap[1^g->displayed], e->gc, x1, y1, x2, y2);
+       if (xx2 > g->wp.width-1)
+               xx2 = g->wp.width-1;
+       if (xx1 < 0)
+               xx1 = 0;
+       if (yy2 > g->wp.height-1)
+               yy2 = g->wp.height-1;
+       if (yy1 < 0)
+               yy1 = 0;
+       debug(DBS_GRAPH_DRAWING) printf ("line: (%d,%d)->(%d,%d)\n", xx1, yy1, xx2,yy2);
+
+       g_assert(e->elment_color_p!=NULL);
+
+#if GTK_CHECK_VERSION(2,22,0)
+       cr = cairo_create (g->surface[1^g->displayed]);
+#else
+       cr = gdk_cairo_create (g->pixmap[1^g->displayed]);
+#endif
+       cairo_set_line_width (cr, 1.0);
+       if(e->elment_color_p!=NULL){
+               gdk_cairo_set_source_color (cr, e->elment_color_p);
+       }
+       cairo_move_to(cr, xx1+0.5, yy1+0.5);
+       cairo_line_to(cr, xx2+0.5, yy2+0.5);
+       cairo_stroke(cr);
+       cairo_destroy(cr);
 }
 
-static void draw_element_arc (struct graph *g, struct element *e)
+static void draw_element_ellipse (struct graph *g, struct element *e)
 {
-       int x1, x2, y1, y2;
-
-       x1 = (int )rint (e->p.arc.dim.x + g->geom.x - g->wp.x);
-       x2 = (int )e->p.arc.dim.width;
-       y1 = (int )rint (g->geom.height-1 - e->p.arc.dim.y + g->geom.y - g->wp.y);
-       y2 = (int )e->p.arc.dim.height;
-       if (x1<-x2 || x1>=g->wp.width || y1<-y2 || y1>=g->wp.height)
+#if GTK_CHECK_VERSION(2,22,0)
+       cairo_t *cr;
+       gdouble w = e->p.ellipse.dim.width;
+       gdouble h = e->p.ellipse.dim.height;
+       gdouble x = e->p.ellipse.dim.x + g->geom.x - g->wp.x;
+       gdouble y = g->geom.height-1 - e->p.ellipse.dim.y + g->geom.y - g->wp.y;
+
+       debug(DBS_GRAPH_DRAWING) printf ("ellipse: (x, y) -> (w, h): (%f, %f) -> (%f, %f)\n", x, y, w, h);
+
+       cr = cairo_create (g->surface[1^g->displayed]);
+       cairo_translate (cr, x + w / 2., y + h / 2.);
+       cairo_scale (cr, w / 2., h / 2.);
+       cairo_arc (cr, 0., 0., 1., 0., 2 * G_PI);
+       cairo_fill(cr);
+       cairo_destroy(cr);
+#else
+       int xx1, xx2, yy1, yy2;
+
+       xx1 = (int )rint (e->p.ellipse.dim.x + g->geom.x - g->wp.x);
+       xx2 = (int )e->p.ellipse.dim.width;
+       yy1 = (int )rint (g->geom.height-1 - e->p.ellipse.dim.y + g->geom.y - g->wp.y);
+       yy2 = (int )e->p.ellipse.dim.height;
+       if (xx1<-xx2 || xx1>=g->wp.width || yy1<-yy2 || yy1>=g->wp.height)
                return;
-       debug(DBS_GRAPH_DRAWING) printf ("arc: (%d,%d)->(%d,%d)\n", x1, y1, x2, y2);
-       gdk_draw_arc (g->pixmap[1^g->displayed], e->gc, e->p.arc.filled, x1,
-                                       y1, x2, y2, e->p.arc.angle1, e->p.arc.angle2);
+       debug(DBS_GRAPH_DRAWING) printf ("ellipse: (%d,%d)->(%d,%d)\n", xx1, yy1, xx2, yy2);
+
+       gdk_draw_arc (g->pixmap[1^g->displayed], g->fg_gc, TRUE, xx1,
+                                       yy1, xx2, yy2, 0, 23040);
+#endif
+       /* NOTE the coordinates and angels needs to be recalculated as cairo_arc works differently */
 }
 
 static void axis_pixmaps_create (struct axis *axis)
 {
        debug(DBS_FENTRY) puts ("axis_pixmaps_create()");
+#if GTK_CHECK_VERSION(2,22,0)
+       if(axis->surface[0]){
+               cairo_surface_destroy (axis->surface[0]);
+               axis->surface[0] = NULL;
+       }
+       if(axis->surface[1]){
+               cairo_surface_destroy (axis->surface[1]);
+               axis->surface[1] = NULL;
+       }
+       axis->surface[0] = gdk_window_create_similar_surface (gtk_widget_get_window(axis->drawing_area),
+                       CAIRO_CONTENT_COLOR,
+                       axis->p.width,
+                       axis->p.height);
+
+       axis->surface[1] = gdk_window_create_similar_surface (gtk_widget_get_window(axis->drawing_area),
+                       CAIRO_CONTENT_COLOR,
+                       axis->p.width,
+                       axis->p.height);
+
+       axis->displayed = 0;
+#else
        if (axis->pixmap[0])
-               gdk_pixmap_unref (axis->pixmap[0]);
+               g_object_unref (axis->pixmap[0]);
        if (axis->pixmap[1])
-               gdk_pixmap_unref (axis->pixmap[1]);
+               g_object_unref (axis->pixmap[1]);
 
-       axis->pixmap[0] = gdk_pixmap_new (axis->drawing_area->window,
+       axis->pixmap[0] = gdk_pixmap_new (gtk_widget_get_window(axis->drawing_area),
                                                        axis->p.width, axis->p.height, -1);
-       axis->pixmap[1] = gdk_pixmap_new (axis->drawing_area->window,
+       axis->pixmap[1] = gdk_pixmap_new (gtk_widget_get_window(axis->drawing_area),
                                                        axis->p.width, axis->p.height, -1);
 
        axis->displayed = 0;
+#endif
 }
 
 static void axis_destroy (struct axis *axis)
 {
-       gdk_pixmap_unref (axis->pixmap[0]);
-       gdk_pixmap_unref (axis->pixmap[1]);
+#if GTK_CHECK_VERSION(2,22,0)
+       if(axis->surface[0]){
+               cairo_surface_destroy (axis->surface[0]);
+               axis->surface[0] = NULL;
+       }
+       if(axis->surface[1]){
+               cairo_surface_destroy (axis->surface[1]);
+               axis->surface[1] = NULL;
+       }
+#else
+       g_object_unref (axis->pixmap[0]);
+       g_object_unref (axis->pixmap[1]);
+#endif
        g_free ( (gpointer) (axis->label) );
 }
 
@@ -2151,6 +2393,7 @@ static void v_axis_pixmap_draw (struct axis *axis)
        int not_disp, rdigits, offset, imin, imax;
        double bottom, top, j, fl, corr;
         PangoLayout *layout;
+       cairo_t *cr;
 
        debug(DBS_FENTRY) puts ("v_axis_pixmap_draw()");
        bottom = (g->geom.height - (g->wp.height + g->wp.y + (-g->geom.y))) /
@@ -2170,12 +2413,30 @@ static void v_axis_pixmap_draw (struct axis *axis)
        }
 
        not_disp = 1 ^ axis->displayed;
-       gdk_draw_rectangle (axis->pixmap[not_disp], g->bg_gc, TRUE, 0, 0,
-                                       axis->p.width, axis->p.height);
+
+#if GTK_CHECK_VERSION(2,22,0)
+       cr = cairo_create (axis->surface[not_disp]);
+#else
+       cr = gdk_cairo_create (axis->pixmap[not_disp]);
+#endif
+       cairo_set_source_rgb (cr, 1, 1, 1);
+       cairo_rectangle (cr, 0, 0, axis->p.width, axis->p.height);
+       cairo_fill (cr);
+       cairo_destroy (cr);
+       cr = NULL;
+
        /* axis */
-       gdk_draw_line (axis->pixmap[not_disp], g->fg_gc, axis->p.width - 1,
-                       (gint) ((axis->p.height-axis->s.height)/2.0), axis->s.width - 1,
-                       axis->p.height);
+#if GTK_CHECK_VERSION(2,22,0)
+       cr = cairo_create (axis->surface[not_disp]);
+#else
+       cr = gdk_cairo_create (axis->pixmap[not_disp]);
+#endif
+       cairo_set_line_width (cr, 1.0);
+       cairo_move_to(cr, axis->p.width - 1.5, (axis->p.height-axis->s.height)/2.0);
+       cairo_line_to(cr, axis->s.width - 1.5, axis->p.height);
+       cairo_stroke(cr);
+       cairo_destroy(cr);
+       cr = NULL;
 
        offset = g->wp.y + (-g->geom.y);
        fl = floor (axis->min / axis->major) * axis->major;
@@ -2195,19 +2456,37 @@ static void v_axis_pixmap_draw (struct axis *axis)
                                                i*axis->major + fl, y);
                if (y < 0 || y > axis->p.height)
                        continue;
-               gdk_draw_line (axis->pixmap[not_disp], g->fg_gc,
-                               axis->s.width - 15, y, axis->s.width - 1, y);
-               g_snprintf (desc, 32, "%.*f", rdigits, i*axis->major + fl);
-                layout = gtk_widget_create_pango_layout(g->drawing_area, desc);
-                pango_layout_get_pixel_size(layout, &w, &h);
-                gdk_draw_layout(axis->pixmap[not_disp], g->fg_gc,
-                                axis->s.width-14-4-w, y - h/2, layout);
-                g_object_unref(G_OBJECT(layout));
+
+#if GTK_CHECK_VERSION(2,22,0)
+               cr = cairo_create (axis->surface[not_disp]);
+#else
+               cr = gdk_cairo_create (axis->pixmap[not_disp]);
+#endif
+               cairo_set_line_width (cr, 1.0);
+               cairo_move_to(cr, axis->p.width - 15, y+0.5);
+               cairo_line_to(cr, axis->s.width - 1, y+0.5);
+               cairo_stroke(cr);
+               cairo_destroy(cr);
+               cr = NULL;
+
+               g_snprintf (desc, sizeof(desc), "%.*f", rdigits, i*axis->major + fl);
+        layout = gtk_widget_create_pango_layout(g->drawing_area, desc);
+        pango_layout_get_pixel_size(layout, &w, &h);
+#if GTK_CHECK_VERSION(2,22,0)
+               cr = cairo_create (axis->surface[not_disp]);
+#else
+               cr = gdk_cairo_create (axis->pixmap[not_disp]);
+#endif
+               cairo_move_to (cr, axis->s.width-14-4-w, y - h/2);
+               pango_cairo_show_layout (cr, layout);
+               cairo_destroy (cr);
+               cr = NULL;
+        g_object_unref(G_OBJECT(layout));
        }
        /* minor ticks */
        if (axis->minor) {
                double minor_tick = axis->minor * g->zoom.y;
-               imin = (int) ((g->geom.height - offset + corr - g->wp.height)/minor_tick + 1);
+               imin = (int) ((g->geom.height - offset + corr - g->wp.height)/minor_tick + 1);
                imax = (int) ((g->geom.height - offset + corr) / minor_tick);
                for (i=imin; i <= imax; i++) {
                        int y = (int) (g->geom.height-1 - (int )rint (i*minor_tick) -
@@ -2215,22 +2494,35 @@ static void v_axis_pixmap_draw (struct axis *axis)
 
                        debug (DBS_AXES_DRAWING) printf ("%f @ %d\n", i*axis->minor+fl, y);
                        if (y > 0 && y < axis->p.height)
-                               gdk_draw_line (axis->pixmap[not_disp], g->fg_gc,
-                                               axis->s.width - 8, y,
-                                               axis->s.width - 1, y);
+#if GTK_CHECK_VERSION(2,22,0)
+                               cr = cairo_create (axis->surface[not_disp]);
+#else
+                               cr = gdk_cairo_create (axis->pixmap[not_disp]);
+#endif
+                               cairo_set_line_width (cr, 1.0);
+                               cairo_move_to(cr, axis->s.width - 8, y+0.5);
+                               cairo_line_to(cr, axis->s.width - 1, y+0.5);
+                               cairo_stroke(cr);
+                               cairo_destroy(cr);
+                               cr = NULL;
                }
        }
        for (i=0; axis->label[i]; i++) {
                gint w, h;
-                layout = gtk_widget_create_pango_layout(g->drawing_area,
-                                                        axis->label[i]);
-                pango_layout_get_pixel_size(layout, &w, &h);
-                gdk_draw_layout(axis->pixmap[not_disp], g->fg_gc,
-                                (axis->p.width - w)/2,
-                                TITLEBAR_HEIGHT-10 - i*(h+3) - h,
-                                layout);
-                g_object_unref(G_OBJECT(layout));
-       }
+        layout = gtk_widget_create_pango_layout(g->drawing_area,
+                                                axis->label[i]);
+        pango_layout_get_pixel_size(layout, &w, &h);
+#if GTK_CHECK_VERSION(2,22,0)
+               cr = cairo_create (axis->surface[not_disp]);
+#else
+        cr = gdk_cairo_create (axis->pixmap[not_disp]);
+#endif
+        cairo_move_to (cr, (axis->p.width - w)/2, TITLEBAR_HEIGHT-10 - i*(h+3) - h);
+        pango_cairo_show_layout (cr, layout);
+        cairo_destroy (cr);
+        cr = NULL;
+        g_object_unref(G_OBJECT(layout));
+    }
 }
 
 static void h_axis_pixmap_draw (struct axis *axis)
@@ -2241,6 +2533,7 @@ static void h_axis_pixmap_draw (struct axis *axis)
        int not_disp, rdigits, offset, imin, imax;
        double left, right, j, fl, corr;
         PangoLayout *layout;
+       cairo_t *cr;
 
        debug(DBS_FENTRY) puts ("h_axis_pixmap_draw()");
        left = (g->wp.x-g->geom.x) /
@@ -2260,11 +2553,31 @@ static void h_axis_pixmap_draw (struct axis *axis)
        }
 
        not_disp = 1 ^ axis->displayed;
-       gdk_draw_rectangle (axis->pixmap[not_disp], g->bg_gc, TRUE, 0, 0,
-                                       axis->p.width, axis->p.height);
+
+#if GTK_CHECK_VERSION(2,22,0)
+       cr = cairo_create (axis->surface[not_disp]);
+#else
+       cr = gdk_cairo_create (axis->pixmap[not_disp]);
+#endif
+       cairo_set_source_rgb (cr, 1, 1, 1);
+       cairo_rectangle (cr, 0, 0, axis->p.width, axis->p.height);
+       cairo_fill (cr);
+       cairo_destroy (cr);
+       cr = NULL;
+
        /* axis */
-       gdk_draw_line (axis->pixmap[not_disp], g->fg_gc, 0, 0,
-                                               (gint) (axis->s.width + (axis->p.width-axis->s.width)/2.0), 0);
+#if GTK_CHECK_VERSION(2,22,0)
+       cr = cairo_create (axis->surface[not_disp]);
+#else
+       cr = gdk_cairo_create (axis->pixmap[not_disp]);
+#endif
+       cairo_set_line_width (cr, 1.0);
+       cairo_move_to(cr, 0, 0.5);
+       cairo_line_to(cr, axis->s.width + (axis->p.width-axis->s.width)/2.0, 0.5);
+       cairo_stroke(cr);
+       cairo_destroy(cr);
+       cr = NULL;
+
        offset = g->wp.x - g->geom.x;
 
        fl = floor (axis->min / axis->major) * axis->major;
@@ -2282,13 +2595,32 @@ static void h_axis_pixmap_draw (struct axis *axis)
                /* printf ("%f @ %d\n", i*axis->major + fl, x); */
                if (x < 0 || x > axis->s.width)
                        continue;
-               gdk_draw_line (axis->pixmap[not_disp], g->fg_gc, x, 0, x, 15);
-               g_snprintf (desc, 32, "%.*f", rdigits, i*axis->major + fl);
-                layout = gtk_widget_create_pango_layout(g->drawing_area, desc);
-                pango_layout_get_pixel_size(layout, &w, &h);
-                gdk_draw_layout(axis->pixmap[not_disp], g->fg_gc,
-                                x - w/2, 15+4, layout);
-                g_object_unref(G_OBJECT(layout));
+#if GTK_CHECK_VERSION(2,22,0)
+               cr = cairo_create (axis->surface[not_disp]);
+#else
+               cr = gdk_cairo_create (axis->pixmap[not_disp]);
+#endif
+               cairo_set_line_width (cr, 1.0);
+               cairo_move_to(cr, x+0.5, 0);
+               cairo_line_to(cr, x+0.5, 15);
+               cairo_stroke(cr);
+               cairo_destroy(cr);
+               cr = NULL;
+
+               g_snprintf (desc, sizeof(desc), "%.*f", rdigits, i*axis->major + fl);
+        layout = gtk_widget_create_pango_layout(g->drawing_area, desc);
+        pango_layout_get_pixel_size(layout, &w, &h);
+#if GTK_CHECK_VERSION(2,22,0)
+               cr = cairo_create (axis->surface[not_disp]);
+#else
+               cr = gdk_cairo_create (axis->pixmap[not_disp]);
+#endif
+               cairo_move_to (cr,  x - w/2, 15+4);
+               pango_cairo_show_layout (cr, layout);
+               cairo_destroy (cr);
+               cr = NULL;
+
+        g_object_unref(G_OBJECT(layout));
        }
        if (axis->minor > 0) {
                /* minor ticks */
@@ -2297,19 +2629,36 @@ static void h_axis_pixmap_draw (struct axis *axis)
                imax = (int) ((offset + corr + g->wp.width) / minor_tick);
                for (i=imin; i <= imax; i++) {
                        int x = (int) (rint (i * minor_tick) - offset - corr);
-                       if (x > 0 && x < axis->s.width)
-                               gdk_draw_line (axis->pixmap[not_disp], g->fg_gc, x, 0, x, 8);
+                       if (x > 0 && x < axis->s.width){
+#if GTK_CHECK_VERSION(2,22,0)
+                               cr = cairo_create (axis->surface[not_disp]);
+#else
+                               cr = gdk_cairo_create (axis->pixmap[not_disp]);
+#endif
+                               cairo_set_line_width (cr, 1.0);
+                               cairo_move_to(cr, x+0.5, 0);
+                               cairo_line_to(cr, x+0.5, 8);
+                               cairo_stroke(cr);
+                               cairo_destroy(cr);
+                               cr = NULL;
+                       }
                }
        }
        for (i=0; axis->label[i]; i++) {
                gint w, h;
-                layout = gtk_widget_create_pango_layout(g->drawing_area,
-                                                        axis->label[i]);
-                pango_layout_get_pixel_size(layout, &w, &h);
-                gdk_draw_layout(axis->pixmap[not_disp], g->fg_gc,
-                                axis->s.width - w - 50, 15+h+15 + i*(h+3),
-                                layout);
-                g_object_unref(G_OBJECT(layout));
+        layout = gtk_widget_create_pango_layout(g->drawing_area,
+                                                axis->label[i]);
+        pango_layout_get_pixel_size(layout, &w, &h);
+#if GTK_CHECK_VERSION(2,22,0)
+               cr = cairo_create (axis->surface[not_disp]);
+#else
+               cr = gdk_cairo_create (axis->pixmap[not_disp]);
+#endif
+               cairo_move_to (cr,  axis->s.width - w - 50, 15+h+15 + i*(h+3));
+               pango_cairo_show_layout (cr, layout);
+               cairo_destroy (cr);
+               cr = NULL;
+        g_object_unref(G_OBJECT(layout));
        }
 }
 
@@ -2320,9 +2669,18 @@ static void axis_pixmaps_switch (struct axis *axis)
 
 static void axis_pixmap_display (struct axis *axis)
 {
-       gdk_draw_pixmap (axis->drawing_area->window, axis->g->fg_gc,
-                       axis->pixmap[axis->displayed], 0, 0, axis->p.x, axis->p.y,
-                       axis->p.width, axis->p.height);
+       cairo_t *cr;
+
+       cr = gdk_cairo_create (gtk_widget_get_window(axis->drawing_area));
+#if GTK_CHECK_VERSION(2,22,0)
+       cairo_set_source_surface (cr, axis->surface[axis->displayed], axis->p.x, axis->p.y);
+#else
+       gdk_cairo_set_source_pixmap (cr, axis->pixmap[axis->displayed], axis->p.x, axis->p.y);
+#endif
+       cairo_rectangle (cr, axis->p.x, axis->p.y, axis->p.width, axis->p.height);
+       cairo_fill (cr);
+       cairo_destroy (cr);
+
 }
 
 static void axis_compute_ticks (struct axis *axis, double x0, double xmax, int dir)
@@ -2450,7 +2808,7 @@ static int get_label_dim (struct axis *axis, int dir, double label)
                        break;
                y = y - floor (y);
        }
-       g_snprintf (str, 32, "%.*f", rdigits, label);
+       g_snprintf (str, sizeof(str), "%.*f", rdigits, label);
        switch (dir) {
        case AXIS_HORIZONTAL:
                 layout = gtk_widget_create_pango_layout(axis->g->drawing_area,
@@ -2487,70 +2845,81 @@ static void graph_select_segment (struct graph *g, int x, int y)
 {
        struct element_list *list;
        struct element *e;
+       guint num = 0;
 
        debug(DBS_FENTRY) puts ("graph_select_segment()");
 
        x -= g->geom.x;
        y = g->geom.height-1 - (y - g->geom.y);
 
+       set_busy_cursor (gtk_widget_get_window(g->drawing_area));
+
        for (list=g->elists; list; list=list->next)
                for (e=list->elements; e->type != ELMT_NONE; e++) {
                        switch (e->type) {
                        case ELMT_RECT:
                                break;
                        case ELMT_LINE:
-                               if (line_detect_collision (e, x, y))
-                                       cf_goto_frame(&cfile, e->parent->num);
+                               if (line_detect_collision (e, x, y)) {
+                                       num = e->parent->num;
+                               }
                                break;
-                       case ELMT_ARC:
-                               if (arc_detect_collision (e, x, y))
-                                       cf_goto_frame(&cfile, e->parent->num);
+                       case ELMT_ELLIPSE:
+                               if (ellipse_detect_collision (e, x, y)) {
+                                       num = e->parent->num;
+                               }
                                break;
                        default:
                                break;
                        }
                }
+
+
+       if (num) {
+               cf_goto_frame(&cfile, num);
+       }
+       unset_busy_cursor (gtk_widget_get_window(g->drawing_area));
 }
 
 static int line_detect_collision (struct element *e, int x, int y)
 {
-       int x1, y1, x2, y2;
+       int xx1, yy1, xx2, yy2;
 
        if (e->p.line.dim.x1 < e->p.line.dim.x2) {
-               x1 = (int )rint (e->p.line.dim.x1);
-               x2 = (int )rint (e->p.line.dim.x2);
+               xx1 = (int )rint (e->p.line.dim.x1);
+               xx2 = (int )rint (e->p.line.dim.x2);
        } else {
-               x1 = (int )rint (e->p.line.dim.x2);
-               x2 = (int )rint (e->p.line.dim.x1);
+               xx1 = (int )rint (e->p.line.dim.x2);
+               xx2 = (int )rint (e->p.line.dim.x1);
        }
        if (e->p.line.dim.y1 < e->p.line.dim.y2) {
-               y1 = (int )rint (e->p.line.dim.y1);
-               y2 = (int )rint (e->p.line.dim.y2);
+               yy1 = (int )rint (e->p.line.dim.y1);
+               yy2 = (int )rint (e->p.line.dim.y2);
        } else {
-               y1 = (int )rint (e->p.line.dim.y2);
-               y2 = (int )rint (e->p.line.dim.y1);
+               yy1 = (int )rint (e->p.line.dim.y2);
+               yy2 = (int )rint (e->p.line.dim.y1);
        }
        /*
-       printf ("line: (%d,%d)->(%d,%d), clicked: (%d,%d)\n", x1, y1, x2, y2, x, y);
+       printf ("line: (%d,%d)->(%d,%d), clicked: (%d,%d)\n", xx1, yy1, xx2, yy2, x, y);
         */
-       if ((x1==x && x2==x && y1<=y && y<=y2)||(y1==y && y2==y && x1<=x && x<=x2))
+       if ((xx1==x && xx2==x && yy1<=y && y<=yy2)||(yy1==y && yy2==y && xx1<=x && x<=xx2))
                return TRUE;
        else
                return FALSE;
 }
 
-static int arc_detect_collision (struct element *e, int x, int y)
+static int ellipse_detect_collision (struct element *e, int x, int y)
 {
-       int x1, y1, x2, y2;
+       int xx1, yy1, xx2, yy2;
 
-       x1 = (int )rint (e->p.arc.dim.x);
-       x2 = (int )rint (e->p.arc.dim.x + e->p.arc.dim.width);
-       y1 = (int )rint (e->p.arc.dim.y - e->p.arc.dim.height);
-       y2 = (int )rint (e->p.arc.dim.y);
+       xx1 = (int )rint (e->p.ellipse.dim.x);
+       xx2 = (int )rint (e->p.ellipse.dim.x + e->p.ellipse.dim.width);
+       yy1 = (int )rint (e->p.ellipse.dim.y - e->p.ellipse.dim.height);
+       yy2 = (int )rint (e->p.ellipse.dim.y);
        /*
-       printf ("arc: (%d,%d)->(%d,%d), clicked: (%d,%d)\n", x1, y1, x2, y2, x, y);
+       printf ("ellipse: (%d,%d)->(%d,%d), clicked: (%d,%d)\n", xx1, yy1, xx2, yy2, x, y);
         */
-       if (x1<=x && x<=x2 && y1<=y && y<=y2)
+       if (xx1<=x && x<=xx2 && yy1<=y && y<=yy2)
                return TRUE;
        else
                return FALSE;
@@ -2558,13 +2927,43 @@ static int arc_detect_collision (struct element *e, int x, int y)
 
 static void cross_xor (struct graph *g, int x, int y)
 {
+#if GTK_CHECK_VERSION(3,0,0)
+       GdkColor color_gray15 = {0x0, 0x2626, 0x2626, 0x2626};
+       cairo_t *cr;
+
+       /* XXX Fix me: lines do not disapere */
+       if (x > g->wp.x && x < g->wp.x+g->wp.width &&
+                               y >= g->wp.y && y < g->wp.y+g->wp.height) {
+               /* Draw horisontal line */
+               cr = gdk_cairo_create (gtk_widget_get_window(g->drawing_area));
+               cairo_set_operator (cr, CAIRO_OPERATOR_XOR);
+               gdk_cairo_set_source_color (cr, &color_gray15);
+               cairo_set_line_width (cr, 1.0);
+               cairo_move_to(cr,  g->wp.x, y);
+               cairo_line_to(cr,  g->wp.x + g->wp.width, y);
+               cairo_stroke(cr);
+               cairo_destroy(cr);
+               /* draw vertical line */
+               cr = gdk_cairo_create (gtk_widget_get_window(g->drawing_area));
+               cairo_set_operator (cr, CAIRO_OPERATOR_XOR);
+               gdk_cairo_set_source_color (cr, &color_gray15);
+               cairo_set_line_width (cr, 1.0);
+               cairo_move_to(cr,  x, g->wp.y);
+               cairo_line_to(cr,  x, g->wp.y + g->wp.height);
+               cairo_stroke(cr);
+               cairo_destroy(cr);
+       }
+
+#else
+
        if (x > g->wp.x && x < g->wp.x+g->wp.width &&
                                y >= g->wp.y && y < g->wp.y+g->wp.height) {
-               gdk_draw_line (g->drawing_area->window, xor_gc, g->wp.x,
+               gdk_draw_line (gtk_widget_get_window(g->drawing_area), xor_gc, g->wp.x,
                                                y, g->wp.x + g->wp.width, y);
-               gdk_draw_line (g->drawing_area->window, xor_gc, x,
+               gdk_draw_line (gtk_widget_get_window(g->drawing_area), xor_gc, x,
                                                g->wp.y, x, g->wp.y + g->wp.height);
        }
+#endif
 }
 
 static void cross_draw (struct graph *g, int x, int y)
@@ -2621,14 +3020,14 @@ static void magnify_create (struct graph *g, int x, int y)
        }
        graph_element_lists_make (mg);
 
-       gdk_window_get_position (GTK_WIDGET (g->toplevel)->window, &pos.x, &pos.y);
+       gdk_window_get_position (gtk_widget_get_window(GTK_WIDGET (g->toplevel)), &pos.x, &pos.y);
        g->magnify.x = pos.x + x - g->magnify.width/2;
        g->magnify.y = pos.y + y - g->magnify.height/2;
        offsetpos.x = g->magnify.x + g->magnify.offset.x;
        offsetpos.x = offsetpos.x >= 0 ? offsetpos.x : 0;
        offsetpos.y = g->magnify.y + g->magnify.offset.y;
        offsetpos.y = offsetpos.y >= 0 ? offsetpos.y : 0;
-       gtk_widget_set_uposition (mg->drawing_area, offsetpos.x, offsetpos.y);
+       gtk_window_set_position (GTK_WINDOW(mg->drawing_area), GTK_WIN_POS_NONE);
        magnify_get_geom (g, x, y);
 
        gtk_widget_show (mg->drawing_area);
@@ -2646,7 +3045,11 @@ static void magnify_create (struct graph *g, int x, int y)
                }
        } while (e);
 
+#if GTK_CHECK_VERSION(2,22,0)
+       mg->surface[0] = mg->surface[1] = NULL;
+#else
        mg->pixmap[0] = mg->pixmap[1] = NULL;
+#endif /* GTK_CHECK_VERSION(2,22,0) */
        graph_pixmaps_create (mg);
        magnify_draw (g);
        g->magnify.active = 1;
@@ -2656,7 +3059,7 @@ static void magnify_move (struct graph *g, int x, int y)
 {
        struct ipoint pos, offsetpos;
 
-       gdk_window_get_position (GTK_WIDGET (g->toplevel)->window, &pos.x, &pos.y);
+       gdk_window_get_position (gtk_widget_get_window(GTK_WIDGET (g->toplevel)), &pos.x, &pos.y);
        g->magnify.x = pos.x + x - g->magnify.width/2;
        g->magnify.y = pos.y + y - g->magnify.height/2;
        offsetpos.x = g->magnify.x + g->magnify.offset.x;
@@ -2664,8 +3067,6 @@ static void magnify_move (struct graph *g, int x, int y)
        offsetpos.y = g->magnify.y + g->magnify.offset.y;
        offsetpos.y = offsetpos.y >= 0 ? offsetpos.y : 0;
        magnify_get_geom (g, x, y);
-       gtk_widget_set_uposition (g->magnify.g->drawing_area, offsetpos.x,
-                                                               offsetpos.y);
        magnify_draw (g);
 }
 
@@ -2675,14 +3076,27 @@ static void magnify_destroy (struct graph *g)
        struct graph *mg = g->magnify.g;
 
        window_destroy (GTK_WIDGET (mg->drawing_area));
-       gdk_pixmap_unref (mg->pixmap[0]);
-       gdk_pixmap_unref (mg->pixmap[1]);
+
+#if GTK_CHECK_VERSION(2,22,0)
+       if(mg->surface[0]){
+                cairo_surface_destroy (mg->surface[0]);
+       }
+       if(mg->surface[1]){
+                cairo_surface_destroy (mg->surface[1]);
+       }
+#else
+       g_object_unref (mg->pixmap[0]);
+       g_object_unref (mg->pixmap[1]);
+#endif /* GTK_CHECK_VERSION(2,22,0) */
        for (list=mg->elists; list; list=list->next)
                g_free (list->elements);
-       while (mg->elists->next) {
-               list = mg->elists->next->next;
-               g_free (mg->elists->next);
-               mg->elists->next = list;
+
+       if (mg->elists) {
+    while (mg->elists->next) {
+      list = mg->elists->next->next;
+      g_free (mg->elists->next);
+      mg->elists->next = list;
+    }
        }
        g_free (g->magnify.g);
        g->magnify.active = 0;
@@ -2692,7 +3106,7 @@ static void magnify_get_geom (struct graph *g, int x, int y)
 {
        int posx, posy;
 
-       gdk_window_get_position (GTK_WIDGET (g->toplevel)->window, &posx, &posy);
+       gdk_window_get_position (gtk_widget_get_window(GTK_WIDGET (g->toplevel)), &posx, &posy);
 
        g->magnify.g->geom.x = g->geom.x;
        g->magnify.g->geom.y = g->geom.y;
@@ -2712,27 +3126,42 @@ static void magnify_get_geom (struct graph *g, int x, int y)
 
 static void magnify_draw (struct graph *g)
 {
+       cairo_t *cr;
        int not_disp = 1 ^ g->magnify.g->displayed;
 
        graph_pixmap_draw (g->magnify.g);
        /* graph pixmap is almost ready, just add border */
-       gdk_draw_line (g->magnify.g->pixmap[not_disp], g->fg_gc, 0, 0,
-                                               g->magnify.width - 1, 0);
-       gdk_draw_line (g->magnify.g->pixmap[not_disp], g->fg_gc,
-                       g->magnify.width - 1, 0, g->magnify.width - 1, g->magnify.height);
-       gdk_draw_line (g->magnify.g->pixmap[not_disp], g->fg_gc, 0, 0,
-                                               0, g->magnify.height - 1);
-       gdk_draw_line (g->magnify.g->pixmap[not_disp], g->fg_gc, 0,
-                       g->magnify.height - 1, g->magnify.width - 1, g->magnify.height - 1);
+#if GTK_CHECK_VERSION(2,22,0)
+       cr = cairo_create (g->magnify.g->surface[not_disp]);
+#else
+       cr = gdk_cairo_create (g->magnify.g->pixmap[not_disp]);
+#endif /* GTK_CHECK_VERSION(2,22,0) */
+       cairo_set_line_width (cr, 1.0);
+       cairo_move_to(cr, 0, 0);
+       cairo_line_to(cr, g->magnify.width - 1, 0);
+       cairo_stroke(cr);
+
+       cairo_move_to(cr, g->magnify.width - 1, 0);
+       cairo_line_to(cr, g->magnify.width - 1, g->magnify.height);
+       cairo_stroke(cr);
+
+       cairo_move_to(cr, 0, 0);
+       cairo_line_to(cr, 0,g->magnify.height - 1);
+       cairo_stroke(cr);
+
+       cairo_move_to(cr, 0, g->magnify.height - 1);
+       cairo_line_to(cr, g->magnify.width - 1, g->magnify.height - 1);
+       cairo_stroke(cr);
+       cairo_destroy(cr);
 
        graph_pixmaps_switch (g->magnify.g);
        graph_pixmap_display (g->magnify.g);
 
 }
 
-static gint configure_event (GtkWidget *widget, GdkEventConfigure *event)
+static gboolean configure_event (GtkWidget *widget, GdkEventConfigure *event, gpointer user_data _U_)
 {
-       struct graph *g = (struct graph *) OBJECT_GET_DATA(widget, "graph");
+        struct graph *g = (struct graph *) g_object_get_data(G_OBJECT(widget), "graph");
        struct {
                double x, y;
        } zoom;
@@ -2789,9 +3218,10 @@ static gint configure_event (GtkWidget *widget, GdkEventConfigure *event)
        return TRUE;
 }
 
-static gint expose_event (GtkWidget *widget, GdkEventExpose *event)
+static gboolean expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer user_data _U_)
 {
-       struct graph *g = (struct graph *) OBJECT_GET_DATA(widget, "graph");
+    struct graph *g = (struct graph *) g_object_get_data(G_OBJECT(widget), "graph");
+    cairo_t *cr;
 
        debug(DBS_FENTRY) puts ("expose_event()");
 
@@ -2799,11 +3229,20 @@ static gint expose_event (GtkWidget *widget, GdkEventExpose *event)
                return TRUE;
 
        /* lower left corner */
-       gdk_draw_rectangle (g->drawing_area->window, g->bg_gc, TRUE, 0,
-                       g->wp.y + g->wp.height, g->y_axis->p.width, g->x_axis->p.height);
+       cr = gdk_cairo_create (gtk_widget_get_window(g->drawing_area));
+       cairo_set_source_rgb (cr, 1, 1, 1);
+       cairo_rectangle (cr, 0, g->wp.y + g->wp.height, g->y_axis->p.width, g->x_axis->p.height);
+       cairo_fill (cr);
+       cairo_destroy(cr);
+       cr = NULL;
+
        /* right margin */
-       gdk_draw_rectangle (g->drawing_area->window, g->bg_gc, TRUE,
-                       g->wp.x + g->wp.width, g->wp.y, RMARGIN_WIDTH, g->wp.height);
+       cr = gdk_cairo_create (gtk_widget_get_window(g->drawing_area));
+       cairo_set_source_rgb (cr, 1, 1, 1);
+       cairo_rectangle (cr, g->wp.x + g->wp.width, g->wp.y, RMARGIN_WIDTH, g->wp.height);
+       cairo_fill (cr);
+       cairo_destroy(cr);
+       cr = NULL;
 
        graph_pixmap_display (g);
        graph_title_pixmap_display (g);
@@ -2813,104 +3252,276 @@ static gint expose_event (GtkWidget *widget, GdkEventExpose *event)
        return TRUE;
 }
 
-static gint button_press_event (GtkWidget *widget, GdkEventButton *event)
+static void do_zoom_mouse (struct graph *g, GdkEventButton *event)
 {
-       struct graph *g = (struct graph *) OBJECT_GET_DATA(widget, "graph");
+       int cur_width = g->geom.width, cur_height = g->geom.height;
+       struct { double x, y; } factor;
+
+       if (g->zoom.flags & ZOOM_OUT) {
+               if (g->zoom.flags & ZOOM_HLOCK)
+                       factor.x = 1.0;
+               else
+                       factor.x = 1 / g->zoom.step_x;
+               if (g->zoom.flags & ZOOM_VLOCK)
+                       factor.y = 1.0;
+               else
+                       factor.y = 1 / g->zoom.step_y;
+       } else {
+               if (g->zoom.flags & ZOOM_HLOCK)
+                       factor.x = 1.0;
+               else
+                       factor.x = g->zoom.step_x;
+               if (g->zoom.flags & ZOOM_VLOCK)
+                       factor.y = 1.0;
+               else
+                       factor.y = g->zoom.step_y;
+       }
+
+       g->geom.width = (int )rint (g->geom.width * factor.x);
+       g->geom.height = (int )rint (g->geom.height * factor.y);
+       if (g->geom.width < g->wp.width)
+               g->geom.width = g->wp.width;
+       if (g->geom.height < g->wp.height)
+               g->geom.height = g->wp.height;
+       g->zoom.x = (g->geom.width - 1) / g->bounds.width;
+       g->zoom.y = (g->geom.height- 1) / g->bounds.height;
+
+       g->geom.x -= (int )rint ((g->geom.width - cur_width) *
+                       ((event->x-g->geom.x)/(double )cur_width));
+       g->geom.y -= (int )rint ((g->geom.height - cur_height) *
+                       ((event->y-g->geom.y)/(double )cur_height));
+
+       if (g->geom.x > g->wp.x)
+               g->geom.x = g->wp.x;
+       if (g->geom.y > g->wp.y)
+               g->geom.y = g->wp.y;
+       if (g->wp.x + g->wp.width > g->geom.x + g->geom.width)
+               g->geom.x = g->wp.width + g->wp.x - g->geom.width;
+       if (g->wp.y + g->wp.height > g->geom.y + g->geom.height)
+               g->geom.y = g->wp.height + g->wp.y - g->geom.height;
+#if 0
+       printf ("button press: graph: (%d,%d), (%d,%d); viewport: (%d,%d), "
+                       "(%d,%d); zooms: (%f,%f)\n", g->geom.x, g->geom.y,
+                       g->geom.width, g->geom.height, g->wp.x, g->wp.y, g->wp.width,
+                       g->wp.height, g->zoom.x, g->zoom.y);
+#endif
+       graph_element_lists_make (g);
+       g->cross.erase_needed = 0;
+       graph_display (g);
+       axis_display (g->y_axis);
+       axis_display (g->x_axis);
+       update_zoom_spins (g);
+       if (g->cross.draw)
+               cross_draw (g, (int) event->x, (int) event->y);
+}
+
+static void do_zoom_keyboard (struct graph *g)
+{
+       int cur_width = g->geom.width, cur_height = g->geom.height;
+       struct { double x, y; } factor;
+       int pointer_x, pointer_y;
+
+       gdk_window_get_pointer (gtk_widget_get_window(g->drawing_area), &pointer_x, &pointer_y, 0);
+
+       if (g->zoom.flags & ZOOM_OUT) {
+               if (g->zoom.flags & ZOOM_HLOCK)
+                       factor.x = 1.0;
+               else
+                       factor.x = 1 / g->zoom.step_x;
+               if (g->zoom.flags & ZOOM_VLOCK)
+                       factor.y = 1.0;
+               else
+                       factor.y = 1 / g->zoom.step_y;
+       } else {
+               if (g->zoom.flags & ZOOM_HLOCK)
+                       factor.x = 1.0;
+               else
+                       factor.x = g->zoom.step_x;
+               if (g->zoom.flags & ZOOM_VLOCK)
+                       factor.y = 1.0;
+               else
+                       factor.y = g->zoom.step_y;
+       }
+
+       g->geom.width = (int )rint (g->geom.width * factor.x);
+       g->geom.height = (int )rint (g->geom.height * factor.y);
+       if (g->geom.width < g->wp.width)
+               g->geom.width = g->wp.width;
+       if (g->geom.height < g->wp.height)
+               g->geom.height = g->wp.height;
+       g->zoom.x = (g->geom.width - 1) / g->bounds.width;
+       g->zoom.y = (g->geom.height- 1) / g->bounds.height;
+
+       g->geom.x -= (int )rint ((g->geom.width - cur_width) *
+                       ((pointer_x - g->geom.x)/(double )cur_width));
+       g->geom.y -= (int )rint ((g->geom.height - cur_height) *
+                       ((pointer_y - g->geom.y)/(double )cur_height));
+
+       if (g->geom.x > g->wp.x)
+               g->geom.x = g->wp.x;
+       if (g->geom.y > g->wp.y)
+               g->geom.y = g->wp.y;
+       if (g->wp.x + g->wp.width > g->geom.x + g->geom.width)
+               g->geom.x = g->wp.width + g->wp.x - g->geom.width;
+       if (g->wp.y + g->wp.height > g->geom.y + g->geom.height)
+               g->geom.y = g->wp.height + g->wp.y - g->geom.height;
+#if 0
+       printf ("key press: graph: (%d,%d), (%d,%d); viewport: (%d,%d), "
+                       "(%d,%d); zooms: (%f,%f)\n", g->geom.x, g->geom.y,
+                       g->geom.width, g->geom.height, g->wp.x, g->wp.y, g->wp.width,
+                       g->wp.height, g->zoom.x, g->zoom.y);
+#endif
+
+       graph_element_lists_make (g);
+       g->cross.erase_needed = 0;
+       graph_display (g);
+       axis_display (g->y_axis);
+       axis_display (g->x_axis);
+       update_zoom_spins (g);
+       if (g->cross.draw)
+               cross_draw (g, pointer_x, pointer_y);
+}
+
+static void do_zoom_in_keyboard (struct graph *g)
+{
+       gtk_toggle_button_set_active (g->zoom.widget.in_toggle, TRUE);
+       do_zoom_keyboard (g);
+}
+
+static void do_zoom_out_keyboard (struct graph *g)
+{
+       gtk_toggle_button_set_active (g->zoom.widget.out_toggle, TRUE);
+       do_zoom_keyboard (g);
+       gtk_toggle_button_set_active (g->zoom.widget.in_toggle, TRUE);
+}
+
+static void do_select_segment (struct graph *g)
+{
+       int pointer_x, pointer_y;
+
+       gdk_window_get_pointer (gtk_widget_get_window(g->drawing_area), &pointer_x, &pointer_y, 0);
+       graph_select_segment (g, pointer_x, pointer_y);
+}
+
+static void do_wscale_graph (struct graph *g)
+{
+       gtk_toggle_button_set_active (g->gt.graph_wscale, TRUE);
+}
+
+static void do_rtt_graph (struct graph *g)
+{
+        gtk_toggle_button_set_active (g->gt.graph_rtt, TRUE);
+}
+
+static void do_throughput_graph (struct graph *g)
+{
+        gtk_toggle_button_set_active (g->gt.graph_tput, TRUE);
+}
+
+static void do_ts_graph_stevens (struct graph *g)
+{
+        gtk_toggle_button_set_active (g->gt.graph_tseqstevens, TRUE);
+}
+
+static void do_ts_graph_tcptrace (struct graph *g)
+{
+        gtk_toggle_button_set_active (g->gt.graph_tseqttrace, TRUE);
+}
+
+static void do_magnify_create (struct graph *g)
+{
+       int pointer_x, pointer_y;
+
+       gdk_window_get_pointer (gtk_widget_get_window(g->drawing_area), &pointer_x, &pointer_y, 0);
+
+       magnify_create (g, (int )rint (pointer_x), (int )rint (pointer_y));
+}
+
+static void do_key_motion (struct graph *g)
+{
+       if (g->geom.x > g->wp.x)
+               g->geom.x = g->wp.x;
+       if (g->geom.y > g->wp.y)
+               g->geom.y = g->wp.y;
+       if (g->wp.x + g->wp.width > g->geom.x + g->geom.width)
+               g->geom.x = g->wp.width + g->wp.x - g->geom.width;
+       if (g->wp.y + g->wp.height > g->geom.y + g->geom.height)
+               g->geom.y = g->wp.height + g->wp.y - g->geom.height;
+       g->cross.erase_needed = 0;
+       graph_display (g);
+       axis_display (g->y_axis);
+       axis_display (g->x_axis);
+       if (g->cross.draw) {
+               int pointer_x, pointer_y;
+               gdk_window_get_pointer (gtk_widget_get_window(g->drawing_area), &pointer_x, &pointer_y, 0);
+               cross_draw (g, pointer_x, pointer_y);
+       }
+}
+
+static void do_key_motion_up (struct graph *g, int step)
+{
+       g->geom.y += step;
+       do_key_motion (g);
+}
+
+static void do_key_motion_down (struct graph *g, int step)
+{
+       g->geom.y -= step;
+       do_key_motion (g);
+}
+
+static void do_key_motion_left (struct graph *g, int step)
+{
+       g->geom.x += step;
+       do_key_motion (g);
+}
+
+static void do_key_motion_right (struct graph *g, int step)
+{
+       g->geom.x -= step;
+       do_key_motion (g);
+}
+
+static gboolean button_press_event (GtkWidget *widget, GdkEventButton *event, gpointer user_data _U_)
+{
+        struct graph *g = (struct graph *) g_object_get_data(G_OBJECT(widget), "graph");
 
        debug(DBS_FENTRY) puts ("button_press_event()");
 
-       if (event->button == 3) {
-               if (event->state & GDK_CONTROL_MASK)
+       if (event->button == MOUSE_BUTTON_RIGHT) {
+               if (event->state & GDK_CONTROL_MASK) {
                        magnify_create (g, (int )rint (event->x), (int )rint (event->y));
-               else {
+               else {
                        g->grab.x = (int )rint (event->x) - g->geom.x;
                        g->grab.y = (int )rint (event->y) - g->geom.y;
                        g->grab.grabbed = TRUE;
                }
-#ifdef _WIN32
+#ifdef ORIGINAL_WIN32_BUTTONS
                                /* Windows mouse control:        */
                                /* [<ctrl>-left] - select packet */
                                /* [left] - zoom in              */
                                /* [<shift>-left] - zoom out     */
-       } else if (event->button == 1) {
+       } else if (event->button == MOUSE_BUTTON_LEFT) {
                if (event->state & GDK_CONTROL_MASK) {
                        graph_select_segment (g, (int)event->x, (int)event->y);
                } else {
-#else /* _WIN32 */
-       } else if (event->button == 2) {
+#else /* !ORIGINAL_WIN32_BUTTONS */
+       } else if (event->button == MOUSE_BUTTON_MIDDLE) {
 #endif
-               int cur_width = g->geom.width, cur_height = g->geom.height;
-               struct { double x, y; } factor;
-
-               if (g->zoom.flags & ZOOM_OUT) {
-                       if (g->zoom.flags & ZOOM_HLOCK)
-                               factor.x = 1.0;
-                       else
-                               factor.x = 1 / g->zoom.step_x;
-                       if (g->zoom.flags & ZOOM_VLOCK)
-                               factor.y = 1.0;
-                       else
-                               factor.y = 1 / g->zoom.step_y;
-               } else {
-                       if (g->zoom.flags & ZOOM_HLOCK)
-                               factor.x = 1.0;
-                       else
-                               factor.x = g->zoom.step_x;
-                       if (g->zoom.flags & ZOOM_VLOCK)
-                               factor.y = 1.0;
-                       else
-                               factor.y = g->zoom.step_y;
-               }
-
-               g->geom.width = (int )rint (g->geom.width * factor.x);
-               g->geom.height = (int )rint (g->geom.height * factor.y);
-               if (g->geom.width < g->wp.width)
-                       g->geom.width = g->wp.width;
-               if (g->geom.height < g->wp.height)
-                       g->geom.height = g->wp.height;
-               g->zoom.x = (g->geom.width - 1) / g->bounds.width;
-               g->zoom.y = (g->geom.height- 1) / g->bounds.height;
-
-               g->geom.x -= (int )rint ((g->geom.width - cur_width) *
-                                               ((event->x-g->geom.x)/(double )cur_width));
-               g->geom.y -= (int )rint ((g->geom.height - cur_height) *
-                                               ((event->y-g->geom.y)/(double )cur_height));
-
-               if (g->geom.x > g->wp.x)
-                       g->geom.x = g->wp.x;
-               if (g->geom.y > g->wp.y)
-                       g->geom.y = g->wp.y;
-               if (g->wp.x + g->wp.width > g->geom.x + g->geom.width)
-                       g->geom.x = g->wp.width + g->wp.x - g->geom.width;
-               if (g->wp.y + g->wp.height > g->geom.y + g->geom.height)
-                       g->geom.y = g->wp.height + g->wp.y - g->geom.height;
-#if 0
-               printf ("button press: graph: (%d,%d), (%d,%d); viewport: (%d,%d), "
-                               "(%d,%d); zooms: (%f,%f)\n", g->geom.x, g->geom.y,
-                               g->geom.width, g->geom.height, g->wp.x, g->wp.y, g->wp.width,
-                               g->wp.height, g->zoom.x, g->zoom.y);
-#endif
-               graph_element_lists_make (g);
-               g->cross.erase_needed = 0;
-               graph_display (g);
-               axis_display (g->y_axis);
-               axis_display (g->x_axis);
-               update_zoom_spins (g);
-               if (g->cross.draw)
-                       cross_draw (g, (int) event->x, (int) event->y);
-#ifndef _WIN32
-       } else if (event->button == 1) {
+               do_zoom_mouse(g, event);
+#ifndef ORIGINAL_WIN32_BUTTONS
+       } else if (event->button == MOUSE_BUTTON_LEFT) {
                graph_select_segment (g, (int )event->x, (int )event->y);
-#else /* _WIN32 */
+#else /* ORIGINAL_WIN32_BUTTONS*/
                }
 #endif
        }
        return TRUE;
 }
 
-static gint motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
+static gboolean motion_notify_event (GtkWidget *widget, GdkEventMotion *event, gpointer user_data _U_)
 {
-       struct graph *g = (struct graph *) OBJECT_GET_DATA(widget, "graph");
+        struct graph *g = (struct graph *) g_object_get_data(G_OBJECT(widget), "graph");
        int x, y;
        GdkModifierType state;
 
@@ -2965,13 +3576,13 @@ static gint motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
        return TRUE;
 }
 
-static gint button_release_event (GtkWidget *widget, GdkEventButton *event)
+static gboolean button_release_event (GtkWidget *widget, GdkEventButton *event, gpointer user_data _U_)
 {
-       struct graph *g = (struct graph *) OBJECT_GET_DATA(widget, "graph");
+        struct graph *g = (struct graph *) g_object_get_data(G_OBJECT(widget), "graph");
 
        debug(DBS_FENTRY) puts ("button_release_event()");
 
-       if (event->button == 3)
+       if (event->button == MOUSE_BUTTON_RIGHT)
                g->grab.grabbed = FALSE;
 
        if (g->magnify.active)
@@ -2979,43 +3590,89 @@ static gint button_release_event (GtkWidget *widget, GdkEventButton *event)
        return TRUE;
 }
 
-static gint key_press_event (GtkWidget *widget, GdkEventKey *event)
+static gboolean key_press_event (GtkWidget *widget, GdkEventKey *event, gpointer user_data _U_)
 {
-       struct graph *g = (struct graph *) OBJECT_GET_DATA(widget, "graph");
+        struct graph *g = (struct graph *) g_object_get_data(G_OBJECT(widget), "graph");
+       int step;
 
        debug(DBS_FENTRY) puts ("key_press_event()");
 
-       if (event->keyval == 32 /*space*/) {
-               g->cross.draw ^= 1;
-#if 0
-               if (g->cross.draw) {
-                       int x, y;
-                       gdk_window_get_pointer (g->drawing_area->window, &x, &y, 0);
-                       cross_draw (g);
-               } else if (g->cross.erase_needed) {
-                       cross_erase (g);
-               }
-#endif
-               /* toggle buttons emit their "toggled" signals so don't bother doing
-                * any real work here, it will be done in signal handlers */
-               if (g->cross.draw)
-                       gtk_toggle_button_set_active (g->cross.on_toggle, TRUE);
-               else
-                       gtk_toggle_button_set_active (g->cross.off_toggle, TRUE);
-       } else if (event->keyval == 't')
+       if((event->state & GDK_CONTROL_MASK) && (event->state & GDK_SHIFT_MASK))
+               step = 0;
+       else if (event->state & GDK_CONTROL_MASK)
+               step = 1;
+       else if (event->state & GDK_SHIFT_MASK)
+               step = 10;
+       else
+               step = 100;
+
+       switch (event->keyval) {
+       case ' ':
+               toggle_crosshairs (g);
+               break;
+       case 't':
                toggle_time_origin (g);
-       else if (event->keyval == 's')
+               break;
+       case 's':
                toggle_seq_origin (g);
-       else if (event->keyval == GDK_Shift_L) {
-               /* g->zoom.flags |= ZOOM_OUT; */
-               gtk_toggle_button_set_active (g->zoom.widget.out_toggle, TRUE);
+               break;
+       case 'r':
+       case GDK_Home:
+               restore_initial_graph_view (g);
+               break;
+       case 'i':
+       case '+':
+               do_zoom_in_keyboard (g);
+               break;
+       case 'o':
+       case '-':
+               do_zoom_out_keyboard (g);
+               break;
+       case 'm':
+               do_magnify_create (g);
+               break;
+       case 'g':
+               do_select_segment (g);
+               break;
+        case '1':
+               do_rtt_graph (g);
+               break;
+       case '2':
+               do_throughput_graph (g);
+               break;
+       case '3':
+               do_ts_graph_stevens (g);
+               break;
+       case '4':
+               do_ts_graph_tcptrace (g);
+               break;
+       case '5':
+               do_wscale_graph(g);
+               break;
+       case GDK_Left:
+               do_key_motion_left (g, step);
+               break;
+       case GDK_Up:
+               do_key_motion_up (g, step);
+               break;
+       case GDK_Right:
+               do_key_motion_right (g, step);
+               break;
+       case GDK_Down:
+               do_key_motion_down (g, step);
+               break;
+       case GDK_F1:
+               callback_create_help (NULL, NULL);
+               break;
+       default:
+               break;
        }
        return TRUE;
 }
 
-static gint key_release_event (GtkWidget *widget, GdkEventKey *event)
+static gboolean key_release_event (GtkWidget *widget, GdkEventKey *event, gpointer user_data _U_)
 {
-       struct graph *g = (struct graph *) OBJECT_GET_DATA(widget, "graph");
+        struct graph *g = (struct graph *) g_object_get_data(G_OBJECT(widget), "graph");
 
        debug(DBS_FENTRY) puts ("key_release_event()");
 
@@ -3026,9 +3683,9 @@ static gint key_release_event (GtkWidget *widget, GdkEventKey *event)
        return TRUE;
 }
 
-static gint leave_notify_event (GtkWidget *widget, GdkEventCrossing *event _U_)
+static gboolean leave_notify_event (GtkWidget *widget, GdkEventCrossing *event _U_, gpointer user_data _U_)
 {
-       struct graph *g = (struct graph *) OBJECT_GET_DATA(widget, "graph");
+        struct graph *g = (struct graph *) g_object_get_data(G_OBJECT(widget), "graph");
 
        if (g->cross.erase_needed)
                cross_erase (g);
@@ -3036,19 +3693,39 @@ static gint leave_notify_event (GtkWidget *widget, GdkEventCrossing *event _U_)
        return TRUE;
 }
 
-static gint enter_notify_event (GtkWidget *widget, GdkEventCrossing *event _U_)
+static gboolean enter_notify_event (GtkWidget *widget, GdkEventCrossing *event _U_, gpointer user_data _U_)
 {
-       struct graph *g = (struct graph *) OBJECT_GET_DATA(widget, "graph");
+        struct graph *g = (struct graph *) g_object_get_data(G_OBJECT(widget), "graph");
 
        /* graph_pixmap_display (g); */
        if (g->cross.draw) {
                int x, y;
-               gdk_window_get_pointer (g->drawing_area->window, &x, &y, 0);
+               gdk_window_get_pointer (gtk_widget_get_window(g->drawing_area), &x, &y, 0);
                cross_draw (g, x, y);
        }
        return TRUE;
 }
 
+static void toggle_crosshairs (struct graph *g)
+{
+       g->cross.draw ^= 1;
+#if 0
+       if (g->cross.draw) {
+               int x, y;
+               gdk_window_get_pointer (gtk_widget_get_window(g->drawing_area), &x, &y, 0);
+               cross_draw (g);
+       } else if (g->cross.erase_needed) {
+               cross_erase (g);
+       }
+#endif
+       /* toggle buttons emit their "toggled" signals so don't bother doing
+        * any real work here, it will be done in signal handlers */
+       if (g->cross.draw)
+               gtk_toggle_button_set_active (g->cross.on_toggle, TRUE);
+       else
+               gtk_toggle_button_set_active (g->cross.off_toggle, TRUE);
+}
+
 static void toggle_time_origin (struct graph *g)
 {
        switch (g->type) {
@@ -3087,6 +3764,15 @@ static void toggle_seq_origin (struct graph *g)
        }
 }
 
+static void restore_initial_graph_view (struct graph *g)
+{
+       g->geom.width = g->wp.width;
+       g->geom.height = g->wp.height;
+       g->geom.x = g->wp.x;
+       g->geom.y = g->wp.y;
+       graph_init_sequence (g);
+}
+
 static int get_num_dsegs (struct graph *g)
 {
        int count;
@@ -3134,7 +3820,7 @@ static void tseq_stevens_read_config (struct graph *g)
        g->s.tseq_stevens.flags = 0;
 
        g->title = (const char ** )g_malloc (2 * sizeof (char *));
-       g->title[0] = "Time/Sequence Graph";
+       g->title[0] = "Time/Sequence Graph (Stevens)";
        g->title[1] = NULL;
        g->y_axis->label = (const char ** )g_malloc (3 * sizeof (char * ));
        g->y_axis->label[0] = "number[B]";
@@ -3267,8 +3953,8 @@ static void tseq_stevens_make_elmtlist (struct graph *g)
 {
        struct segment *tmp;
        struct element *elements, *e;
-       double x0 = g->bounds.x0, y0 = g->bounds.y0;
-       guint32 seq_base = (guint32) y0;
+       double xx0 = g->bounds.x0, yy0 = g->bounds.y0;
+       guint32 seq_base = (guint32) yy0;
        guint32 seq_cur;
 
        debug(DBS_FENTRY) puts ("tseq_stevens_make_elmtlist()");
@@ -3290,19 +3976,15 @@ static void tseq_stevens_make_elmtlist (struct graph *g)
                }
                /* data seg */
                seq_cur = tmp->th_seq - seq_base;
-               secs = g->zoom.x * (tmp->rel_secs + tmp->rel_usecs / 1000000.0 - x0);
+               secs = g->zoom.x * (tmp->rel_secs + tmp->rel_usecs / 1000000.0 - xx0);
                seqno = g->zoom.y * seq_cur;
 
-               e->type = ELMT_ARC;
+               e->type = ELMT_ELLIPSE;
                e->parent = tmp;
-               e->gc = g->fg_gc;
-               e->p.arc.dim.width = g->s.tseq_stevens.seq_width;
-               e->p.arc.dim.height = g->s.tseq_stevens.seq_height;
-               e->p.arc.dim.x = secs - g->s.tseq_stevens.seq_width/2.0;
-               e->p.arc.dim.y = seqno + g->s.tseq_stevens.seq_height/2.0;
-               e->p.arc.filled = TRUE;
-               e->p.arc.angle1 = 0;
-               e->p.arc.angle2 = 23040;
+               e->p.ellipse.dim.width = g->s.tseq_stevens.seq_width;
+               e->p.ellipse.dim.height = g->s.tseq_stevens.seq_height;
+               e->p.ellipse.dim.x = secs - g->s.tseq_stevens.seq_width/2.0;
+               e->p.ellipse.dim.y = seqno + g->s.tseq_stevens.seq_height/2.0;
                e++;
        }
        e->type = ELMT_NONE;
@@ -3335,59 +4017,26 @@ static void tseq_stevens_toggle_time_origin (struct graph *g)
 
 static void tseq_tcptrace_read_config (struct graph *g)
 {
-       GdkColormap *colormap;
-       GdkColor color;
+
+       /* Black */
+       g->s.tseq_tcptrace.seq_color.pixel=0;
+       g->s.tseq_tcptrace.seq_color.red=0;
+       g->s.tseq_tcptrace.seq_color.green=0;
+       g->s.tseq_tcptrace.seq_color.blue=0;
+
+       /* LightSlateGray */
+       g->s.tseq_tcptrace.ack_color[0].pixel=0;
+       g->s.tseq_tcptrace.ack_color[0].red=0x7777;
+       g->s.tseq_tcptrace.ack_color[0].green=0x8888;
+       g->s.tseq_tcptrace.ack_color[0].blue=0x9999;
+
+       /* LightGray */
+       g->s.tseq_tcptrace.ack_color[1].pixel=0;
+       g->s.tseq_tcptrace.ack_color[1].red=0xd3d3;
+       g->s.tseq_tcptrace.ack_color[1].green=0xd3d3;
+       g->s.tseq_tcptrace.ack_color[1].blue=0xd3d3;
 
        g->s.tseq_tcptrace.flags = 0;
-       g->s.tseq_tcptrace.gc_seq = gdk_gc_new (g->drawing_area->window);
-       g->s.tseq_tcptrace.gc_ack[0] = gdk_gc_new (g->drawing_area->window);
-       g->s.tseq_tcptrace.gc_ack[1] = gdk_gc_new (g->drawing_area->window);
-       colormap = gdk_window_get_colormap (g->drawing_area->window);
-       if (!gdk_color_parse ("black", &color)) {
-               /*
-                * XXX - do more than just warn.
-                */
-               simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
-                   "Could not parse color black.");
-       }
-       if (!gdk_colormap_alloc_color (colormap, &color, FALSE, TRUE)) {
-               /*
-                * XXX - do more than just warn.
-                */
-               simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
-                   "Could not allocate color black.");
-       }
-       gdk_gc_set_foreground (g->s.tseq_tcptrace.gc_seq, &color);
-       if (!gdk_color_parse ("LightSlateGray", &color)) {
-               /*
-                * XXX - do more than just warn.
-                */
-               simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
-                   "Could not parse color LightSlateGray.");
-       }
-       if (!gdk_colormap_alloc_color (colormap, &color, FALSE, TRUE)) {
-               /*
-                * XXX - do more than just warn.
-                */
-               simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
-                   "Could not allocate color LightSlateGray.");
-       }
-       gdk_gc_set_foreground (g->s.tseq_tcptrace.gc_ack[0], &color);
-       if (!gdk_color_parse ("LightGray", &color)) {
-               /*
-                * XXX - do more than just warn.
-                */
-               simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
-                   "Could not parse color LightGray.");
-       }
-       if (!gdk_colormap_alloc_color (colormap, &color, FALSE, TRUE)) {
-               /*
-                * XXX - do more than just warn.
-                */
-               simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
-                   "Could not allocate color LightGray.");
-       }
-       gdk_gc_set_foreground (g->s.tseq_tcptrace.gc_ack[1], &color);
 
        g->elists->next = (struct element_list * )
                                g_malloc (sizeof (struct element_list));
@@ -3395,7 +4044,7 @@ static void tseq_tcptrace_read_config (struct graph *g)
        g->elists->next->elements = NULL;
 
        g->title = (const char ** )g_malloc (2 * sizeof (char *));
-       g->title[0] = "Time/Sequence Graph";
+       g->title[0] = "Time/Sequence Graph (tcptrace)";
        g->title[1] = NULL;
        g->y_axis->label = (const char ** )g_malloc (3 * sizeof (char * ));
        g->y_axis->label[0] = "number[B]";
@@ -3411,7 +4060,7 @@ static void tseq_tcptrace_make_elmtlist (struct graph *g)
        struct segment *tmp;
        struct element *elements0, *e0;         /* list of elmts with prio 0 */
        struct element *elements1, *e1;         /* list of elmts with prio 1 */
-       double x0, y0;
+       double xx0, yy0;
        double p_t = 0; /* ackno, window and time of previous segment */
        double p_ackno = 0, p_win = 0;
        gboolean ack_seen=FALSE;
@@ -3433,16 +4082,16 @@ static void tseq_tcptrace_make_elmtlist (struct graph *g)
        } else
                e1 = elements1 = g->elists->next->elements;
 
-       x0 = g->bounds.x0;
-       y0 = g->bounds.y0;
-       seq_base = (guint32) y0;
+       xx0 = g->bounds.x0;
+       yy0 = g->bounds.y0;
+       seq_base = (guint32) yy0;
 
        for (tmp=g->segments; tmp; tmp=tmp->next) {
                double secs, data;
                double x;
 
                secs = tmp->rel_secs + tmp->rel_usecs / 1000000.0;
-               x = secs - x0;
+               x = secs - xx0;
                x *= g->zoom.x;
                if(compare_headers(&g->current->ip_src, &g->current->ip_dst,
                                   g->current->th_sport, g->current->th_dport,
@@ -3450,7 +4099,7 @@ static void tseq_tcptrace_make_elmtlist (struct graph *g)
                                   tmp->th_sport, tmp->th_dport,
                                   COMPARE_CURR_DIR)) {
                        /* forward direction -> we need seqno and amount of data */
-                       double y1, y2;
+                       double yy1, yy2;
 
                        seq_cur = tmp->th_seq - seq_base;
                        if (TCP_SYN (tmp->th_flags) || TCP_FIN (tmp->th_flags))
@@ -3458,28 +4107,31 @@ static void tseq_tcptrace_make_elmtlist (struct graph *g)
                        else
                                data = tmp->th_seglen;
 
-                       y1 = g->zoom.y * (seq_cur);
-                       y2 = g->zoom.y * (seq_cur + data);
+                       yy1 = g->zoom.y * (seq_cur);
+                       yy2 = g->zoom.y * (seq_cur + data);
                        e1->type = ELMT_LINE;
                        e1->parent = tmp;
-                       e1->gc = g->s.tseq_tcptrace.gc_seq;
+                       /* Set the drawing color */
+                       e1->elment_color_p = &g->s.tseq_tcptrace.seq_color;
                        e1->p.line.dim.x1 = e1->p.line.dim.x2 = x;
-                       e1->p.line.dim.y1 = y1;
-                       e1->p.line.dim.y2 = y2;
+                       e1->p.line.dim.y1 = yy1;
+                       e1->p.line.dim.y2 = yy2;
                        e1++;
                        e1->type = ELMT_LINE;
                        e1->parent = tmp;
-                       e1->gc = g->s.tseq_tcptrace.gc_seq;
+                       /* Set the drawing color */
+                       e1->elment_color_p = &g->s.tseq_tcptrace.seq_color;
                        e1->p.line.dim.x1 = x - 1;
                        e1->p.line.dim.x2 = x + 1;
-                       e1->p.line.dim.y1 = e1->p.line.dim.y2 = y1;
+                       e1->p.line.dim.y1 = e1->p.line.dim.y2 = yy1;
                        e1++;
                        e1->type = ELMT_LINE;
                        e1->parent = tmp;
-                       e1->gc = g->s.tseq_tcptrace.gc_seq;
+                       /* Set the drawing color */
+                       e1->elment_color_p = &g->s.tseq_tcptrace.seq_color;
                        e1->p.line.dim.x1 = x + 1;
                        e1->p.line.dim.x2 = x - 1;
-                       e1->p.line.dim.y1 = e1->p.line.dim.y2 = y2;
+                       e1->p.line.dim.y1 = e1->p.line.dim.y2 = yy2;
                        e1++;
                } else {
                        double ackno, win;
@@ -3495,7 +4147,8 @@ static void tseq_tcptrace_make_elmtlist (struct graph *g)
                        if (ack_seen == TRUE) { /* don't plot the first ack */
                                e0->type = ELMT_LINE;
                                e0->parent = tmp;
-                               e0->gc = g->s.tseq_tcptrace.gc_ack[toggle];
+                               /* Set the drawing color */
+                               e0->elment_color_p = &g->s.tseq_tcptrace.ack_color[toggle];
                                e0->p.line.dim.x1 = p_t;
                                e0->p.line.dim.y1 = p_ackno;
                                e0->p.line.dim.x2 = x;
@@ -3503,7 +4156,8 @@ static void tseq_tcptrace_make_elmtlist (struct graph *g)
                                e0++;
                                e0->type = ELMT_LINE;
                                e0->parent = tmp;
-                               e0->gc = g->s.tseq_tcptrace.gc_ack[toggle];
+                               /* Set the drawing color */
+                               e0->elment_color_p = &g->s.tseq_tcptrace.ack_color[toggle];
                                e0->p.line.dim.x1 = x;
                                e0->p.line.dim.y1 = p_ackno;
                                e0->p.line.dim.x2 = x;
@@ -3512,7 +4166,8 @@ static void tseq_tcptrace_make_elmtlist (struct graph *g)
                                /* window line */
                                e0->type = ELMT_LINE;
                                e0->parent = tmp;
-                               e0->gc = g->s.tseq_tcptrace.gc_ack[toggle];
+                               /* Set the drawing color */
+                               e0->elment_color_p = &g->s.tseq_tcptrace.ack_color[toggle];
                                e0->p.line.dim.x1 = p_t;
                                e0->p.line.dim.y1 = p_win + p_ackno;
                                e0->p.line.dim.x2 = x;
@@ -3520,7 +4175,8 @@ static void tseq_tcptrace_make_elmtlist (struct graph *g)
                                e0++;
                                e0->type = ELMT_LINE;
                                e0->parent = tmp;
-                               e0->gc = g->s.tseq_tcptrace.gc_ack[toggle];
+                               /* Set the drawing color */
+                               e0->elment_color_p = &g->s.tseq_tcptrace.ack_color[toggle];
                                e0->p.line.dim.x1 = x;
                                e0->p.line.dim.y1 = p_win + p_ackno;
                                e0->p.line.dim.x2 = x;
@@ -3578,8 +4234,8 @@ static void tput_make_elmtlist (struct graph *g)
                e = elements = g->elists->elements;
 
        for (oldest=g->segments,tmp=g->segments->next,i=0; tmp; tmp=tmp->next,i++) {
-               double time = tmp->rel_secs + tmp->rel_usecs/1000000.0;
-               dtime = time - (oldest->rel_secs + oldest->rel_usecs/1000000.0);
+               double time_val = tmp->rel_secs + tmp->rel_usecs/1000000.0;
+               dtime = time_val - (oldest->rel_secs + oldest->rel_usecs/1000000.0);
                if (i>g->s.tput.nsegs) {
                        sum -= oldest->th_seglen;
                        oldest=oldest->next;
@@ -3588,16 +4244,12 @@ static void tput_make_elmtlist (struct graph *g)
                tput = sum / dtime;
                /* debug(DBS_TPUT_ELMTS) printf ("tput=%f\n", tput); */
 
-               e->type = ELMT_ARC;
+               e->type = ELMT_ELLIPSE;
                e->parent = tmp;
-               e->gc = g->fg_gc;
-               e->p.arc.dim.width = g->s.tput.width;
-               e->p.arc.dim.height = g->s.tput.height;
-               e->p.arc.dim.x = g->zoom.x*(time - g->bounds.x0) - g->s.tput.width/2.0;
-               e->p.arc.dim.y = g->zoom.y*tput + g->s.tput.height/2.0;
-               e->p.arc.filled = TRUE;
-               e->p.arc.angle1 = 0;
-               e->p.arc.angle2 = 23040;
+               e->p.ellipse.dim.width = g->s.tput.width;
+               e->p.ellipse.dim.height = g->s.tput.height;
+               e->p.ellipse.dim.x = g->zoom.x*(time_val - g->bounds.x0) - g->s.tput.width/2.0;
+               e->p.ellipse.dim.y = g->zoom.y*tput + g->s.tput.height/2.0;
                e++;
        }
        e->type = ELMT_NONE;
@@ -3612,7 +4264,7 @@ static void tput_initialize (struct graph *g)
        struct segment *tmp, *oldest, *last;
        int i, sum=0;
        double dtime, tput, tputmax=0;
-       double t, t0, tmax = 0, y0, ymax;
+       double t, t0, tmax = 0, yy0, ymax;
 
        debug(DBS_FENTRY) puts ("tput_initialize()");
 
@@ -3637,13 +4289,13 @@ static void tput_initialize (struct graph *g)
        }
 
        t0 = g->segments->rel_secs + g->segments->rel_usecs / 1000000.0;
-       y0 = 0;
+       yy0 = 0;
        ymax = tputmax;
 
        g->bounds.x0 = t0;
-       g->bounds.y0 = y0;
+       g->bounds.y0 = yy0;
        g->bounds.width = tmax - t0;
-       g->bounds.height = ymax - y0;
+       g->bounds.height = ymax - yy0;
        g->zoom.x = (g->geom.width - 1) / g->bounds.width;
        g->zoom.y = (g->geom.height -1) / g->bounds.height;
 }
@@ -3705,7 +4357,7 @@ static void rtt_initialize (struct graph *g)
        struct segment *tmp, *first=NULL;
        struct unack *unack = NULL, *u;
        double rttmax=0;
-       double x0, y0, ymax;
+       double xx0, yy0, ymax;
        guint32 xmax = 0;
        guint32 seq_base = 0;
 
@@ -3727,8 +4379,8 @@ static void rtt_initialize (struct graph *g)
                        }
                        seqno -= seq_base;
                        if (tmp->th_seglen && !rtt_is_retrans (unack, seqno)) {
-                               double time = tmp->rel_secs + tmp->rel_usecs / 1000000.0;
-                               u = rtt_get_new_unack (time, seqno);
+                               double time_val = tmp->rel_secs + tmp->rel_usecs / 1000000.0;
+                               u = rtt_get_new_unack (time_val, seqno);
                                if (!u) return;
                                rtt_put_unack_on_list (&unack, u);
                        }
@@ -3737,12 +4389,12 @@ static void rtt_initialize (struct graph *g)
                                xmax = seqno + tmp->th_seglen;
                } else if (first) {
                        guint32 ackno = tmp->th_ack -seq_base;
-                       double time = tmp->rel_secs + tmp->rel_usecs / 1000000.0;
+                       double time_val = tmp->rel_secs + tmp->rel_usecs / 1000000.0;
                        struct unack *v;
 
                        for (u=unack; u; u=v)
                                if (ackno > u->seqno) {
-                                       double rtt = time - u->time;
+                                       double rtt = time_val - u->time;
                                        if (rtt > rttmax)
                                                rttmax = rtt;
                                        v=u->next;
@@ -3752,14 +4404,14 @@ static void rtt_initialize (struct graph *g)
                }
        }
 
-       x0 = seq_base;
-       y0 = 0;
+       xx0 = seq_base;
+       yy0 = 0;
        ymax = rttmax;
 
-       g->bounds.x0 = x0;
-       g->bounds.y0 = y0;
+       g->bounds.x0 = xx0;
+       g->bounds.y0 = yy0;
        g->bounds.width = xmax;
-       g->bounds.height = ymax - y0;
+       g->bounds.height = ymax - yy0;
        g->zoom.x = g->geom.width / g->bounds.width;
        g->zoom.y = g->geom.height / g->bounds.height;
 }
@@ -3775,7 +4427,7 @@ static int rtt_is_retrans (struct unack *list, unsigned int seqno)
        return FALSE;
 }
 
-static struct unack *rtt_get_new_unack (double time, unsigned int seqno)
+static struct unack *rtt_get_new_unack (double time_val, unsigned int seqno)
 {
        struct unack *u;
 
@@ -3783,7 +4435,7 @@ static struct unack *rtt_get_new_unack (double time, unsigned int seqno)
        if (!u)
                return NULL;
        u->next = NULL;
-       u->time = time;
+       u->time = time_val;
        u->seqno = seqno;
        return u;
 }
@@ -3846,30 +4498,26 @@ static void rtt_make_elmtlist (struct graph *g)
                        guint32 seqno = tmp->th_seq -seq_base;
 
                        if (tmp->th_seglen && !rtt_is_retrans (unack, seqno)) {
-                               double time = tmp->rel_secs + tmp->rel_usecs / 1000000.0;
-                               u = rtt_get_new_unack (time, seqno);
+                               double time_val = tmp->rel_secs + tmp->rel_usecs / 1000000.0;
+                               u = rtt_get_new_unack (time_val, seqno);
                                if (!u) return;
                                rtt_put_unack_on_list (&unack, u);
                        }
                } else {
                        guint32 ackno = tmp->th_ack -seq_base;
-                       double time = tmp->rel_secs + tmp->rel_usecs / 1000000.0;
+                       double time_val = tmp->rel_secs + tmp->rel_usecs / 1000000.0;
                        struct unack *v;
 
                        for (u=unack; u; u=v)
                                if (ackno > u->seqno) {
-                                       double rtt = time - u->time;
+                                       double rtt = time_val - u->time;
 
-                                       e->type = ELMT_ARC;
+                                       e->type = ELMT_ELLIPSE;
                                        e->parent = tmp;
-                                       e->gc = g->fg_gc;
-                                       e->p.arc.dim.width = g->s.rtt.width;
-                                       e->p.arc.dim.height = g->s.rtt.height;
-                                       e->p.arc.dim.x = g->zoom.x * u->seqno - g->s.rtt.width/2.0;
-                                       e->p.arc.dim.y = g->zoom.y * rtt + g->s.rtt.height/2.0;
-                                       e->p.arc.filled = TRUE;
-                                       e->p.arc.angle1 = 0;
-                                       e->p.arc.angle2 = 23040;
+                                       e->p.ellipse.dim.width = g->s.rtt.width;
+                                       e->p.ellipse.dim.height = g->s.rtt.height;
+                                       e->p.ellipse.dim.x = g->zoom.x * u->seqno - g->s.rtt.width/2.0;
+                                       e->p.ellipse.dim.y = g->zoom.y * rtt + g->s.rtt.height/2.0;
                                        e++;
 
                                        v=u->next;
@@ -3892,6 +4540,139 @@ static void rtt_toggle_seq_origin (struct graph *g)
                g->x_axis->min = 0;
 }
 
+/* WSCALE Graph */
+
+static void wscale_read_config(struct graph* g)
+{
+       debug(DBS_FENTRY) puts ("wscale_read_config()");
+
+       g->s.wscale.win_width = 4;
+       g->s.wscale.win_height = 4;
+       g->s.wscale.flags = 0;
+
+       g->title = (const char ** )g_malloc (2 * sizeof (char *));
+       g->title[0] = "Window Scaling Graph";
+       g->title[1] = NULL;
+       g->y_axis->label = (const char ** )g_malloc (3 * sizeof (char * ));
+       g->y_axis->label[0] = "[bytes]";
+       g->y_axis->label[1] = "Windowsize";
+       g->y_axis->label[2] = NULL;
+       g->x_axis->label = (const char ** )g_malloc (2 * sizeof (char * ));
+       g->x_axis->label[0] = "Time [s]";
+       g->x_axis->label[1] = NULL;
+}
+
+/*
+    (1) Find maximum and minimum values for Window-Size(scaled) and seconds
+    (2) call function to define window related values
+*/
+static void wscale_initialize(struct graph* g)
+{
+
+       struct segment* segm = NULL;
+       guint32 wsize_max = 0;
+       guint32 wsize_min = 0;
+       gdouble sec_max = 0.0;
+       gdouble sec_base = -1.0;
+
+       wscale_read_config (g);
+
+       debug(DBS_FENTRY) puts ("wscale_initialize()");
+
+       for (segm = g->segments; segm; segm = segm->next)
+       {
+               if (compare_headers(&g->current->ip_src, &g->current->ip_dst,
+                                       g->current->th_sport, g->current->th_dport,
+                                       &segm->ip_src, &segm->ip_dst,
+                                       segm->th_sport, segm->th_dport,
+                                       COMPARE_CURR_DIR))
+               {
+                       gdouble sec = segm->rel_secs + ( segm->rel_usecs / 1000000.0 );
+                       guint16 flags = segm->th_flags;
+                       guint32 wsize = segm->th_win;
+
+                       /* only data segments */
+                       if ( (flags & (TH_SYN|TH_RST)) == 0 )
+                               if ( wsize > wsize_max )
+                                       wsize_max = wsize;
+
+                       /* remind time of first probe */
+                       if ( sec_base < 0 && sec > 0 )
+                               sec_base = sec;
+
+                       if ( sec_max < sec )
+                               sec_max = sec;
+
+               }
+
+       }
+
+       g->bounds.x0 = 0;
+       g->bounds.y0 = wsize_min;
+       g->bounds.width = sec_max - sec_base + 5;
+       g->bounds.height = wsize_max + 5;
+       g->zoom.x = g->geom.width / g->bounds.width;
+       g->zoom.y = g->geom.height / g->bounds.height;
+
+}
+
+/*
+   (1) Fill & allocate memory for segments times elements,
+*/
+static void wscale_make_elmtlist(struct graph* g)
+{
+       struct segment* segm = NULL;
+       struct element* elements = NULL;
+       struct element* e = NULL;
+       gdouble sec_base = -1.0;
+
+       debug(DBS_FENTRY) puts ("wscale_make_elmtlist()");
+
+       /* Allocate memory for elements if not already done */
+       if (g->elists->elements == NULL)
+       {
+               int n = 1 + get_num_dsegs(g);
+               e = elements = (struct element*)g_malloc(n*sizeof(struct element));
+       }
+       else
+               e = elements = g->elists->elements;
+
+
+       for ( segm = g->segments; segm; segm = segm->next )
+       {
+               if (compare_headers(&g->current->ip_src, &g->current->ip_dst,
+                                       g->current->th_sport, g->current->th_dport,
+                                       &segm->ip_src, &segm->ip_dst,
+                                       segm->th_sport, segm->th_dport,
+                                       COMPARE_CURR_DIR))
+               {
+                       gdouble sec = segm->rel_secs + (segm->rel_usecs / 1000000.0);
+                       guint16 flags = segm->th_flags;
+                       guint32 wsize = segm->th_win;
+
+                       /* remind time of first probe */
+                       if ( sec_base < 0 && sec > 0 )
+                               sec_base = sec;
+
+                       /* only data or ack segments */
+                       if ( (flags & (TH_SYN|TH_RST)) == 0 )
+                       {
+                               e->type = ELMT_ELLIPSE;
+                               e->parent = segm;
+                               e->p.ellipse.dim.width = g->s.wscale.win_width;
+                               e->p.ellipse.dim.height = g->s.wscale.win_height;
+                               e->p.ellipse.dim.x = g->zoom.x * (sec - sec_base) - g->s.wscale.win_width / 2.0;
+                               e->p.ellipse.dim.y = g->zoom.y * wsize - g->s.wscale.win_height / 2.0;
+                               e++;
+                       }
+               }
+       }
+       /* finished populating element list */
+       e->type = ELMT_NONE;
+       g->elists->elements = elements;
+}
+
+
 #if defined(_WIN32) && !defined(__MINGW32__)
 /* replacement of Unix rint() for Windows */
 static int rint (double x)
@@ -3908,8 +4689,12 @@ static int rint (double x)
 }
 #endif
 
-
-static gboolean tcp_graph_selected_packet_enabled(frame_data *current_frame, epan_dissect_t *edt, gpointer callback_data _U_)
+#ifdef MAIN_MENU_USE_UIMANAGER
+gboolean tcp_graph_selected_packet_enabled(frame_data *current_frame, epan_dissect_t *edt, gpointer callback_data _U_)
+#else
+static
+gboolean tcp_graph_selected_packet_enabled(frame_data *current_frame, epan_dissect_t *edt, gpointer callback_data _U_)
+#endif
 {
     return current_frame != NULL ? (edt->pi.ipproto == IP_PROTO_TCP) : FALSE;
 }
@@ -3918,12 +4703,18 @@ static gboolean tcp_graph_selected_packet_enabled(frame_data *current_frame, epa
 void
 register_tap_listener_tcp_graph(void)
 {
-    register_stat_menu_item("TCP Stream Graph/Time-Sequence Graph (Stevens)", REGISTER_STAT_GROUP_NONE,
+#ifdef MAIN_MENU_USE_UIMANAGER
+#else
+    register_stat_menu_item("TCP Stream Graph/Time-Sequence Graph (Stevens)", REGISTER_STAT_GROUP_UNSORTED,
         tcp_graph_cb, tcp_graph_selected_packet_enabled, NULL, GINT_TO_POINTER(0));
-    register_stat_menu_item("TCP Stream Graph/Time-Sequence Graph (tcptrace)", REGISTER_STAT_GROUP_NONE,
+    register_stat_menu_item("TCP Stream Graph/Time-Sequence Graph (tcptrace)", REGISTER_STAT_GROUP_UNSORTED,
         tcp_graph_cb, tcp_graph_selected_packet_enabled, NULL, GINT_TO_POINTER(1));
-    register_stat_menu_item("TCP Stream Graph/Throughput Graph", REGISTER_STAT_GROUP_NONE,
+    register_stat_menu_item("TCP Stream Graph/Throughput Graph", REGISTER_STAT_GROUP_UNSORTED,
         tcp_graph_cb, tcp_graph_selected_packet_enabled, NULL, GINT_TO_POINTER(2));
-    register_stat_menu_item("TCP Stream Graph/Round Trip Time Graph", REGISTER_STAT_GROUP_NONE,
+    register_stat_menu_item("TCP Stream Graph/Round Trip Time Graph", REGISTER_STAT_GROUP_UNSORTED,
         tcp_graph_cb, tcp_graph_selected_packet_enabled, NULL, GINT_TO_POINTER(3));
+    register_stat_menu_item("TCP Stream Graph/Window Scaling Graph", REGISTER_STAT_GROUP_UNSORTED,
+       tcp_graph_cb, tcp_graph_selected_packet_enabled, NULL, GINT_TO_POINTER(GRAPH_WSCALE));
+#endif
+
 }