2 * Graphic Analysis addition for ethereal
6 * Copyright 2004, Verso Technologies Inc.
7 * By Alejandro Vaquero <alejandrovaquero@yahoo.com>
9 * based on rtp_analysis.c and io_stat
12 * Ethereal - Network traffic analyzer
13 * By Gerald Combs <gerald@ethereal.com>
14 * Copyright 1998 Gerald Combs
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
35 #include "graph_analysis.h"
37 #include <epan/epan_dissect.h>
42 #include <epan/dissectors/packet-rtp.h>
43 #include <epan/addr_resolv.h>
47 #include <gdk/gdkkeysyms.h>
48 #include "gtkglobals.h"
50 #include "dlg_utils.h"
53 #include "compat_macros.h"
62 /****************************************************************************/
65 #define OK_TEXT "[ Ok ]"
66 #define PT_UNDEFINED -1
69 #if GTK_MAJOR_VERSION < 2
71 GdkColormap *colormap;
74 /****************************************************************************/
75 /* Reset the user_data structure */
76 static void graph_analysis_reset(graph_analysis_data_t* user_data)
80 user_data->num_nodes = 0;
81 user_data->num_items = 0;
82 for (i=0; i<MAX_NUM_NODES; i++){
83 user_data->nodes[i].type = AT_NONE;
84 user_data->nodes[i].len = 0;
85 g_free((void *)user_data->nodes[i].data);
88 user_data->dlg.first_node=0;
89 user_data->dlg.first_item=0;
90 user_data->dlg.left_x_border=0;
91 user_data->dlg.selected_item=0xFFFFFFFF; /*not item selected */
94 /****************************************************************************/
95 /* Reset the user_data structure */
96 static void graph_analysis_init_dlg(graph_analysis_data_t* user_data)
98 /* init dialog_graph */
99 user_data->dlg.needs_redraw=TRUE;
100 user_data->dlg.draw_area=NULL;
101 user_data->dlg.pixmap=NULL;
102 user_data->dlg.h_scrollbar=NULL;
103 user_data->dlg.h_scrollbar_adjustment=NULL;
104 user_data->dlg.v_scrollbar=NULL;
105 user_data->dlg.v_scrollbar_adjustment=NULL;
106 user_data->dlg.pixmap_width=600;
107 user_data->dlg.pixmap_height=400;
108 user_data->dlg.first_node=0;
109 user_data->dlg.first_item=0;
110 user_data->dlg.left_x_border=0;
111 user_data->dlg.selected_item=0xFFFFFFFF; /*not item selected */
112 user_data->dlg.window=NULL;
115 /****************************************************************************/
119 /****************************************************************************/
120 /* close the dialog window and remove the tap listener */
121 static void on_destroy(GtkWidget *win _U_, graph_analysis_data_t *user_data _U_)
124 for (i=0; i<MAX_NUM_NODES; i++){
125 user_data->nodes[i].type = AT_NONE;
126 user_data->nodes[i].len = 0;
127 g_free((void *)user_data->nodes[i].data);
133 /****************************************************************************/
134 static void dialog_graph_set_title(graph_analysis_data_t* user_data)
137 if (!user_data->dlg.window){
140 title = g_strdup_printf("Ale");
142 gtk_window_set_title(GTK_WINDOW(user_data->dlg.window), title);
146 #define RIGHT_ARROW 1
148 #define WIDTH_ARROW 8
149 #define HEIGHT_ARROW 6
151 /****************************************************************************/
152 static void draw_arrow(GdkDrawable *pixmap, GdkGC *gc, gint x, gint y, gboolean direction)
154 GdkPoint arrow_point[3];
156 arrow_point[0].x = x;
157 arrow_point[0].y = y-HEIGHT_ARROW/2;
158 if (direction == RIGHT_ARROW)
159 arrow_point[1].x = x+WIDTH_ARROW;
161 arrow_point[1].x = x-WIDTH_ARROW;
162 arrow_point[1].y = y;
163 arrow_point[2].x = x;
164 arrow_point[2].y = y+HEIGHT_ARROW/2;;
166 gdk_draw_polygon(pixmap, gc, TRUE,
171 #define MAX_COMMENT 60
172 #define ITEM_HEIGHT 20
173 #define NODE_WIDTH 100
174 #define TOP_Y_BORDER 40
175 #define BOTTOM_Y_BORDER 0
176 #define COMMENT_WIDTH 250
178 /****************************************************************************/
179 static void dialog_graph_draw(graph_analysis_data_t* user_data)
181 guint32 i, last_item, first_item, last_node, first_node, display_items, display_nodes;
182 guint32 start_arrow, end_arrow, label_x, src_port_x, dst_port_x, arrow_width;
183 guint32 current_item;
184 guint32 left_x_border;
185 guint32 right_x_border;
186 guint32 top_y_border;
187 guint32 bottom_y_border;
188 graph_analysis_item_t *gai;
189 gboolean display_label;
191 #if GTK_MAJOR_VERSION < 2
194 FONT_TYPE *small_font;
197 PangoLayout *big_layout;
198 PangoLayout *small_layout;
200 guint32 label_width, label_height;
201 guint32 draw_width, draw_height;
202 char label_string[MAX_COMMENT];
207 #if GTK_MAJOR_VERSION <2
208 font = user_data->dlg.draw_area->style->font;
209 big_font = gdk_font_load("-adobe-helvetica-bold-r-normal--12-120-75-75-p-70-iso8859-1");
210 small_font = gdk_font_load("-adobe-helvetica-bold-r-normal--10-120-75-75-p-70-iso8859-1");
212 if(!user_data->dlg.needs_redraw){
215 user_data->dlg.needs_redraw=FALSE;
220 gdk_draw_rectangle(user_data->dlg.pixmap,
221 user_data->dlg.draw_area->style->white_gc,
224 user_data->dlg.draw_area->allocation.width,
225 user_data->dlg.draw_area->allocation.height);
227 /* Calculate the y border */
228 top_y_border=TOP_Y_BORDER; /* to display the node address */
229 bottom_y_border=BOTTOM_Y_BORDER;
231 draw_height=user_data->dlg.pixmap_height-top_y_border-bottom_y_border;
233 first_item = user_data->dlg.first_item;
234 display_items = draw_height/ITEM_HEIGHT;
235 last_item = first_item+display_items-1;
237 /* get the items to display and fill the matrix array */
238 list = g_list_first(user_data->graph_info->list);
245 if (current_item>=display_items) break; /* the item is outside the display */
247 user_data->dlg.items[current_item].frame_num = gai->frame_num;
248 user_data->dlg.items[current_item].time = gai->time;
249 user_data->dlg.items[current_item].port_src = gai->port_src;
250 user_data->dlg.items[current_item].port_dst = gai->port_dst;
251 /* Add "..." if the length is 50 characters */
252 if (strlen(gai->frame_label) > 48) {
253 gai->frame_label[48] = '.';
254 gai->frame_label[47] = '.';
255 gai->frame_label[46] = '.';
257 user_data->dlg.items[current_item].frame_label = gai->frame_label;
258 user_data->dlg.items[current_item].comment = gai->comment;
259 user_data->dlg.items[current_item].conv_num = gai->conv_num;
260 user_data->dlg.items[current_item].src_node = gai->src_node;
261 user_data->dlg.items[current_item].dst_node = gai->dst_node;
262 user_data->dlg.items[current_item].line_style = gai->line_style;
268 list = g_list_next(list);
270 /* in case the windows is resized so we have to move the top item */
271 if ((first_item + display_items) > user_data->num_items){
272 if (display_items>user_data->num_items)
275 first_item = user_data->num_items - display_items;
278 /* in case there are less items than possible displayed */
279 display_items = current_item;
280 last_item = first_item+display_items-1;
282 /* if not items to display */
283 if (display_items == 0) return;
286 /* Calculate the x borders */
287 /* We use time from the last display item to calcultate the x left border */
288 g_snprintf(label_string, MAX_LABEL, "%.3f", user_data->dlg.items[display_items-1].time);
289 #if GTK_MAJOR_VERSION < 2
290 label_width=gdk_string_width(font, label_string);
291 label_height=gdk_string_height(font, label_string);
293 layout = gtk_widget_create_pango_layout(user_data->dlg.draw_area, label_string);
294 big_layout = gtk_widget_create_pango_layout(user_data->dlg.draw_area, label_string);
295 small_layout = gtk_widget_create_pango_layout(user_data->dlg.draw_area, label_string);
297 /* XXX - to prevent messages like "Couldn't load font x, falling back to y", I've changed font
298 description from "Helvetica-Bold 8" to "Helvetica,Sans,Bold 8", this seems to be
299 conforming to the API, see http://developer.gnome.org/doc/API/2.0/pango/pango-Fonts.html */
300 pango_layout_set_font_description(big_layout, pango_font_description_from_string("Helvetica,Sans,Bold 8"));
301 pango_layout_set_font_description(small_layout, pango_font_description_from_string("Helvetica,Sans,Bold 7"));
303 pango_layout_get_pixel_size(layout, &label_width, &label_height);
305 left_x_border=label_width+10;
306 user_data->dlg.left_x_border = left_x_border;
308 right_x_border=COMMENT_WIDTH;
310 /* Calculate the number of nodes to display */
311 draw_width=user_data->dlg.pixmap_width-right_x_border-left_x_border;
312 display_nodes = draw_width/NODE_WIDTH;
313 first_node = user_data->dlg.first_node;
315 /* in case the windows is resized so we have to move the left node */
316 if ((first_node + display_nodes) > user_data->num_nodes){
317 if (display_nodes>user_data->num_nodes)
320 first_node=user_data->num_nodes - display_nodes;
323 /* in case there are less nodes than possible displayed */
324 if (display_nodes>user_data->num_nodes) display_nodes=user_data->num_nodes;
326 last_node = first_node + display_nodes-1;
328 /* Paint the background items */
329 for (current_item=0; current_item<display_items; current_item++){
330 /* Paint background */
331 gdk_draw_rectangle(user_data->dlg.pixmap,
332 user_data->dlg.bg_gc[user_data->dlg.items[current_item].conv_num%MAX_NUM_COL_CONV],
335 top_y_border+current_item*ITEM_HEIGHT,
341 /* Draw the node names on top and the division lines */
342 for (i=0; i<display_nodes; i++){
343 /* print the node identifiers */
344 /* XXX we assign 5 pixels per character in the node identity */
345 g_snprintf(label_string, NODE_WIDTH/5, "%s",
346 get_addr_name(&(user_data->nodes[i+first_node])));
347 #if GTK_MAJOR_VERSION < 2
348 label_width=gdk_string_width(font, label_string);
349 label_height=gdk_string_height(font, label_string);
350 gdk_draw_string(user_data->dlg.pixmap,
352 user_data->dlg.draw_area->style->black_gc,
353 left_x_border+NODE_WIDTH/2-label_width/2+NODE_WIDTH*i,
354 top_y_border/2-label_height/2,
357 pango_layout_set_text(layout, label_string, -1);
358 pango_layout_get_pixel_size(layout, &label_width, &label_height);
359 gdk_draw_layout(user_data->dlg.pixmap,
360 user_data->dlg.draw_area->style->black_gc,
361 left_x_border+NODE_WIDTH/2-label_width/2+NODE_WIDTH*i,
362 top_y_border/2-label_height/2,
366 /* draw the node division lines */
367 gdk_draw_line(user_data->dlg.pixmap, user_data->dlg.div_line_gc,
368 left_x_border+NODE_WIDTH/2+NODE_WIDTH*i,
370 left_x_border+NODE_WIDTH/2+NODE_WIDTH*i,
371 user_data->dlg.pixmap_height-bottom_y_border);
380 for (current_item=0; current_item<display_items; current_item++){
382 g_snprintf(label_string, MAX_LABEL, "%.3f", user_data->dlg.items[current_item].time);
383 #if GTK_MAJOR_VERSION < 2
384 label_width=gdk_string_width(font, label_string);
385 label_height=gdk_string_height(font, label_string);
386 gdk_draw_string(user_data->dlg.pixmap,
388 user_data->dlg.draw_area->style->black_gc,
389 left_x_border-label_width-4,
390 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2+label_height/4,
393 pango_layout_set_text(layout, label_string, -1);
394 pango_layout_get_pixel_size(layout, &label_width, &label_height);
395 gdk_draw_layout(user_data->dlg.pixmap,
396 user_data->dlg.draw_area->style->black_gc,
397 left_x_border-label_width-4,
398 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2-label_height/2,
402 /*draw the comments */
403 g_snprintf(label_string, MAX_COMMENT, "%s", user_data->dlg.items[current_item].comment);
404 #if GTK_MAJOR_VERSION < 2
405 label_width=gdk_string_width(small_font, label_string);
406 label_height=gdk_string_height(small_font, label_string);
407 gdk_draw_string(user_data->dlg.pixmap,
409 user_data->dlg.draw_area->style->black_gc,
410 user_data->dlg.pixmap_width-right_x_border+3,
411 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2+label_height/4,
414 pango_layout_set_text(small_layout, label_string, -1);
415 pango_layout_get_pixel_size(small_layout, &label_width, &label_height);
416 gdk_draw_layout(user_data->dlg.pixmap,
417 user_data->dlg.draw_area->style->black_gc,
418 user_data->dlg.pixmap_width-right_x_border+3,
419 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2-label_height/2,
423 /* draw the arrow an frame label*/
424 display_label = FALSE;
425 if (user_data->dlg.items[current_item].src_node>=first_node){
426 if (user_data->dlg.items[current_item].src_node<=last_node){
427 start_arrow = left_x_border+(user_data->dlg.items[current_item].src_node-first_node)*NODE_WIDTH+NODE_WIDTH/2;
428 display_label = TRUE;
430 start_arrow = user_data->dlg.pixmap_width - right_x_border;
433 start_arrow = left_x_border;
436 if (user_data->dlg.items[current_item].dst_node>=first_node){
437 if (user_data->dlg.items[current_item].dst_node<=last_node){
438 end_arrow = left_x_border+(user_data->dlg.items[current_item].dst_node-first_node)*NODE_WIDTH+NODE_WIDTH/2;
439 display_label = TRUE;
441 end_arrow = user_data->dlg.pixmap_width - right_x_border;
444 end_arrow = left_x_border;
447 if (start_arrow != end_arrow){
448 /* draw the arrow line */
449 gdk_draw_line(user_data->dlg.pixmap, user_data->dlg.draw_area->style->black_gc,
451 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-7,
453 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-7);
455 /* draw the additional line when line style is 2 pixels width */
456 if (user_data->dlg.items[current_item].line_style == 2){
457 gdk_draw_line(user_data->dlg.pixmap, user_data->dlg.draw_area->style->black_gc,
459 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-6,
461 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-6);
465 if (start_arrow<end_arrow)
466 draw_arrow(user_data->dlg.pixmap, user_data->dlg.draw_area->style->black_gc, end_arrow-WIDTH_ARROW,top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-7, RIGHT_ARROW);
468 draw_arrow(user_data->dlg.pixmap, user_data->dlg.draw_area->style->black_gc, end_arrow+WIDTH_ARROW,top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-7, LEFT_ARROW);
471 /* draw the frame comment */
473 g_snprintf(label_string, MAX_LABEL, "%s", user_data->dlg.items[current_item].frame_label);
474 #if GTK_MAJOR_VERSION < 2
475 label_width=gdk_string_width(big_font, label_string);
476 label_height=gdk_string_height(big_font, label_string);
478 pango_layout_set_text(big_layout, label_string, -1);
479 pango_layout_get_pixel_size(big_layout, &label_width, &label_height);
482 if (start_arrow<end_arrow){
483 arrow_width = end_arrow-start_arrow;
484 label_x = arrow_width/2+start_arrow;
487 arrow_width = start_arrow-end_arrow;
488 label_x = arrow_width/2+end_arrow;
491 if (label_width>arrow_width) arrow_width = label_width;
493 if (left_x_border > (label_x-label_width/2)) label_x = left_x_border + label_width/2;
495 if ((user_data->dlg.pixmap_width - right_x_border) < (label_x+label_width/2)) label_x = user_data->dlg.pixmap_width - right_x_border - label_width/2;
497 #if GTK_MAJOR_VERSION < 2
498 gdk_draw_string(user_data->dlg.pixmap,
500 user_data->dlg.draw_area->style->black_gc,
501 label_x - label_width/2,
502 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2+label_height/4-3,
505 gdk_draw_layout(user_data->dlg.pixmap,
506 user_data->dlg.draw_area->style->black_gc,
507 label_x - label_width/2,
508 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT/2-label_height/2-3,
512 /* draw the source port number */
513 if ((start_arrow != left_x_border) && (start_arrow != (user_data->dlg.pixmap_width - right_x_border))){
514 g_snprintf(label_string, MAX_LABEL, "(%i)", user_data->dlg.items[current_item].port_src);
515 #if GTK_MAJOR_VERSION < 2
516 label_width=gdk_string_width(small_font, label_string);
517 label_height=gdk_string_height(small_font, label_string);
519 pango_layout_set_text(small_layout, label_string, -1);
520 pango_layout_get_pixel_size(small_layout, &label_width, &label_height);
522 if (start_arrow<end_arrow){
523 src_port_x = start_arrow - label_width - 2;
526 src_port_x = start_arrow + 2;
528 #if GTK_MAJOR_VERSION < 2
529 gdk_draw_string(user_data->dlg.pixmap,
531 user_data->dlg.div_line_gc,
533 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-2+label_height/4-2,
536 gdk_draw_layout(user_data->dlg.pixmap,
537 user_data->dlg.div_line_gc,
539 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-2-label_height/2-2,
544 /* draw the destination port number */
545 if ((end_arrow != left_x_border) && (end_arrow != (user_data->dlg.pixmap_width - right_x_border))){
546 g_snprintf(label_string, MAX_LABEL, "(%i)", user_data->dlg.items[current_item].port_dst);
547 #if GTK_MAJOR_VERSION < 2
548 label_width=gdk_string_width(small_font, label_string);
549 label_height=gdk_string_height(small_font, label_string);
551 pango_layout_set_text(small_layout, label_string, -1);
552 pango_layout_get_pixel_size(small_layout, &label_width, &label_height);
554 if (start_arrow<end_arrow){
555 dst_port_x = end_arrow + 2;
558 dst_port_x = end_arrow - label_width - 2;
560 #if GTK_MAJOR_VERSION < 2
561 gdk_draw_string(user_data->dlg.pixmap,
563 user_data->dlg.div_line_gc,
565 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-2+label_height/4-2,
568 gdk_draw_layout(user_data->dlg.pixmap,
569 user_data->dlg.div_line_gc,
571 top_y_border+current_item*ITEM_HEIGHT+ITEM_HEIGHT-2-label_height/2-2,
579 #if GTK_MAJOR_VERSION >= 2
580 g_object_unref(G_OBJECT(layout));
583 /* draw the border on the selected item */
584 if ( (user_data->dlg.selected_item != 0xFFFFFFFF) && ( (user_data->dlg.selected_item>=first_item) && (user_data->dlg.selected_item<=last_item) )){
585 gdk_draw_rectangle(user_data->dlg.pixmap, user_data->dlg.draw_area->style->black_gc,
588 (user_data->dlg.selected_item-first_item)*ITEM_HEIGHT+TOP_Y_BORDER,
589 user_data->dlg.pixmap_width-COMMENT_WIDTH-left_x_border+1,
595 gdk_draw_pixmap(user_data->dlg.draw_area->window,
596 user_data->dlg.draw_area->style->fg_gc[GTK_WIDGET_STATE(user_data->dlg.draw_area)],
597 user_data->dlg.pixmap,
600 user_data->dlg.pixmap_width, user_data->dlg.pixmap_height);
603 /* update the h_scrollbar */
604 user_data->dlg.h_scrollbar_adjustment->upper=(gfloat) user_data->num_nodes-1;
605 user_data->dlg.h_scrollbar_adjustment->step_increment=1;
606 user_data->dlg.h_scrollbar_adjustment->page_increment=(gfloat) (last_node-first_node);
607 user_data->dlg.h_scrollbar_adjustment->page_size=(gfloat) (last_node-first_node);
608 user_data->dlg.h_scrollbar_adjustment->value=(gfloat) first_node;
610 gtk_adjustment_changed(user_data->dlg.h_scrollbar_adjustment);
611 gtk_adjustment_value_changed(user_data->dlg.h_scrollbar_adjustment);
613 /* update the v_scrollbar */
614 user_data->dlg.v_scrollbar_adjustment->upper=(gfloat) user_data->num_items-1;
615 user_data->dlg.v_scrollbar_adjustment->step_increment=1;
616 user_data->dlg.v_scrollbar_adjustment->page_increment=(gfloat) (last_item-first_item);
617 user_data->dlg.v_scrollbar_adjustment->page_size=(gfloat) (last_item-first_item);
618 user_data->dlg.v_scrollbar_adjustment->value=(gfloat) first_item;
620 gtk_adjustment_changed(user_data->dlg.v_scrollbar_adjustment);
621 gtk_adjustment_value_changed(user_data->dlg.v_scrollbar_adjustment);
625 /****************************************************************************/
626 static void dialog_graph_redraw(graph_analysis_data_t* user_data)
628 user_data->dlg.needs_redraw=TRUE;
629 dialog_graph_draw(user_data);
632 /****************************************************************************/
633 static gint quit(GtkWidget *widget, GdkEventExpose *event _U_)
635 graph_analysis_data_t *user_data;
637 user_data=(graph_analysis_data_t *)OBJECT_GET_DATA(widget, "graph_analysis_data_t");
639 user_data->dlg.window = NULL;
645 /****************************************************************************/
646 static gint button_press_event(GtkWidget *widget, GdkEventButton *event _U_)
648 graph_analysis_data_t *user_data;
651 user_data=(graph_analysis_data_t *)OBJECT_GET_DATA(widget, "graph_analysis_data_t");
653 if (event->type != GDK_BUTTON_PRESS) return TRUE;
655 if (event->y<TOP_Y_BORDER) return TRUE;
657 /* get the item clicked */
658 item = ((guint32)event->y - TOP_Y_BORDER) / ITEM_HEIGHT;
659 user_data->dlg.selected_item = item + user_data->dlg.first_item;
661 user_data->dlg.needs_redraw=TRUE;
662 dialog_graph_draw(user_data);
664 cf_goto_frame(&cfile, user_data->dlg.items[item].frame_num);
669 /****************************************************************************/
670 static gint scroll_event(GtkWidget *widget, GdkEventButton *event _U_)
672 graph_analysis_data_t *user_data;
674 user_data=(graph_analysis_data_t *)OBJECT_GET_DATA(widget, "graph_analysis_data_t");
677 if (event->state == 0){
678 if (user_data->dlg.first_item == 0) return TRUE;
679 if (user_data->dlg.first_item < 3)
680 user_data->dlg.first_item = 0;
682 user_data->dlg.first_item -= 3;
686 if ((user_data->dlg.first_item+user_data->dlg.v_scrollbar_adjustment->page_size+1 == user_data->num_items)) return TRUE;
687 if ((user_data->dlg.first_item+user_data->dlg.v_scrollbar_adjustment->page_size+1) > (user_data->num_items-3))
688 user_data->dlg.first_item = user_data->num_items-(guint32)user_data->dlg.v_scrollbar_adjustment->page_size-1;
690 user_data->dlg.first_item += 3;
692 dialog_graph_redraw(user_data);
697 /****************************************************************************/
698 static gint key_press_event(GtkWidget *widget, GdkEventKey *event _U_)
700 graph_analysis_data_t *user_data;
702 user_data=(graph_analysis_data_t *)OBJECT_GET_DATA(widget, "graph_analysis_data_t");
705 if (event->keyval == GDK_Up){
706 if (user_data->dlg.selected_item == 0) return TRUE;
707 user_data->dlg.selected_item--;
708 if ( (user_data->dlg.selected_item<user_data->dlg.first_item) || (user_data->dlg.selected_item>user_data->dlg.first_item+user_data->dlg.v_scrollbar_adjustment->page_size) )
709 user_data->dlg.first_item = user_data->dlg.selected_item;
711 } else if (event->keyval == GDK_Down){
712 if (user_data->dlg.selected_item == user_data->num_items-1) return TRUE;
713 user_data->dlg.selected_item++;
714 if ( (user_data->dlg.selected_item<user_data->dlg.first_item) || (user_data->dlg.selected_item>user_data->dlg.first_item+user_data->dlg.v_scrollbar_adjustment->page_size) )
715 user_data->dlg.first_item = (guint32)user_data->dlg.selected_item-(guint32)user_data->dlg.v_scrollbar_adjustment->page_size;
716 } else if (event->keyval == GDK_Left){
717 if (user_data->dlg.first_node == 0) return TRUE;
718 user_data->dlg.first_node--;
719 } else if (event->keyval == GDK_Right){
720 if ((user_data->dlg.first_node+user_data->dlg.h_scrollbar_adjustment->page_size+1 == user_data->num_nodes)) return TRUE;
721 user_data->dlg.first_node++;
724 user_data->dlg.needs_redraw=TRUE;
725 dialog_graph_draw(user_data);
727 cf_goto_frame(&cfile, user_data->dlg.items[user_data->dlg.selected_item-user_data->dlg.first_item].frame_num);
732 /****************************************************************************/
733 static gint expose_event(GtkWidget *widget, GdkEventExpose *event)
735 graph_analysis_data_t *user_data;
737 user_data=(graph_analysis_data_t *)OBJECT_GET_DATA(widget, "graph_analysis_data_t");
743 gdk_draw_pixmap(widget->window,
744 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
745 user_data->dlg.pixmap,
746 event->area.x, event->area.y,
747 event->area.x, event->area.y,
748 event->area.width, event->area.height);
753 static const GdkColor COLOR_GRAY = {0, 0x7fff, 0x7fff, 0x7fff};
755 /****************************************************************************/
756 static gint configure_event(GtkWidget *widget, GdkEventConfigure *event _U_)
758 graph_analysis_data_t *user_data;
760 GdkColor color_div_line = COLOR_GRAY;
762 static GdkColor col[MAX_NUM_COL_CONV] = {
763 {0, 0x00FF, 0xFFFF, 0x00FF},
764 {0, 0xFFFF, 0xFFFF, 0x00FF},
765 {0, 0xFFFF, 0x00FF, 0x00FF},
766 {0, 0xFFFF, 0x00FF, 0xFFFF},
767 {0, 0x00FF, 0x00FF, 0xFFFF},
768 {0, 0x00FF, 0xFFFF, 0xFFFF},
769 {0, 0xFFFF, 0x80FF, 0x00FF},
770 {0, 0x80FF, 0x00FF, 0xFFFF},
771 {0, 0x00FF, 0x80FF, 0xFFFF},
772 {0, 0xFFFF, 0x00FF, 0x80FF}
775 user_data=(graph_analysis_data_t *)OBJECT_GET_DATA(widget, "graph_analysis_data_t");
781 if(user_data->dlg.pixmap){
782 gdk_pixmap_unref(user_data->dlg.pixmap);
783 user_data->dlg.pixmap=NULL;
786 user_data->dlg.pixmap=gdk_pixmap_new(widget->window,
787 widget->allocation.width,
788 widget->allocation.height,
790 user_data->dlg.pixmap_width=widget->allocation.width;
791 user_data->dlg.pixmap_height=widget->allocation.height;
793 gdk_draw_rectangle(user_data->dlg.pixmap,
794 widget->style->white_gc,
797 widget->allocation.width,
798 widget->allocation.height);
800 /* create gc for division lines and set the line stype to dash*/
801 user_data->dlg.div_line_gc=gdk_gc_new(user_data->dlg.pixmap);
802 gdk_gc_set_line_attributes(user_data->dlg.div_line_gc, 1, GDK_LINE_ON_OFF_DASH, 0, 0);
803 #if GTK_MAJOR_VERSION < 2
804 colormap = gtk_widget_get_colormap (widget);
805 if (!gdk_color_alloc (colormap, &color_div_line)){
806 g_warning ("Couldn't allocate color");
808 gdk_gc_set_foreground(user_data->dlg.div_line_gc, &color_div_line);
810 gdk_gc_set_rgb_fg_color(user_data->dlg.div_line_gc, &color_div_line);
813 /* create gcs for the background items */
815 for (i=0; i<MAX_NUM_COL_CONV; i++){
816 user_data->dlg.bg_gc[i]=gdk_gc_new(user_data->dlg.pixmap);
817 #if GTK_MAJOR_VERSION < 2
818 colormap = gtk_widget_get_colormap (widget);
819 if (!gdk_color_alloc (colormap, &col[i])){
820 g_warning ("Couldn't allocate color");
822 gdk_gc_set_foreground(user_data->dlg.bg_gc[i], &col[i]);
824 gdk_gc_set_rgb_fg_color(user_data->dlg.bg_gc[i], &col[i]);
828 dialog_graph_redraw(user_data);
832 /****************************************************************************/
833 static gint h_scrollbar_changed(GtkWidget *widget _U_, gpointer data)
835 graph_analysis_data_t *user_data=(graph_analysis_data_t *)data;
837 if ((user_data->dlg.first_node+user_data->dlg.h_scrollbar_adjustment->page_size+1 == user_data->num_nodes)
838 && (user_data->dlg.h_scrollbar_adjustment->value >= user_data->dlg.first_node ))
841 if (user_data->dlg.first_node == (guint16) user_data->dlg.h_scrollbar_adjustment->value)
844 user_data->dlg.first_node = (guint16) user_data->dlg.h_scrollbar_adjustment->value;
846 dialog_graph_redraw(user_data);
850 /****************************************************************************/
851 static gint v_scrollbar_changed(GtkWidget *widget _U_, gpointer data)
853 graph_analysis_data_t *user_data=(graph_analysis_data_t *)data;
854 if ((user_data->dlg.first_item+user_data->dlg.v_scrollbar_adjustment->page_size+1 == user_data->num_items)
855 && (user_data->dlg.v_scrollbar_adjustment->value >= user_data->dlg.first_item ))
858 if (user_data->dlg.first_item == user_data->dlg.v_scrollbar_adjustment->value)
861 user_data->dlg.first_item = (guint32) user_data->dlg.v_scrollbar_adjustment->value;
863 dialog_graph_redraw(user_data);
867 /****************************************************************************/
868 static void create_draw_area(graph_analysis_data_t* user_data, GtkWidget *box)
873 hbox=gtk_hbox_new(FALSE, 0);
874 gtk_widget_show(hbox);
876 vbox=gtk_vbox_new(FALSE, 0);
877 gtk_widget_show(vbox);
880 user_data->dlg.draw_area=gtk_drawing_area_new();
881 GTK_WIDGET_SET_FLAGS(user_data->dlg.draw_area, GTK_CAN_FOCUS);
882 gtk_widget_grab_focus(user_data->dlg.draw_area);
884 SIGNAL_CONNECT(user_data->dlg.draw_area, "destroy", quit, user_data);
885 OBJECT_SET_DATA(user_data->dlg.draw_area, "graph_analysis_data_t", user_data);
887 WIDGET_SET_SIZE(user_data->dlg.draw_area, user_data->dlg.pixmap_width, user_data->dlg.pixmap_height);
889 /* signals needed to handle backing pixmap */
890 SIGNAL_CONNECT(user_data->dlg.draw_area, "expose_event", expose_event, NULL);
891 SIGNAL_CONNECT(user_data->dlg.draw_area, "configure_event", configure_event, user_data);
893 gtk_widget_add_events (user_data->dlg.draw_area,
894 GDK_BUTTON_PRESS_MASK);
895 SIGNAL_CONNECT(user_data->dlg.draw_area, "button_press_event", button_press_event, user_data);
896 SIGNAL_CONNECT(user_data->dlg.draw_area, "scroll_event", scroll_event, user_data);
897 SIGNAL_CONNECT(user_data->dlg.draw_area, "key_press_event", key_press_event, user_data);
899 gtk_widget_show(user_data->dlg.draw_area);
900 gtk_box_pack_start(GTK_BOX(vbox), user_data->dlg.draw_area, TRUE, TRUE, 0);
902 /* create the associated h_scrollbar */
903 user_data->dlg.h_scrollbar_adjustment=(GtkAdjustment *)gtk_adjustment_new(0,0,0,0,0,0);
904 user_data->dlg.h_scrollbar=gtk_hscrollbar_new(user_data->dlg.h_scrollbar_adjustment);
905 gtk_widget_show(user_data->dlg.h_scrollbar);
906 gtk_box_pack_end(GTK_BOX(vbox), user_data->dlg.h_scrollbar, FALSE, FALSE, 0);
907 SIGNAL_CONNECT(user_data->dlg.h_scrollbar_adjustment, "value_changed", h_scrollbar_changed, user_data);
909 gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
911 /* create the associated v_scrollbar */
912 user_data->dlg.v_scrollbar_adjustment=(GtkAdjustment *)gtk_adjustment_new(0,0,0,0,0,0);
913 user_data->dlg.v_scrollbar=gtk_vscrollbar_new(user_data->dlg.v_scrollbar_adjustment);
914 gtk_widget_show(user_data->dlg.v_scrollbar);
915 gtk_box_pack_end(GTK_BOX(hbox), user_data->dlg.v_scrollbar, FALSE, FALSE, 0);
916 SIGNAL_CONNECT(user_data->dlg.v_scrollbar_adjustment, "value_changed", v_scrollbar_changed, user_data);
918 gtk_box_pack_start(GTK_BOX(box), hbox, TRUE, TRUE, 0);
922 /****************************************************************************/
923 static void dialog_graph_create_window(graph_analysis_data_t* user_data)
929 /* create the main window */
930 user_data->dlg.window=window_new(GTK_WINDOW_TOPLEVEL, "Graph Analysis");
933 vbox=gtk_vbox_new(FALSE, 0);
934 gtk_container_add(GTK_CONTAINER(user_data->dlg.window), vbox);
935 gtk_widget_show(vbox);
937 create_draw_area(user_data, vbox);
939 hbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
940 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
941 gtk_widget_show(hbox);
943 bt_close = OBJECT_GET_DATA(hbox, GTK_STOCK_CLOSE);
944 window_set_cancel_button(user_data->dlg.window, bt_close, window_cancel_button_cb);
946 SIGNAL_CONNECT(user_data->dlg.window, "delete_event", window_delete_event_cb, NULL);
948 gtk_widget_show(user_data->dlg.window);
949 window_present(user_data->dlg.window);
952 /* Return the index array if the node is in the array. Return -1 if there is room in the array
953 * and Return -2 if the array is full
955 /****************************************************************************/
956 gint is_node_array(graph_analysis_data_t* user_data, address* node)
959 for (i=0; i<MAX_NUM_NODES; i++){
960 if (user_data->nodes[i].type == AT_NONE) return -1; /* it is not in the array */
961 if (ADDRESSES_EQUAL((&user_data->nodes[i]),node)) return i; /* it is in the array */
963 return -2; /* array full */
967 /* Get the nodes from the list */
968 /****************************************************************************/
969 void get_nodes(graph_analysis_data_t* user_data)
972 graph_analysis_item_t *gai;
975 /* fill the node array */
976 list = g_list_first(user_data->graph_info->list);
981 user_data->num_items++;
982 /* check source node address */
983 index = is_node_array(user_data, &(gai->src_addr));
985 case -2: /* array full */
986 gai->src_node = NODE_OVERFLOW;
988 case -1: /* not in array */
989 COPY_ADDRESS(&(user_data->nodes[user_data->num_nodes]),&(gai->src_addr));
990 gai->src_node = user_data->num_nodes;
991 user_data->num_nodes++;
993 default: /* it is in the array, just update the src_node */
994 gai->src_node = (guint16)index;
997 /* check destination node address*/
998 index = is_node_array(user_data, &(gai->dst_addr));
1000 case -2: /* array full */
1001 gai->dst_node = NODE_OVERFLOW;
1003 case -1: /* not in array */
1004 COPY_ADDRESS(&(user_data->nodes[user_data->num_nodes]),&(gai->dst_addr));
1005 gai->dst_node = user_data->num_nodes;
1006 user_data->num_nodes++;
1008 default: /* it is in the array, just update the dst_node */
1009 gai->dst_node = (guint16)index;
1013 list = g_list_next(list);
1017 /****************************************************************************/
1018 graph_analysis_data_t* graph_analysis_init(void)
1020 graph_analysis_data_t* user_data;
1022 user_data = g_malloc(sizeof(graph_analysis_data_t));
1024 /* init user_data */
1025 graph_analysis_init_dlg(user_data);
1030 /****************************************************************************/
1031 void graph_analysis_create(graph_analysis_data_t* user_data)
1033 /* reset the data */
1034 graph_analysis_reset(user_data);
1036 /* get nodes (each node is an address) */
1037 get_nodes(user_data);
1039 /* create the graph windows */
1040 dialog_graph_create_window(user_data);
1042 /* redraw the graph */
1043 dialog_graph_redraw(user_data);
1048 /****************************************************************************/
1049 void graph_analysis_update(graph_analysis_data_t* user_data)
1051 /* reset the data */
1052 graph_analysis_reset(user_data);
1054 /* get nodes (each node is an address) */
1055 get_nodes(user_data);
1057 /* redraw the graph */
1058 dialog_graph_redraw(user_data);
1060 window_present(user_data->dlg.window);