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