Use glib equivalent of ntohs
[obnox/wireshark/wip.git] / gtk / sctp_graph_dlg.c
1 /*
2  * Copyright 2004, Irene Ruengeler <i.ruengeler [AT] fh-muenster.de>
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #  include <config.h>
27 #endif
28
29
30 #include <gtk/gtk.h>
31 #include <gdk/gdk.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <math.h>
35 #include <string.h>
36 #include "globals.h"
37 #include "epan/filesystem.h"
38 #include "../color.h"
39 #include "dlg_utils.h"
40 #include "ui_util.h"
41 #include "main.h"
42 #include "compat_macros.h"
43 #include "simple_dialog.h"
44 #include "sctp_stat.h"
45
46 #define DEFAULT_PIXELS_PER_TICK 2
47 #define MAX_PIXELS_PER_TICK 4
48 #define AUTO_MAX_YSCALE 0
49 #define MAX_TICK_VALUES 5
50 #define DEFAULT_TICK_VALUE 3
51 #define MAX_YSCALE 22
52 #define MAX_COUNT_TYPES 3
53
54 #define COUNT_TYPE_FRAMES   0
55 #define COUNT_TYPE_BYTES    1
56 #define COUNT_TYPE_ADVANCED 2
57
58 #define LEFT_BORDER 60
59 #define RIGHT_BORDER 10
60 #define TOP_BORDER 10
61 #define BOTTOM_BORDER 50
62
63 #define SUB_32(a, b)    a-b
64 #define POINT_SIZE      3
65
66 struct chunk_header {
67         guint8  type;
68         guint8  flags;
69         guint16 length;
70 };
71
72 struct data_chunk_header {
73         guint8  type;
74         guint8  flags;
75         guint16 length;
76         guint32 tsn;
77         guint16 sid;
78         guint16 ssn;
79         guint32 ppi;
80 };
81
82 struct init_chunk_header {
83         guint8  type;
84         guint8  flags;
85         guint16 length;
86         guint32 initiate_tag;
87         guint32 a_rwnd;
88         guint16 mos;
89         guint16 mis;
90         guint32 initial_tsn;
91 };
92
93 struct gaps {
94         guint16 start;
95         guint16 end;
96 };
97
98 struct sack_chunk_header {
99         guint8  type;
100         guint8  flags;
101         guint16 length;
102         guint32 cum_tsn_ack;
103         guint32 a_rwnd;
104         guint16 nr_of_gaps;
105         guint16 nr_of_dups;
106         struct gaps gaps[1];
107 };
108
109
110 static gboolean label_set = FALSE;
111 static guint32 max_tsn=0, min_tsn=0;
112 static void sctp_graph_set_title(struct sctp_udata *u_data);
113 static void create_draw_area(GtkWidget *box, struct sctp_udata *u_data);
114 static GtkWidget *zoomout_bt;
115 #if defined(_WIN32) && !defined(__MINGW32__)
116 static int rint (double );      /* compiler template for Windows */
117 #endif
118
119 static void draw_sack_graph(struct sctp_udata *u_data)
120 {
121         tsn_t   *sack;
122         GList *list=NULL, *tlist;
123         guint16 gap_start=0, gap_end=0, i, j, nr;
124         guint8 type;
125         guint32 tsnumber;
126         gint xvalue, yvalue;
127         GdkColor red_color = {0, 65535, 0, 0};
128         GdkColor green_color = {0, 0, 65535, 0};
129         GdkGC *red_gc, *green_gc;
130         struct sack_chunk_header *sack_header;
131         struct gaps *gap;
132         guint32 max_num, diff;
133 #if GTK_MAJOR_VERSION < 2
134         GdkColormap *colormap;
135 #endif
136
137         red_gc = gdk_gc_new(u_data->io->draw_area->window);
138 #if GTK_MAJOR_VERSION < 2
139                 colormap = gtk_widget_get_colormap (u_data->io->draw_area);
140                 if (!gdk_color_alloc (colormap, &red_color))
141                 {
142                         g_warning ("Couldn't allocate color");
143                 }
144
145                 gdk_gc_set_foreground(red_gc, &red_color);
146 #else
147                 gdk_gc_set_rgb_fg_color(red_gc, &red_color);
148 #endif
149
150         green_gc = gdk_gc_new(u_data->io->draw_area->window);
151 #if GTK_MAJOR_VERSION < 2
152                 colormap = gtk_widget_get_colormap (u_data->io->draw_area);
153                 if (!gdk_color_alloc (colormap, &green_color))
154                 {
155                         g_warning ("Couldn't allocate color");
156                 }
157
158                 gdk_gc_set_foreground(green_gc, &green_color);
159 #else
160                 gdk_gc_set_rgb_fg_color(green_gc, &green_color);
161 #endif
162
163         if (u_data->dir==2)
164         {
165
166                 list = g_list_last(u_data->assoc->sack2);
167                 if (u_data->io->tmp==FALSE)
168                 {
169                         min_tsn=u_data->assoc->min_tsn2;
170                         max_tsn=u_data->assoc->max_tsn2;
171                 }
172                 else
173                 {
174                         min_tsn=u_data->assoc->min_tsn2+u_data->io->tmp_min_tsn2;
175                         max_tsn=u_data->assoc->min_tsn2+u_data->io->tmp_max_tsn2;
176                 }
177         }
178         else if (u_data->dir==1)
179         {
180                 list = g_list_last(u_data->assoc->sack1);
181                 if (u_data->io->tmp==FALSE)
182                 {
183                         min_tsn=u_data->assoc->min_tsn1;
184                         max_tsn=u_data->assoc->max_tsn1;
185                 }
186                 else
187                 {
188                         min_tsn=u_data->assoc->min_tsn1+u_data->io->tmp_min_tsn1;
189                         max_tsn=u_data->assoc->min_tsn1+u_data->io->tmp_max_tsn1;
190                 }
191         }
192
193         while (list)
194         {
195                 sack = (tsn_t*) (list->data);
196                 tlist = g_list_first(sack->tsns);
197                 while (tlist)
198                 {
199                         type = ((struct chunk_header *)tlist->data)->type;
200
201                         if (type == SCTP_SACK_CHUNK_ID)
202                         {
203                                 sack_header =(struct sack_chunk_header *)tlist->data;
204                                 nr=g_ntohs(sack_header->nr_of_gaps);
205                                 tsnumber = g_ntohl(sack_header->cum_tsn_ack);
206
207                                 if (sack->secs>=u_data->io->x1_tmp_sec)
208                                 {
209                                         if (nr>0)
210                                         {
211                                                 gap = &sack_header->gaps[0];
212                                                 for(i=0;i<nr; i++)
213                                                 {
214                                                         gap_start=g_ntohs(gap->start);
215                                                         gap_end = g_ntohs(gap->end);
216                                                         max_num=gap_end+tsnumber;
217                                                         for (j=gap_start; j<=gap_end; j++)
218                                                         {
219                                                                 if (u_data->io->uoff)
220                                                                         diff = sack->secs - u_data->io->min_x;
221                                                                 else
222                                                                         diff=sack->secs*1000000+sack->usecs-u_data->io->min_x;
223                                                                 xvalue = (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff);
224                                                                 yvalue = (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-POINT_SIZE-u_data->io->offset-((SUB_32(j+tsnumber,min_tsn))*u_data->io->y_interval));
225                                                                 if (xvalue >= LEFT_BORDER+u_data->io->offset &&
226                                                                     xvalue <= u_data->io->pixmap_width-RIGHT_BORDER+u_data->io->offset &&
227                                                                     yvalue >= TOP_BORDER-u_data->io->offset &&
228                                                                     yvalue <= u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset)
229                                                                         gdk_draw_arc(u_data->io->pixmap,green_gc,TRUE,
230                                                                                     xvalue,
231                                                                                     yvalue,
232                                                                                     POINT_SIZE, POINT_SIZE,0, (64*360) );
233                                                         }
234                                                         if (i < nr-1)
235                                                                 gap++;
236                                                 }
237                                         }
238                                         else
239                                                 max_num=tsnumber;
240                                         if (tsnumber>=min_tsn)
241                                         {
242                                                 if (u_data->io->uoff)
243                                                         diff = sack->secs - u_data->io->min_x;
244                                                 else
245                                                         diff=sack->secs*1000000+sack->usecs-u_data->io->min_x;
246                                                 xvalue = (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff);
247                                                 yvalue = (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-POINT_SIZE -u_data->io->offset-((SUB_32(tsnumber,min_tsn))*u_data->io->y_interval));
248                                                 if (xvalue >= LEFT_BORDER+u_data->io->offset && 
249                                                     xvalue <= u_data->io->pixmap_width-RIGHT_BORDER+u_data->io->offset &&
250                                                     yvalue >= TOP_BORDER-u_data->io->offset &&
251                                                     yvalue <= u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset)
252                                                         gdk_draw_arc(u_data->io->pixmap,red_gc,TRUE,
253                                                                      xvalue,
254                                                                      yvalue,
255                                                                      POINT_SIZE, POINT_SIZE,0, (64*360) );
256                                         }
257                                 }
258                         tlist = g_list_next(tlist);
259                         }
260                 }
261                 list = g_list_previous(list);
262         }
263 #if GTK_MAJOR_VERSION >= 2
264                 g_object_unref(G_OBJECT(red_gc));
265                 g_object_unref(G_OBJECT(green_gc));
266 #endif
267 }
268
269
270 static void draw_tsn_graph(struct sctp_udata *u_data)
271 {
272         tsn_t *tsn;
273         GList *list=NULL, *tlist;
274         guint8 type;
275         guint32 tsnumber=0;
276         guint32 min_secs=0, diff;
277         gint xvalue, yvalue;
278
279         if (u_data->dir==1)
280         {
281                 list = g_list_last(u_data->assoc->tsn1);
282                 if (u_data->io->tmp==FALSE)
283                 {
284                         min_tsn=u_data->assoc->min_tsn1;
285                         max_tsn=u_data->assoc->max_tsn1;
286                 }
287                 else
288                 {
289                         min_tsn=u_data->assoc->min_tsn1+u_data->io->tmp_min_tsn1;
290                         max_tsn=u_data->assoc->min_tsn1+u_data->io->tmp_max_tsn1;
291                 }
292         }
293         else if (u_data->dir==2)
294         {
295                 list = g_list_last(u_data->assoc->tsn2);
296                 if (u_data->io->tmp==FALSE)
297                 {
298                         min_tsn=u_data->assoc->min_tsn2;
299                         max_tsn=u_data->assoc->max_tsn2;
300                 }
301                 else
302                 {
303                         min_tsn=u_data->assoc->min_tsn2+u_data->io->tmp_min_tsn2;
304                         max_tsn=u_data->assoc->min_tsn2+u_data->io->tmp_max_tsn2;
305                 }
306         }
307
308         while (list)
309         {
310                 tsn = (tsn_t*) (list->data);
311                 tlist = g_list_first(tsn->tsns);
312                 while (tlist)
313                 {
314                         type = ((struct chunk_header *)tlist->data)->type;
315                         if (type == SCTP_DATA_CHUNK_ID)
316                                 tsnumber = g_ntohl(((struct data_chunk_header *)tlist->data)->tsn);
317                         if (tsnumber>=min_tsn && tsnumber<=max_tsn && tsn->secs>=min_secs)
318                         {
319                                         if (u_data->io->uoff)
320                                                 diff = tsn->secs - u_data->io->min_x;
321                                         else
322                                                 diff=tsn->secs*1000000+tsn->usecs-u_data->io->min_x;
323                                         xvalue = (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff);
324                                         yvalue = (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-POINT_SIZE-u_data->io->offset-((SUB_32(tsnumber,min_tsn))*u_data->io->y_interval));
325                                         if (xvalue >= LEFT_BORDER+u_data->io->offset && 
326                                             xvalue <= u_data->io->pixmap_width-RIGHT_BORDER+u_data->io->offset &&
327                                             yvalue >= TOP_BORDER-u_data->io->offset &&
328                                             yvalue <= u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset)
329                                                 gdk_draw_arc(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,TRUE,
330                                                              xvalue,
331                                                              yvalue,
332                                                              POINT_SIZE, POINT_SIZE, 0, (64*360));
333                         }
334                         tlist = g_list_next(tlist);
335                 }
336                 list = g_list_previous(list);
337         }
338 }
339
340
341 static void sctp_graph_draw(struct sctp_udata *u_data)
342 {
343         int length, lwidth;
344         guint32  distance=5, i, e, sec, w, start, a, b, j;
345         gint label_width, label_height;
346         char label_string[15];
347         gfloat dis;
348         gboolean write_label = FALSE;
349
350 #if GTK_MAJOR_VERSION < 2
351         GdkFont *font;
352 #else
353         PangoLayout  *layout;
354 #endif
355
356         if (u_data->io->x1_tmp_sec==0 && u_data->io->x1_tmp_usec==0)
357                 u_data->io->offset=0;
358         else
359                 u_data->io->offset=5;
360
361         if (u_data->io->x2_tmp_sec - u_data->io->x1_tmp_sec > 1500)
362         {
363                 u_data->io->min_x=u_data->io->x1_tmp_sec;
364                 u_data->io->max_x=u_data->io->x2_tmp_sec;
365                 u_data->io->uoff = TRUE;
366         }
367         else
368         {
369                 u_data->io->min_x=(guint32)(u_data->io->x1_tmp_sec*1000000.0+u_data->io->x1_tmp_usec);
370                 u_data->io->max_x=(guint32)(u_data->io->x2_tmp_sec*1000000.0+u_data->io->x2_tmp_usec);
371                 u_data->io->uoff = FALSE;
372         }
373
374         u_data->io->tmp_width=u_data->io->max_x-u_data->io->min_x;
375
376         if (u_data->dir==1)
377         {
378                 if (u_data->io->tmp==FALSE)
379                 {
380                         if (u_data->assoc->tsn1!=NULL || u_data->assoc->sack1!=NULL)
381                                 u_data->io->max_y=u_data->io->tmp_max_tsn1 - u_data->io->tmp_min_tsn1;
382                         else
383                                 u_data->io->max_y= 0;
384                         u_data->io->min_y = 0;
385                 }
386                 else
387                 {
388                         u_data->io->max_y = u_data->io->tmp_max_tsn1;
389                         u_data->io->min_y = u_data->io->tmp_min_tsn1;
390                 }
391         }
392         else if (u_data->dir==2)
393         {
394                 if (u_data->io->tmp==FALSE)
395                 {
396                         if (u_data->assoc->tsn2!=NULL || u_data->assoc->sack2!=NULL)
397                                         u_data->io->max_y=u_data->io->tmp_max_tsn2 -u_data->io->tmp_min_tsn2;
398                         else
399                                 u_data->io->max_y= 0;
400                         u_data->io->min_y = 0;
401                 }
402                 else
403                 {
404                         u_data->io->max_y = u_data->io->tmp_max_tsn2;
405                         u_data->io->min_y = u_data->io->tmp_min_tsn2;
406                 }
407         }
408
409         gdk_draw_rectangle(u_data->io->pixmap,
410                            u_data->io->draw_area->style->white_gc,
411                            TRUE,
412                            0, 0,
413                            u_data->io->draw_area->allocation.width,
414                            u_data->io->draw_area->allocation.height);
415
416         distance=5;
417         /* x_axis */
418         gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc, LEFT_BORDER+u_data->io->offset,u_data->io->pixmap_height-BOTTOM_BORDER,u_data->io->pixmap_width-RIGHT_BORDER+u_data->io->offset, u_data->io->pixmap_height-BOTTOM_BORDER);
419         gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,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);
420         gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,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);
421         u_data->io->axis_width=u_data->io->pixmap_width-LEFT_BORDER-RIGHT_BORDER-u_data->io->offset;
422
423         /* try to avoid dividing by zero */
424         if(u_data->io->tmp_width>0){
425                 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*/
426         } else {
427                 u_data->io->x_interval = (float)(u_data->io->axis_width);
428         }
429
430         e=0; /*number of decimals of x_interval*/
431         if (u_data->io->x_interval<1)
432         {
433                 dis=1/u_data->io->x_interval;
434                 while (dis >1)
435                 {
436                         dis/=10;
437                         e++;
438                 }
439                 distance=1;
440                 for (i=0; i<=e+1; i++)
441                         distance*=10; /*distance per 100 pixels*/
442         }
443         else
444                 distance=5;
445
446 #if GTK_MAJOR_VERSION < 2
447         font = u_data->io->draw_area->style->font;
448 #endif
449
450 #if GTK_MAJOR_VERSION < 2
451         label_width=gdk_string_width(font, label_string);
452         label_height=gdk_string_height(font, label_string);
453 #else
454         g_snprintf(label_string, 15, "%d", 0);
455         memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
456         layout = gtk_widget_create_pango_layout(u_data->io->draw_area, label_string);
457         pango_layout_get_pixel_size(layout, &label_width, &label_height);
458
459 #endif
460
461         if (u_data->io->x1_tmp_usec==0)
462                 sec=u_data->io->x1_tmp_sec;
463         else
464                 sec=u_data->io->x1_tmp_sec+1;
465
466
467         if (u_data->io->offset!=0)
468         {
469                 g_snprintf(label_string, 15, "%u", u_data->io->x1_tmp_sec);
470
471 #if GTK_MAJOR_VERSION < 2
472                 lwidth=gdk_string_width(font, label_string);
473                 gdk_draw_string(u_data->io->pixmap,font,u_data->io->draw_area->style->black_gc,
474                                 LEFT_BORDER-25,
475                                 u_data->io->pixmap_height-BOTTOM_BORDER+20,
476                                 label_string);
477 #else
478                 memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
479                 pango_layout_set_text(layout, label_string, -1);
480                 pango_layout_get_pixel_size(layout, &lwidth, NULL);
481
482                 gdk_draw_layout(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
483                                 LEFT_BORDER-25,
484                                 u_data->io->pixmap_height-BOTTOM_BORDER+20,
485                                 layout);
486 #endif
487         }
488
489         w=(guint32)(500/(guint32)(distance*u_data->io->x_interval)); /*there will be a label for every w_th tic*/
490
491         if (w==0)
492                 w=1;
493         
494         if (w==4 || w==3 || w==2)
495         {
496                 w=5;
497                 a=distance/10;  /*distance between two tics*/
498                 b = (guint32)((u_data->io->min_x/100000))%10; /* start for labels*/
499         }
500         else
501         {
502                 a=distance/5;
503                 b=0;
504         }
505         
506
507         if (!u_data->io->uoff)  
508         {
509                 if (a>=1000000)
510                 {
511                         start=u_data->io->min_x/1000000*1000000;
512                         if (a==1000000)
513                                 b = 0;
514                 }
515                 else
516                 {
517                         start=u_data->io->min_x/100000;
518                         if (start%2!=0)
519                                 start--;
520                         start*=100000;
521                         b = (guint32)((start/100000))%10;
522                 }
523         }
524         else
525         {
526                 start = u_data->io->min_x;
527                 if (start%2!=0)
528                         start--;
529                 b = 0;
530                 
531         }
532
533         for (i=start, j=b; i<=u_data->io->max_x; i+=a, j++)
534         {
535                 if (!u_data->io->uoff)
536                 if (i>=u_data->io->min_x && i%1000000!=0)
537                 {
538                         length=5;
539                         g_snprintf(label_string, 15, "%d", i%1000000);
540                         if (j%w==0)
541                         {
542                                 length=10;
543
544                                 #if GTK_MAJOR_VERSION < 2
545                                         lwidth=gdk_string_width(font, label_string);
546                                         gdk_draw_string(u_data->io->pixmap,font,u_data->io->draw_area->style->black_gc,
547                                                 (guint32)(LEFT_BORDER+u_data->io->offset+(i-u_data->io->min_x)*u_data->io->x_interval-lwidth/2),
548                                                 u_data->io->pixmap_height-BOTTOM_BORDER+10,
549                                                 label_string);
550                                 #else
551                                         memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
552                                         pango_layout_set_text(layout, label_string, -1);
553                                         pango_layout_get_pixel_size(layout, &lwidth, NULL);
554                                         gdk_draw_layout(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
555                                                 (guint32)(LEFT_BORDER+u_data->io->offset+(i-u_data->io->min_x)*u_data->io->x_interval-lwidth/2),
556                                                 u_data->io->pixmap_height-BOTTOM_BORDER+10,
557                                                 layout);
558                                 #endif
559                         }
560                         gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
561                                 (guint32)(LEFT_BORDER+u_data->io->offset+(i-u_data->io->min_x)*u_data->io->x_interval),
562                                 u_data->io->pixmap_height-BOTTOM_BORDER,
563                                 (guint32)(LEFT_BORDER+u_data->io->offset+(i-u_data->io->min_x)*u_data->io->x_interval),
564                                 u_data->io->pixmap_height-BOTTOM_BORDER+length);
565                 }
566
567                 if (!u_data->io->uoff)
568                 {
569                         if (i%1000000==0 && j%w==0)
570                         {
571                                 sec=i/1000000;
572                                 write_label = TRUE;
573                         }
574                 }
575                 else
576                 {
577                         if (j%w == 0)
578                         {
579                                 sec = i;
580                                 write_label = TRUE;
581                         }
582                 }
583                 if (write_label)
584                 {
585                         gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
586                         (guint32)(LEFT_BORDER+u_data->io->offset+(i-u_data->io->min_x)*u_data->io->x_interval),
587                         u_data->io->pixmap_height-BOTTOM_BORDER,
588                         (guint32)(LEFT_BORDER+u_data->io->offset+(i-u_data->io->min_x)*u_data->io->x_interval),
589                         u_data->io->pixmap_height-BOTTOM_BORDER+10);
590
591                         g_snprintf(label_string, 15, "%d", sec);
592                         #if GTK_MAJOR_VERSION < 2
593                                 lwidth=gdk_string_width(font, label_string);
594                                 gdk_draw_string(u_data->io->pixmap,font,u_data->io->draw_area->style->black_gc,
595                                         (guint32)(LEFT_BORDER+u_data->io->offset+(i-u_data->io->min_x)*u_data->io->x_interval-10),
596                                         u_data->io->pixmap_height-BOTTOM_BORDER+20,
597                                         label_string);
598                         #else
599                                 memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
600                                 pango_layout_set_text(layout, label_string, -1);
601                                 pango_layout_get_pixel_size(layout, &lwidth, NULL);
602
603                                 gdk_draw_layout(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
604                                 (guint32)(LEFT_BORDER+u_data->io->offset+(i-u_data->io->min_x)*u_data->io->x_interval-10),
605                                         u_data->io->pixmap_height-BOTTOM_BORDER+20,
606                                         layout);
607                         #endif
608                         write_label = FALSE;
609                 }
610                 
611         }
612
613         strcpy(label_string, "sec");
614
615 #if GTK_MAJOR_VERSION < 2
616         lwidth=gdk_string_width(font, label_string);
617         gdk_draw_string(u_data->io->pixmap,
618                         font,
619                         u_data->io->draw_area->style->black_gc,
620                         u_data->io->pixmap_width-RIGHT_BORDER-10,
621                         u_data->io->pixmap_height-BOTTOM_BORDER+30,
622                         label_string);
623 #else
624         memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
625         pango_layout_set_text(layout, label_string, -1);
626         pango_layout_get_pixel_size(layout, &lwidth, NULL);
627         gdk_draw_layout(u_data->io->pixmap,
628                         u_data->io->draw_area->style->black_gc,
629                         u_data->io->pixmap_width-RIGHT_BORDER-10,
630                         u_data->io->pixmap_height-BOTTOM_BORDER+30,
631                         layout);
632 #endif
633
634         distance=5;
635
636         /* y-axis */
637         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,u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset);
638         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+5);
639         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+5);
640
641         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));
642
643         e=0;
644         if (u_data->io->y_interval<1)
645         {
646                 dis=1/u_data->io->y_interval;
647                 while (dis >1)
648                 {
649                         dis/=10;
650                         e++;
651                 }
652                 distance=1;
653                 for (i=0; i<=e; i++)
654                         distance=distance*10;
655         }
656         else if (u_data->io->y_interval<2)
657                 distance = 10;
658
659         if (u_data->io->max_y>0)
660         {
661                 for (i=u_data->io->min_y/distance*distance; i<=u_data->io->max_y; i+=distance/5)
662                 {
663                         if (i>=u_data->io->min_y)
664                         {
665                                 length=5;
666                                 g_snprintf(label_string, 15, "%d", i);
667                                 if (i%distance==0 || (distance<=5 && u_data->io->y_interval>10))
668                                 {
669                                         length=10;
670
671 #if GTK_MAJOR_VERSION < 2
672                                                 lwidth=gdk_string_width(font, label_string);
673                                                 gdk_draw_string(u_data->io->pixmap,font,u_data->io->draw_area->style->black_gc,
674                                                                 LEFT_BORDER-length-lwidth-5,
675                                                                 (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-(i-u_data->io->min_y)*u_data->io->y_interval-POINT_SIZE),
676                                                                 label_string);
677 #else
678                                                 memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
679                                                 pango_layout_set_text(layout, label_string, -1);
680                                                 pango_layout_get_pixel_size(layout, &lwidth, NULL);
681                                                 gdk_draw_layout(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
682                                                                 LEFT_BORDER-length-lwidth-5,
683                                                                 (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-(i-u_data->io->min_y)*u_data->io->y_interval-POINT_SIZE),
684                                                                 layout);
685 #endif
686                                 }
687                                 gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,LEFT_BORDER-length,
688                                               (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-(i-u_data->io->min_y)*u_data->io->y_interval),
689                                               LEFT_BORDER,
690                                               (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-(i-u_data->io->min_y)*u_data->io->y_interval));
691                         }
692                 }
693         }
694         else if ((u_data->dir==1 && u_data->assoc->n_array_tsn1==0) || (u_data->dir==2 && u_data->assoc->n_array_tsn2==0))
695                 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, "No Data Chunks sent");
696 }
697
698
699 static void sctp_graph_redraw(struct sctp_udata *u_data)
700 {
701 sctp_graph_t *ios;
702
703         u_data->io->needs_redraw=TRUE;
704
705         sctp_graph_draw(u_data);
706         switch (u_data->io->graph_type)
707         {
708                 case 0:
709                         draw_sack_graph(u_data);
710                         draw_tsn_graph(u_data);
711                         break;
712                 case 1:
713                         draw_tsn_graph(u_data);
714                         break;
715                 case 2:
716                         draw_sack_graph(u_data);
717                         break;
718         }
719         ios=(sctp_graph_t *)OBJECT_GET_DATA(u_data->io->draw_area, "sctp_graph_t");
720
721         if(!ios){
722                 exit(10);
723         }
724
725
726         gdk_draw_pixmap(u_data->io->draw_area->window,
727                         u_data->io->draw_area->style->fg_gc[GTK_WIDGET_STATE(u_data->io->draw_area)],
728                         ios->pixmap,
729                         0,0,
730                         0, 0,
731                         u_data->io->draw_area->allocation.width,
732                         u_data->io->draw_area->allocation.height);
733 }
734
735
736 static void on_sack_bt(GtkWidget *widget _U_, struct sctp_udata *u_data)
737 {
738
739         u_data = (struct sctp_udata *) u_data;
740         u_data->io->graph_type=2;
741         sctp_graph_redraw(u_data);
742 }
743
744 static void on_tsn_bt(GtkWidget *widget _U_, struct sctp_udata *u_data)
745 {
746
747         u_data->io->graph_type=1;
748         sctp_graph_redraw(u_data);
749 }
750
751 static void on_both_bt(GtkWidget *widget _U_, struct sctp_udata *u_data)
752 {
753
754         u_data->io->graph_type=0;
755         sctp_graph_redraw(u_data);
756 }
757
758 static void
759 sctp_graph_close_cb(GtkWidget* widget _U_, gpointer u_data)
760 {
761         struct sctp_udata *udata;
762         int dir;
763
764         udata = (struct sctp_udata *)u_data;
765         dir=udata->dir-1;
766         gtk_grab_remove(GTK_WIDGET(udata->io->window));
767         gtk_widget_destroy(GTK_WIDGET(udata->io->window));
768
769 }
770
771 static gint
772 configure_event(GtkWidget *widget, GdkEventConfigure *event _U_, struct sctp_udata *u_data)
773 {
774         if(!u_data->io){
775                 exit(10);
776         }
777
778         if(u_data->io->pixmap){
779                 gdk_pixmap_unref(u_data->io->pixmap);
780                 u_data->io->pixmap=NULL;
781         }
782
783         u_data->io->pixmap=gdk_pixmap_new(widget->window,
784                         widget->allocation.width,
785                         widget->allocation.height,
786                         -1);
787         u_data->io->pixmap_width=widget->allocation.width;
788         u_data->io->pixmap_height=widget->allocation.height;
789
790         gdk_draw_rectangle(u_data->io->pixmap,
791                         widget->style->white_gc,
792                         TRUE,
793                         0, 0,
794                         widget->allocation.width,
795                         widget->allocation.height);
796         sctp_graph_redraw(u_data);
797         return TRUE;
798 }
799
800 static gint
801 expose_event(GtkWidget *widget, GdkEventExpose *event)
802 {
803         sctp_graph_t *ios;
804
805         ios=(sctp_graph_t *)OBJECT_GET_DATA(widget, "sctp_graph_t");
806         if(!ios){
807                 exit(10);
808         }
809
810         gdk_draw_pixmap(widget->window,
811                         widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
812                         ios->pixmap,
813                         event->area.x, event->area.y,
814                         event->area.x, event->area.y,
815                         event->area.width, event->area.height);
816
817         return FALSE;
818 }
819
820
821 static void
822 on_zoomin_bt (GtkWidget *widget _U_, struct sctp_udata *u_data)
823 {
824         sctp_min_max_t *tmp_minmax;
825
826         if (u_data->io->rectangle_present==TRUE)
827         {
828                 tmp_minmax = g_malloc(sizeof(sctp_min_max_t));
829
830                 u_data->io->tmp_min_tsn1=u_data->io->y1_tmp+u_data->io->min_y;
831                 u_data->io->tmp_max_tsn1=u_data->io->y2_tmp+1+u_data->io->min_y;
832                 u_data->io->tmp_min_tsn2=u_data->io->tmp_min_tsn1;
833                 u_data->io->tmp_max_tsn2=u_data->io->tmp_max_tsn1;
834                 tmp_minmax->tmp_min_secs=u_data->io->x1_tmp_sec;
835                 tmp_minmax->tmp_min_usecs=      u_data->io->x1_tmp_usec;
836                 tmp_minmax->tmp_max_secs=       u_data->io->x2_tmp_sec;
837                 tmp_minmax->tmp_max_usecs=      u_data->io->x2_tmp_usec;
838                 tmp_minmax->tmp_min_tsn1=u_data->io->tmp_min_tsn1;
839                 tmp_minmax->tmp_max_tsn1=u_data->io->tmp_max_tsn1;
840                 tmp_minmax->tmp_min_tsn2=u_data->io->tmp_min_tsn2;
841                 tmp_minmax->tmp_max_tsn2=u_data->io->tmp_max_tsn2;
842                 u_data->assoc->min_max = g_slist_prepend(u_data->assoc->min_max, tmp_minmax);
843                 u_data->io->length = g_slist_length(u_data->assoc->min_max);
844                 u_data->io->tmp=TRUE;
845                 u_data->io->rectangle=FALSE;
846                 u_data->io->rectangle_present=FALSE;
847                 gtk_widget_set_sensitive(zoomout_bt, TRUE);
848                 sctp_graph_redraw(u_data);
849         }
850         else
851         {
852                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Please draw a rectangle around the area you want to zoom in!");
853         }
854 }
855
856 static void
857 zoomin_bt (struct sctp_udata *u_data)
858 {
859         sctp_min_max_t *tmp_minmax;
860
861         tmp_minmax = g_malloc(sizeof(sctp_min_max_t));
862
863         u_data->io->tmp_min_tsn1=u_data->io->y1_tmp+u_data->io->min_y;
864         u_data->io->tmp_max_tsn1=u_data->io->y2_tmp+1+u_data->io->min_y;
865         u_data->io->tmp_min_tsn2=u_data->io->tmp_min_tsn1;
866         u_data->io->tmp_max_tsn2=u_data->io->tmp_max_tsn1;
867         tmp_minmax->tmp_min_secs=u_data->io->x1_tmp_sec;
868         tmp_minmax->tmp_min_usecs=      u_data->io->x1_tmp_usec;
869         tmp_minmax->tmp_max_secs=       u_data->io->x2_tmp_sec;
870         tmp_minmax->tmp_max_usecs=      u_data->io->x2_tmp_usec;
871         tmp_minmax->tmp_min_tsn1=u_data->io->tmp_min_tsn1;
872         tmp_minmax->tmp_max_tsn1=u_data->io->tmp_max_tsn1;
873         tmp_minmax->tmp_min_tsn2=u_data->io->tmp_min_tsn2;
874         tmp_minmax->tmp_max_tsn2=u_data->io->tmp_max_tsn2;
875         u_data->assoc->min_max = g_slist_prepend(u_data->assoc->min_max, tmp_minmax);
876         u_data->io->length = g_slist_length(u_data->assoc->min_max);
877         u_data->io->tmp=TRUE;
878         u_data->io->rectangle=FALSE;
879         u_data->io->rectangle_present=FALSE;
880         gtk_widget_set_sensitive(zoomout_bt, TRUE);
881         sctp_graph_redraw(u_data);
882         
883 }
884
885
886
887 static void
888 on_zoomout_bt (GtkWidget *widget _U_, struct sctp_udata *u_data)
889 {
890         sctp_min_max_t *tmp_minmax, *mm;
891         gint l;
892
893         l = g_slist_length(u_data->assoc->min_max);
894
895         if (u_data->assoc->min_max!=NULL)
896         {
897                 mm=(sctp_min_max_t *)((u_data->assoc->min_max)->data);
898                 u_data->assoc->min_max=g_slist_remove(u_data->assoc->min_max, mm);
899                 g_free(mm);
900                 if (l>2)
901                 {
902                         tmp_minmax = (sctp_min_max_t *)u_data->assoc->min_max->data;
903                         u_data->io->x1_tmp_sec=tmp_minmax->tmp_min_secs;
904                         u_data->io->x1_tmp_usec=tmp_minmax->tmp_min_usecs;
905                         u_data->io->x2_tmp_sec=tmp_minmax->tmp_max_secs;
906                         u_data->io->x2_tmp_usec=tmp_minmax->tmp_max_usecs;
907                         u_data->io->tmp_min_tsn1=tmp_minmax->tmp_min_tsn1;
908                         u_data->io->tmp_max_tsn1=tmp_minmax->tmp_max_tsn1;
909                         u_data->io->tmp_min_tsn2=tmp_minmax->tmp_min_tsn2;
910                         u_data->io->tmp_max_tsn2=tmp_minmax->tmp_max_tsn2;
911                         u_data->io->tmp=TRUE;
912                 }
913                 else
914                 {
915                         u_data->io->x1_tmp_sec=u_data->assoc->min_secs;
916                         u_data->io->x1_tmp_usec=u_data->assoc->min_usecs;
917                         u_data->io->x2_tmp_sec=u_data->assoc->max_secs;
918                         u_data->io->x2_tmp_usec=u_data->assoc->max_usecs;
919                         u_data->io->tmp_min_tsn1=u_data->assoc->min_tsn1;
920                         u_data->io->tmp_max_tsn1=u_data->assoc->max_tsn1;
921                         u_data->io->tmp_min_tsn2=u_data->assoc->min_tsn2;
922                         u_data->io->tmp_max_tsn2=u_data->assoc->max_tsn2;
923                         u_data->io->tmp=FALSE;
924                 }
925         }
926         else
927         {
928                 u_data->io->x1_tmp_sec=u_data->assoc->min_secs;
929                 u_data->io->x1_tmp_usec=u_data->assoc->min_usecs;
930                 u_data->io->x2_tmp_sec=u_data->assoc->max_secs;
931                 u_data->io->x2_tmp_usec=u_data->assoc->max_usecs;
932                 u_data->io->tmp_min_tsn1=u_data->assoc->min_tsn1;
933                 u_data->io->tmp_max_tsn1=u_data->assoc->max_tsn1;
934                 u_data->io->tmp_min_tsn2=u_data->assoc->min_tsn2;
935                 u_data->io->tmp_max_tsn2=u_data->assoc->max_tsn2;
936                 u_data->io->tmp=FALSE;
937         }
938         if (g_slist_length(u_data->assoc->min_max)==1)
939                 gtk_widget_set_sensitive(zoomout_bt, FALSE);
940         sctp_graph_redraw(u_data);
941 }
942
943 static gint
944 on_button_press (GtkWidget *widget _U_, GdkEventButton *event, struct sctp_udata *u_data)
945 {
946         sctp_graph_t *ios;
947
948         if (u_data->io->rectangle==TRUE)
949         {
950                 gdk_draw_rectangle(u_data->io->pixmap,u_data->io->draw_area->style->white_gc,
951                                    FALSE,
952                                    (gint)floor(MIN(u_data->io->x_old,u_data->io->x_new)),
953                                    (gint)floor(MIN(u_data->io->y_old,u_data->io->y_new)),
954                                    (gint)floor(abs((long)(u_data->io->x_new-u_data->io->x_old))),
955                                    (gint)floor(abs((long)(u_data->io->y_new-u_data->io->y_old))));
956                 ios=(sctp_graph_t *)OBJECT_GET_DATA(u_data->io->draw_area, "sctp_graph_t");
957
958                 if(!ios){
959                         exit(10);
960                 }
961
962                 gdk_draw_pixmap(u_data->io->draw_area->window,
963                                 u_data->io->draw_area->style->fg_gc[GTK_WIDGET_STATE(u_data->io->draw_area)],
964                                 ios->pixmap,
965                                 0,0,
966                                 0, 0,
967                                 (gint)(abs((long)(u_data->io->x_new-u_data->io->x_old))),
968                                 (gint)(abs((long)(u_data->io->y_new-u_data->io->y_old))));
969                 sctp_graph_redraw(u_data);
970         }
971         u_data->io->x_old=event->x;
972         u_data->io->y_old=event->y;
973         if (u_data->io->y_old>u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-POINT_SIZE)
974                 u_data->io->y_old=u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-POINT_SIZE;
975         if (u_data->io->x_old<LEFT_BORDER+u_data->io->offset)
976                 u_data->io->x_old=LEFT_BORDER+u_data->io->offset;
977         u_data->io->rectangle=FALSE;
978
979         return TRUE;
980 }
981
982
983 static gint
984 on_button_release (GtkWidget *widget _U_, GdkEventButton *event, struct sctp_udata *u_data)
985 {
986         sctp_graph_t *ios;
987         guint32 helpx, helpy, x1_tmp, x2_tmp,  y_value, t_size=0, s_size=0, i, y_tolerance;
988         gint label_width, label_height;
989         gdouble x_value, position, s_diff=0, t_diff=0, x_tolerance=0.0001;
990         gint lwidth;
991         char label_string[30];
992         GdkGC *text_color;
993         GPtrArray *tsnlist = NULL, *sacklist=NULL;
994         struct tsn_sort *tsn, *sack=NULL;
995         gboolean sack_found = FALSE;
996
997         #if GTK_MAJOR_VERSION < 2
998                 GdkFont *font;
999 #else
1000                 PangoLayout  *layout;
1001 #endif
1002
1003 #if GTK_MAJOR_VERSION < 2
1004                 font = u_data->io->draw_area->style->font;
1005 #endif
1006
1007 #if GTK_MAJOR_VERSION < 2
1008                 label_width=gdk_string_width(font, label_string);
1009                 label_height=gdk_string_height(font, label_string);
1010 #else
1011                 g_snprintf(label_string, 15, "%d", 0);
1012                 memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
1013                 layout = gtk_widget_create_pango_layout(u_data->io->draw_area, label_string);
1014                 pango_layout_get_pixel_size(layout, &label_width, &label_height);
1015
1016 #endif
1017
1018         if (event->y>u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset)
1019                 event->y = u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset;
1020         if (event->x < LEFT_BORDER+u_data->io->offset)
1021                 event->x = LEFT_BORDER+u_data->io->offset;
1022         if (abs((long)(event->x-u_data->io->x_old))>10 || abs((long)(event->y-u_data->io->y_old))>10)
1023         {
1024                 u_data->io->rect_x_min = (gint)floor(MIN(u_data->io->x_old,event->x));
1025                 u_data->io->rect_x_max = (gint)ceil(MAX(u_data->io->x_old,event->x));
1026                 u_data->io->rect_y_min = (gint)floor(MIN(u_data->io->y_old,event->y));
1027                 u_data->io->rect_y_max = (gint)ceil(MAX(u_data->io->y_old,event->y))+POINT_SIZE;
1028                 gdk_draw_rectangle(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
1029                                    FALSE,
1030                                    u_data->io->rect_x_min, u_data->io->rect_y_min,
1031                                    u_data->io->rect_x_max - u_data->io->rect_x_min,
1032                                    u_data->io->rect_y_max - u_data->io->rect_y_min);
1033                 ios=(sctp_graph_t *)OBJECT_GET_DATA(u_data->io->draw_area, "sctp_graph_t");
1034
1035                 if(!ios){
1036                         exit(10);
1037                 }
1038
1039                 gdk_draw_pixmap(u_data->io->draw_area->window,
1040                                 u_data->io->draw_area->style->fg_gc[GTK_WIDGET_STATE(u_data->io->draw_area)],
1041                                 ios->pixmap,
1042                                 0, 0,
1043                                 0, 0,
1044                                 u_data->io->draw_area->allocation.width,
1045                                 u_data->io->draw_area->allocation.height);
1046
1047                 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));
1048                 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));
1049                 helpx=MIN(x1_tmp, x2_tmp);
1050                 if (helpx==x2_tmp)
1051                 {
1052                         x2_tmp=x1_tmp;
1053                         x1_tmp=helpx;
1054                 }
1055                 if (u_data->io->uoff)
1056                 {
1057                         if (x2_tmp - x1_tmp <= 1500)                    
1058                                 u_data->io->uoff = FALSE;
1059                         u_data->io->x1_tmp_sec=(guint32)x1_tmp;
1060                         u_data->io->x1_tmp_usec=0;
1061                         u_data->io->x2_tmp_sec=(guint32)x2_tmp;
1062                         u_data->io->x2_tmp_usec=0;
1063                 }
1064                 else 
1065                 {
1066                         u_data->io->x1_tmp_sec=(guint32)x1_tmp/1000000;
1067                         u_data->io->x1_tmp_usec=x1_tmp%1000000;
1068                         u_data->io->x2_tmp_sec=(guint32)x2_tmp/1000000;
1069                         u_data->io->x2_tmp_usec=x2_tmp%1000000;
1070                 }
1071                 u_data->io->x1_akt_sec = u_data->io->x1_tmp_sec;
1072                 u_data->io->x1_akt_usec = u_data->io->x1_tmp_usec;
1073                 u_data->io->x2_akt_sec = u_data->io->x2_tmp_sec;
1074                 u_data->io->x2_akt_usec = u_data->io->x2_tmp_usec;
1075
1076                 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);
1077                 u_data->io->y2_tmp=(guint32)((u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-event->y)/u_data->io->y_interval);
1078                 helpy = MIN(u_data->io->y1_tmp, u_data->io->y2_tmp);
1079                 u_data->io->y2_tmp = MAX(u_data->io->y1_tmp, u_data->io->y2_tmp);
1080                 u_data->io->y1_tmp = helpy;
1081                 u_data->io->x_new=event->x;
1082                 u_data->io->y_new=event->y;
1083                 u_data->io->rectangle=TRUE;
1084                 u_data->io->rectangle_present=TRUE;
1085         }
1086         else
1087         {
1088                 if (u_data->io->rectangle_present==TRUE)
1089                 {
1090                         u_data->io->rectangle_present=FALSE;
1091                         if (event->x >= u_data->io->rect_x_min && event->x <= u_data->io->rect_x_max && 
1092                              event->y >= u_data->io->rect_y_min && event->y <= u_data->io->rect_y_max)
1093                                 zoomin_bt(u_data);
1094                         else
1095                         {
1096                                 u_data->io->x1_tmp_sec = u_data->io->x1_akt_sec;
1097                                 u_data->io->x1_tmp_usec = u_data->io->x1_akt_usec;
1098                                 u_data->io->x2_tmp_sec = u_data->io->x2_akt_sec;
1099                                 u_data->io->x2_tmp_usec = u_data->io->x2_akt_usec;
1100                                 sctp_graph_redraw(u_data);
1101                         }
1102                 }
1103                 else if (label_set)
1104                 {
1105                         label_set = FALSE;
1106                         sctp_graph_redraw(u_data);
1107                 }
1108                 else
1109                 {
1110                         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-RIGHT_BORDER-u_data->io->offset))+u_data->io->x1_tmp_sec+u_data->io->x1_tmp_usec/1000000.0;
1111                         y_value = (gint)rint((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;
1112                         text_color = u_data->io->draw_area->style->black_gc;
1113
1114                         if (u_data->dir == 1)
1115                         {
1116                                 tsnlist = u_data->assoc->sort_tsn1;
1117                                 t_size = u_data->assoc->n_data_chunks_ep1;
1118                                 sacklist = u_data->assoc->sort_sack1;
1119                                 s_size = u_data->assoc->n_sack_chunks_ep1;
1120                         }
1121                         else
1122                         {
1123                                 tsnlist = u_data->assoc->sort_tsn2;
1124                                 t_size = u_data->assoc->n_data_chunks_ep2;
1125                                 sacklist = u_data->assoc->sort_sack2;
1126                                 s_size = u_data->assoc->n_sack_chunks_ep2;
1127                         }
1128                         x_tolerance = (gdouble)((u_data->io->tmp_width / u_data->io->axis_width*1.0))*5/1000000.0;
1129                         y_tolerance = (guint32)(((u_data->io->max_y - u_data->io->min_y) / (u_data->io->pixmap_height-TOP_BORDER-BOTTOM_BORDER-u_data->io->offset)) * 2.0);
1130                         if (y_tolerance==0)
1131                                 y_tolerance = 2;
1132                         else if (y_tolerance > 5)
1133                                 y_tolerance = 5;
1134
1135                         for (i=0; i<s_size; i++)
1136                         {
1137                                 sack = (struct tsn_sort*)(g_ptr_array_index(sacklist, i));
1138                                 if ((guint32)abs(sack->tsnumber - y_value)<y_tolerance)
1139                                 {
1140                                         s_diff = fabs((sack->secs+sack->usecs/1000000.0)- x_value);
1141                                         if (s_diff < x_tolerance)
1142                                                 sack_found = TRUE;
1143                                         break;
1144                                 }
1145                         }
1146
1147                         for (i=0; i<t_size; i++)
1148                         {
1149                                 tsn = (struct tsn_sort*)(g_ptr_array_index(tsnlist, i));
1150                                 if ((guint32)abs(tsn->tsnumber - y_value)<y_tolerance)
1151                                 {
1152                                         t_diff = fabs((tsn->secs+tsn->usecs/1000000.0)- x_value);
1153                                         if (sack_found && s_diff < t_diff)
1154                                         {
1155                                                 cf_goto_frame(&cfile, sack->framenumber);
1156                                                 x_value = sack->secs+sack->usecs/1000000.0;
1157                                                 y_value = sack->tsnumber;
1158                                         }
1159                                         else if (t_diff < x_tolerance)
1160                                         {
1161                                                 cf_goto_frame(&cfile, tsn->framenumber);
1162                                                 x_value = tsn->secs+tsn->usecs/1000000.0;
1163                                                 y_value = tsn->tsnumber;
1164                                         }
1165                                         break;
1166                                 }
1167                         }
1168
1169                         g_snprintf(label_string, 30, "(%.6lf, %u)", x_value, y_value);
1170
1171                         label_set = TRUE;
1172
1173                         gdk_draw_line(u_data->io->pixmap,text_color, (gint)(event->x-2), (gint)(event->y), (gint)(event->x+2), (gint)(event->y));
1174                         gdk_draw_line(u_data->io->pixmap,text_color, (gint)(event->x), (gint)(event->y-2), (gint)(event->x), (gint)(event->y+2));
1175                         if (event->x+150>=u_data->io->pixmap_width)
1176                                 position = event->x - 150;
1177                         else
1178                                 position = event->x + 5;
1179
1180
1181 #if GTK_MAJOR_VERSION < 2
1182                         lwidth=gdk_string_width(font, label_string);
1183                                             gdk_draw_string(u_data->io->pixmap,font,text_color,
1184                                             (gint)position,
1185                                             (gint)(event->y-10),
1186                                             label_string);
1187 #else
1188                         memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
1189                         pango_layout_set_text(layout, label_string, -1);
1190                         pango_layout_get_pixel_size(layout, &lwidth, NULL);
1191
1192                         gdk_draw_layout(u_data->io->pixmap,text_color,
1193                                             (gint)position,
1194                                             (gint)(event->y-10),
1195                                             layout);
1196         #endif
1197
1198                         ios=(sctp_graph_t *)OBJECT_GET_DATA(u_data->io->draw_area, "sctp_graph_t");
1199
1200                         if(!ios){
1201                                 exit(10);
1202                         }
1203                         gdk_draw_pixmap(u_data->io->draw_area->window,
1204                                     u_data->io->draw_area->style->fg_gc[GTK_WIDGET_STATE(u_data->io->draw_area)],
1205                                     ios->pixmap,
1206                                     0, 0,
1207                                     0, 0,
1208                                     u_data->io->draw_area->allocation.width,
1209                                     u_data->io->draw_area->allocation.height);
1210                 }
1211         }
1212         return TRUE;
1213 }
1214
1215
1216 static void init_sctp_graph_window(struct sctp_udata *u_data)
1217 {
1218         GtkWidget *vbox;
1219         GtkWidget *hbox;
1220         GtkWidget *bt_close, *sack_bt, *tsn_bt, *both_bt, *zoomin_bt;
1221         GtkTooltips *tooltip_in, *tooltip_out;
1222
1223         /* create the main window */
1224
1225         u_data->io->window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
1226
1227         gtk_widget_set_name(u_data->io->window, "SCTP Graphics");
1228
1229         vbox=gtk_vbox_new(FALSE, 0);
1230         gtk_container_add(GTK_CONTAINER(u_data->io->window), vbox);
1231         gtk_widget_show(vbox);
1232
1233         create_draw_area(vbox, u_data);
1234
1235         sctp_graph_set_title(u_data);
1236
1237         hbox = gtk_hbutton_box_new();
1238         gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
1239         gtk_container_set_border_width(GTK_CONTAINER(hbox), 10);
1240         gtk_button_box_set_layout(GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_SPREAD);
1241         gtk_button_box_set_spacing(GTK_BUTTON_BOX (hbox), 0);
1242         gtk_box_set_child_packing(GTK_BOX(vbox), hbox, FALSE, FALSE, 0, GTK_PACK_START);
1243         gtk_widget_show(hbox);
1244
1245         sack_bt = gtk_button_new_with_label ("Show Sacks");
1246         gtk_box_pack_start(GTK_BOX(hbox), sack_bt, FALSE, FALSE, 0);
1247         gtk_widget_show(sack_bt);
1248
1249         gtk_signal_connect(GTK_OBJECT(sack_bt), "clicked", (GtkSignalFunc)on_sack_bt, u_data);
1250
1251         tsn_bt = gtk_button_new_with_label ("Show TSNs");
1252         gtk_box_pack_start(GTK_BOX(hbox), tsn_bt, FALSE, FALSE, 0);
1253         gtk_widget_show(tsn_bt);
1254         SIGNAL_CONNECT(tsn_bt, "clicked", on_tsn_bt, u_data);
1255
1256         both_bt = gtk_button_new_with_label ("Show both");
1257         gtk_box_pack_start(GTK_BOX(hbox), both_bt, FALSE, FALSE, 0);
1258         gtk_widget_show(both_bt);
1259         SIGNAL_CONNECT(both_bt, "clicked", on_both_bt, u_data);
1260
1261         zoomin_bt = gtk_button_new_with_label ("Zoom in");
1262         gtk_box_pack_start(GTK_BOX(hbox), zoomin_bt, FALSE, FALSE, 0);
1263         gtk_widget_show(zoomin_bt);
1264         SIGNAL_CONNECT(zoomin_bt, "clicked", on_zoomin_bt, u_data);
1265         tooltip_in = gtk_tooltips_new();
1266         gtk_tooltips_set_tip(tooltip_in, zoomin_bt, "Zoom in the area you have selected", NULL);
1267
1268         zoomout_bt = gtk_button_new_with_label ("Zoom out");
1269         gtk_box_pack_start(GTK_BOX(hbox), zoomout_bt, FALSE, FALSE, 0);
1270         gtk_widget_show(zoomout_bt);
1271         SIGNAL_CONNECT(zoomout_bt, "clicked", on_zoomout_bt, u_data);
1272         tooltip_out = gtk_tooltips_new();
1273         gtk_tooltips_set_tip(tooltip_out, zoomout_bt, "Zoom out one step", NULL);
1274         gtk_widget_set_sensitive(zoomout_bt, FALSE);
1275
1276         bt_close = BUTTON_NEW_FROM_STOCK(GTK_STOCK_CLOSE);
1277         gtk_box_pack_start(GTK_BOX(hbox), bt_close, FALSE, FALSE, 0);
1278         gtk_widget_show(bt_close);
1279         SIGNAL_CONNECT(bt_close, "clicked", sctp_graph_close_cb, u_data);
1280
1281         gtk_signal_connect(GTK_OBJECT(u_data->io->draw_area),"button_press_event",(GtkSignalFunc)on_button_press, u_data);
1282         gtk_signal_connect(GTK_OBJECT(u_data->io->draw_area),"button_release_event",(GtkSignalFunc)on_button_release, u_data);
1283         gtk_widget_set_events(u_data->io->draw_area, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_EXPOSURE_MASK);
1284
1285         gtk_widget_show(u_data->io->window);
1286 }
1287
1288 static void sctp_graph_set_title(struct sctp_udata *u_data)
1289 {
1290         char *title;
1291
1292         if(!u_data->io->window)
1293         {
1294                 return;
1295         }
1296         title = g_strdup_printf("SCTP TSNs and Sacks over Time: %s Port1 %u Port2 %u Endpoint %u",
1297                                 cf_get_display_name(&cfile), u_data->parent->assoc->port1, u_data->parent->assoc->port2, u_data->dir);
1298         gtk_window_set_title(GTK_WINDOW(u_data->io->window), title);
1299         g_free(title);
1300 }
1301
1302 static void
1303 gtk_sctpgraph_init(struct sctp_udata *u_data)
1304 {
1305         sctp_graph_t *io;
1306         gint dir;
1307         sctp_min_max_t* tmp_minmax;
1308
1309         io=g_malloc(sizeof(sctp_graph_t));
1310         io->needs_redraw=TRUE;
1311         io->x_interval=1000;
1312         io->window=NULL;
1313         io->draw_area=NULL;
1314         io->pixmap=NULL;
1315         io->pixmap_width=800;
1316         io->pixmap_height=600;
1317         io->graph_type=0;
1318         dir=u_data->dir-1;
1319         u_data->io=io;
1320         u_data->io->x1_tmp_sec=u_data->assoc->min_secs;
1321         u_data->io->x1_tmp_usec=u_data->assoc->min_usecs;
1322         u_data->io->x2_tmp_sec=u_data->assoc->max_secs;
1323         u_data->io->x2_tmp_usec=u_data->assoc->max_usecs;
1324         u_data->io->tmp_min_tsn1=u_data->assoc->min_tsn1;
1325         u_data->io->tmp_max_tsn1=u_data->assoc->max_tsn1;
1326         u_data->io->tmp_min_tsn2=u_data->assoc->min_tsn2;
1327         u_data->io->tmp_max_tsn2=u_data->assoc->max_tsn2;
1328         u_data->io->tmp=FALSE;
1329
1330         tmp_minmax = g_malloc(sizeof(sctp_min_max_t));
1331         tmp_minmax->tmp_min_secs = u_data->assoc->min_secs;
1332         tmp_minmax->tmp_min_usecs=u_data->assoc->min_usecs;
1333         tmp_minmax->tmp_max_secs=u_data->assoc->max_secs;
1334         tmp_minmax->tmp_max_usecs=u_data->assoc->max_usecs;
1335         tmp_minmax->tmp_min_tsn2=u_data->assoc->min_tsn2;
1336         tmp_minmax->tmp_min_tsn1=u_data->assoc->min_tsn1;
1337         tmp_minmax->tmp_max_tsn1=u_data->assoc->max_tsn1;
1338         tmp_minmax->tmp_max_tsn2=u_data->assoc->max_tsn2;
1339         u_data->assoc->min_max = g_slist_prepend(u_data->assoc->min_max, tmp_minmax);
1340
1341         /* build the GUI */
1342         init_sctp_graph_window(u_data);
1343         sctp_graph_redraw(u_data);
1344
1345 }
1346
1347
1348 static gint
1349 quit(GtkObject *object _U_, gpointer user_data)
1350 {
1351         struct sctp_udata *u_data=(struct sctp_udata*)user_data;
1352
1353         decrease_childcount(u_data->parent);
1354         remove_child(u_data, u_data->parent);
1355
1356         g_free(u_data->io);
1357
1358         u_data->assoc->min_max = NULL;
1359         g_free(u_data);
1360         return TRUE;
1361 }
1362
1363
1364 static void create_draw_area(GtkWidget *box, struct sctp_udata *u_data)
1365 {
1366
1367         u_data->io->draw_area=gtk_drawing_area_new();
1368         SIGNAL_CONNECT(u_data->io->draw_area, "destroy", quit, u_data);
1369         OBJECT_SET_DATA(u_data->io->draw_area, "sctp_graph_t", u_data->io);
1370
1371         WIDGET_SET_SIZE(u_data->io->draw_area, u_data->io->pixmap_width, u_data->io->pixmap_height);
1372
1373         /* signals needed to handle backing pixmap */
1374         SIGNAL_CONNECT(u_data->io->draw_area, "expose_event", expose_event, NULL);
1375         SIGNAL_CONNECT(u_data->io->draw_area, "configure_event", configure_event, u_data);
1376
1377         gtk_widget_show(u_data->io->draw_area);
1378         gtk_box_pack_start(GTK_BOX(box), u_data->io->draw_area, TRUE, TRUE, 0);
1379 }
1380
1381
1382
1383 void create_graph(guint16 dir, struct sctp_analyse* userdata)
1384 {
1385         struct sctp_udata *u_data;
1386
1387         u_data=g_malloc(sizeof(struct sctp_udata));
1388         u_data->assoc=g_malloc(sizeof(sctp_assoc_info_t));
1389         u_data->assoc=userdata->assoc;
1390         u_data->io=NULL;
1391         u_data->dir = dir;
1392         u_data->parent = userdata;
1393         if ((u_data->dir==1 && u_data->assoc->n_array_tsn1==0)|| (u_data->dir==2 && u_data->assoc->n_array_tsn2==0))
1394                 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, "No Data Chunks sent");
1395         else
1396         {
1397                 set_child(u_data, u_data->parent);
1398                 increase_childcount(u_data->parent);
1399                 gtk_sctpgraph_init(u_data);
1400         }
1401 }
1402
1403 #if defined(_WIN32) && !defined(__MINGW32__)
1404 /* replacement of Unix rint() for Windows */
1405 static int rint (double x)
1406 {
1407         char *buf;
1408         int i,dec,sig;
1409
1410         buf = _fcvt(x, 0, &dec, &sig);
1411         i = atoi(buf);
1412         if(sig == 1) {
1413                 i = i * -1;
1414         }
1415         return(i);
1416 }
1417 #endif