Immediately quit routines if fwrite() fails - further writes will
[obnox/wireshark/wip.git] / gtk / sctp_byte_graph_dlg.c
index 4802014b3b8b041aabf1461f6781aa07314fedd5..6d12e52ff838f27ef1c0b4344e624368f3caa374 100644 (file)
@@ -1,10 +1,10 @@
-/* 
+/*
  * Copyright 2004, Irene Ruengeler <i.ruengeler [AT] fh-muenster.de>
  *
  * $Id$
  *
- * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@ethereal.com>
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
  * Copyright 1998 Gerald Combs
  *
  * This program is free software; you can redistribute it and/or
@@ -21,7 +21,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
+
 #ifdef HAVE_CONFIG_H
 #  include <config.h>
 #endif
@@ -35,9 +35,8 @@
 #include "globals.h"
 #include "epan/filesystem.h"
 #include "../color.h"
-#include "stat_menu.h"
 #include "dlg_utils.h"
-#include "gui_utils.h"
+#include "ui_util.h"
 #include "main.h"
 #include "compat_macros.h"
 #include "simple_dialog.h"
 #define COUNT_TYPE_BYTES    1
 #define COUNT_TYPE_ADVANCED 2
 
-#define LEFT_BORDER   60
+#define LEFT_BORDER   80
 #define RIGHT_BORDER  10
 #define TOP_BORDER    10
 #define BOTTOM_BORDER 50
 
 #define SUB_32(a, b)   a-b
-#define MINI(a,b) (a<b)?a:b
-#define MAXI(a,b) (a>b)?a:b
 
 struct chunk_header {
        guint8  type;
@@ -107,37 +104,24 @@ struct gaps {
        guint16 end;
 };
 
+static gboolean label_set = FALSE;
+static guint32 max_tsn=0, min_tsn=0;
 
 
 static void sctp_graph_set_title(struct sctp_udata *u_data);
 static void create_draw_area(GtkWidget *box, struct sctp_udata *u_data);
-
-
-gint tsn_cmp(gconstpointer aa, gconstpointer bb)
-{
-       const struct tsn_sort* a = aa;
-       const struct tsn_sort* b = bb;
-
-       if (a->tsnumber < b->tsnumber)
-               return -1;
-       if (a->tsnumber == b->tsnumber)
-               return 0;
-       if (a->tsnumber > b->tsnumber)
-               return 1;
-
-       return 0;
-}
+static GtkWidget *zoomout_bt;
 
 static void draw_sack_graph(struct sctp_udata *u_data)
 {
        GdkColor red_color = {0, 65535, 0, 0};
        GdkColor green_color = {0, 0, 65535, 0};
        GdkGC *red_gc, *green_gc;
-       guint32 diff;
+       gint diff;
        GPtrArray *array = NULL;
-       guint32 min_tsn = 0, max_tsn = 0;
-       guint32 i, size = 0, start, end;
+       guint32 i, size = 0, start=0, end;
        gboolean more = FALSE;
+       gint width;
 
 #if GTK_MAJOR_VERSION < 2
        GdkColormap *colormap;
@@ -200,11 +184,14 @@ static void draw_sack_graph(struct sctp_udata *u_data)
                }
        }
 
+       width = u_data->io->max_x - u_data->io->min_x;
 
        for (i=0; i<size; i++)
        {
-               diff = ((struct tsn_sort*)(g_ptr_array_index(array,  i)))->secs * 1000000 + ((struct tsn_sort*)(g_ptr_array_index(array,  i)))->usecs - u_data->io->min_x;
-               start = ((struct tsn_sort*)(g_ptr_array_index(array,  i)))->offset;
+               if (u_data->io->uoff)
+                       diff = (gint)((struct tsn_sort*)(g_ptr_array_index(array,  i)))->secs - u_data->io->min_x;
+               else
+                       diff = (gint)((struct tsn_sort*)(g_ptr_array_index(array,  i)))->secs * 1000000 + ((struct tsn_sort*)(g_ptr_array_index(array,  i)))->usecs - u_data->io->min_x;
                end = start + ((struct tsn_sort*)(g_ptr_array_index(array,  i)))->length;
                if (end>max_tsn)
                {
@@ -212,7 +199,7 @@ static void draw_sack_graph(struct sctp_udata *u_data)
                        more = TRUE;
                }
 
-               if (start >= min_tsn)
+               if (start >= min_tsn && diff > 0 && diff <= width)
                {
                        gdk_draw_line(u_data->io->pixmap,red_gc,
                                     (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff),
@@ -241,8 +228,8 @@ static void draw_sack_graph(struct sctp_udata *u_data)
 static void draw_tsn_graph(struct sctp_udata *u_data)
 {
 GPtrArray *array = NULL;
-guint32 min_tsn = 0, max_tsn = 0;
-guint32 diff, i, size = 0, start, end;
+guint32 i, size = 0, start, end;
+gint diff, width;
 
        if (u_data->dir == 1)
        {
@@ -274,13 +261,17 @@ guint32 diff, i, size = 0, start, end;
                        max_tsn = u_data->io->tmp_max_tsn2;
                }
        }
+       width = u_data->io->max_x - u_data->io->min_x;
 
        for (i=0; i<size; i++)
        {
-               diff = ((struct tsn_sort*)(g_ptr_array_index(array, i)))->secs*1000000 + ((struct tsn_sort*)(g_ptr_array_index(array, i)))->usecs-u_data->io->min_x;
+               if (u_data->io->uoff)
+                       diff = (gint)((struct tsn_sort*)(g_ptr_array_index(array, i)))->secs -u_data->io->min_x;
+               else
+                       diff = (gint)((struct tsn_sort*)(g_ptr_array_index(array, i)))->secs*1000000 + ((struct tsn_sort*)(g_ptr_array_index(array, i)))->usecs-u_data->io->min_x;
                start = ((struct tsn_sort*)(g_ptr_array_index(array, i)))->offset;
                end = start + ((struct tsn_sort*)(g_ptr_array_index(array, i)))->length;
-               if (start >= min_tsn)
+               if (start >= min_tsn && diff > 0 && diff <= width)
                        gdk_draw_line(u_data->io->pixmap,
                                      u_data->io->draw_area->style->black_gc,
                                      (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff),
@@ -294,10 +285,12 @@ guint32 diff, i, size = 0, start, end;
 
 static void sctp_graph_draw(struct sctp_udata *u_data)
 {
-       int length, lwidth, j, b;
-       guint32 label_width, label_height, distance=5, i, e, sec, w, start, a;
+       int length, lwidth;
+       guint32 distance=5, i, e, sec, w, start, a, j, b;
+       gint label_width, label_height;
        char label_string[15];
        gfloat dis;
+       gboolean write_label = FALSE;
 
 #if GTK_MAJOR_VERSION < 2
        GdkFont *font;
@@ -310,8 +303,19 @@ static void sctp_graph_draw(struct sctp_udata *u_data)
        else
                u_data->io->offset = 5;
 
-       u_data->io->min_x     = u_data->io->x1_tmp_sec * 1000000 + u_data->io->x1_tmp_usec;
-       u_data->io->max_x     = u_data->io->x2_tmp_sec * 1000000 + u_data->io->x2_tmp_usec;
+       if (u_data->io->x2_tmp_sec - u_data->io->x1_tmp_sec > 1500)
+       {
+               u_data->io->min_x=u_data->io->x1_tmp_sec;
+               u_data->io->max_x=u_data->io->x2_tmp_sec;
+               u_data->io->uoff = TRUE;
+       }
+       else
+       {
+               u_data->io->min_x=((guint32) (u_data->io->x1_tmp_sec*1000000.0))+u_data->io->x1_tmp_usec;
+               u_data->io->max_x=((guint32) (u_data->io->x2_tmp_sec*1000000.0))+u_data->io->x2_tmp_usec;               
+               u_data->io->uoff = FALSE;
+       }       
+
        u_data->io->tmp_width = u_data->io->max_x - u_data->io->min_x;
 
        if (u_data->dir == 1)
@@ -361,7 +365,11 @@ static void sctp_graph_draw(struct sctp_udata *u_data)
                      u_data->io->pixmap_width - RIGHT_BORDER + u_data->io->offset, u_data->io->pixmap_height - BOTTOM_BORDER, u_data->io->pixmap_width - RIGHT_BORDER + u_data->io->offset - 5, u_data->io->pixmap_height - BOTTOM_BORDER + 5);
        u_data->io->axis_width = u_data->io->pixmap_width - LEFT_BORDER - RIGHT_BORDER - u_data->io->offset;
 
-       u_data->io->x_interval = (float)((u_data->io->axis_width * 1.0) / u_data->io->tmp_width);
+       if(u_data->io->tmp_width>0){
+               u_data->io->x_interval = (float)((u_data->io->axis_width*1.0)/u_data->io->tmp_width); /*distance in pixels between 2 data points*/
+       } else {
+               u_data->io->x_interval = (float)(u_data->io->axis_width);
+       }
 
        e=0;
        if (u_data->io->x_interval < 1)
