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