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