@@ -405,7 +413,7 @@ static void sctp_graph_draw(struct sctp_udata *u_data)
 #if GTK_MAJOR_VERSION < 2
                lwidth = gdk_string_width(font, label_string);
                gdk_draw_string(u_data->io->pixmap,font,u_data->io->draw_area->style->black_gc,
-                               LEFT_BORDER - 10,
+                               LEFT_BORDER - 25,
                                u_data->io->pixmap_height - BOTTOM_BORDER + 20,
                                label_string);
 #else
@@ -414,7 +422,7 @@ static void sctp_graph_draw(struct sctp_udata *u_data)
                pango_layout_get_pixel_size(layout, &lwidth, NULL);
 
                gdk_draw_layout(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
-                               LEFT_BORDER - 10,
+                               LEFT_BORDER - 25,
                                u_data->io->pixmap_height - BOTTOM_BORDER + 20,
                                layout);
 #endif
@@ -422,11 +430,11 @@ static void sctp_graph_draw(struct sctp_udata *u_data)
        w = (guint32)(500 / (guint32)(distance * u_data->io->x_interval));
        if (w == 0)
                w = 1;
-       if (w == 4)
+       if (w == 4 || w==3 || w==2)
        {
                w = 5;
                a = distance / 10;
-               b = 10 + (((u_data->io->min_x / 100000) - 1) % 5);
+               b = (guint32)((u_data->io->min_x/100000))%10; /* start for labels*/
        }
        else
        {
@@ -434,19 +442,35 @@ static void sctp_graph_draw(struct sctp_udata *u_data)
                b = 0;
        }
 
