Move the APIs for registering and processing "-z" command-line arguments
[obnox/wireshark/wip.git] / gtk / sctp_byte_graph_dlg.c
1 /* 
2  * Copyright 2004, Irene Ruengeler <i.ruengeler [AT] fh-muenster.de>
3  *
4  * $Id$
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
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 <stdio.h>
32 #include <stdlib.h>
33 #include <math.h>
34 #include <string.h>
35 #include "globals.h"
36 #include "epan/filesystem.h"
37 #include "../color.h"
38 #include "stat_menu.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 MINI(a,b) (a<b)?a:b
65 #define MAXI(a,b) (a>b)?a:b
66
67 struct chunk_header {
68         guint8  type;
69         guint8  flags;
70         guint16 length;
71 };
72
73 struct data_chunk_header {
74         guint8  type;
75         guint8  flags;
76         guint16 length;
77         guint32  tsn;
78         guint16 sid;
79         guint16 ssn;
80         guint32  ppi;
81 };
82
83 struct init_chunk_header {
84         guint8  type;
85         guint8  flags;
86         guint16 length;
87         guint32  initiate_tag;
88         guint32  a_rwnd;
89         guint16 mos;
90         guint16 mis;
91         guint32  initial_tsn;
92 };
93
94 struct sack_chunk_header {
95         guint8  type;
96         guint8  flags;
97         guint16 length;
98         guint32  cum_tsn_ack;
99         guint32  a_rwnd;
100         guint16 nr_of_gaps;
101         guint16 nr_of_dups;
102         guint8  *tsns;
103 };
104
105 struct gaps {
106         guint16 start;
107         guint16 end;
108 };
109
110
111
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
115
116 gint tsn_cmp(gconstpointer aa, gconstpointer bb)
117 {
118         const struct tsn_sort* a = aa;
119         const struct tsn_sort* b = bb;
120
121         if (a->tsnumber < b->tsnumber)
122                 return -1;
123         if (a->tsnumber == b->tsnumber)
124                 return 0;
125         if (a->tsnumber > b->tsnumber)
126                 return 1;
127
128         return 0;
129 }
130
131 static void draw_sack_graph(struct sctp_udata *u_data)
132 {
133         GdkColor red_color = {0, 65535, 0, 0};
134         GdkColor green_color = {0, 0, 65535, 0};
135         GdkGC *red_gc, *green_gc;
136         guint32 diff;
137         GPtrArray *array = NULL;
138         guint32 min_tsn = 0, max_tsn = 0;
139         guint32 i, size = 0, start, end;
140         gboolean more = FALSE;
141
142 #if GTK_MAJOR_VERSION < 2
143         GdkColormap *colormap;
144 #endif
145
146         red_gc = gdk_gc_new(u_data->io->draw_area->window);
147 #if GTK_MAJOR_VERSION < 2
148         colormap = gtk_widget_get_colormap (u_data->io->draw_area);
149         if (!gdk_color_alloc (colormap, &red_color))
150         {
151                 g_warning ("Couldn't allocate color");
152         }
153
154                 gdk_gc_set_foreground(red_gc, &red_color);
155 #else
156                 gdk_gc_set_rgb_fg_color(red_gc, &red_color);
157 #endif
158
159         green_gc = gdk_gc_new(u_data->io->draw_area->window);
160 #if GTK_MAJOR_VERSION < 2
161         colormap = gtk_widget_get_colormap (u_data->io->draw_area);
162         if (!gdk_color_alloc (colormap, &green_color))
163         {
164                 g_warning ("Couldn't allocate color");
165         }
166
167                 gdk_gc_set_foreground(green_gc, &green_color);
168 #else
169         gdk_gc_set_rgb_fg_color(green_gc, &green_color);
170 #endif
171
172         if (u_data->dir == 1)
173         {
174                 array = u_data->assoc->sort_sack1;
175                 size=u_data->assoc->n_sack_chunks_ep1;
176                 if (u_data->io->tmp == FALSE)
177                 {
178                         min_tsn = 0;
179                         max_tsn = u_data->assoc->max_bytes1;
180                 }
181                 else
182                 {
183                         min_tsn = u_data->io->tmp_min_tsn1;
184                         max_tsn = u_data->io->tmp_max_tsn1;
185                 }
186         }
187         else if (u_data->dir == 2)
188         {
189                 array = u_data->assoc->sort_sack2;
190                 size = u_data->assoc->n_sack_chunks_ep2;
191                 if (u_data->io->tmp == FALSE)
192                 {
193                         min_tsn = 0;
194                         max_tsn = u_data->assoc->max_bytes2;
195                 }
196                 else
197                 {
198                         min_tsn = u_data->io->tmp_min_tsn2;
199                         max_tsn = u_data->io->tmp_max_tsn2;
200                 }
201         }
202
203
204         for (i=0; i<size; i++)
205         {
206                 diff = ((struct tsn_sort*)(g_ptr_array_index(array,  i)))->secs * 1000000 + ((struct tsn_sort*)(g_ptr_array_index(array,  i)))->usecs - u_data->io->min_x;
207                 start = ((struct tsn_sort*)(g_ptr_array_index(array,  i)))->offset;
208                 end = start + ((struct tsn_sort*)(g_ptr_array_index(array,  i)))->length;
209                 if (end>max_tsn)
210                 {
211                         end = max_tsn;
212                         more = TRUE;
213                 }
214
215                 if (start >= min_tsn)
216                 {
217                         gdk_draw_line(u_data->io->pixmap,red_gc,
218                                      (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff),
219                                      (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-((SUB_32(start,min_tsn))*u_data->io->y_interval)),
220                                      (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff),
221                                      (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-((SUB_32(end,min_tsn))*u_data->io->y_interval)));
222                         if (more == TRUE)
223                         {
224                                 gdk_draw_line(u_data->io->pixmap,green_gc,
225                                               (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff),
226                                               (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-((SUB_32(end,min_tsn))*u_data->io->y_interval)),
227                                               (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff),
228                                               (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-((SUB_32(end+10,min_tsn))*u_data->io->y_interval)));
229                                 more = FALSE;
230                         }
231                 }
232
233         }
234 #if GTK_MAJOR_VERSION >= 2
235         g_object_unref(G_OBJECT(red_gc));
236         g_object_unref(G_OBJECT(green_gc));
237 #endif
238 }
239
240
241 static void draw_tsn_graph(struct sctp_udata *u_data)
242 {
243 GPtrArray *array = NULL;
244 guint32 min_tsn = 0, max_tsn = 0;
245 guint32 diff, i, size = 0, start, end;
246
247         if (u_data->dir == 1)
248         {
249                 array = u_data->assoc->sort_tsn1;
250                 size = u_data->assoc->n_data_chunks_ep1;
251                 if (u_data->io->tmp == FALSE)
252                 {
253                         min_tsn = 0;
254                         max_tsn = u_data->assoc->max_bytes1;
255                 }
256                 else
257                 {
258                         min_tsn = u_data->io->tmp_min_tsn1;
259                         max_tsn = u_data->io->tmp_max_tsn1;
260                 }
261         }
262         else if (u_data->dir == 2)
263         {
264                 array = u_data->assoc->sort_tsn2;
265                 size  = u_data->assoc->n_data_chunks_ep2;
266                 if (u_data->io->tmp == FALSE)
267                 {
268                         min_tsn = 0;
269                         max_tsn = u_data->assoc->max_bytes2;
270                 }
271                 else
272                 {
273                         min_tsn = u_data->io->tmp_min_tsn2;
274                         max_tsn = u_data->io->tmp_max_tsn2;
275                 }
276         }
277
278         for (i=0; i<size; i++)
279         {
280                 diff = ((struct tsn_sort*)(g_ptr_array_index(array, i)))->secs*1000000 + ((struct tsn_sort*)(g_ptr_array_index(array, i)))->usecs-u_data->io->min_x;
281                 start = ((struct tsn_sort*)(g_ptr_array_index(array, i)))->offset;
282                 end = start + ((struct tsn_sort*)(g_ptr_array_index(array, i)))->length;
283                 if (start >= min_tsn)
284                         gdk_draw_line(u_data->io->pixmap,
285                                       u_data->io->draw_area->style->black_gc,
286                                       (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff),
287                                       (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-((SUB_32(start,min_tsn))*u_data->io->y_interval)),
288                                       (guint32)(LEFT_BORDER+u_data->io->offset+u_data->io->x_interval*diff),
289                                       (guint32)(u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset-((SUB_32(end,min_tsn))*u_data->io->y_interval)));
290         }
291
292 }
293
294
295 static void sctp_graph_draw(struct sctp_udata *u_data)
296 {
297         int length, lwidth, j, b;
298         guint32 label_width, label_height, distance=5, i, e, sec, w, start, a;
299         char label_string[15];
300         gfloat dis;
301
302 #if GTK_MAJOR_VERSION < 2
303         GdkFont *font;
304 #else
305         PangoLayout  *layout;
306 #endif
307
308         if (u_data->io->x1_tmp_sec == 0 && u_data->io->x1_tmp_usec == 0)
309                 u_data->io->offset = 0;
310         else
311                 u_data->io->offset = 5;
312
313         u_data->io->min_x     = u_data->io->x1_tmp_sec * 1000000 + u_data->io->x1_tmp_usec;
314         u_data->io->max_x     = u_data->io->x2_tmp_sec * 1000000 + u_data->io->x2_tmp_usec;
315         u_data->io->tmp_width = u_data->io->max_x - u_data->io->min_x;
316
317         if (u_data->dir == 1)
318         {
319                 if (u_data->io->tmp == FALSE)
320                 {
321                         if (u_data->assoc->sort_tsn1 != NULL)
322                                 u_data->io->max_y = u_data->io->tmp_max_tsn1 - u_data->io->tmp_min_tsn1;
323                         else
324                                 u_data->io->max_y = 0;
325                         u_data->io->min_y = 0;
326                 }
327                 else
328                 {
329                         u_data->io->max_y = u_data->io->tmp_max_tsn1;
330                         u_data->io->min_y = u_data->io->tmp_min_tsn1;
331                 }
332         }
333         else if (u_data->dir == 2)
334         {
335                 if (u_data->io->tmp == FALSE)
336                 {
337                         if (u_data->assoc->tsn2 != NULL)
338                                 u_data->io->max_y = u_data->io->tmp_max_tsn2 - u_data->io->tmp_min_tsn2;
339                         else
340                                 u_data->io->max_y = 0;
341                         u_data->io->min_y = 0;
342                 }
343                 else
344                 {
345                         u_data->io->max_y = u_data->io->tmp_max_tsn2;
346                         u_data->io->min_y = u_data->io->tmp_min_tsn2;
347                 }
348         }
349         gdk_draw_rectangle(u_data->io->pixmap, u_data->io->draw_area->style->white_gc,
350                            TRUE, 0, 0, u_data->io->draw_area->allocation.width,
351                            u_data->io->draw_area->allocation.height);
352
353         distance = 5;
354         /* x_axis */
355         gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
356                       LEFT_BORDER+u_data->io->offset,u_data->io->pixmap_height - BOTTOM_BORDER,
357                       u_data->io->pixmap_width - RIGHT_BORDER + u_data->io->offset, u_data->io->pixmap_height - BOTTOM_BORDER);
358         gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
359                       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);
360         gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
361                       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);
362         u_data->io->axis_width = u_data->io->pixmap_width - LEFT_BORDER - RIGHT_BORDER - u_data->io->offset;
363
364         u_data->io->x_interval = (float)((u_data->io->axis_width * 1.0) / u_data->io->tmp_width);
365
366         e=0;
367         if (u_data->io->x_interval < 1)
368         {
369                 dis = 1 / u_data->io->x_interval;
370                 while (dis >1)
371                 {
372                         dis /= 10;
373                         e++;
374                 }
375                 distance = 1;
376                         for (i=0; i<=e+1; i++)
377                         distance *= 10;
378         }
379         else
380                 distance = 5;
381
382 #if GTK_MAJOR_VERSION < 2
383         font = u_data->io->draw_area->style->font;
384 #endif
385
386 #if GTK_MAJOR_VERSION < 2
387         label_width  = gdk_string_width(font, label_string);
388         label_height = gdk_string_height(font, label_string);
389 #else
390         g_snprintf(label_string, 15, "%d", 0);
391         memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
392         layout = gtk_widget_create_pango_layout(u_data->io->draw_area, label_string);
393         pango_layout_get_pixel_size(layout, &label_width, &label_height);
394
395 #endif
396
397         if (u_data->io->x1_tmp_usec == 0)
398                 sec = u_data->io->x1_tmp_sec;
399         else
400                 sec = u_data->io->x1_tmp_sec+1;
401
402         if (u_data->io->offset != 0)
403         {
404                 g_snprintf(label_string, 15, "%u", u_data->io->x1_tmp_sec);
405 #if GTK_MAJOR_VERSION < 2
406                 lwidth = gdk_string_width(font, label_string);
407                 gdk_draw_string(u_data->io->pixmap,font,u_data->io->draw_area->style->black_gc,
408                                 LEFT_BORDER - 10,
409                                 u_data->io->pixmap_height - BOTTOM_BORDER + 20,
410                                 label_string);
411 #else
412                 memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
413                 pango_layout_set_text(layout, label_string, -1);
414                 pango_layout_get_pixel_size(layout, &lwidth, NULL);
415
416                 gdk_draw_layout(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
417                                 LEFT_BORDER - 10,
418                                 u_data->io->pixmap_height - BOTTOM_BORDER + 20,
419                                 layout);
420 #endif
421         }
422         w = (guint32)(500 / (guint32)(distance * u_data->io->x_interval));
423         if (w == 0)
424                 w = 1;
425         if (w == 4)
426         {
427                 w = 5;
428                 a = distance / 10;
429                 b = 10 + (((u_data->io->min_x / 100000) - 1) % 5);
430         }
431         else
432         {
433                 a = distance / 5;
434                 b = 0;
435         }
436
437         if (a > 1000000)
438                 start = u_data->io->min_x / 1000000 * 1000000;
439         else
440         {
441                 start = u_data->io->min_x / 100000;
442                 if (start % 2 != 0)
443                         start--;
444                 start *= 100000;
445         }
446
447
448         for (i=start, j=b; i<=u_data->io->max_x; i+=a, j++)
449         {
450                 if (i >= u_data->io->min_x && i % 1000000 != 0)
451                 {
452                         length = 5;
453                         g_snprintf(label_string, 15, "%d", i%1000000);
454
455                         if (j % w == 0)
456                         {
457                                 length = 10;
458
459                                 #if GTK_MAJOR_VERSION < 2
460                                         lwidth = gdk_string_width(font, label_string);
461                                         gdk_draw_string(u_data->io->pixmap,font,u_data->io->draw_area->style->black_gc,
462                                                         (guint32)(LEFT_BORDER + u_data->io->offset + (i-u_data->io->min_x) * u_data->io->x_interval - lwidth / 2),
463                                                         u_data->io->pixmap_height - BOTTOM_BORDER + 10,
464                                                         label_string);
465                                 #else
466                                         memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
467                                         pango_layout_set_text(layout, label_string, -1);
468                                         pango_layout_get_pixel_size(layout, &lwidth, NULL);
469                                         gdk_draw_layout(u_data->io->pixmap,
470                                                         u_data->io->draw_area->style->black_gc,
471                                                         (guint32)(LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval - lwidth / 2),
472                                                         u_data->io->pixmap_height - BOTTOM_BORDER + 10,
473                                                         layout);
474                                 #endif
475
476                         }
477                         gdk_draw_line(u_data->io->pixmap,
478                                       u_data->io->draw_area->style->black_gc,
479                                       (guint32)(LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval),
480                                       u_data->io->pixmap_height - BOTTOM_BORDER,
481                                       (guint32)(LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval),
482                                       u_data->io->pixmap_height - BOTTOM_BORDER + length);
483                 }
484
485                 if (i % 1000000 == 0)
486                 {
487                         sec = i / 1000000;
488                         gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
489                                       (guint32)(LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval),
490                                       u_data->io->pixmap_height - BOTTOM_BORDER,
491                                       (guint32)(LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval),
492                                       u_data->io->pixmap_height - BOTTOM_BORDER + 10);
493
494                         g_snprintf(label_string, 15, "%d", sec);
495 #if GTK_MAJOR_VERSION < 2
496                                 lwidth = gdk_string_width(font, label_string);
497                                 gdk_draw_string(u_data->io->pixmap,font,u_data->io->draw_area->style->black_gc,
498                                                 (guint32)(LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval),
499                                                 u_data->io->pixmap_height - BOTTOM_BORDER + 20,
500                                                 label_string);
501 #else
502                                 memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
503                                 pango_layout_set_text(layout, label_string, -1);
504                                 pango_layout_get_pixel_size(layout, &lwidth, NULL);
505
506                                 gdk_draw_layout(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
507                                                 (guint32)(LEFT_BORDER + u_data->io->offset + (i - u_data->io->min_x) * u_data->io->x_interval),
508                                                 u_data->io->pixmap_height - BOTTOM_BORDER + 20,
509                                                 layout);
510 #endif
511                 }
512         }
513
514         strcpy(label_string, "sec");
515
516 #if GTK_MAJOR_VERSION < 2
517         lwidth = gdk_string_width(font, label_string);
518         gdk_draw_string(u_data->io->pixmap,
519                         font,
520                         u_data->io->draw_area->style->black_gc,
521                         u_data->io->pixmap_width - RIGHT_BORDER - 10,
522                         u_data->io->pixmap_height - BOTTOM_BORDER + 20,
523                         label_string);
524 #else
525         memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
526         pango_layout_set_text(layout, label_string, -1);
527         pango_layout_get_pixel_size(layout, &lwidth, NULL);
528         gdk_draw_layout(u_data->io->pixmap,
529                         u_data->io->draw_area->style->black_gc,
530                         u_data->io->pixmap_width - RIGHT_BORDER - 10,
531                         u_data->io->pixmap_height - BOTTOM_BORDER + 25,
532                         layout);
533 #endif
534
535         distance = 5;
536
537         /* y-axis */
538         gdk_draw_line(u_data->io->pixmap,
539                       u_data->io->draw_area->style->black_gc,
540                       LEFT_BORDER,TOP_BORDER - u_data->io->offset,
541                       LEFT_BORDER,
542                       u_data->io->pixmap_height - BOTTOM_BORDER - u_data->io->offset);
543         gdk_draw_line(u_data->io->pixmap,
544                       u_data->io->draw_area->style->black_gc,
545                       LEFT_BORDER,
546                       TOP_BORDER - u_data->io->offset, 
547                       LEFT_BORDER - 5, 
548                       TOP_BORDER - u_data->io->offset + 5);
549         gdk_draw_line(u_data->io->pixmap,
550                       u_data->io->draw_area->style->black_gc,
551                       LEFT_BORDER,
552                       TOP_BORDER - u_data->io->offset, 
553                       LEFT_BORDER + 5, 
554                       TOP_BORDER - u_data->io->offset + 5);
555
556         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));
557
558         e = 0;
559         if (u_data->io->y_interval < 1)
560         {
561                 dis = 1 / u_data->io->y_interval;
562                 while (dis > 1)
563                 {
564                         dis /= 10;
565                         e++;
566                 }
567                 distance = 1;
568                 for (i=0; i<=e; i++)
569                         distance = distance * 10;
570         }
571
572         if (u_data->io->max_y > 0)
573         {
574                 for (i=u_data->io->min_y/distance*distance; i<=u_data->io->max_y; i+=distance/5)
575                 {
576                         if (i >= u_data->io->min_y)
577                         {
578                                 length = 5;
579                                 g_snprintf(label_string, 15, "%d", i);
580
581                                 if (i%distance == 0 || (distance <= 5 && u_data->io->y_interval > 10))
582                                 {
583                                         length = 10;
584
585 #if GTK_MAJOR_VERSION < 2
586                                         lwidth = gdk_string_width(font, label_string);
587                                         gdk_draw_string(u_data->io->pixmap,font,
588                                                         u_data->io->draw_area->style->black_gc,
589                                                         LEFT_BORDER - length - lwidth - 5,
590                                                         (guint32)(u_data->io->pixmap_height - BOTTOM_BORDER - u_data->io->offset - (i - u_data->io->min_y) * u_data->io->y_interval - 3),
591                                                         label_string);
592 #else
593                                         memcpy(label_string,(gchar *)g_locale_to_utf8(label_string, -1 , NULL, NULL, NULL), 15);
594                                         pango_layout_set_text(layout, label_string, -1);
595                                         pango_layout_get_pixel_size(layout, &lwidth, NULL);
596                                         gdk_draw_layout(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
597                                                         LEFT_BORDER - length - lwidth - 5,
598                                                         (guint32)(u_data->io->pixmap_height - BOTTOM_BORDER - u_data->io->offset - (i - u_data->io->min_y) * u_data->io->y_interval - 3),
599                                                         layout);
600 #endif
601                                 }
602                         gdk_draw_line(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
603                                       LEFT_BORDER - length,
604                                       (guint32)(u_data->io->pixmap_height - BOTTOM_BORDER - u_data->io->offset - (i - u_data->io->min_y) * u_data->io->y_interval),
605                                       LEFT_BORDER,
606                                       (guint32)(u_data->io->pixmap_height - BOTTOM_BORDER - u_data->io->offset - (i - u_data->io->min_y) * u_data->io->y_interval));
607                         }
608                 }
609         }
610         else
611                 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, "No Data Chunks sent");
612 }
613
614
615 static void sctp_graph_redraw(struct sctp_udata *u_data)
616 {
617         sctp_graph_t *ios;
618
619         u_data->io->needs_redraw = TRUE;
620
621         sctp_graph_draw(u_data);
622         switch (u_data->io->graph_type)
623         {
624                 case 0:
625                         draw_sack_graph(u_data);
626                         draw_tsn_graph(u_data);
627                         break;
628                 case 1: 
629                         draw_tsn_graph(u_data);
630                         break;
631                 case 2:
632                         draw_sack_graph(u_data);
633                         break;
634         }
635         ios=(sctp_graph_t *)OBJECT_GET_DATA(u_data->io->draw_area, "sctp_graph_t");
636
637         if(!ios){
638                 exit(10);
639         }
640
641
642         gdk_draw_pixmap(u_data->io->draw_area->window,
643                         u_data->io->draw_area->style->fg_gc[GTK_WIDGET_STATE(u_data->io->draw_area)],
644                         ios->pixmap,
645                         0,0,
646                         0, 0,
647                         u_data->io->draw_area->allocation.width,
648                         u_data->io->draw_area->allocation.height);
649 }
650
651
652 static void on_sack_bt(GtkWidget *widget _U_, struct sctp_udata *u_data)
653 {
654         u_data = (struct sctp_udata *) u_data;
655         u_data->io->graph_type = 2;
656         sctp_graph_redraw(u_data);
657 }
658
659 static void on_tsn_bt(GtkWidget *widget _U_, struct sctp_udata *u_data)
660 {
661         u_data->io->graph_type = 1;
662         sctp_graph_redraw(u_data);
663 }
664
665 static void on_both_bt(GtkWidget *widget _U_, struct sctp_udata *u_data)
666 {
667         u_data->io->graph_type = 0;
668         sctp_graph_redraw(u_data);
669 }
670
671 static void
672 sctp_graph_close_cb(GtkWidget* widget _U_, gpointer u_data)
673 {
674         struct sctp_udata *udata;
675         int dir;
676
677         udata = (struct sctp_udata *)u_data;
678         dir = udata->dir - 1;
679         gtk_grab_remove(GTK_WIDGET(udata->io->window));
680         gtk_widget_destroy(GTK_WIDGET(udata->io->window));
681 }
682
683
684
685 static gint
686 configure_event(GtkWidget *widget, GdkEventConfigure *event _U_, struct sctp_udata *u_data)
687 {
688         if(!u_data->io){
689                 exit(10);
690         }
691
692         if(u_data->io->pixmap){
693                 gdk_pixmap_unref(u_data->io->pixmap);
694                 u_data->io->pixmap = NULL;
695         }
696
697         u_data->io->pixmap = gdk_pixmap_new(widget->window,
698                                             widget->allocation.width,
699                                             widget->allocation.height,
700                                             -1);
701         u_data->io->pixmap_width = widget->allocation.width;
702         u_data->io->pixmap_height = widget->allocation.height;
703
704         gdk_draw_rectangle(u_data->io->pixmap,
705                            widget->style->white_gc,
706                            TRUE,
707                            0, 0,
708                            widget->allocation.width,
709                            widget->allocation.height);
710         sctp_graph_redraw(u_data);
711         return TRUE;
712 }
713
714 static gint
715 expose_event(GtkWidget *widget, GdkEventExpose *event)
716 {
717         sctp_graph_t *ios;
718
719         ios=(sctp_graph_t *)OBJECT_GET_DATA(widget, "sctp_graph_t");
720         if(!ios){
721                 exit(10);
722         }
723
724         gdk_draw_pixmap(widget->window,
725                         widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
726                         ios->pixmap,
727                         event->area.x, event->area.y,
728                         event->area.x, event->area.y,
729                         event->area.width, event->area.height);
730
731         return FALSE;
732 }
733
734
735 static void
736 on_zoomin_bt (GtkWidget *widget _U_, struct sctp_udata *u_data)
737 {
738         sctp_min_max_t *tmp_minmax;
739
740         if (u_data->io->rectangle==TRUE)
741         {
742                 tmp_minmax = g_malloc(sizeof(sctp_min_max_t));
743
744                 u_data->io->tmp_min_tsn1=u_data->io->y1_tmp+u_data->io->min_y;
745                 u_data->io->tmp_max_tsn1=u_data->io->y2_tmp+1+u_data->io->min_y;
746                 u_data->io->tmp_min_tsn2=u_data->io->tmp_min_tsn1;
747                 u_data->io->tmp_max_tsn2=u_data->io->tmp_max_tsn1;
748                 tmp_minmax->tmp_min_secs=u_data->io->x1_tmp_sec;
749                 tmp_minmax->tmp_min_usecs=      u_data->io->x1_tmp_usec;
750                 tmp_minmax->tmp_max_secs=       u_data->io->x2_tmp_sec;
751                 tmp_minmax->tmp_max_usecs=      u_data->io->x2_tmp_usec;
752                 tmp_minmax->tmp_min_tsn1=u_data->io->tmp_min_tsn1;
753                 tmp_minmax->tmp_max_tsn1=u_data->io->tmp_max_tsn1;
754                 tmp_minmax->tmp_min_tsn2=u_data->io->tmp_min_tsn2;
755                 tmp_minmax->tmp_max_tsn2=u_data->io->tmp_max_tsn2;
756                 u_data->assoc->min_max = g_slist_prepend(u_data->assoc->min_max, tmp_minmax);
757                 u_data->io->length = g_slist_length(u_data->assoc->min_max);
758                 u_data->io->tmp=TRUE;
759                 u_data->io->rectangle=FALSE;
760                 sctp_graph_redraw(u_data);
761         }
762 }
763
764 static void
765 on_zoomout_bt (GtkWidget *widget _U_, struct sctp_udata *u_data)
766 {
767         sctp_min_max_t *tmp_minmax, *mm;
768         gint l;
769
770         l = g_slist_length(u_data->assoc->min_max);
771
772         if (u_data->assoc->min_max!=NULL)
773         {
774                 mm=(sctp_min_max_t *)((u_data->assoc->min_max)->data);
775                 u_data->assoc->min_max=g_slist_remove(u_data->assoc->min_max, mm);
776                 g_free(mm);
777
778                 if (l>2)
779                 {
780                         tmp_minmax = (sctp_min_max_t *)u_data->assoc->min_max->data;
781                         u_data->io->x1_tmp_sec=tmp_minmax->tmp_min_secs;
782                         u_data->io->x1_tmp_usec=tmp_minmax->tmp_min_usecs;
783                         u_data->io->x2_tmp_sec=tmp_minmax->tmp_max_secs;
784                         u_data->io->x2_tmp_usec=tmp_minmax->tmp_max_usecs;
785                         u_data->io->tmp_min_tsn1=tmp_minmax->tmp_min_tsn1;
786                         u_data->io->tmp_max_tsn1=tmp_minmax->tmp_max_tsn1;
787                         u_data->io->tmp_min_tsn2=tmp_minmax->tmp_min_tsn2;
788                         u_data->io->tmp_max_tsn2=tmp_minmax->tmp_max_tsn2;
789                         u_data->io->tmp=TRUE;
790                 }
791                 else
792                 {
793                         u_data->io->x1_tmp_sec=u_data->assoc->min_secs;
794                         u_data->io->x1_tmp_usec=u_data->assoc->min_usecs;
795                         u_data->io->x2_tmp_sec=u_data->assoc->max_secs;
796                         u_data->io->x2_tmp_usec=u_data->assoc->max_usecs;
797                         u_data->io->tmp_min_tsn1=0;
798                         u_data->io->tmp_max_tsn1=u_data->assoc->max_bytes1;
799                         u_data->io->tmp_min_tsn2=0;
800                         u_data->io->tmp_max_tsn2=u_data->assoc->max_bytes2;
801                         u_data->io->tmp=FALSE;
802                 }
803         }
804         else
805         {
806                 u_data->io->x1_tmp_sec=u_data->assoc->min_secs;
807                 u_data->io->x1_tmp_usec=u_data->assoc->min_usecs;
808                 u_data->io->x2_tmp_sec=u_data->assoc->max_secs;
809                 u_data->io->x2_tmp_usec=u_data->assoc->max_usecs;
810                 u_data->io->tmp_min_tsn1=0;
811                 u_data->io->tmp_max_tsn1=u_data->assoc->max_bytes1;
812                 u_data->io->tmp_min_tsn2=0;
813                 u_data->io->tmp_max_tsn2=u_data->assoc->max_bytes2;
814                 u_data->io->tmp=FALSE;
815         }
816         sctp_graph_redraw(u_data);
817 }
818
819
820 static gint
821 on_button_press (GtkWidget *widget _U_, GdkEventButton *event, struct sctp_udata *u_data)
822 {
823         sctp_graph_t *ios;
824
825         if (u_data->io->rectangle==TRUE)
826         {
827                 gdk_draw_rectangle(u_data->io->pixmap,u_data->io->draw_area->style->white_gc,
828                                    FALSE,
829                                    (gint)floor(MINI(u_data->io->x_old,u_data->io->x_new)),
830                                    (gint)floor(MINI(u_data->io->y_old,u_data->io->y_new)),
831                                    (gint)abs((long)(u_data->io->x_new-u_data->io->x_old)),
832                                    (gint)abs((long)(u_data->io->y_new-u_data->io->y_old)));
833                 ios=(sctp_graph_t *)OBJECT_GET_DATA(u_data->io->draw_area, "sctp_graph_t");
834
835                 if(!ios){
836                         exit(10);
837                 }
838
839                 gdk_draw_pixmap(u_data->io->draw_area->window,
840                                 u_data->io->draw_area->style->fg_gc[GTK_WIDGET_STATE(u_data->io->draw_area)],
841                                 ios->pixmap,
842                                 0, 0,
843                                 0, 0,
844                                 (gint)abs((long)(u_data->io->x_new-u_data->io->x_old)),
845                                 (gint)abs((long)(u_data->io->y_new-u_data->io->y_old)));
846                 sctp_graph_redraw(u_data);
847         }
848
849         u_data->io->x_old=event->x;
850         u_data->io->y_old=event->y;
851         if (u_data->io->y_old>u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset)
852                 u_data->io->y_old=u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset;
853         if (u_data->io->x_old<LEFT_BORDER+u_data->io->offset)
854                 u_data->io->x_old=LEFT_BORDER+u_data->io->offset;
855         u_data->io->rectangle=FALSE;
856
857         return TRUE;
858 }
859
860
861 static gint
862 on_button_release (GtkWidget *widget _U_, GdkEventButton *event, struct sctp_udata *u_data)
863 {
864         sctp_graph_t *ios;
865         guint32 helpx;
866         guint32 helpy, x1_tmp, x2_tmp;
867
868         if (event->y>u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset)
869                 event->y = u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->offset;
870         if (event->x < LEFT_BORDER+u_data->io->offset)
871                 event->x = LEFT_BORDER+u_data->io->offset;
872
873         if (abs((long)(event->x-u_data->io->x_old))>10 || abs((long)(event->y-u_data->io->y_old))>10)
874         {
875                 gdk_draw_rectangle(u_data->io->pixmap,u_data->io->draw_area->style->black_gc,
876                                    FALSE,
877                                   (gint)floor(MINI(u_data->io->x_old,event->x)), (gint)floor(MINI(u_data->io->y_old,event->y)),
878                                  (gint)abs((long)(event->x-u_data->io->x_old)),
879                                  (gint)abs((long)(event->y-u_data->io->y_old)));
880                 ios=(sctp_graph_t *)OBJECT_GET_DATA(u_data->io->draw_area, "sctp_graph_t");
881
882                 if(!ios){
883                         exit(10);
884                 }
885
886                 gdk_draw_pixmap(u_data->io->draw_area->window,
887                                 u_data->io->draw_area->style->fg_gc[GTK_WIDGET_STATE(u_data->io->draw_area)],
888                                 ios->pixmap,
889                                 0, 0,
890                                 0, 0,
891                                 u_data->io->draw_area->allocation.width,
892                                 u_data->io->draw_area->allocation.height);
893
894                 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));
895                 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));
896                 helpx=MINI(x1_tmp, x2_tmp);
897                 if (helpx==x2_tmp)
898                 {
899                         x2_tmp=x1_tmp;
900                         x1_tmp=helpx;
901                 }
902                 u_data->io->x1_tmp_sec=(guint32)x1_tmp/1000000;
903                 u_data->io->x1_tmp_usec=x1_tmp%1000000;
904                 u_data->io->x2_tmp_sec=(guint32)x2_tmp/1000000;
905                 u_data->io->x2_tmp_usec=x2_tmp%1000000;
906
907                 u_data->io->y1_tmp=(guint32)((u_data->io->pixmap_height-BOTTOM_BORDER-u_data->io->y_old)/u_data->io->y_interval);
908                 u_data->io->y2_tmp=(guint32)((u_data->io->pixmap_height-BOTTOM_BORDER-event->y)/u_data->io->y_interval);
909                 helpy = MINI(u_data->io->y1_tmp, u_data->io->y2_tmp);
910                 u_data->io->y2_tmp = MAXI(u_data->io->y1_tmp, u_data->io->y2_tmp);
911                 u_data->io->y1_tmp = helpy;
912                 u_data->io->x_new=event->x;
913                 u_data->io->y_new=event->y;
914                 u_data->io->rectangle=TRUE;
915
916         }
917         return TRUE;
918 }
919
920 static void init_sctp_graph_window(struct sctp_udata *u_data)
921 {
922         GtkWidget *vbox;
923         GtkWidget *hbox;
924         GtkWidget *bt_close, *sack_bt, *tsn_bt, *both_bt, *zoomin_bt, *zoomout_bt;
925         GtkTooltips *tooltip_in, *tooltip_out;
926
927         /* create the main window */
928
929         u_data->io->window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
930
931         gtk_widget_set_name(u_data->io->window, "SCTP Graphics");
932
933         vbox=gtk_vbox_new(FALSE, 0);
934         gtk_container_add(GTK_CONTAINER(u_data->io->window), vbox);
935         gtk_widget_show(vbox);
936
937         create_draw_area(vbox, u_data);
938
939         sctp_graph_set_title(u_data);
940
941         hbox = gtk_hbutton_box_new();
942         gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
943         gtk_container_set_border_width(GTK_CONTAINER(hbox), 10);
944         gtk_button_box_set_layout(GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_SPREAD);
945         gtk_button_box_set_spacing(GTK_BUTTON_BOX (hbox), 0);
946         gtk_box_set_child_packing(GTK_BOX(vbox), hbox, FALSE, FALSE, 0, GTK_PACK_START);
947         gtk_widget_show(hbox);
948
949         sack_bt = gtk_button_new_with_label ("Adv. Rec. Window");
950         gtk_box_pack_start(GTK_BOX(hbox), sack_bt, FALSE, FALSE, 0);
951         gtk_widget_show(sack_bt);
952
953         gtk_signal_connect(GTK_OBJECT(sack_bt), "clicked", (GtkSignalFunc)on_sack_bt, u_data);
954
955         tsn_bt = gtk_button_new_with_label ("Data bytes sent");
956         gtk_box_pack_start(GTK_BOX(hbox), tsn_bt, FALSE, FALSE, 0);
957         gtk_widget_show(tsn_bt);
958         SIGNAL_CONNECT(tsn_bt, "clicked", on_tsn_bt, u_data);
959
960         both_bt = gtk_button_new_with_label ("Show both");
961         gtk_box_pack_start(GTK_BOX(hbox), both_bt, FALSE, FALSE, 0);
962         gtk_widget_show(both_bt);
963         SIGNAL_CONNECT(both_bt, "clicked", on_both_bt, u_data);
964
965         zoomin_bt = gtk_button_new_with_label ("Zoom in");
966         gtk_box_pack_start(GTK_BOX(hbox), zoomin_bt, FALSE, FALSE, 0);
967         gtk_widget_show(zoomin_bt);
968         SIGNAL_CONNECT(zoomin_bt, "clicked", on_zoomin_bt, u_data);
969         tooltip_in = gtk_tooltips_new();
970         gtk_tooltips_set_tip(tooltip_in, zoomin_bt, "Draw a rectangle around the area you want to zoom in", NULL);
971
972         zoomout_bt = gtk_button_new_with_label ("Zoom out");
973         gtk_box_pack_start(GTK_BOX(hbox), zoomout_bt, FALSE, FALSE, 0);
974         gtk_widget_show(zoomout_bt);
975         SIGNAL_CONNECT(zoomout_bt, "clicked", on_zoomout_bt, u_data);
976         tooltip_out = gtk_tooltips_new();
977         gtk_tooltips_set_tip(tooltip_out, zoomout_bt, "Zoom out one step", NULL);
978
979
980         bt_close = BUTTON_NEW_FROM_STOCK(GTK_STOCK_CLOSE);
981         gtk_box_pack_start(GTK_BOX(hbox), bt_close, FALSE, FALSE, 0);
982         gtk_widget_show(bt_close);
983         SIGNAL_CONNECT(bt_close, "clicked", sctp_graph_close_cb, u_data);
984
985         gtk_signal_connect(GTK_OBJECT(u_data->io->draw_area),"button_press_event",(GtkSignalFunc)on_button_press, u_data);
986         gtk_signal_connect(GTK_OBJECT(u_data->io->draw_area),"button_release_event",(GtkSignalFunc)on_button_release, u_data);
987         gtk_widget_set_events(u_data->io->draw_area, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_EXPOSURE_MASK);
988         /* dlg_set_cancel(u_data->io->window, bt_close); */
989         
990
991         gtk_widget_show(u_data->io->window);
992 }
993
994 static void sctp_graph_set_title(struct sctp_udata *u_data)
995 {
996         char *title;
997
998         if(!u_data->io->window)
999         {
1000                 return;
1001         }
1002         title = g_strdup_printf("SCTP Data and Adv.Rcv.Window over Time: %s Port1 %u Port2 %u Endpoint %u",
1003                                 cf_get_display_name(&cfile), u_data->parent->assoc->port1, u_data->parent->assoc->port2, u_data->dir);
1004         gtk_window_set_title(GTK_WINDOW(u_data->io->window), title);
1005         g_free(title);
1006 }
1007
1008
1009 static void
1010 gtk_sctpgraph_init(struct sctp_udata *u_data)
1011 {
1012         sctp_graph_t *io;
1013         gint dir;
1014         sctp_min_max_t* tmp_minmax;
1015
1016         io=g_malloc(sizeof(sctp_graph_t));
1017         io->needs_redraw=TRUE;
1018         io->x_interval=1000;
1019         io->window=NULL;
1020         io->draw_area=NULL;
1021         io->pixmap=NULL;
1022         io->pixmap_width=800;
1023         io->pixmap_height=600;
1024         io->graph_type=0;
1025         dir=u_data->dir-1;
1026         u_data->io=io;
1027
1028
1029         u_data->io->x1_tmp_sec=u_data->assoc->min_secs;
1030         u_data->io->x1_tmp_usec=u_data->assoc->min_usecs;
1031         u_data->io->x2_tmp_sec=u_data->assoc->max_secs;
1032         u_data->io->x2_tmp_usec=u_data->assoc->max_usecs;
1033         u_data->io->tmp_min_tsn1=0;
1034         u_data->io->tmp_max_tsn1=u_data->assoc->max_bytes1;
1035         u_data->io->tmp_min_tsn2=0;
1036         u_data->io->tmp_max_tsn2=u_data->assoc->max_bytes2;
1037         u_data->io->tmp=FALSE;
1038         tmp_minmax = g_malloc(sizeof(sctp_min_max_t));
1039         tmp_minmax->tmp_min_secs = u_data->assoc->min_secs;
1040         tmp_minmax->tmp_min_usecs=u_data->assoc->min_usecs;
1041         tmp_minmax->tmp_max_secs=u_data->assoc->max_secs;
1042         tmp_minmax->tmp_max_usecs=u_data->assoc->max_usecs;
1043         tmp_minmax->tmp_min_tsn2=u_data->io->tmp_min_tsn2;
1044         tmp_minmax->tmp_min_tsn1=u_data->io->tmp_min_tsn1;
1045         tmp_minmax->tmp_max_tsn1=u_data->io->tmp_max_tsn1;
1046         tmp_minmax->tmp_max_tsn2=u_data->io->tmp_max_tsn2;
1047         u_data->assoc->min_max = g_slist_prepend(u_data->assoc->min_max, tmp_minmax);
1048
1049         /* build the GUI */
1050         init_sctp_graph_window(u_data);
1051         sctp_graph_redraw(u_data);
1052 }
1053
1054
1055 static gint
1056 quit(GtkObject *object _U_, gpointer user_data)
1057 {
1058         struct sctp_udata *u_data=(struct sctp_udata*)user_data;
1059
1060         decrease_childcount(u_data->parent);
1061         remove_child(u_data, u_data->parent);
1062         g_free(u_data->io);
1063         u_data->assoc->min_max = NULL;
1064         g_free(u_data);
1065         return TRUE;
1066 }
1067
1068
1069 static void create_draw_area(GtkWidget *box, struct sctp_udata *u_data)
1070 {
1071         u_data->io->draw_area=gtk_drawing_area_new();
1072         SIGNAL_CONNECT(u_data->io->draw_area, "destroy", quit, u_data);
1073         OBJECT_SET_DATA(u_data->io->draw_area, "sctp_graph_t", u_data->io);
1074
1075         WIDGET_SET_SIZE(u_data->io->draw_area, u_data->io->pixmap_width, u_data->io->pixmap_height);
1076
1077         /* signals needed to handle backing pixmap */
1078         SIGNAL_CONNECT(u_data->io->draw_area, "expose_event", expose_event, NULL);
1079         SIGNAL_CONNECT(u_data->io->draw_area, "configure_event", configure_event, u_data);
1080
1081         gtk_widget_show(u_data->io->draw_area);
1082         gtk_box_pack_start(GTK_BOX(box), u_data->io->draw_area, TRUE, TRUE, 0);
1083 }
1084
1085 void insertion(GPtrArray *array, guint32 N)
1086 {
1087         guint32 i, j;
1088         guint32 v;
1089         struct tsn_sort *help=NULL;
1090
1091         for (i=1; i<N; i++)
1092         {
1093                 v = ((struct tsn_sort*)(g_ptr_array_index(array,i)))->tsnumber;
1094                 j=i;
1095                 while (j>=1 && ((struct tsn_sort*)(g_ptr_array_index(array, j-1)))->tsnumber > v)
1096                 {
1097                         help=g_ptr_array_index(array, j);
1098                         g_ptr_array_index(array, j)=g_ptr_array_index(array, j-1);
1099                         g_ptr_array_index(array, j-1)=help;
1100                         j--;
1101                 }
1102                 ((struct tsn_sort*)(g_ptr_array_index(array, j)))->tsnumber=v;
1103         }
1104 }
1105
1106 void set_arw_offsets(struct sctp_udata *u_data)
1107 {
1108         GPtrArray *s_array=NULL, *t_array=NULL;
1109         guint32 i, j=0;
1110
1111         if (u_data->dir==1 && u_data->assoc->n_sack_chunks_ep1>0)
1112         {
1113                 s_array=u_data->assoc->sort_sack1;
1114                 t_array=u_data->assoc->sort_tsn1;
1115                 insertion(s_array,u_data->assoc->n_sack_chunks_ep1);
1116
1117                 for (i=0; i<u_data->assoc->n_sack_chunks_ep1; i++)
1118                 {
1119                         while (((struct tsn_sort*)(g_ptr_array_index(s_array, i)))->tsnumber > ((struct tsn_sort*)(g_ptr_array_index(t_array, j)))->tsnumber)
1120                         {
1121                                 j++;
1122                         }
1123                         ((struct tsn_sort*)(g_ptr_array_index(s_array,i)))->offset = ((struct tsn_sort*)(g_ptr_array_index(t_array, j)))->offset
1124                           + ((struct tsn_sort*)(g_ptr_array_index(t_array, j)))->length;                         
1125                 }
1126
1127                 u_data->assoc->sort_sack1=s_array;
1128         }
1129
1130         if (u_data->dir==2 && u_data->assoc->n_sack_chunks_ep2>0)
1131         {
1132                 s_array=u_data->assoc->sort_sack2;
1133                 t_array=u_data->assoc->sort_tsn2;
1134                 insertion(s_array,u_data->assoc->n_sack_chunks_ep2);
1135                 j=0;
1136                 for (i=0; i<u_data->assoc->n_sack_chunks_ep2; i++)
1137                 {
1138                         while (((struct tsn_sort*)(g_ptr_array_index(s_array, i)))->tsnumber > ((struct tsn_sort*)(g_ptr_array_index(t_array,j)))->tsnumber)
1139                         {
1140                                 j++;
1141                         }
1142                         ((struct tsn_sort*)(g_ptr_array_index(s_array, i)))->offset = ((struct tsn_sort*)(g_ptr_array_index(t_array, j)))->offset
1143                          + ((struct tsn_sort*)(g_ptr_array_index(t_array, j)))->length;
1144                 }
1145                 u_data->assoc->sort_sack2=s_array;
1146         }
1147 }
1148
1149 void compute_offsets(struct sctp_udata *u_data)
1150 {
1151         struct tsn_sort t_sort;
1152         GPtrArray *array=NULL;
1153         guint32 i;
1154         guint32 sum=0;
1155         guint32 tsntmp=0;
1156
1157         if (u_data->dir==1 && u_data->assoc->n_array_tsn1>0)
1158         {
1159                 array=u_data->assoc->sort_tsn1;
1160                 insertion(array,u_data->assoc->n_array_tsn1);
1161
1162                 for (i=0; i<u_data->assoc->n_array_tsn1; i++)
1163                 {
1164                         ((struct tsn_sort*)(g_ptr_array_index(array, i)))->offset=sum;                  
1165                         t_sort.tsnumber=((struct tsn_sort*)(g_ptr_array_index(array, i)))->tsnumber;
1166                         if (t_sort.tsnumber>tsntmp)
1167                                 sum+=((struct tsn_sort*)(g_ptr_array_index(array, i)))->length;
1168                         tsntmp=t_sort.tsnumber;
1169                 }
1170                 u_data->assoc->max_bytes1= ((struct tsn_sort*)(g_ptr_array_index(array, i-1)))->offset + ((struct tsn_sort*)(g_ptr_array_index(array, i-1)))->length;
1171                 u_data->assoc->sort_tsn1=array;
1172         }
1173         if (u_data->dir==2 && u_data->assoc->n_array_tsn2>0)
1174         {
1175                 sum=0;
1176                 array=u_data->assoc->sort_tsn2;
1177                 insertion(array,u_data->assoc->n_array_tsn2);
1178
1179                 for (i=0; i<u_data->assoc->n_array_tsn2; i++)
1180                 {
1181                         ((struct tsn_sort*)(g_ptr_array_index(array,i)))->offset=sum;
1182                         t_sort.tsnumber=((struct tsn_sort*)(g_ptr_array_index(array, i)))->tsnumber;
1183                         if (t_sort.tsnumber>tsntmp)
1184                                 sum+=((struct tsn_sort*)(g_ptr_array_index(array, i)))->length;
1185                         tsntmp=t_sort.tsnumber;
1186                 }
1187
1188                 u_data->assoc->max_bytes2= ((struct tsn_sort*)(g_ptr_array_index(array,  u_data->assoc->n_data_chunks_ep2-1)))->offset + ((struct tsn_sort*)(g_ptr_array_index(array,  u_data->assoc->n_data_chunks_ep2-1)))->length;
1189                 u_data->assoc->sort_tsn2=array;
1190         }
1191 }
1192
1193 void create_byte_graph(guint16 dir, struct sctp_analyse* userdata)
1194 {
1195         struct sctp_udata *u_data;
1196
1197         u_data=g_malloc(sizeof(struct sctp_udata));
1198         u_data->assoc=g_malloc(sizeof(sctp_assoc_info_t));
1199         u_data->assoc=userdata->assoc;
1200         u_data->io=NULL;
1201         u_data->dir = dir;
1202         u_data->parent = userdata;
1203         if ((u_data->dir==1 && (u_data->assoc->n_array_tsn1==0))|| (u_data->dir==2 && (u_data->assoc->n_array_tsn2==0)))
1204                 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, "No Data Chunks sent");
1205         else
1206         {
1207                 set_child(u_data, u_data->parent);
1208                 increase_childcount(u_data->parent);            
1209                 compute_offsets(u_data);                
1210                 set_arw_offsets(u_data);                
1211                 gtk_sctpgraph_init(u_data);
1212         }
1213
1214 }
1215