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