-       if (a > 1000000)
-               start = u_data->io->min_x / 1000000 * 1000000;
+       if (!u_data->io->uoff)  
+       {
+               if (a>=1000000)
+               {
+                       start=u_data->io->min_x/1000000*1000000;
+                       if (a==1000000)
+                               b = 0;
+               }
+               else
+               {
+                       start=u_data->io->min_x/100000;
+                       if (start%2!=0)
+                               start--;
+                       start*=100000;
+                       b = (guint32)((start/100000))%10;
+               }
+       }
        else
        {
-               start = u_data->io->min_x / 100000;
-               if (start % 2 != 0)
+               start = u_data->io->min_x;
+               if (start%2!=0)
                        start--;
-               start *= 100000;
+               b = 0;
+               
        }
 
-
        for (i=start, j=b; i<=u_data->io->max_x; i+=a, j++)
        {
+               if (!u_data->io->uoff)
                if (i >= u_data->io->min_x && i % 1000000 != 0)
                {
                        length = 5;
@@ -482,9 +506,24 @@ static void sctp_graph_draw(struct sctp_udata *u_data)
                                      u_data->io->pixmap_height - BOTTOM_BORDER + length);
                }
 
-               if (i % 1000000 == 0)
+               if (!u_data->io->uoff)
+               {
+                       if (i%1000000==0 && j%w==0)
+                       {
+                               sec=i/1000000;
+                               write_label = TRUE;
+                       }
+               }
+               else
+               {
+                       if (j%w == 0)
+                       {
+                               sec = i;
+                               write_label = TRUE;
+                       }
+               }
+               if (write_label)
                {
-                       sec = i / 1000000;
                        gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
                                      (guint32)(LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval),
                                      u_data->io->pixmap_height - BOTTOM_BORDER,
@@ -495,7 +534,7 @@ static void sctp_graph_draw(struct sctp_udata *u_data)
 #if GTK_MAJOR_VERSION < 2
                                lwidth = gdk_string_width(font, label_string);
                                gdk_draw_string(u_data->io->pixmap,font,u_data->io->draw_area->style->black_gc,
-                                               (guint32)(LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval),
+                                               (guint32)(LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval-10),
                                                u_data->io->pixmap_height - BOTTOM_BORDER + 20,
                                                label_string);
 #else
@@ -504,10 +543,11 @@ static void sctp_graph_draw(struct sctp_udata *u_data)
                                pango_layout_get_pixel_size(layout, &lwidth, NULL);
 
                                gdk_draw_layout(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
-                                               (guint32)(LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval),
+                                               (guint32)(LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval-10),
                                                u_data->io->pixmap_height - BOTTOM_BORDER + 20,
                                                layout);
 #endif
+                       write_label = FALSE;
                }
        }
 
@@ -519,7 +559,7 @@ static void sctp_graph_draw(struct sctp_udata *u_data)
                        font,
                        u_data->io->draw_area->style->black_gc,
                        u_data->io->pixmap_width - RIGHT_BORDER - 10,
-                       u_data->io->pixmap_height - BOTTOM_BORDER + 20,
+                       u_data->io->pixmap_height - BOTTOM_BORDER + 30,
                        label_string);
 #else
        memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
@@ -528,7 +568,7 @@ static void sctp_graph_draw(struct sctp_udata *u_data)
        gdk_draw_layout(u_data->io->pixmap,
                        u_data->io->draw_area->style->black_gc,
                        u_data->io->pixmap_width - RIGHT_BORDER - 10,
-                       u_data->io->pixmap_height - BOTTOM_BORDER + 25,
+                       u_data->io->pixmap_height - BOTTOM_BORDER + 30,
                        layout);
 #endif
 
@@ -543,14 +583,14 @@ static void sctp_graph_draw(struct sctp_udata *u_data)
        gdk_draw_line(u_data->io->pixmap,
                      u_data->io->draw_area->style->black_gc,
                      LEFT_BORDER,
-                     TOP_BORDER - u_data->io->offset, 
-                     LEFT_BORDER - 5, 
+                     TOP_BORDER - u_data->io->offset,
+                     LEFT_BORDER - 5,
                      TOP_BORDER - u_data->io->offset + 5);
        gdk_draw_line(u_data->io->pixmap,
                      u_data->io->draw_area->style->black_gc,
                      LEFT_BORDER,
-                     TOP_BORDER - u_data->io->offset, 
-                     LEFT_BORDER + 5, 
+                     TOP_BORDER - u_data->io->offset,
+                     LEFT_BORDER + 5,
                      TOP_BORDER - u_data->io->offset + 5);
 
        u_data->io->y_interval = (float)(((u_data->io->pixmap_height - TOP_BORDER - BOTTOM_BORDER) * 1.0)/(u_data->io->max_y - u_data->io->min_y));
@@ -568,6 +608,8 @@ static void sctp_graph_draw(struct sctp_udata *u_data)
                for (i=0; i<=e; i++)
                        distance = distance * 10;
        }
+       else if (u_data->io->y_interval<2)
+               distance = 10;
 
        if (u_data->io->max_y > 0)
        {
@@ -625,7 +667,7 @@ static void sctp_graph_redraw(struct sctp_udata *u_data)
                        draw_sack_graph(u_data);
                        draw_tsn_graph(u_data);
                        break;
-               case 1: 
+               case 1:
                        draw_tsn_graph(u_data);
                        break;
                case 2:
@@ -743,6 +785,7 @@ on_zoomin_bt (GtkWidget *widget _U_, struct sctp_udata *u_data)
 
                u_data->io->tmp_min_tsn1=u_data->io->y1_tmp+u_data->io->min_y;
                u_data->io->tmp_max_tsn1=u_data->io->y2_tmp+1+u_data->io->min_y;
+
                u_data->io->tmp_min_tsn2=u_data->io->tmp_min_tsn1;
                u_data->io->tmp_max_tsn2=u_data->io->tmp_max_tsn1;
                tmp_minmax->tmp_min_secs=u_data->io->x1_tmp_sec;
@@ -757,8 +800,41 @@ on_zoomin_bt (GtkWidget *widget _U_, struct sctp_udata *u_data)
                u_data->io->length = g_slist_length(u_data->assoc->min_max);
                u_data->io->tmp=TRUE;
                u_data->io->rectangle=FALSE;
+               gtk_widget_set_sensitive(zoomout_bt, TRUE);
                sctp_graph_redraw(u_data);
        }
+       else
+       {
+               simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Please draw a rectangle around the area you want to zoom in!");
+       }
+}
+
+static void
+zoomin_bt (struct sctp_udata *u_data)
+{
+       sctp_min_max_t *tmp_minmax;
+
+       tmp_minmax = g_malloc(sizeof(sctp_min_max_t));
+
+       u_data->io->tmp_min_tsn1=u_data->io->y1_tmp+u_data->io->min_y;
+       u_data->io->tmp_max_tsn1=u_data->io->y2_tmp+1+u_data->io->min_y;
+
+       u_data->io->tmp_min_tsn2=u_data->io->tmp_min_tsn1;
+       u_data->io->tmp_max_tsn2=u_data->io->tmp_max_tsn1;
+       tmp_minmax->tmp_min_secs=u_data->io->x1_tmp_sec;
+       tmp_minmax->tmp_min_usecs=u_data->io->x1_tmp_usec;
+       tmp_minmax->tmp_max_secs=u_data->io->x2_tmp_sec;
+       tmp_minmax->tmp_max_usecs=u_data->io->x2_tmp_usec;
+       tmp_minmax->tmp_min_tsn1=u_data->io->tmp_min_tsn1;
+       tmp_minmax->tmp_max_tsn1=u_data->io->tmp_max_tsn1;
+       tmp_minmax->tmp_min_tsn2=u_data->io->tmp_min_tsn2;
+       tmp_minmax->tmp_max_tsn2=u_data->io->tmp_max_tsn2;
+       u_data->assoc->min_max = g_slist_prepend(u_data->assoc->min_max, tmp_minmax);
+       u_data->io->length = g_slist_length(u_data->assoc->min_max);
+       u_data->io->tmp=TRUE;
+       u_data->io->rectangle=FALSE;
+       gtk_widget_set_sensitive(zoomout_bt, TRUE);
+       sctp_graph_redraw(u_data);
 }
 
 static void
@@ -813,6 +889,8 @@ on_zoomout_bt (GtkWidget *widget _U_, struct sctp_udata *u_data)
                u_data->io->tmp_max_tsn2=u_data->assoc->max_bytes2;
                u_data->io->tmp=FALSE;
        }
+       if (g_slist_length(u_data->assoc->min_max)==1)
+               gtk_widget_set_sensitive(zoomout_bt, FALSE);
        sctp_graph_redraw(u_data);
 }
 
@@ -826,8 +904,8 @@ on_button_press (GtkWidget *widget _U_, GdkEventButton *event, struct sctp_udata
        {
                gdk_draw_rectangle(u_data->io->pixmap,u_data->io->draw_area->style->white_gc,
                                   FALSE,
-                                  (gint)floor(MINI(u_data->io->x_old,u_data->io->x_new)),
-                                  (gint)floor(MINI(u_data->io->y_old,u_data->io->y_new)),
+                                  (gint)floor(MIN(u_data->io->x_old,u_data->io->x_new)),
+                                  (gint)floor(MIN(u_data->io->y_old,u_data->io->y_new)),
                                   (gint)abs((long)(u_data->io->x_new-u_data->io->x_old)),
                                   (gint)abs((long)(u_data->io->y_new-u_data->io->y_old)));
                ios=(sctp_graph_t *)OBJECT_GET_DATA(u_data->io->draw_area, "sctp_graph_t");
@@ -862,21 +940,50 @@ static gint
 on_button_release (GtkWidget *widget _U_, GdkEventButton *event, struct sctp_udata *u_data)
 {
        sctp_graph_t *ios;
-       guint32 helpx;
-       guint32 helpy, x1_tmp, x2_tmp;
+       guint32 helpx, helpy, x1_tmp, x2_tmp, y_value, frame;
+       gint label_width, label_height;
+       gdouble x_value, position, tfirst;
+       gint lwidth;
+       char label_string[30];
+       GdkGC *text_color;
+       GList *tsnlist=NULL;
+       tsn_t *tsn, *tmptsn;
+       #if GTK_MAJOR_VERSION < 2
+               GdkFont *font;
+#else
+               PangoLayout  *layout;
+#endif
+
+#if GTK_MAJOR_VERSION < 2
+               font = u_data->io->draw_area->style->font;
+#endif
+
+#if GTK_MAJOR_VERSION < 2
+               label_width=gdk_string_width(font, label_string);
+               label_height=gdk_string_height(font, label_string);
+#else
+               g_snprintf(label_string, 15, "%d", 0);
+               memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
+               layout = gtk_widget_create_pango_layout(u_data->io->draw_area, label_string);
+               pango_layout_get_pixel_size(layout, &label_width, &label_height);
 
-       if (event->y>u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset)
+#endif
+       if (event->y > u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset)
                event->y = u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset;
        if (event->x < LEFT_BORDER+u_data->io->offset)
                event->x = LEFT_BORDER+u_data->io->offset;
 
        if (abs((long)(event->x-u_data->io->x_old))>10 || abs((long)(event->y-u_data->io->y_old))>10)
        {
+               u_data->io->rect_x_min = (guint32) floor(MIN(u_data->io->x_old,event->x));
+               u_data->io->rect_x_max = (guint32) ceil(MAX(u_data->io->x_old,event->x));
+               u_data->io->rect_y_min = (guint32) floor(MIN(u_data->io->y_old,event->y));
+               u_data->io->rect_y_max = (guint32) ceil(MAX(u_data->io->y_old,event->y));
                gdk_draw_rectangle(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
-                                  FALSE,
-                                 (gint)floor(MINI(u_data->io->x_old,event->x)), (gint)floor(MINI(u_data->io->y_old,event->y)),
-                                (gint)abs((long)(event->x-u_data->io->x_old)),
-                                (gint)abs((long)(event->y-u_data->io->y_old)));
+                                  FALSE,
+                                  u_data->io->rect_x_min, u_data->io->rect_y_min,
+                                  u_data->io->rect_x_max - u_data->io->rect_x_min,
+                                  u_data->io->rect_y_max - u_data->io->rect_y_min);
                ios=(sctp_graph_t *)OBJECT_GET_DATA(u_data->io->draw_area, "sctp_graph_t");
 
                if(!ios){
@@ -891,28 +998,144 @@ on_button_release (GtkWidget *widget _U_, GdkEventButton *event, struct sctp_uda
                                u_data->io->draw_area->allocation.width,
                                u_data->io->draw_area->allocation.height);
 
-               x1_tmp=(unsigned int)floor(u_data->io->min_x+((u_data->io->x_old-LEFT_BORDER-u_data->io->offset)*u_data->io->tmp_width/u_data->io->axis_width));
-               x2_tmp=(unsigned int)floor(u_data->io->min_x+((event->x-LEFT_BORDER-u_data->io->offset)*u_data->io->tmp_width/u_data->io->axis_width));
-               helpx=MINI(x1_tmp, x2_tmp);
+               x1_tmp=(guint32) floor(u_data->io->min_x+((u_data->io->x_old-LEFT_BORDER-u_data->io->offset)*u_data->io->tmp_width/u_data->io->axis_width));
+               x2_tmp=(guint32) floor(u_data->io->min_x+((event->x-LEFT_BORDER-u_data->io->offset)*u_data->io->tmp_width/u_data->io->axis_width));
+               helpx=MIN(x1_tmp, x2_tmp);
                if (helpx==x2_tmp)
                {
                        x2_tmp=x1_tmp;
                        x1_tmp=helpx;
                }
-               u_data->io->x1_tmp_sec=(guint32)x1_tmp/1000000;
-               u_data->io->x1_tmp_usec=x1_tmp%1000000;
-               u_data->io->x2_tmp_sec=(guint32)x2_tmp/1000000;
-               u_data->io->x2_tmp_usec=x2_tmp%1000000;
-
-               u_data->io->y1_tmp=(guint32)((u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->y_old)/u_data->io->y_interval);
-               u_data->io->y2_tmp=(guint32)((u_data->io->pixmap_height-BOTTOM_BORDER-event->y)/u_data->io->y_interval);
-               helpy = MINI(u_data->io->y1_tmp, u_data->io->y2_tmp);
-               u_data->io->y2_tmp = MAXI(u_data->io->y1_tmp, u_data->io->y2_tmp);
+               if (u_data->io->uoff)
+               {
+                       if (x2_tmp - x1_tmp <= 1500)                    
+                               u_data->io->uoff = FALSE;
+                       u_data->io->x1_tmp_sec=(guint32)x1_tmp;
+                       u_data->io->x1_tmp_usec=0;
+                       u_data->io->x2_tmp_sec=(guint32)x2_tmp;
+                       u_data->io->x2_tmp_usec=0;
+               }
+               else 
+               {
+                       u_data->io->x1_tmp_sec=(guint32)x1_tmp/1000000;
+                       u_data->io->x1_tmp_usec=x1_tmp%1000000;
+                       u_data->io->x2_tmp_sec=(guint32)x2_tmp/1000000;
+                       u_data->io->x2_tmp_usec=x2_tmp%1000000;
+               }
+               u_data->io->x1_akt_sec = u_data->io->x1_tmp_sec;
+               u_data->io->x1_akt_usec = u_data->io->x1_tmp_usec;
+               u_data->io->x2_akt_sec = u_data->io->x2_tmp_sec;
+               u_data->io->x2_akt_usec = u_data->io->x2_tmp_usec;
+
+               u_data->io->y1_tmp=(guint32)((u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-u_data->io->y_old)/u_data->io->y_interval);
+               u_data->io->y2_tmp=(guint32)((u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-event->y)/u_data->io->y_interval);
+               helpy = MIN(u_data->io->y1_tmp, u_data->io->y2_tmp);
+               u_data->io->y2_tmp = MAX(u_data->io->y1_tmp, u_data->io->y2_tmp);
                u_data->io->y1_tmp = helpy;
                u_data->io->x_new=event->x;
                u_data->io->y_new=event->y;
                u_data->io->rectangle=TRUE;
+               u_data->io->rectangle_present=TRUE;
+       }
+               else
+       {
+               if (u_data->io->rectangle_present==TRUE)
+               {
+                       u_data->io->rectangle_present=FALSE;
+                       if (event->x >= u_data->io->rect_x_min && event->x <= u_data->io->rect_x_max && 
+                            event->y >= u_data->io->rect_y_min && event->y <= u_data->io->rect_y_max)
+                               zoomin_bt(u_data);
+                       else
+                       {
+                               u_data->io->x1_tmp_sec = u_data->io->x1_akt_sec;
+                               u_data->io->x1_tmp_usec = u_data->io->x1_akt_usec;
+                               u_data->io->x2_tmp_sec = u_data->io->x2_akt_sec;
+                               u_data->io->x2_tmp_usec = u_data->io->x2_akt_usec;
+                               sctp_graph_redraw(u_data);
+                       }
+               }
+               else if (label_set)
+               {
+                       label_set = FALSE;
+                       sctp_graph_redraw(u_data);
+               }
+               else
+               {
+                       x_value = ((event->x-LEFT_BORDER-u_data->io->offset) * ((u_data->io->x2_tmp_sec+u_data->io->x2_tmp_usec/1000000.0)-(u_data->io->x1_tmp_sec+u_data->io->x1_tmp_usec/1000000.0)) / (u_data->io->pixmap_width-LEFT_BORDER-u_data->io->offset))+u_data->io->x1_tmp_sec+u_data->io->x1_tmp_usec/1000000.0;
+                       y_value = (guint32) floor((u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-event->y) * (max_tsn - min_tsn) / (u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset)) + min_tsn;
+                       text_color = u_data->io->draw_area->style->black_gc;
+
+                       if (u_data->dir == 1)
+                               tsnlist = g_list_last(u_data->assoc->tsn1);
+                       else
+                               tsnlist = g_list_last(u_data->assoc->tsn2);
+
+                       tsn = (tsn_t*) (tsnlist->data);
+                       tmptsn =(tsn_t*)(tsnlist->data);
+                       tfirst = tsn->secs + tsn->usecs/1000000.0;
+                       frame = tsn->frame_number;
+                       
+                       while (tsnlist)
+                       {
+                               tsnlist = g_list_previous(tsnlist);
+                               tsn = (tsn_t*) (tsnlist->data);
+                               if (tsn->secs+tsn->usecs/1000000.0<x_value)
+                               {
+                                       tfirst = tsn->secs+tsn->usecs/1000000.0;
+                                       tmptsn =tsn;
+                               }
+                               else
+                               {
+                                       if ((tfirst+tsn->secs+tsn->usecs/1000000.0)/2.0<x_value)
+                                       {
+                                               x_value = tsn->secs+tsn->usecs/1000000.0;
+                                               tmptsn = tsn;
+                                       }
+                                       else
+                                               x_value = tmptsn->secs+tmptsn->usecs/1000000.0;
+                                       break;
+                               }
+                       }
+                       cf_goto_frame(&cfile, tmptsn->frame_number);
+                       g_snprintf(label_string, 30, "(%.6f, %u)", x_value, y_value);
+                       label_set = TRUE;
+
+                       gdk_draw_line(u_data->io->pixmap,text_color, (gint)(event->x-2), (gint)(event->y), (gint)(event->x+2), (gint)(event->y));
+                       gdk_draw_line(u_data->io->pixmap,text_color, (gint)(event->x), (gint)(event->y-2), (gint)(event->x), (gint)(event->y+2));
+                       if (event->x+150>=u_data->io->pixmap_width)
+                               position = event->x - 150;
+                       else
+                               position = event->x + 5;
+
+#if GTK_MAJOR_VERSION < 2
+                       lwidth=gdk_string_width(font, label_string);
+                                           gdk_draw_string(u_data->io->pixmap,font,text_color,
+                                           (gint)(position),
+                                           (gint)(event->y-10),
+                                           label_string);
+#else
+                       memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
+                       pango_layout_set_text(layout, label_string, -1);
+                       pango_layout_get_pixel_size(layout, &lwidth, NULL);
+
+                       gdk_draw_layout(u_data->io->pixmap,text_color,
+                                                       (gint)(position),
+                                                       (gint)(event->y-10),
+                                                       layout);
+#endif
+                       ios=(sctp_graph_t *)OBJECT_GET_DATA(u_data->io->draw_area, "sctp_graph_t");
 
+                       if(!ios){
+                               exit(10);
+                       }
+                       gdk_draw_pixmap(u_data->io->draw_area->window,
+                                   u_data->io->draw_area->style->fg_gc[GTK_WIDGET_STATE(u_data->io->draw_area)],
+                                   ios->pixmap,
+                                   0, 0,
+                                   0, 0,
+                                   u_data->io->draw_area->allocation.width,
+                                   u_data->io->draw_area->allocation.height);
+               }
        }
        return TRUE;
 }
@@ -921,7 +1144,7 @@ static void init_sctp_graph_window(struct sctp_udata *u_data)
 {
        GtkWidget *vbox;
        GtkWidget *hbox;
-       GtkWidget *bt_close, *sack_bt, *tsn_bt, *both_bt, *zoomin_bt, *zoomout_bt;
+       GtkWidget *bt_close, *sack_bt, *tsn_bt, *both_bt, *zoomin_bt;
        GtkTooltips *tooltip_in, *tooltip_out;
 
        /* create the main window */
@@ -967,7 +1190,7 @@ static void init_sctp_graph_window(struct sctp_udata *u_data)
        gtk_widget_show(zoomin_bt);
        SIGNAL_CONNECT(zoomin_bt, "clicked", on_zoomin_bt, u_data);
        tooltip_in = gtk_tooltips_new();
-       gtk_tooltips_set_tip(tooltip_in, zoomin_bt, "Draw a rectangle around the area you want to zoom in", NULL);
+       gtk_tooltips_set_tip(tooltip_in, zoomin_bt, "Zoom in the area you have selected", NULL);
 
        zoomout_bt = gtk_button_new_with_label ("Zoom out");
        gtk_box_pack_start(GTK_BOX(hbox), zoomout_bt, FALSE, FALSE, 0);
@@ -975,7 +1198,7 @@ static void init_sctp_graph_window(struct sctp_udata *u_data)
        SIGNAL_CONNECT(zoomout_bt, "clicked", on_zoomout_bt, u_data);
        tooltip_out = gtk_tooltips_new();
        gtk_tooltips_set_tip(tooltip_out, zoomout_bt, "Zoom out one step", NULL);
-
+       gtk_widget_set_sensitive(zoomout_bt, FALSE);
 
        bt_close = BUTTON_NEW_FROM_STOCK(GTK_STOCK_CLOSE);
        gtk_box_pack_start(GTK_BOX(hbox), bt_close, FALSE, FALSE, 0);
@@ -986,7 +1209,7 @@ static void init_sctp_graph_window(struct sctp_udata *u_data)
        gtk_signal_connect(GTK_OBJECT(u_data->io->draw_area),"button_release_event",(GtkSignalFunc)on_button_release, u_data);
        gtk_widget_set_events(u_data->io->draw_area, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_EXPOSURE_MASK);
        /* dlg_set_cancel(u_data->io->window, bt_close); */
-       
+
 
        gtk_widget_show(u_data->io->window);
 }
@@ -1082,7 +1305,7 @@ static void create_draw_area(GtkWidget *box, struct sctp_udata *u_data)
        gtk_box_pack_start(GTK_BOX(box), u_data->io->draw_area, TRUE, TRUE, 0);
 }
 
-void insertion(GPtrArray *array, guint32 N)
+static void insertion(GPtrArray *array, guint32 N)
 {
        guint32 i, j;
        guint32 v;
@@ -1103,7 +1326,7 @@ void insertion(GPtrArray *array, guint32 N)
        }
 }
 
-void set_arw_offsets(struct sctp_udata *u_data)
+static void set_arw_offsets(struct sctp_udata *u_data)
 {
        GPtrArray *s_array=NULL, *t_array=NULL;
        guint32 i, j=0;
@@ -1121,7 +1344,7 @@ void set_arw_offsets(struct sctp_udata *u_data)
                                j++;
                        }
                        ((struct tsn_sort*)(g_ptr_array_index(s_array,i)))->offset = ((struct tsn_sort*)(g_ptr_array_index(t_array, j)))->offset
-                         + ((struct tsn_sort*)(g_ptr_array_index(t_array, j)))->length;                         
+                         + ((struct tsn_sort*)(g_ptr_array_index(t_array, j)))->length;
                }
 
                u_data->assoc->sort_sack1=s_array;
@@ -1146,7 +1369,7 @@ void set_arw_offsets(struct sctp_udata *u_data)
        }
 }
 
-void compute_offsets(struct sctp_udata *u_data)
+static void compute_offsets(struct sctp_udata *u_data)
 {
        struct tsn_sort t_sort;
        GPtrArray *array=NULL;
@@ -1161,7 +1384,7 @@ void compute_offsets(struct sctp_udata *u_data)
 
                for (i=0; i<u_data->assoc->n_array_tsn1; i++)
                {
-                       ((struct tsn_sort*)(g_ptr_array_index(array, i)))->offset=sum;                  
+                       ((struct tsn_sort*)(g_ptr_array_index(array, i)))->offset=sum;
                        t_sort.tsnumber=((struct tsn_sort*)(g_ptr_array_index(array, i)))->tsnumber;
                        if (t_sort.tsnumber>tsntmp)
                                sum+=((struct tsn_sort*)(g_ptr_array_index(array, i)))->length;
@@ -1205,9 +1428,9 @@ void create_byte_graph(guint16 dir, struct sctp_analyse* userdata)
        else
        {
                set_child(u_data, u_data->parent);
-               increase_childcount(u_data->parent);            
-               compute_offsets(u_data);                
-               set_arw_offsets(u_data);                
+               increase_childcount(u_data->parent);
+               compute_offsets(u_data);
+               set_arw_offsets(u_data);
                gtk_sctpgraph_init(u_data);
        }