AC_PREREQ(2.57)
AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)
#AC_WITH_LTDL # not needed ?
-AM_INIT_AUTOMAKE(LinuxTraceToolkitViewer,0.8.33-12032006)
+AM_INIT_AUTOMAKE(LinuxTraceToolkitViewer,0.8.34-17032006)
AM_CONFIG_HEADER(config.h)
AM_PROG_LIBTOOL
lttv/modules/gui/controlflow/Makefile
lttv/modules/gui/detailedevents/Makefile
lttv/modules/gui/statistics/Makefile
+ lttv/modules/gui/histogram/Makefile
lttv/modules/gui/filter/Makefile
lttv/modules/gui/tracecontrol/Makefile
ltt/Makefile
# WARNING : subdirs order is important : mainWin depends on API
-SUBDIRS = lttvwindow controlflow detailedevents statistics filter tracecontrol interrupts diskperformance
+SUBDIRS = lttvwindow controlflow detailedevents statistics filter tracecontrol interrupts diskperformance histogram
--- /dev/null
+# This file is part of the Linux Trace Toolkit viewer
+# Copyright (C) 2003-2004 Mathieu Desnoyers
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License Version 2 as
+# published by the Free Software Foundation;
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+
+
+
+#
+# Makefile for LTT New generation user interface : plugins.
+#
+# Created by Mathieu Desnoyers on May 6, 2003
+#
+
+AM_CFLAGS = $(GLIB_CFLAGS)
+AM_CFLAGS += $(GTK_CFLAGS)
+LIBS += $(GLIB_LIBS)
+LIBS += $(GTK_LIBS) -L${top_srcdir}/lttv/modules/gui/lttvwindow/lttvwindow -llttvwindow
+
+libdir = ${lttvplugindir}
+
+lib_LTLIBRARIES = libguihistogram.la
+libguihistogram_la_LDFLAGS = -module
+libguihistogram_la_SOURCES = histomodule.c histoeventhooks.c histocfv.c \
+ histobuttonwidget.c histodrawing.c histodrawitem.c
+
+noinst_HEADERS = histoeventhooks.h histocfv.h \
+ histobuttonwidget.h histodrawing.h histodrawitem.h
+
+EXTRA_DIST = \
+ hHistogramInsert.xpm stock_zoom_in_24.xpm stock_zoom_out_24.xpm \ stock_zoom_fit_24.xpm
--- /dev/null
+/* XPM */
+static char *hHistogramInsert_xpm[]={
+"22 22 10 1",
+"b c None",
+". c None",
+"f c #0000c0",
+"e c #0000ff",
+"g c #004000",
+"d c #008080",
+"a c #00ff00",
+"c c #800000",
+"# c #808000",
+"h c #ffff00",
+"......................",
+"####aaaaaaaaaaaaaaaaaa",
+".....bbbbbb####b......",
+"...ccccbbbccccb#b#..##",
+"....cc.bbbbcc.b.#.#.#.",
+"....cc..bbbcc..ddd.#..",
+"....cc..bbbcc.dd.dd...",
+"....cc..bbbcc.d...d...",
+"....cc..bbbcceeee.dfff",
+"....ccccccccc.d...d...",
+"....cc..bbbccd....dd..",
+"....cc..bbbcc...eeee..",
+"....cc..bbbcc......dd.",
+"...#cc#####cc.......dd",
+"....cc.bbbbcc..bbbbb..",
+"...cccc.bbcccc.bbbbb..",
+"....bbggbbbbb.ggbbbb..",
+"hhhh.ghhghbbbghhghbbhh",
+"g.bbbgbbgbbbbgbbg..b..",
+"gbbbbgbbgbbbbgbbg..bbg",
+".gbhhhhbbghhghb..ghhgb",
+"bbgg...b..gg......gg.."};
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2006 Parisa Heidari
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <glib.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "histobuttonwidget.h"
+#include "histodrawing.h"
+#include "histodrawitem.h"
+#include "stock_zoom_in_24.xpm"
+#include "stock_zoom_out_24.xpm"
+#include "stock_zoom_fit_24.xpm"
+
+#define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
+#define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format)
+
+/* Preallocated Size of the index_to_pixmap array */
+#define ALLOCATE_PROCESSES 1000
+
+/*****************************************************************************
+ * *
+ *****************************************************************************/
+static GtkWidget *xpm_label_box( gchar *xpm_filename,
+ gchar *label_text );
+static gboolean gplus( GtkWidget *widget,gpointer user_data)
+{
+ HistoControlFlowData *histo_cfd = (HistoControlFlowData *)user_data;
+ //histo_cfd->vertical_ratio =histo_cfd->vertical_ratio * (1.0/2.0);
+ if(histo_cfd->max_height>1)
+ {
+ histo_cfd->max_height /= 2;
+ //just redraw.horizontal scale is not changed so Array's data are valid.
+ histogram_show(histo_cfd ,0,histo_cfd->number_of_process->len);
+ }
+ else
+ g_warning("Zoom more than 1 event is impossible");
+
+ histo_drawing_update_vertical_ruler(histo_cfd->drawing);//, TimeWindow *time_window);
+ return 0;
+}
+
+static gboolean gMinus( GtkWidget *widget,
+ gpointer user_data )
+{
+ HistoControlFlowData *histo_cfd = (HistoControlFlowData *)user_data;
+ histo_cfd->max_height *= 2;
+
+ //just redraw.horizontal scale is not changed so Array's data are valid.
+ histogram_show(histo_cfd ,0,histo_cfd->number_of_process->len);
+ histo_drawing_update_vertical_ruler(histo_cfd->drawing);//, TimeWindow *time_window);
+ return 0;
+}
+
+static gboolean gFit( GtkWidget *widget,
+ gpointer user_data )
+{
+ /*find the maximum value and put max_height equal with this maximum*/
+ HistoControlFlowData *histo_cfd = (HistoControlFlowData *)user_data;
+ gint i=1,x;
+ guint maximum;
+ maximum =g_array_index(histo_cfd->number_of_process,guint,i);
+ for (i=1; i < histo_cfd->number_of_process-> len ;i++)
+ {
+ x=g_array_index(histo_cfd->number_of_process,guint,i);
+ maximum=MAX(x,maximum);
+ }
+ if (maximum >0)
+ {
+ histo_cfd->max_height=maximum;
+ histogram_show (histo_cfd,0,histo_cfd->number_of_process->len);
+ }
+ histo_drawing_update_vertical_ruler(histo_cfd->drawing);
+
+ return 0;
+}
+/* Create a new hbox with an image and a label packed into it
+ * and return the box. */
+
+static GtkWidget *xpm_label_box( gchar* xpm_filename,
+ gchar *label_text )
+{
+ GtkWidget *box;
+ GtkWidget *label;
+ GtkWidget *image;
+
+ GdkPixbuf *pixbufP;
+ //GError **error;
+ /* Create box for image and label */
+ box = gtk_hbox_new (FALSE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (box), 1);
+
+ /* Now on to the image stuff */
+
+ pixbufP = gdk_pixbuf_new_from_xpm_data((const char*)xpm_filename);
+ image = gtk_image_new_from_pixbuf(pixbufP);
+
+ /* Create a label for the button */
+ label = gtk_label_new (label_text);
+
+ /* Pack the image and label into the box */
+ gtk_box_pack_start (GTK_BOX (box), image, FALSE, FALSE, 1);
+ gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 1);
+
+ gtk_widget_show (image);
+ gtk_widget_show (label);
+
+ return box;
+}
+
+ButtonWidget *histo_buttonwidget_construct(HistoControlFlowData *histocontrol_flow_data)
+{
+ GtkWidget *boxPlus, *boxMinus , *boxfit;//containing text and image for each button.
+
+ ButtonWidget *buttonwidget = g_new(ButtonWidget,1);
+ buttonwidget->histo_control_flow_data = histocontrol_flow_data;
+ /* Put + and - on the vbox and assign related functions to each button */
+ buttonwidget-> vbox1 = gtk_vbox_new (FALSE, 0);
+
+// Add 2 buttons on the vbox
+// buttonwidget ->buttonP = gtk_button_new_with_mnemonic ("+");
+// buttonwidget->buttonM = gtk_button_new_with_mnemonic ("-");
+// Instead, add 2 button with image and text:
+
+ buttonwidget ->buttonP =gtk_button_new ();
+ buttonwidget ->buttonM =gtk_button_new ();
+ buttonwidget ->buttonFit =gtk_button_new ();
+
+/* This calls our box creating function */
+ boxPlus = xpm_label_box (stock_zoom_in_24, "vertical");
+ boxMinus = xpm_label_box (stock_zoom_out_24, "vertical");
+ boxfit = xpm_label_box (stock_zoom_fit_24, "vertical");
+
+/* Pack and show all widgets */
+ gtk_widget_show (boxPlus);
+ gtk_widget_show (boxMinus);
+ gtk_widget_show (boxfit);
+
+ gtk_container_add (GTK_CONTAINER (buttonwidget -> buttonP), boxPlus);
+ gtk_container_add (GTK_CONTAINER (buttonwidget -> buttonM), boxMinus);
+ gtk_container_add (GTK_CONTAINER (buttonwidget -> buttonFit), boxfit);
+
+ gtk_box_pack_start (GTK_BOX (buttonwidget->vbox1),buttonwidget->buttonP, TRUE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (buttonwidget->vbox1),buttonwidget->buttonM, TRUE, FALSE, 0);
+ gtk_box_pack_end (GTK_BOX (buttonwidget->vbox1),buttonwidget->buttonFit, TRUE, FALSE, 0);
+
+ /* When the button receives the "clicked" signal, it will call the
+ * function gplus() passing it NULL as its argument. The gplus()
+ * function is defined above . */
+
+ g_signal_connect (G_OBJECT (buttonwidget ->buttonP), "clicked",
+ G_CALLBACK (gplus), (gpointer)histocontrol_flow_data);
+ g_signal_connect (G_OBJECT ( buttonwidget->buttonM), "clicked",
+ G_CALLBACK (gMinus), (gpointer)histocontrol_flow_data);
+ g_signal_connect (G_OBJECT ( buttonwidget->buttonFit), "clicked",
+ G_CALLBACK (gFit), (gpointer)histocontrol_flow_data);
+
+ gtk_widget_show (buttonwidget -> vbox1);
+ gtk_widget_show (buttonwidget ->buttonP);
+ gtk_widget_show (buttonwidget ->buttonM);
+ gtk_widget_show (buttonwidget ->buttonFit);
+
+ return buttonwidget;
+}
+
+void histo_buttonwidget_destroy(ButtonWidget *buttonwidget)
+{
+ g_debug("buttonwidget_destroy %p", buttonwidget);
+
+ g_free(buttonwidget);
+ g_debug("buttonwidget_destroy end");
+}
+
+GtkWidget *histo_buttonwidget_get_widget(ButtonWidget *button_widget)
+{
+ return button_widget->vbox1;
+}
+
+
+
+void histo_rectangle_pixmap (GdkGC *gc,
+ gboolean filled, gint x, gint y, gint width, gint height,
+ histoDrawing_t *value)
+{
+ if(height == -1)
+ height = value->drawing_area->allocation.height;
+ if(width == -1)
+ height = value->drawing_area->allocation.width;
+ gdk_draw_rectangle (value->pixmap,
+ gc,
+ filled,
+ x, y,
+ width, height);
+}
+
+//This could be usefull if a vertical scroll bar is added to viewer:
+void histo_copy_pixmap_region(histoDrawing_t *drawing,GdkDrawable *dest,
+ GdkGC *gc, GdkDrawable *src,
+ gint xsrc, gint ysrc,
+ gint xdest, gint ydest, gint width, gint height)
+{
+
+ if(dest == NULL)
+ dest = drawing->pixmap;
+ if(src == NULL)
+ src = drawing->pixmap;
+
+ gdk_draw_drawable (dest,gc,src,xsrc, ysrc,
+ xdest, ydest,width, height);
+}
+
+void histo_update_pixmap_size(histoDrawing_t *value,
+ guint width)
+{
+ GdkPixmap *old_pixmap = value->pixmap;
+
+ value->pixmap =
+ gdk_pixmap_new(old_pixmap,
+ width,
+ value->height,
+ -1);
+
+ gdk_pixmap_unref(old_pixmap);
+}
+
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2006 Parisa Heidari
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef _HISTOBUTTONWIDGET_H
+#define _HISTOBUTTONWIDGET_H
+
+#include <gtk/gtk.h>
+#include <lttv/state.h>
+#include <ltt/ltt.h>
+#include "histocfv.h"
+#include "histodrawitem.h"
+
+
+/* The ButtonWidget
+ *
+ * Tasks :
+ * Create a widget
+ * containing 3 buttons zoomIn,zoonOut and zoomFit to change the vertical scale.
+ *
+ */
+#ifndef TYPE_ButtonWidget_DEFINED
+#define TYPE_ButtonWidget_DEFINED
+typedef struct _ButtonWidget ButtonWidget;
+#endif //TYPE_ButtonWidget_DEFINED
+
+#ifndef TYPE_HistoControlFlowData_DEFINED
+#define TYPE_HistoControlFlowData_DEFINED
+typedef struct _HistoControlFlowData HistoControlFlowData;
+#endif //TYPE_HistoControlFlowData_DEFINED
+
+struct _ButtonWidget {
+
+ GtkWidget *buttonP;
+ GtkWidget *buttonM;
+ GtkWidget *buttonFit;
+
+ GtkWidget *vbox1;//buttons are placed on this vbox
+
+ GtkWidget *hbox;//Parent Widget containing buttons and drawing area.
+ HistoControlFlowData *histo_control_flow_data;
+
+};
+
+
+void histo_copy_pixmap_region(histoDrawing_t *drawing,GdkDrawable *dest,
+ GdkGC *gc, GdkDrawable *src,
+ gint xsrc, gint ysrc,
+ gint xdest, gint ydest, gint width, gint height);
+
+void histo_rectangle_pixmap (GdkGC *gc,gboolean filled, gint x, gint y,
+ gint width, gint height,histoDrawing_t *value);
+
+ButtonWidget *histo_buttonwidget_construct(HistoControlFlowData *histocontrol_flow_data);
+
+void histo_buttonwidget_destroy(ButtonWidget *buttonwidget);
+
+
+static gboolean gplus( GtkWidget *widget,gpointer user_data);//assigned to zoomIn
+static gboolean gMinus( GtkWidget *widget,gpointer user_data );//assigned to zoomOut
+static gboolean gFit( GtkWidget *widget,gpointer user_data );//assigned to zoomFit
+
+GtkWidget *histo_buttonwidget_get_widget(ButtonWidget *button_widget);
+void histo_update_pixmap_size(histoDrawing_t *value,
+ guint width);
+#endif //_HISTOBUTTONWIDGET_H
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2006 Parisa heidari (inspired from CFV by Mathieu Desnoyers)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <lttv/lttv.h>
+#include <lttvwindow/lttvwindow.h>
+
+#include "histocfv.h"
+#include "histodrawing.h"
+#include "histobuttonwidget.h"
+#include "histoeventhooks.h"
+
+#define PREDEFINED_HEIGHT 5000
+
+extern GSList *g_histo_control_flow_data_list;
+
+static gboolean
+header_size_allocate(GtkWidget *widget,
+ GtkAllocation *allocation,
+ gpointer user_data)
+{
+ histoDrawing_t *drawing = (histoDrawing_t*)user_data;
+
+ gtk_widget_set_size_request(drawing->ruler, -1, allocation->height);
+ //gtk_widget_queue_resize(drawing->padding);
+ //gtk_widget_queue_resize(drawing->ruler);
+ gtk_container_check_resize(GTK_CONTAINER(drawing->ruler_hbox));
+ return 0;
+}
+
+
+/*****************************************************************************
+ * Histo Control Flow Viewer class implementation *
+ *****************************************************************************/
+/**
+ * Histo Control Flow Viewer's constructor
+ *
+ * This constructor is given as a parameter to the menuitem and toolbar button
+ * registration. It creates the drawing widget.
+ * @param ParentWindow A pointer to the parent window.
+ * @return The widget created.
+ */
+HistoControlFlowData *
+guihistocontrolflow(Tab *tab)
+{
+ GtkWidget *button_widget, *drawing_widget, *drawing_area;
+ GtkWidget *buttonP,*buttonM;
+ histoDrawing_t *drawing;
+ HistoControlFlowData* histo_control_flow_data = g_new(HistoControlFlowData,1) ;
+
+
+ histo_control_flow_data->tab = tab;
+ histo_control_flow_data->max_height = PREDEFINED_HEIGHT;
+
+ /*histo_control_flow_data->v_adjust =
+ GTK_ADJUSTMENT(gtk_adjustment_new( 0.0, // Value
+ 0.0, // Lower
+ 0.0, // Upper
+ 0.0, // Step inc.
+ 0.0, // Page inc.
+ 0.0)); // page size */
+
+ // Create the drawing
+ histo_control_flow_data->drawing = histo_drawing_construct(histo_control_flow_data);
+
+ drawing = histo_control_flow_data->drawing;
+ drawing_widget = histo_drawing_get_widget(drawing);
+
+ drawing_area = histo_drawing_get_drawing_area(drawing);
+
+ histo_control_flow_data->number_of_process = 0;
+
+ ///histo_control_flow_data->background_info_waiting = 0;
+
+ // Create the Button widget
+ histo_control_flow_data->buttonwidget = histo_buttonwidget_construct(histo_control_flow_data);
+
+ button_widget = histo_buttonwidget_get_widget( histo_control_flow_data-> buttonwidget);
+ buttonP =histo_control_flow_data-> buttonwidget->buttonP;
+ buttonM =histo_control_flow_data-> buttonwidget->buttonM;
+
+ //set the size of ruler fix
+ gtk_widget_set_size_request(histo_control_flow_data->drawing->ruler, -1, 25);
+ gtk_container_check_resize(GTK_CONTAINER(histo_control_flow_data->drawing->ruler_hbox));
+
+/*//or set the size of ruler by button P
+ g_signal_connect (G_OBJECT(buttonP),
+ "size-allocate",
+ G_CALLBACK(header_size_allocate),
+ (gpointer)histo_control_flow_data->drawing);*/
+
+
+ ///histo_control_flow_data->h_paned = gtk_hpaned_new();
+
+ ///changed for histogram
+ histo_control_flow_data->box = gtk_hbox_new(FALSE, 0);
+ histo_control_flow_data->ev_box = gtk_event_box_new();
+
+ /// histo_control_flow_data->top_widget =gtk_event_box_new();
+ gtk_container_add(GTK_CONTAINER(histo_control_flow_data->ev_box),
+ drawing_widget);
+ ///Now add button widget and drawing area on the top_widget.
+ gtk_box_pack_start (GTK_BOX (histo_control_flow_data->box),
+ button_widget,FALSE,FALSE, 10);
+ gtk_box_pack_end (GTK_BOX (histo_control_flow_data->box),
+ histo_control_flow_data->ev_box,TRUE,TRUE, 0);
+ histo_control_flow_data->top_widget = histo_control_flow_data->box;
+
+ /*gtk_container_add(GTK_CONTAINER(histo_control_flow_data->box),
+ histo_control_flow_data->h_paned);
+
+ gtk_paned_pack1(GTK_PANED(histo_control_flow_data->h_paned),
+ button_widget->vbox1, FALSE, TRUE);
+ gtk_paned_pack2(GTK_PANED(histo_control_flow_data->h_paned),
+ drawing_widget, TRUE, TRUE);
+ */
+ gtk_container_set_border_width(GTK_CONTAINER(histo_control_flow_data->ev_box), 1);
+
+ // Set the size of the drawing area
+ //drawing_Resize(drawing, h, w);
+
+ // Get trace statistics
+ //histo_control_flow_data->Trace_Statistics = get_trace_statistics(Trace);
+
+ gtk_widget_show(drawing_widget);
+ gtk_widget_show(button_widget);
+ /*gtk_widget_show(histo_control_flow_data->h_paned);*/
+ gtk_widget_show(histo_control_flow_data->box);
+ gtk_widget_show(histo_control_flow_data->ev_box);
+ gtk_widget_show(histo_control_flow_data->top_widget);
+ g_object_set_data_full(
+ G_OBJECT(histo_control_flow_data->top_widget),
+ "histo_control_flow_data",
+ histo_control_flow_data,
+ (GDestroyNotify)guihistocontrolflow_destructor);
+
+ g_object_set_data(
+ G_OBJECT(drawing_area),
+ "histo_control_flow_data",
+ histo_control_flow_data);
+
+ g_histo_control_flow_data_list = g_slist_append(
+ g_histo_control_flow_data_list,
+ histo_control_flow_data);
+ histo_control_flow_data->number_of_process =g_array_new (FALSE,
+ TRUE,
+ sizeof(guint));
+ g_array_set_size (histo_control_flow_data->number_of_process,
+ drawing_area->allocation.width);
+
+ //WARNING : The widget must be
+ //inserted in the main window before the drawing area
+ //can be configured (and this must happend before sending
+ //data)
+
+ return histo_control_flow_data;
+
+}
+
+/* Destroys widget also */
+void guihistocontrolflow_destructor_full(HistoControlFlowData *histo_control_flow_data)
+{
+ g_info("HISTOCFV.c : guihistocontrolflow_destructor_full, %p", histo_control_flow_data);
+ /* May already have been done by GTK window closing */
+ if(GTK_IS_WIDGET(guihistocontrolflow_get_widget(histo_control_flow_data)))
+ gtk_widget_destroy(guihistocontrolflow_get_widget(histo_control_flow_data));
+ //histo_control_flow_data->mw = NULL;
+ //FIXME guihistocontrolflow_destructor(histo_control_flow_data);
+}
+
+/* When this destructor is called, the widgets are already disconnected */
+void guihistocontrolflow_destructor(HistoControlFlowData *histo_control_flow_data)
+{
+ Tab *tab = histo_control_flow_data->tab;
+
+ g_info("HISTOCFV.c : guihistocontrolflow_destructor, %p", histo_control_flow_data);
+ g_info("%p, %p, %p", histo_update_time_window_hook, histo_control_flow_data, tab);
+ if(GTK_IS_WIDGET(guihistocontrolflow_get_widget(histo_control_flow_data)))
+ g_info("widget still exists");
+
+ /* ButtonWidget is removed with it's widget */
+ //buttonwidget_destroy(histo_control_flow_data->buttonwidget);
+ if(tab != NULL)
+ {
+ // Delete reading hooks
+ lttvwindow_unregister_traceset_notify(tab,
+ histo_traceset_notify,
+ histo_control_flow_data);
+
+ lttvwindow_unregister_time_window_notify(tab,
+ histo_update_time_window_hook,
+ histo_control_flow_data);
+
+ lttvwindow_unregister_current_time_notify(tab,
+ histo_update_current_time_hook,
+ histo_control_flow_data);
+
+ lttvwindow_unregister_redraw_notify(tab, histo_redraw_notify, histo_control_flow_data);
+ lttvwindow_unregister_continue_notify(tab,
+ histo_continue_notify,
+ histo_control_flow_data);
+
+ lttvwindow_events_request_remove_all(histo_control_flow_data->tab,
+ histo_control_flow_data);
+
+ lttvwindow_unregister_filter_notify(tab,
+ histo_filter_changed, histo_control_flow_data);
+
+ }
+ lttvwindowtraces_background_notify_remove(histo_control_flow_data);
+ g_histo_control_flow_data_list =
+ g_slist_remove(g_histo_control_flow_data_list,histo_control_flow_data);
+
+ g_array_free(histo_control_flow_data->number_of_process, TRUE);
+
+ g_info("HISTOCFV.c : guihistocontrolflow_destructor end, %p", histo_control_flow_data);
+ g_free(histo_control_flow_data);
+
+}
+
+
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2006 Parisa heidari (inspired from CFV by Mathieu Desnoyers)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+
+
+#ifndef _HISTOCFV_H
+#define _HISTOCFV_H
+
+#include <gtk/gtk.h>
+#include <lttvwindow/mainwindow.h>
+//#include "histobuttonwidget.h"
+
+extern GQuark LTT_NAME_CPU;
+
+
+#ifndef TYPE_histoDrawing_t_DEFINED
+#define TYPE_histoDrawing_t_DEFINED
+typedef struct _histoDrawing_t histoDrawing_t;
+#endif //TYPE_histoDrawing_t_DEFINED
+
+#ifndef TYPE_ButtonWidget_DEFINED
+#define TYPE_ButtonWidget_DEFINED
+typedef struct _ButtonWidget ButtonWidget;
+#endif //TYPE_ButtonWidget_DEFINED
+
+#ifndef TYPE_HistoControlFlowData_DEFINED
+#define TYPE_HistoControlFlowData_DEFINED
+typedef struct _HistoControlFlowData HistoControlFlowData;
+#endif //TYPE_HistoControlFlowData_DEFINED
+
+
+
+struct _HistoControlFlowData {
+
+ GtkWidget *top_widget;//The hbox containing buttons and drawing area.
+ Tab *tab;
+ GtkWidget *box;
+ GtkWidget *ev_box;//for histogram
+ ButtonWidget *buttonwidget;
+
+ histoDrawing_t *drawing;
+ //GtkAdjustment *v_adjust ;//may be used later for scrollbar
+
+ /* Shown events information */
+// TimeWindow time_window;
+// LttTime current_time;
+
+ //guint currently_Selected_Event ;
+ GArray *number_of_process;//number of events
+ guint background_info_waiting; /* Number of background requests waited for
+ in order to have all the info ready. */
+// For histogram
+ guint max_height;
+
+ LttvFilter *histo_main_win_filter;
+} ;
+
+/* Control Flow Data constructor */
+HistoControlFlowData *guihistocontrolflow(Tab *tab);
+void
+guihistocontrolflow_destructor_full(HistoControlFlowData *histo_control_flow_data);
+void
+guihistocontrolflow_destructor(HistoControlFlowData *histo_control_flow_data);
+
+static inline GtkWidget *guihistocontrolflow_get_widget(
+ HistoControlFlowData *histo_control_flow_data)
+{
+ return histo_control_flow_data->top_widget ;
+}
+
+static inline ButtonWidget *guihistocontrolflow_get_buttonwidget
+ (HistoControlFlowData *histo_control_flow_data)
+{
+ return histo_control_flow_data->buttonwidget ;
+}
+
+
+
+#endif // _HISTOCFV_H
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2006 Parisa heidari (inspired from CFV by Mathieu Desnoyers)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <string.h>
+
+#include <ltt/trace.h>
+
+#include <lttv/lttv.h>
+#include <lttv/tracecontext.h>
+#include <lttvwindow/lttvwindow.h>
+#include <lttv/state.h>
+#include <lttv/hook.h>
+
+#include "histodrawing.h"
+#include "histoeventhooks.h"
+#include "histocfv.h"
+
+#define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
+#define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format)
+
+//FIXME
+#define TRACE_NUMBER 0
+#define EXTRA_ALLOC 1024 // pixels
+#define padding_width 50
+
+#if 0 /* colors for two lines representation */
+GdkColor histo_drawing_colors[NUM_COLORS] =
+{ /* Pixel, R, G, B */
+ { 0, 0, 0, 0 }, /* COL_BLACK */
+ { 0, 0xFFFF, 0xFFFF, 0xFFFF }, /* COL_WHITE */
+ { 0, 0x0FFF, 0xFFFF, 0xFFFF }, /* COL_WAIT_FORK : pale blue */
+ { 0, 0xFFFF, 0xFFFF, 0x0000 }, /* COL_WAIT_CPU : yellow */
+ { 0, 0xFFFF, 0xA000, 0xFCFF }, /* COL_EXIT : pale magenta */
+ { 0, 0xFFFF, 0x0000, 0xFFFF }, /* COL_ZOMBIE : purple */
+ { 0, 0xFFFF, 0x0000, 0x0000 }, /* COL_WAIT : red */
+ { 0, 0x0000, 0xFFFF, 0x0000 }, /* COL_RUN : green */
+ { 0, 0x8800, 0xFFFF, 0x8A00 }, /* COL_USER_MODE : pale green */
+ { 0, 0x09FF, 0x01FF, 0xFFFF }, /* COL_SYSCALL : blue */
+ { 0, 0xF900, 0x4200, 0xFF00 }, /* COL_TRAP : pale purple */
+ { 0, 0xFFFF, 0x5AFF, 0x01FF }, /* COL_IRQ : orange */
+ { 0, 0xFFFF, 0xFFFF, 0xFFFF } /* COL_MODE_UNKNOWN : white */
+
+};
+#endif //0
+
+
+ GdkColor histo_drawing_colors[NUM_COLORS] =
+{ /* Pixel, R, G, B */
+ { 0, 0, 0, 0 }, /* COL_BLACK */
+ { 0, 0xFFFF, 0xFFFF, 0xFFFF }, /* COL_WHITE */
+ { 0, 0x0000, 0xFF00, 0x0000 }, /* COL_RUN_USER_MODE : green */
+ { 0, 0x0100, 0x9E00, 0xFFFF }, /* COL_RUN_SYSCALL : pale blue */
+ { 0, 0xFF00, 0xFF00, 0x0100 }, /* COL_RUN_TRAP : yellow */
+ { 0, 0xFFFF, 0x5E00, 0x0000 }, /* COL_RUN_IRQ : red */
+ { 0, 0x6600, 0x0000, 0x0000 }, /* COL_WAIT : dark red */
+ { 0, 0x7700, 0x7700, 0x0000 }, /* COL_WAIT_CPU : dark yellow */
+ { 0, 0x6400, 0x0000, 0x5D00 }, /* COL_ZOMBIE : dark purple */
+ { 0, 0x0700, 0x6400, 0x0000 }, /* COL_WAIT_FORK : dark green */
+ { 0, 0x8900, 0x0000, 0x8400 }, /* COL_EXIT : "less dark" magenta */
+ { 0, 0xFFFF, 0xFFFF, 0xFFFF }, /* COL_MODE_UNKNOWN : white */
+ { 0, 0xFFFF, 0xFFFF, 0xFFFF } /* COL_UNNAMED : white */
+
+};
+
+/*
+RUN+USER MODE green
+RUN+SYSCALL
+RUN+TRAP
+RUN+IRQ
+WAIT+foncé
+WAIT CPU + WAIT FORK vert foncé ou jaune
+IRQ rouge
+TRAP: orange
+SYSCALL: bleu pâle
+
+ZOMBIE + WAIT EXIT
+*/
+
+
+/*****************************************************************************
+ * drawing functions *
+ *****************************************************************************/
+
+static gboolean
+histo_expose_ruler( GtkWidget *widget, GdkEventExpose *event, gpointer user_data );
+
+static gboolean
+histo_expose_vertical_ruler( GtkWidget *widget, GdkEventExpose *event, gpointer user_data );
+
+static gboolean
+histo_motion_notify_ruler(GtkWidget *widget, GdkEventMotion *event, gpointer user_data);
+
+static gboolean
+histo_motion_notify_vertical_ruler(GtkWidget *widget, GdkEventMotion *event, gpointer user_data);
+
+/* Function responsible for updating the exposed area.
+ * It must do an events request to the lttvwindow API to ask for this update.
+ * Note : this function cannot clear the background, because it may
+ * erase drawing already present (SAFETY).
+ */
+void histo_drawing_data_request(histoDrawing_t *drawing,
+ gint x, gint y,
+ gint width,
+ gint height)
+{
+
+}
+
+
+void histo_drawing_data_request_begin(EventsRequest *events_request, LttvTracesetState *tss)
+{
+ g_debug("Begin of data request");
+ HistoControlFlowData *cfd = events_request->viewer_data;
+ LttvTracesetContext *tsc = LTTV_TRACESET_CONTEXT(tss);
+ TimeWindow time_window =
+ lttvwindow_get_time_window(cfd->tab);
+
+ guint width = cfd->drawing->width;
+ guint x=0;
+
+ cfd->drawing->last_start = events_request->start_time;
+
+ histo_convert_time_to_pixels(
+ time_window,
+ events_request->start_time,
+ width,
+ &x);
+
+ }
+
+ void histo_drawing_chunk_begin(EventsRequest *events_request, LttvTracesetState *tss)
+{
+ g_debug("Begin of chunk");
+ HistoControlFlowData *cfd = events_request->viewer_data;
+ LttvTracesetContext *tsc = LTTV_TRACESET_CONTEXT(tss);
+ //LttTime current_time = lttv_traceset_context_get_current_tfc(tsc)->timestamp;
+ guint num_cpu =
+ ltt_trace_get_num_cpu(tss->parent.traces[TRACE_NUMBER]->t);
+
+ /* //disabled for histogram
+ cfd->process_list->current_hash_data = g_new(HashedProcessData*,num_cpu);
+ memset(cfd->process_list->current_hash_data, 0,
+ sizeof(HashedProcessData*)*num_cpu);*/
+ //cfd->drawing->last_start = LTT_TIME_MIN(current_time,
+ // events_request->end_time);
+}
+
+
+void histo_drawing_request_expose(EventsRequest *events_request,
+ LttvTracesetState *tss,
+ LttTime end_time)
+{
+ HistoControlFlowData *cfd = events_request->viewer_data;
+ histoDrawing_t *drawing = cfd->drawing;
+
+ gint x, x_end, width;
+ LttvTracesetContext *tsc = (LttvTracesetContext*)tss;
+
+ TimeWindow time_window =
+ lttvwindow_get_time_window(cfd->tab);
+
+ g_debug("histo request expose");
+
+ histo_convert_time_to_pixels(
+ time_window,
+ end_time,
+ drawing->width,
+ &x_end);
+ x = drawing->damage_begin;
+
+ width = x_end - x;
+
+ drawing->damage_begin = x+width;
+
+ // FIXME ?
+ //changed for histogram:
+ gtk_widget_queue_draw_area ( drawing->drawing_area,
+ x, 0,
+ width,
+ drawing->/*drawing_area->allocation.*/height);
+
+ // Update directly when scrolling
+ gdk_window_process_updates(drawing->drawing_area->window,
+ TRUE);
+}
+
+
+/* Callbacks */
+
+
+/* Create a new backing pixmap of the appropriate size */
+/* As the scaling will always change, it's of no use to copy old
+ * pixmap.
+ *
+ * Change the size if width or height changes.
+ * (different from control flow viewer!)
+ */
+static gboolean
+histo_configure_event( GtkWidget *widget, GdkEventConfigure *event,
+ gpointer user_data)
+{
+ histoDrawing_t *drawing = (histoDrawing_t*)user_data;
+
+ /* First, get the new time interval of the main window */
+ /* we assume (see documentation) that the main window
+ * has updated the time interval before this configure gets
+ * executed.
+ */
+ //lttvwindow_get_time_window(drawing->histo_control_flow_data->mw,
+ // &drawing->histo_control_flow_data->time_window);
+
+ /* New pixmap, size of the configure event */
+ //GdkPixmap *pixmap = gdk_pixmap_new(widget->window,
+ // widget->allocation.width + SAFETY,
+ // widget->allocation.height + SAFETY,
+ // -1);
+ g_debug("drawing configure event");
+ g_debug("New alloc draw size : %i by %i",widget->allocation.width,
+ widget->allocation.height);
+
+/*modified for histogram, if width is not changed, GArray is valid so
+ just redraw, else recalculate all.(event request again)*/
+
+//enabled again for histogram:
+ if(drawing->pixmap)
+ gdk_pixmap_unref(drawing->pixmap);
+
+ drawing->pixmap = gdk_pixmap_new(widget->window,
+ widget->allocation.width ,//+ SAFETY + EXTRA_ALLOC,
+ widget->allocation.height + EXTRA_ALLOC,
+ -1);
+
+//end add
+ drawing->alloc_width = drawing->width + SAFETY + EXTRA_ALLOC;
+ drawing->alloc_height = drawing->height + EXTRA_ALLOC;
+
+ //drawing->height = widget->allocation.height;
+
+
+
+// Clear the image
+// gdk_draw_rectangle (drawing->pixmap,
+// widget->style->black_gc,
+// TRUE,
+// 0, 0,
+// drawing->width+SAFETY,
+// drawing->height);
+
+ //g_info("init data request");
+
+
+ /* Initial data request */
+ /* no, do initial data request in the expose event */
+ // Do not need to ask for data of 1 pixel : not synchronized with
+ // main window time at this moment.
+ //histo_drawing_data_request(drawing, &drawing->pixmap, 0, 0,
+ // widget->allocation.width,
+ // widget->allocation.height);
+
+ //drawing->width = widget->allocation.width;
+ //drawing->height = widget->allocation.height;
+
+ drawing->damage_begin = 0;
+ drawing->damage_end = widget->allocation.width;
+
+ if((widget->allocation.width != 1 &&
+ widget->allocation.height != 1)
+ /*&& drawing->damage_begin < drawing->damage_end */)
+ {
+
+ gdk_draw_rectangle (drawing->pixmap,
+ drawing->drawing_area->style->black_gc,
+ TRUE,
+ 0, 0,
+ drawing->drawing_area->allocation.width, drawing->drawing_area->allocation.height);
+ /* histo_drawing_data_request(drawing,
+ drawing->damage_begin,
+ 0,
+ drawing->damage_end - drawing->damage_begin,
+ drawing->height);*/
+ }
+//modified for histogram
+
+ if(widget->allocation.width == drawing->width)
+ {
+
+ drawing->height = widget->allocation.height;
+ histogram_show( drawing->histo_control_flow_data,0,
+ drawing->histo_control_flow_data->number_of_process->len);
+ }
+ else
+ {
+ drawing->width = widget->allocation.width;
+ drawing->height = widget->allocation.height;
+
+ g_array_set_size (drawing->histo_control_flow_data->number_of_process,
+ widget->allocation.width);
+ histo_request_event( drawing->histo_control_flow_data,drawing->damage_begin
+ ,drawing->damage_end - drawing->damage_begin);
+ }
+ return TRUE;
+}
+
+
+/* Redraw the screen from the backing pixmap */
+static gboolean
+histo_expose_event( GtkWidget *widget, GdkEventExpose *event, gpointer user_data )
+{
+ histoDrawing_t *drawing = (histoDrawing_t*)user_data;
+
+ HistoControlFlowData *histo_control_flow_data =
+ (HistoControlFlowData*)g_object_get_data(
+ G_OBJECT(widget),
+ "histo_control_flow_data");
+#if 0
+ if(unlikely(drawing->gc == NULL)) {
+ drawing->gc = gdk_gc_new(drawing->drawing_area->window);
+ gdk_gc_copy(drawing->gc, drawing->drawing_area->style->black_gc);
+ }
+#endif //0
+ TimeWindow time_window =
+ lttvwindow_get_time_window(histo_control_flow_data->tab);
+ LttTime current_time =
+ lttvwindow_get_current_time(histo_control_flow_data->tab);
+
+ guint cursor_x=0;
+
+ LttTime window_end = time_window.end_time;
+
+
+ /* update the screen from the pixmap buffer */
+//added again for histogram:
+
+ gdk_draw_pixmap(widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ drawing->pixmap,
+ event->area.x, event->area.y,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+ //0
+
+ drawing->height = drawing-> drawing_area ->allocation.height;
+
+#if 0
+ copy_pixmap_to_screen(histo_control_flow_data->process_list,
+ widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+#endif //0
+
+
+ /* //disabled for histogram
+ copy_pixmap_to_screen(histo_control_flow_data->process_list,
+ widget->window,
+ drawing->gc,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);*/
+
+ /* Erase the dotted lines left.. */
+ if(widget->allocation.height > drawing->height)
+ {
+ gdk_draw_rectangle (widget->window,
+ drawing->drawing_area->style->black_gc,
+ TRUE,
+ event->area.x, drawing->height,
+ event->area.width, // do not overlap
+ widget->allocation.height - drawing->height);
+ }
+ if(ltt_time_compare(time_window.start_time, current_time) <= 0 &&
+ ltt_time_compare(window_end, current_time) >= 0)
+ {
+ /* Draw the dotted lines */
+ histo_convert_time_to_pixels(
+ time_window,
+ current_time,
+ drawing->width,
+ &cursor_x);
+
+#if 0
+ if(drawing->dotted_gc == NULL) {
+
+ drawing->dotted_gc = gdk_gc_new(drawing->drawing_area->window);
+ gdk_gc_copy(drawing->dotted_gc, widget->style->white_gc);
+
+ gint8 dash_list[] = { 1, 2 };
+ gdk_gc_set_line_attributes(drawing->dotted_gc,
+ 1,
+ GDK_LINE_ON_OFF_DASH,
+ GDK_CAP_BUTT,
+ GDK_JOIN_MITER);
+ gdk_gc_set_dashes(drawing->dotted_gc,
+ 0,
+ dash_list,
+ 2);
+ }
+#endif //0
+ gint height_tot = MAX(widget->allocation.height, drawing->height);
+ gdk_draw_line(widget->window,
+ drawing->dotted_gc,
+ cursor_x, 0,
+ cursor_x, height_tot);
+ }
+
+ return FALSE;
+}
+
+static gboolean
+histo_after_expose_event( GtkWidget *widget, GdkEventExpose *event, gpointer user_data )
+{
+ //g_assert(0);
+ g_debug("AFTER EXPOSE");
+
+ return FALSE;
+}
+
+/* mouse click */
+static gboolean
+histo_button_press_event( GtkWidget *widget, GdkEventButton *event, gpointer user_data )
+{
+ HistoControlFlowData *histo_control_flow_data =
+ (HistoControlFlowData*)g_object_get_data(
+ G_OBJECT(widget),
+ "histo_control_flow_data");
+ histoDrawing_t *drawing = histo_control_flow_data->drawing;
+ TimeWindow time_window =
+ lttvwindow_get_time_window(histo_control_flow_data->tab);
+
+ g_debug("click");
+ if(event->button == 1)
+ {
+ LttTime time;
+
+ /* left mouse button click */
+ g_debug("x click is : %f", event->x);
+
+ histo_convert_pixels_to_time(drawing->width, (guint)event->x,
+ time_window,
+ &time);
+
+ lttvwindow_report_current_time(histo_control_flow_data->tab, time);
+ ////report event->y for vertical zoom +,-
+ }
+
+ return FALSE;
+}
+/*
+ //Viewer's vertical scroll bar is already omitted, not needed for histogram.
+static gboolean
+scrollbar_size_allocate(GtkWidget *widget,
+ GtkAllocation *allocation,
+ gpointer user_data)
+{
+ histoDrawing_t *drawing = (histoDrawing_t*)user_data;
+
+ gtk_widget_set_size_request(drawing->padding, allocation->width, -1);
+ //gtk_widget_queue_resize(drawing->padding);
+ //gtk_widget_queue_resize(drawing->ruler);
+ gtk_container_check_resize(GTK_CONTAINER(drawing->ruler_hbox));
+ return 0;
+}
+*/
+
+
+histoDrawing_t *histo_drawing_construct(HistoControlFlowData *histo_control_flow_data)
+{
+ histoDrawing_t *drawing = g_new(histoDrawing_t, 1);
+
+ drawing->histo_control_flow_data = histo_control_flow_data;
+
+ drawing->vbox = gtk_vbox_new(FALSE, 1);
+
+
+ drawing->ruler_hbox = gtk_hbox_new(FALSE, 1);
+ drawing->ruler = gtk_drawing_area_new ();
+ //gtk_widget_set_size_request(drawing->ruler, -1, 27);
+
+ drawing->padding = gtk_drawing_area_new ();
+ //gtk_widget_set_size_request(drawing->padding, -1, 27);
+
+ gtk_box_pack_start(GTK_BOX(drawing->ruler_hbox), drawing->padding,FALSE, FALSE, 0);
+
+ gtk_box_pack_end(GTK_BOX(drawing->ruler_hbox), drawing->ruler,
+ TRUE, TRUE, 0);
+
+ drawing->drawing_area = gtk_drawing_area_new ();
+
+ drawing->gc = NULL;
+ /*
+ ///at this time not necessary for histogram
+ drawing->hbox = gtk_hbox_new(FALSE, 1);
+
+ drawing->viewport = gtk_viewport_new(NULL, histo_control_flow_data->v_adjust);
+ drawing->scrollbar = gtk_vscrollbar_new(histo_control_flow_data->v_adjust);
+ gtk_box_pack_start(GTK_BOX(drawing->hbox), drawing->viewport,
+ TRUE, TRUE, 0);
+ gtk_box_pack_end(GTK_BOX(drawing->hbox), drawing->scrollbar,
+ FALSE, FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(drawing->viewport),
+ drawing->drawing_area);*/
+
+ //add vertical ruler:
+ drawing->vruler_drawing_hbox = gtk_hbox_new(FALSE, 1);
+ drawing-> vertical_ruler =gtk_drawing_area_new ();
+ gtk_box_pack_start(GTK_BOX(drawing->vruler_drawing_hbox), drawing->vertical_ruler,
+ FALSE, FALSE, 0);
+ gtk_box_pack_end(GTK_BOX(drawing->vruler_drawing_hbox), drawing->drawing_area,
+ TRUE, TRUE, 1);
+ gtk_widget_set_size_request(drawing->vertical_ruler, padding_width, -1);
+
+ gtk_box_pack_start(GTK_BOX(drawing->vbox), drawing->ruler_hbox,
+ FALSE, FALSE, 1);
+ gtk_box_pack_end(GTK_BOX(drawing->vbox), drawing->vruler_drawing_hbox/*drawing_area*/,
+ TRUE, TRUE, 1);
+
+ drawing->pango_layout =
+ gtk_widget_create_pango_layout(drawing->drawing_area, NULL);
+
+ drawing->height = 1;
+ drawing->width = 1;
+ drawing->depth = 0;
+ drawing->alloc_height = 1;
+ drawing->alloc_width = 1;
+
+ drawing->damage_begin = 0;
+ drawing->damage_end = 0;
+ drawing->horizontal_sel = -1;
+
+ //gtk_widget_set_size_request(drawing->drawing_area->window, 50, 50);
+ g_object_set_data_full(
+ G_OBJECT(drawing->drawing_area),
+ "histo_Link_drawing_Data",
+ drawing,
+ (GDestroyNotify)histo_drawing_destroy);
+
+ g_object_set_data(
+ G_OBJECT(drawing->ruler),
+ "histo_drawing",
+ drawing);
+
+ g_object_set_data(
+ G_OBJECT(drawing->vertical_ruler),
+ "histo_drawing",
+ drawing);
+
+ //gtk_widget_modify_bg( drawing->drawing_area,
+ // GTK_STATE_NORMAL,
+ // &CF_Colors[BLACK]);
+
+ //gdk_window_get_geometry(drawing->drawing_area->window,
+ // NULL, NULL,
+ // &(drawing->width),
+ // &(drawing->height),
+ // -1);
+
+ //drawing->pixmap = gdk_pixmap_new(
+ // drawing->drawing_area->window,
+ // drawing->width,
+ // drawing->height,
+ // drawing->depth);
+
+ drawing->pixmap = NULL;
+
+// drawing->pixmap = gdk_pixmap_new(drawing->drawing_area->window,
+// drawing->drawing_area->allocation.width,
+// drawing->drawing_area->allocation.height,
+// -1);
+
+ g_signal_connect (G_OBJECT(drawing->drawing_area),
+ "configure_event",
+ G_CALLBACK (histo_configure_event),
+ (gpointer)drawing);
+
+ g_signal_connect (G_OBJECT(drawing->ruler),
+ "expose_event",
+ G_CALLBACK(histo_expose_ruler),
+ (gpointer)drawing);
+
+ gtk_widget_add_events(drawing->ruler, GDK_POINTER_MOTION_MASK);
+ gtk_widget_add_events(drawing->vertical_ruler, GDK_POINTER_MOTION_MASK);
+
+ g_signal_connect (G_OBJECT(drawing->ruler),
+ "motion-notify-event",
+ G_CALLBACK(histo_motion_notify_ruler),
+ (gpointer)drawing);
+
+
+ g_signal_connect (G_OBJECT(drawing->vertical_ruler),
+ "expose_event",
+ G_CALLBACK(histo_expose_vertical_ruler),
+ (gpointer)drawing);
+
+ g_signal_connect (G_OBJECT(drawing->vertical_ruler),
+ "motion-notify-event",
+ G_CALLBACK(histo_motion_notify_vertical_ruler),
+ (gpointer)drawing);
+
+/*//not necessary for historam.
+ g_signal_connect (G_OBJECT(drawing->drawing_area),
+ "size-allocate",
+ G_CALLBACK(scrollbar_size_allocate),
+ (gpointer)drawing); */
+
+
+ gtk_widget_set_size_request(drawing->padding, padding_width, -1);//use it for vertical ruler
+
+ g_signal_connect (G_OBJECT(drawing->drawing_area),
+ "expose_event",
+ G_CALLBACK (histo_expose_event),
+ (gpointer)drawing);
+
+ g_signal_connect_after (G_OBJECT(drawing->drawing_area),
+ "expose_event",
+ G_CALLBACK (histo_after_expose_event),
+ (gpointer)drawing);
+
+ g_signal_connect (G_OBJECT(drawing->drawing_area),
+ "button-press-event",
+ G_CALLBACK (histo_button_press_event),
+ (gpointer)drawing);
+
+ gtk_widget_show(drawing->ruler);
+ gtk_widget_show(drawing->padding);
+ gtk_widget_show(drawing->ruler_hbox);
+ gtk_widget_show(drawing->vertical_ruler);
+ gtk_widget_show(drawing->vruler_drawing_hbox);
+ gtk_widget_show(drawing->drawing_area);
+
+ /// gtk_widget_show(drawing->viewport);
+ /// gtk_widget_show(drawing->scrollbar);
+ /// gtk_widget_show(drawing->hbox);
+
+ /* Allocate the colors */
+ GdkColormap* colormap = gdk_colormap_get_system();
+ gboolean success[NUM_COLORS];
+ gdk_colormap_alloc_colors(colormap, histo_drawing_colors, NUM_COLORS, FALSE,
+ TRUE, success);
+
+ drawing->gc =
+ gdk_gc_new(GDK_DRAWABLE(main_window_get_widget(histo_control_flow_data->tab)->window));
+ drawing->dotted_gc =
+ gdk_gc_new(GDK_DRAWABLE(main_window_get_widget(histo_control_flow_data->tab)->window));
+
+ gdk_gc_copy(drawing->gc,
+ main_window_get_widget(histo_control_flow_data->tab)->style->black_gc);
+ gdk_gc_copy(drawing->dotted_gc,
+ main_window_get_widget(histo_control_flow_data->tab)->style->white_gc);
+
+ gint8 dash_list[] = { 1, 2 };
+ gdk_gc_set_line_attributes(drawing->dotted_gc,
+ 1,
+ GDK_LINE_ON_OFF_DASH,
+ GDK_CAP_BUTT,
+ GDK_JOIN_MITER);
+ gdk_gc_set_dashes(drawing->dotted_gc,
+ 0,
+ dash_list,
+ 2);
+
+ drawing->ruler_gc_butt =
+ gdk_gc_new(GDK_DRAWABLE(main_window_get_widget(histo_control_flow_data->tab)->window));
+ gdk_gc_copy(drawing->ruler_gc_butt,
+ main_window_get_widget(histo_control_flow_data->tab)->style->black_gc);
+ drawing->ruler_gc_round =
+ gdk_gc_new(GDK_DRAWABLE(main_window_get_widget(histo_control_flow_data->tab)->window));
+ gdk_gc_copy(drawing->ruler_gc_round,
+ main_window_get_widget(histo_control_flow_data->tab)->style->black_gc);
+
+
+ gdk_gc_set_line_attributes(drawing->ruler_gc_butt,
+ 2,
+ GDK_LINE_SOLID,
+ GDK_CAP_BUTT,
+ GDK_JOIN_MITER);
+
+ gdk_gc_set_line_attributes(drawing->ruler_gc_round,
+ 2,
+ GDK_LINE_SOLID,
+ GDK_CAP_ROUND,
+ GDK_JOIN_ROUND);
+ return drawing;
+}
+
+void histo_drawing_destroy(histoDrawing_t *drawing)
+{
+ g_info("histo_drawing_destroy %p", drawing);
+
+ /* Free the colors */
+ GdkColormap* colormap = gdk_colormap_get_system();
+
+ gdk_colormap_free_colors(colormap, histo_drawing_colors, NUM_COLORS);
+
+ // Do not unref here, histoDrawing_t destroyed by it's widget.
+ //g_object_unref( G_OBJECT(drawing->drawing_area));
+ if(drawing->gc != NULL)
+ gdk_gc_unref(drawing->gc);
+
+ g_free(drawing->pango_layout);
+ if(drawing->dotted_gc != NULL) gdk_gc_unref(drawing->dotted_gc);
+ if(drawing->ruler_gc_butt != NULL) gdk_gc_unref(drawing->ruler_gc_butt);
+ if(drawing->ruler_gc_round != NULL) gdk_gc_unref(drawing->ruler_gc_round);
+
+ //added for histogram
+ if(drawing->pixmap)
+ gdk_pixmap_unref(drawing->pixmap);
+ g_free(drawing);
+ g_info("histo_drawing_destroy end");
+}
+
+ GtkWidget *histo_drawing_get_drawing_area(histoDrawing_t *drawing)
+{
+ return drawing->drawing_area;
+}
+
+ GtkWidget *histo_drawing_get_widget(histoDrawing_t *drawing)
+{
+ return drawing->vbox;
+}
+
+ void histo_drawing_draw_line( histoDrawing_t *drawing,
+ GdkPixmap *pixmap,
+ guint x1, guint y1,
+ guint x2, guint y2,
+ GdkGC *GC)
+{
+ gdk_draw_line (pixmap,
+ GC,
+ x1, y1, x2, y2);
+}
+
+void histo_drawing_clear(histoDrawing_t *drawing,guint clear_from,guint clear_to)
+{
+
+ HistoControlFlowData *cfd = drawing->histo_control_flow_data;
+ guint clear_width = clear_to- clear_from;
+ /*
+ //disabled for histogram
+ rectangle_pixmap(cfd->process_list,
+ drawing->drawing_area->style->black_gc,
+ TRUE,
+ 0, 0,
+ drawing->alloc_width, // do not overlap
+ -1);*/
+ //instead, this is added for histogram
+
+ histo_rectangle_pixmap (drawing->drawing_area->style->black_gc,
+ TRUE,
+ clear_from/*0*/, 0,
+ clear_width/*drawing->width*/,
+ -1,drawing);
+
+
+
+/* gdk_draw_rectangle (drawing->pixmap,
+ drawing->drawing_area->style->black_gc,
+ TRUE,
+ 0,0,
+ drawing->drawing_area->allocation.width,drawing->drawing_area->allocation.height );
+
+ /* ask for the buffer to be redrawn */
+//enabled again for histogram.
+ gtk_widget_queue_draw_area ( drawing->drawing_area,
+ clear_from, 0,
+ clear_width, drawing->height);
+ gdk_window_process_updates(drawing->drawing_area->window,TRUE);
+//disabled instead for histogram
+ //gtk_widget_queue_draw ( drawing->drawing_area);
+ return;
+}
+
+#if 0
+/* Insert a square corresponding to a new process in the list */
+/* Applies to whole drawing->width */
+void drawing_insert_square(histoDrawing_t *drawing,
+ guint y,
+ guint height)
+{
+ //GdkRectangle update_rect;
+ gboolean reallocate = FALSE;
+ GdkPixmap *new_pixmap;
+
+ /* Allocate a new pixmap with new height */
+ if(drawing->alloc_height < drawing->height + height) {
+
+ new_pixmap = gdk_pixmap_new(drawing->drawing_area->window,
+ drawing->width + SAFETY + EXTRA_ALLOC,
+ drawing->height + height + EXTRA_ALLOC,
+ -1);
+ drawing->alloc_width = drawing->width + SAFETY + EXTRA_ALLOC;
+ drawing->alloc_height = drawing->height + height + EXTRA_ALLOC;
+ reallocate = TRUE;
+
+ /* Copy the high region */
+ gdk_draw_pixmap (new_pixmap,
+ drawing->drawing_area->style->black_gc,
+ drawing->pixmap,
+ 0, 0,
+ 0, 0,
+ drawing->width + SAFETY, y);
+
+ } else {
+ new_pixmap = drawing->pixmap;
+ }
+
+ //GdkPixmap *pixmap = gdk_pixmap_new(drawing->drawing_area->window,
+ // drawing->width + SAFETY,
+ // drawing->height + height,
+ // -1);
+
+ /* add an empty square */
+ gdk_draw_rectangle (new_pixmap,
+ drawing->drawing_area->style->black_gc,
+ TRUE,
+ 0, y,
+ drawing->width + SAFETY, // do not overlap
+ height);
+
+ /* copy the bottom of the region */
+ gdk_draw_pixmap (new_pixmap,
+ drawing->drawing_area->style->black_gc,
+ drawing->pixmap,
+ 0, y,
+ 0, y + height,
+ drawing->width+SAFETY, drawing->height - y);
+
+
+ if(reallocate && likely(drawing->pixmap)) {
+ gdk_pixmap_unref(drawing->pixmap);
+ drawing->pixmap = new_pixmap;
+ }
+
+ if(unlikely(drawing->height==1)) drawing->height = height;
+ else drawing->height += height;
+
+ gtk_widget_set_size_request(drawing->drawing_area,
+ -1,
+ drawing->height);
+ gtk_widget_queue_resize_no_redraw(drawing->drawing_area);
+
+ /* ask for the buffer to be redrawn */
+ gtk_widget_queue_draw_area ( drawing->drawing_area,
+ 0, y,
+ drawing->width, drawing->height-y);
+}
+
+
+/* Remove a square corresponding to a removed process in the list */
+void drawing_remove_square(histoDrawing_t *drawing,
+ guint y,
+ guint height)
+{
+ GdkPixmap *pixmap;
+
+ if(unlikely((guint)drawing->height == height)) {
+ //pixmap = gdk_pixmap_new(
+ // drawing->drawing_area->window,
+ // drawing->width + SAFETY,
+ // 1,
+ // -1);
+ pixmap = drawing->pixmap;
+ drawing->height=1;
+ } else {
+ /* Allocate a new pixmap with new height */
+ //pixmap = gdk_pixmap_new(
+ // drawing->drawing_area->window,
+ // drawing->width + SAFETY,
+ // drawing->height - height,
+ // -1);
+ /* Keep the same preallocated pixmap */
+ pixmap = drawing->pixmap;
+
+ /* Copy the high region */
+ gdk_draw_pixmap (pixmap,
+ drawing->drawing_area->style->black_gc,
+ drawing->pixmap,
+ 0, 0,
+ 0, 0,
+ drawing->width + SAFETY, y);
+
+ /* Copy up the bottom of the region */
+ gdk_draw_pixmap (pixmap,
+ drawing->drawing_area->style->black_gc,
+ drawing->pixmap,
+ 0, y + height,
+ 0, y,
+ drawing->width, drawing->height - y - height);
+
+ drawing->height-=height;
+ }
+
+ //if(likely(drawing->pixmap))
+ // gdk_pixmap_unref(drawing->pixmap);
+
+ //drawing->pixmap = pixmap;
+
+ gtk_widget_set_size_request(drawing->drawing_area,
+ -1,
+ drawing->height);
+ gtk_widget_queue_resize_no_redraw(drawing->drawing_area);
+ /* ask for the buffer to be redrawn */
+ gtk_widget_queue_draw_area ( drawing->drawing_area,
+ 0, y,
+ drawing->width, MAX(drawing->height-y, 1));
+}
+#endif //0
+
+void histo_drawing_update_ruler(histoDrawing_t *drawing, TimeWindow *time_window)
+{
+ GtkRequisition req;
+ GdkRectangle rect;
+
+ req.width = drawing->ruler->allocation.width;
+ req.height = drawing->ruler->allocation.height;
+
+
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = req.width;
+ rect.height = req.height;
+
+ gtk_widget_queue_draw(drawing->ruler);
+ //gtk_widget_draw( drawing->ruler, &rect);
+}
+
+/* Redraw the ruler */
+static gboolean
+histo_expose_ruler( GtkWidget *widget, GdkEventExpose *event, gpointer user_data )
+{
+ histoDrawing_t *drawing = (histoDrawing_t*)user_data;
+ TimeWindow time_window = lttvwindow_get_time_window(drawing->histo_control_flow_data->tab);
+ gchar text[255];
+
+ PangoContext *context;
+ PangoLayout *layout;
+ PangoFontDescription *FontDesc;
+ PangoRectangle ink_rect;
+ gint global_width=0;
+ GdkColor foreground = { 0, 0, 0, 0 };
+ GdkColor background = { 0, 0xffff, 0xffff, 0xffff };
+
+ LttTime window_end = time_window.end_time;
+ LttTime half_width =
+ ltt_time_div(time_window.time_width,2.0);
+ LttTime window_middle =
+ ltt_time_add(half_width,
+ time_window.start_time);
+ g_debug("ruler expose event");
+
+ gdk_draw_rectangle (drawing->ruler->window,
+ drawing->ruler->style->white_gc,
+ TRUE,
+ event->area.x, event->area.y,
+ event->area.width,
+ event->area.height);
+
+ gdk_draw_line (drawing->ruler->window,
+ drawing->ruler_gc_butt,
+ event->area.x, 1,
+ event->area.x + event->area.width, 1);
+
+
+ snprintf(text, 255, "%lus\n%luns",
+ time_window.start_time.tv_sec,
+ time_window.start_time.tv_nsec);
+
+ layout = gtk_widget_create_pango_layout(drawing->drawing_area, NULL);
+
+ context = pango_layout_get_context(layout);
+ FontDesc = pango_context_get_font_description(context);
+
+ pango_font_description_set_size(FontDesc, 6*PANGO_SCALE);
+ pango_layout_context_changed(layout);
+
+ pango_layout_set_text(layout, text, -1);
+ pango_layout_get_pixel_extents(layout, &ink_rect, NULL);
+ global_width += ink_rect.width;
+
+ gdk_draw_layout_with_colors(drawing->ruler->window,
+ drawing->ruler_gc_butt,
+ 0,
+ 6,
+ layout, &foreground, &background);
+
+ gdk_draw_line (drawing->ruler->window,
+ drawing->ruler_gc_round,
+ 1, 1,
+ 1, 7);
+
+
+ snprintf(text, 255, "%lus\n%luns", window_end.tv_sec,
+ window_end.tv_nsec);
+
+ pango_layout_set_text(layout, text, -1);
+ pango_layout_get_pixel_extents(layout, &ink_rect, NULL);
+ global_width += ink_rect.width;
+
+ if(global_width <= drawing->ruler->allocation.width)
+ {
+ gdk_draw_layout_with_colors(drawing->ruler->window,
+ drawing->ruler_gc_butt,
+ drawing->ruler->allocation.width - ink_rect.width,
+ 6,
+ layout, &foreground, &background);
+
+ gdk_draw_line (drawing->ruler->window,
+ drawing->ruler_gc_butt,
+ drawing->ruler->allocation.width-1, 1,
+ drawing->ruler->allocation.width-1, 7);
+ }
+
+
+ snprintf(text, 255, "%lus\n%luns", window_middle.tv_sec,
+ window_middle.tv_nsec);
+
+ pango_layout_set_text(layout, text, -1);
+ pango_layout_get_pixel_extents(layout, &ink_rect, NULL);
+ global_width += ink_rect.width;
+
+ if(global_width <= drawing->ruler->allocation.width)
+ {
+ gdk_draw_layout_with_colors(drawing->ruler->window,
+ drawing->ruler_gc_butt,
+ (drawing->ruler->allocation.width - ink_rect.width)/2,
+ 6,
+ layout, &foreground, &background);
+
+ gdk_draw_line (drawing->ruler->window,
+ drawing->ruler_gc_butt,
+ drawing->ruler->allocation.width/2, 1,
+ drawing->ruler->allocation.width/2, 7);
+ }
+
+ g_object_unref(layout);
+
+ return FALSE;
+}
+
+ void histo_drawing_update_vertical_ruler(histoDrawing_t *drawing)//, TimeWindow *time_window)
+{
+ GtkRequisition req;
+ GdkRectangle rect;
+
+ req.width = drawing->vertical_ruler->allocation.width;
+ req.height = drawing->vertical_ruler->allocation.height;
+
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = req.width;
+ rect.height = req.height;
+
+ gtk_widget_queue_draw(drawing->vertical_ruler);
+ //gtk_widget_draw( drawing->ruler, &rect);
+}
+
+/* notify mouse on ruler */
+static gboolean
+histo_motion_notify_ruler(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
+{
+ //g_debug("motion");
+ //eventually follow mouse and show time here
+}
+
+static gboolean
+histo_motion_notify_vertical_ruler(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
+{
+ //g_debug("motion");
+ //eventually follow mouse and show time here
+}
+
+
+
+/* Redraw the vertical ruler */
+static gboolean
+histo_expose_vertical_ruler( GtkWidget *widget, GdkEventExpose *event, gpointer user_data )
+{
+ histoDrawing_t *drawing = (histoDrawing_t*)user_data;
+ HistoControlFlowData *histo_cfv = drawing->histo_control_flow_data;
+ gchar text[255];
+
+ PangoContext *context;
+ PangoLayout *layout;
+ PangoFontDescription *FontDesc;
+ PangoRectangle ink_rect;
+ gint global_height=0;
+ GdkColor foreground = { 0, 0, 0, 0 };
+ GdkColor background = { 0, 0xffff, 0xffff, 0xffff };
+ GdkColor red ={ 0, 0xFFFF, 0x1E00, 0x1000 };
+ GdkColor magneta ={ 0, 0x8900, 0x0000, 0x8400 };
+ g_debug("vertical ruler expose event");
+
+ gdk_draw_rectangle (drawing->vertical_ruler->window,
+ drawing->vertical_ruler->style->white_gc,
+ TRUE,
+ event->area.x, event->area.y,
+ event->area.width,
+ event->area.height);
+
+ gdk_draw_line (drawing->vertical_ruler->window,
+ drawing->ruler_gc_butt,
+ padding_width-1/*event->area.width-1*/,event->area.y,
+ padding_width-1/*event->area.width-1*/,event->area.y + event->area.height);
+
+ snprintf(text, 255, "%.1f", (float)histo_cfv->max_height);
+
+ layout = gtk_widget_create_pango_layout(drawing->drawing_area, NULL);
+
+ context = pango_layout_get_context(layout);
+ FontDesc = pango_context_get_font_description(context);
+
+ pango_font_description_set_size(FontDesc, 6*PANGO_SCALE);
+ pango_layout_context_changed(layout);
+
+ pango_layout_set_text(layout, text, -1);
+ pango_layout_get_pixel_extents(layout, &ink_rect, NULL);
+ global_height += ink_rect.height;
+
+ gdk_draw_layout_with_colors(drawing->vertical_ruler->window,
+ drawing->ruler_gc_butt,
+ 1,
+ 1,
+ layout, &foreground, &background);
+
+ gdk_draw_line (drawing->vertical_ruler->window,
+ drawing->ruler_gc_round,
+ drawing->vertical_ruler-> allocation.width-1, 1,
+ drawing->vertical_ruler-> allocation.width-7, 1);
+
+
+ snprintf(text, 255, "%lu",0);
+
+ pango_layout_set_text(layout, text, -1);
+ pango_layout_get_pixel_extents(layout, &ink_rect, NULL);
+ global_height += ink_rect.height;
+
+ if(global_height <= drawing->vertical_ruler->allocation.height)
+ {
+ gdk_draw_layout_with_colors(drawing->vertical_ruler->window,
+ drawing->ruler_gc_butt,
+ 1,
+ drawing->vertical_ruler->allocation.height - ink_rect.height-2,
+ layout, &foreground, &background);
+
+ gdk_draw_line (drawing->vertical_ruler->window,
+ drawing->ruler_gc_butt,
+ drawing->vertical_ruler-> allocation.width-1,
+ drawing->vertical_ruler->allocation.height-1,
+ drawing->vertical_ruler-> allocation.width-7,
+ drawing->vertical_ruler->allocation.height-1);
+ }
+
+
+ snprintf(text, 255, "%.1f",(float) histo_cfv->max_height/2.0);
+
+ pango_layout_set_text(layout, text, -1);
+ pango_layout_get_pixel_extents(layout, &ink_rect, NULL);
+ global_height += ink_rect.height;
+
+ if(global_height <= drawing->vertical_ruler->allocation.height)
+ {
+ gdk_draw_layout_with_colors(drawing->vertical_ruler->window,
+ drawing->ruler_gc_butt,
+ 1,
+ (drawing->vertical_ruler->allocation.height - ink_rect.height)/2,
+ layout, &foreground, &background);
+
+ gdk_draw_line (drawing->vertical_ruler->window,
+ drawing->ruler_gc_butt,
+ drawing->vertical_ruler-> allocation.width-1,
+ drawing->vertical_ruler-> allocation.height/2,
+ drawing->vertical_ruler-> allocation.width-7,
+ drawing->vertical_ruler->allocation.height/2);
+ }
+
+ //show number of events at current time:
+ LttTime current_time =
+ lttvwindow_get_current_time(histo_cfv->tab);
+ TimeWindow time_window =
+ lttvwindow_get_time_window(histo_cfv->tab);
+ LttTime time_begin = time_window.start_time;
+ LttTime time_width = time_window.time_width;
+ LttTime time_end = ltt_time_add(time_begin, time_width);
+ if((ltt_time_compare(current_time, time_begin) >= 0)&&
+ (ltt_time_compare(current_time, time_end) <= 0))
+ {
+ guint *events_at_currenttime;
+ guint max_height=histo_cfv ->max_height;
+ guint x;
+ histo_convert_time_to_pixels(
+ time_window,
+ current_time,
+ drawing->width,
+ &x);
+ // if(x_test<histo_cfv->number_of_process->len)
+
+ {
+ events_at_currenttime =
+ &g_array_index(histo_cfv->number_of_process,guint,x);
+
+
+ if((*events_at_currenttime) > max_height)
+ {
+ snprintf(text, 255, "OverFlow!");
+ pango_layout_set_text(layout, text, -1);
+ pango_layout_get_pixel_extents(layout, &ink_rect, NULL);
+ global_height += ink_rect.height;
+ gdk_draw_layout_with_colors(drawing->vertical_ruler->window,
+ drawing->ruler_gc_butt,
+ 1,
+ (drawing->vertical_ruler->allocation.height - ink_rect.height)/5,
+ layout, &red, &background);
+ }else
+ // if((*events_at_currenttime) <= max_height)
+ {
+ snprintf(text, 255, "%.1f",
+ (float) *events_at_currenttime);
+
+ pango_layout_set_text(layout, text, -1);
+ pango_layout_get_pixel_extents(layout, &ink_rect, NULL);
+ global_height += ink_rect.height;
+
+ if ((*events_at_currenttime) == 0)
+ {
+ gdk_draw_layout_with_colors(drawing->vertical_ruler->window,
+ drawing->ruler_gc_butt,
+ 1,
+ (drawing->vertical_ruler->allocation.height - ink_rect.height)-2,
+ layout, &red, &background);
+ }
+ else if ((*events_at_currenttime) == max_height)
+ {
+ gdk_draw_layout_with_colors(drawing->vertical_ruler->window,
+ drawing->ruler_gc_butt,
+ 1,
+ 1,
+ layout, &red, &background);
+ }
+ /*else if ((*events_at_currenttime) == max_height/2)
+ {
+ gdk_draw_layout_with_colors(drawing->vertical_ruler->window,
+ drawing->ruler_gc_butt,
+ 1,
+ (drawing->vertical_ruler->allocation.height - ink_rect.height)/2,
+ layout, &red, &background);
+ }*/
+ else if ((*events_at_currenttime) > max_height/2)
+ {
+ gdk_draw_layout_with_colors(drawing->vertical_ruler->window,
+ drawing->ruler_gc_butt,
+ 1,
+ (drawing->vertical_ruler->allocation.height - ink_rect.height)/4,
+ layout, &red, &background);
+ }
+ else{
+ gdk_draw_layout_with_colors(drawing->vertical_ruler->window,
+ drawing->ruler_gc_butt,
+ 1,
+ ((drawing->vertical_ruler->allocation.height
+ - ink_rect.height)*3)/4,
+ layout, &red, &background);
+ }
+ }
+
+ }
+ }
+
+ g_object_unref(layout);
+
+ return FALSE;
+}
+
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2006 Parisa heidari (inspired from CFV by Mathieu Desnoyers)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+
+#ifndef _HISTODRAWING_H
+#define _HISTODRAWING_H
+
+#include <glib.h>
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+#include <ltt/ltt.h>
+#include <lttv/tracecontext.h>
+#include <lttv/state.h>
+#include <lttvwindow/lttvwindow.h>
+#include "histocfv.h"
+#include "histodrawitem.h"
+
+
+#define SAFETY 50 // safety pixels at right and bottom of pixmap buffer
+
+typedef enum _draw_color {
+ COL_BLACK,
+ COL_WHITE,
+ COL_RUN_USER_MODE,/* green */
+ COL_RUN_SYSCALL, /* pale blue */
+ COL_RUN_TRAP, /* yellow */
+ COL_RUN_IRQ, /* red */
+ COL_WAIT, /* dark red */
+ COL_WAIT_CPU, /* dark yellow */
+ COL_ZOMBIE, /* dark purple */
+ COL_WAIT_FORK, /* dark green */
+ COL_EXIT, /* "less dark" magenta */
+ COL_MODE_UNKNOWN, /* white */
+ COL_UNNAMED, /* white */
+ NUM_COLORS } draw_color;
+
+extern GdkColor histo_drawing_colors[NUM_COLORS];
+
+/* This part of the viewer does :
+ * Draw horizontal lines, getting graphic context as arg.
+ * Copy region of the screen into another.
+ * Modify the boundaries to reflect a scale change. (resize)
+ * Refresh the physical screen with the pixmap
+ * A helper function is provided here to convert from time to process
+ * identifier to pixels and the contrary (will be useful for mouse selection).
+ * Insert an empty square in the drawing, moving the bottom part.
+ *
+ * Note: The last point is exactly why it would not be so easy to add the
+ * vertical line functionnality as in the original version of LTT. In order
+ * to do so, we should keep all processes in the list for the duration of
+ * all the trace instead of dynamically adding and removing them when we
+ * scroll. Another possibility is to redraw all the visible area when a new
+ * process is added to the list. The second solution seems more appropriate
+ * to me.
+ *
+ *
+ * The pixmap used has the width of the physical window, but the height
+ * of the shown processes.
+ */
+
+#ifndef TYPE_histoDrawing_t_DEFINED
+#define TYPE_histoDrawing_t_DEFINED
+typedef struct _histoDrawing_t histoDrawing_t;
+#endif //TYPE_DRAWING_T_DEFINED
+
+#ifndef TYPE_HistoControlFlowData_DEFINED
+#define TYPE_HistoControlFlowData_DEFINED
+typedef struct _HistoControlFlowData HistoControlFlowData;
+#endif //TYPE_HistoControlFlowData_DEFINED
+
+struct _histoDrawing_t {
+ GtkWidget *vbox;
+ GtkWidget *drawing_area;
+ /*
+ GtkWidget *hbox;
+ GtkWidget *viewport;
+ GtkWidget *scrollbar;*///at this time,not necessary for histogram
+
+ GtkWidget *ruler_hbox;
+ GtkWidget *ruler;
+ GtkWidget *padding;
+//vertical ruler
+ GtkWidget *vruler_drawing_hbox;
+ GtkWidget *vertical_ruler;
+
+ GdkPixmap *pixmap;
+ HistoControlFlowData *histo_control_flow_data;
+
+ PangoLayout *pango_layout;
+
+ gint height, width, depth;
+ /* height and width of allocated buffer pixmap */
+ gint alloc_height, alloc_width;
+
+ /* X coordinate of damaged region */
+ gint damage_begin, damage_end; /* damaged region to be exposed,
+ updated per chunk */
+ LttTime last_start;
+ GdkGC *dotted_gc;
+ GdkGC *gc;
+ GdkGC *ruler_gc_butt;
+ GdkGC *ruler_gc_round;
+
+ /* Position of the horizontal selector, -1 for none */
+ gint horizontal_sel;
+};
+
+histoDrawing_t *histo_drawing_construct(HistoControlFlowData *histo_control_flow_data);
+void histo_drawing_destroy(histoDrawing_t *drawing);
+
+
+void histo_drawing_data_request(histoDrawing_t *drawing,
+ gint x, gint y,
+ gint width,
+ gint height);
+
+ GtkWidget *histo_drawing_get_widget(histoDrawing_t *drawing);
+GtkWidget *histo_drawing_get_drawing_area(histoDrawing_t *drawing);
+
+ void histo_drawing_draw_line(histoDrawing_t *drawing,
+ GdkPixmap *pixmap,
+ guint x1, guint y1,
+ guint x2, guint y2,
+ GdkGC *GC);
+
+//void drawing_copy(histoDrawing_t *drawing,
+// guint xsrc, guint ysrc,
+// guint xdest, guint ydest,
+// guint width, guint height);
+
+/* Clear the drawing : make it 1xwidth. */
+void histo_drawing_clear(histoDrawing_t *drawing,guint clear_from,guint clear_to);
+
+/* Insert a square corresponding to a new process in the list */
+static void drawing_insert_square(histoDrawing_t *drawing,
+ guint y,
+ guint height);
+
+/* Remove a square corresponding to a removed process in the list */
+static void drawing_remove_square(histoDrawing_t *drawing,
+ guint y,
+ guint height);
+
+void histo_drawing_update_ruler(histoDrawing_t *drawing, TimeWindow *time_window);
+
+void histo_drawing_update_vertical_ruler(histoDrawing_t *drawing);//, TimeWindow *time_window);
+
+void histo_drawing_request_expose(EventsRequest *events_request,
+ LttvTracesetState *tss,
+ LttTime end_time);
+
+void histo_drawing_data_request_begin(EventsRequest *events_request,
+ LttvTracesetState *tss);
+void histo_drawing_chunk_begin(EventsRequest *events_request, LttvTracesetState *tss);
+
+
+
+static void
+tree_row_activated(GtkTreeModel *treemodel,
+ GtkTreePath *arg1,
+ GtkTreeViewColumn *arg2,
+ gpointer user_data);
+
+
+/* histo_convert_pixels_to_time
+ *
+ * Convert from window pixel and time interval to an absolute time.
+ */
+static inline void histo_convert_pixels_to_time(
+ gint width,
+ guint x,
+ TimeWindow time_window,
+ LttTime *time)
+{
+ double time_d;
+
+ time_d = time_window.time_width_double;
+ time_d = time_d / (double)width * (double)x;
+ *time = ltt_time_from_double(time_d);
+ *time = ltt_time_add(time_window.start_time, *time);
+}
+
+
+static inline void histo_convert_time_to_pixels(
+ TimeWindow time_window,
+ LttTime time,
+ int width,
+ guint *x)
+{
+ double time_d;
+#ifdef EXTRA_CHECK
+ g_assert(ltt_time_compare(window_time_begin, time) <= 0 &&
+ ltt_time_compare(window_time_end, time) >= 0);
+#endif //EXTRA_CHECK
+
+ time = ltt_time_sub(time, time_window.start_time);
+
+ time_d = ltt_time_to_double(time);
+
+ if(time_window.time_width_double == 0.0) {
+ g_assert(time_d == 0.0);
+ *x = 0;
+ } else {
+ *x = (guint)(time_d / time_window.time_width_double * (double)width);
+ }
+
+}
+
+#endif // _DRAWING_H
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Mathieu Desnoyers
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+
+
+/******************************************************************************
+ * drawitem.c
+ *
+ * This file contains methods responsible for drawing a generic type of data
+ * in a drawable. Doing this generically will permit user defined drawing
+ * behavior in a later time.
+ *
+ * This file provides an API which is meant to be reusable for all viewers that
+ * need to show information in line, icon, text, background or point form in
+ * a drawable area having time for x axis. The y axis, in the control flow
+ * viewer case, is corresponding to the different processes, but it can be
+ * reused integrally for cpu, and eventually locks, buffers, network
+ * interfaces... What will differ between the viewers is the precise
+ * information which interests us. We may think that the most useful
+ * information for control flow are some specific events, like schedule
+ * change, and processes'states. It may differ for a cpu viewer : the
+ * interesting information could be more the execution mode of each cpu.
+ * This API in meant to make viewer's writers life easier : it will become
+ * a simple choice of icons and line types for the precise information
+ * the viewer has to provide (agremented with keeping supplementary records
+ * and modifying slightly the DrawContext to suit the needs.)
+ *
+ * We keep each data type in attributes, keys to specific information
+ * being formed from the GQuark corresponding to the information received.
+ * (facilities / facility_name / events / eventname.)
+ * (cpus/cpu_name, process_states/ps_name,
+ * execution_modes/em_name, execution_submodes/es_name).
+ * The goal is then to provide a generic way to print information on the
+ * screen for all this different information.
+ *
+ * Information can be printed as
+ *
+ * - text (text + color + size + position (over or under line)
+ * - icon (icon filename, corresponding to a loaded icon, accessible through
+ * a GQuark. Icons are loaded statically at the guiControlFlow level during
+ * module initialization and can be added on the fly if not present in the
+ * GQuark.) The habitual place for xpm icons is in
+ * ${prefix}/share/LinuxTraceToolkit.) + position (over or under line)
+ * - line (color, width, style)
+ * - Arc (big points) (color, size)
+ * - background color (color)
+ *
+ * An item is a leaf of the attributes tree. It is, in that case, including
+ * all kind of events categories we can have. It then associates each category
+ * with one or more actions (drawing something) or nothing.
+ *
+ * Each item has an array of hooks (hook list). Each hook represents an
+ * operation to perform. We seek the array each time we want to
+ * draw an item. We execute each operation in order. An operation type
+ * is associated with each hook to permit user listing and modification
+ * of these operations. The operation type is also used to find the
+ * corresponding priority for the sorting. Operation type and priorities
+ * are enum and a static int table.
+ *
+ * The array has to be sorted by priority each time we add a task in it.
+ * A priority is associated with each operation type. It permits
+ * to perform background color selection before line or text drawing. We also
+ * draw lines before text, so the text appears over the lines.
+ *
+ * Executing all the arrays of operations for a specific event (which
+ * implies information for state, event, cpu, execution mode and submode)
+ * has to be done in a same DrawContext. The goal there is to keep the offset
+ * of the text and icons over and under the middle line, so a specific
+ * event could be printed as ( R Si 0 for running, scheduled in, cpu 0 ),
+ * text being easy to replace with icons. The DrawContext is passed as
+ * call_data for the operation hooks.
+ *
+ * We use the lttv global attributes to keep track of the loaded icons.
+ * If we need an icon, we look for it in the icons / icon name pathname.
+ * If found, we use the pointer to it. If not, we load the pixmap in
+ * memory and set the pointer to the GdkPixmap in the attributes. The
+ * structure pointed to contains the pixmap and the mask bitmap.
+ *
+ * Author : Mathieu Desnoyers, October 2003
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <lttv/hook.h>
+#include <lttv/attribute.h>
+#include <lttv/iattribute.h>
+#include <string.h>
+
+#include <lttv/tracecontext.h>
+#include <lttv/state.h>
+#include <lttv/lttv.h>
+
+#include "histodrawitem.h"
+
+
+#define MAX_PATH_LEN 256
+
+/* drawing hook functions */
+gboolean histo_draw_text( void *hook_data, void *call_data)
+{
+ histo_PropertiesText *properties = (histo_PropertiesText*)hook_data;
+ histo_DrawContext *draw_context = (histo_DrawContext*)call_data;
+
+ PangoContext *context;
+ PangoLayout *layout;
+ PangoFontDescription *font_desc;// = pango_font_description_new();
+ PangoRectangle ink_rect;
+
+ layout = draw_context->pango_layout;
+
+ context = pango_layout_get_context(layout);
+ font_desc = pango_context_get_font_description(context);
+
+ pango_font_description_set_size(font_desc, properties->size*PANGO_SCALE);
+ pango_layout_context_changed(layout);
+
+ pango_layout_set_text(layout, properties->text, -1);
+ pango_layout_get_pixel_extents(layout, &ink_rect, NULL);
+
+ gint x=0, y=0;
+ gint *offset=NULL;
+ gboolean enough_space = FALSE;
+ gint width = ink_rect.width;
+
+ switch(properties->histo_position.x) {
+ case POS_START:
+ x = draw_context->histo_drawinfo.start.x;
+ switch(properties->histo_position.y) {
+ case OVER:
+ offset = &draw_context->histo_drawinfo.start.offset.over;
+ x += draw_context->histo_drawinfo.start.offset.over;
+ y = draw_context->histo_drawinfo.y.over;
+ break;
+ case MIDDLE:
+ offset = &draw_context->histo_drawinfo.start.offset.middle;
+ x += draw_context->histo_drawinfo.start.offset.middle;
+ y = draw_context->histo_drawinfo.y.middle;
+ break;
+ case UNDER:
+ offset = &draw_context->histo_drawinfo.start.offset.under;
+ x += draw_context->histo_drawinfo.start.offset.under;
+ y = draw_context->histo_drawinfo.y.under;
+ break;
+ }
+ /* verify if there is enough space to draw */
+ if(unlikely(x + width <= draw_context->histo_drawinfo.end.x)) {
+ enough_space = TRUE;
+ *offset += width;
+ }
+ break;
+ case POS_END:
+ x = draw_context->histo_drawinfo.end.x;
+ switch(properties->histo_position.y) {
+ case OVER:
+ offset = &draw_context->histo_drawinfo.end.offset.over;
+ x += draw_context->histo_drawinfo.end.offset.over;
+ y = draw_context->histo_drawinfo.y.over;
+ break;
+ case MIDDLE:
+ offset = &draw_context->histo_drawinfo.end.offset.middle;
+ x += draw_context->histo_drawinfo.end.offset.middle;
+ y = draw_context->histo_drawinfo.y.middle;
+ break;
+ case UNDER:
+ offset = &draw_context->histo_drawinfo.end.offset.under;
+ x += draw_context->histo_drawinfo.end.offset.under;
+ y = draw_context->histo_drawinfo.y.under;
+ break;
+ }
+ /* verify if there is enough space to draw */
+ if(unlikely(x - width >= draw_context->histo_drawinfo.start.x)) {
+ enough_space = TRUE;
+ *offset -= width;
+ }
+ break;
+ }
+
+ if(unlikely(enough_space))
+ gdk_draw_layout_with_colors(draw_context->drawable,
+ draw_context->gc,
+ x,
+ y,
+ layout, properties->foreground, properties->background);
+
+ return 0;
+}
+
+
+/* To speed up the process, search in already loaded icons list first. Only
+ * load it if not present.
+ */
+gboolean histo_draw_icon( void *hook_data, void *call_data)
+{
+ histo_PropertiesIcon *properties = (histo_PropertiesIcon*)hook_data;
+ histo_DrawContext *draw_context = (histo_DrawContext*)call_data;
+
+ LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes());
+ LttvAttributeValue value;
+ gchar icon_name[MAX_PATH_LEN] = "icons/";
+ histo_IconStruct *icon_info;
+
+ strcat(icon_name, properties->icon_name);
+
+ g_assert(lttv_iattribute_find_by_path(attributes, icon_name,
+ LTTV_POINTER, &value));
+ if(unlikely(*(value.v_pointer) == NULL))
+ {
+ *(value.v_pointer) = icon_info = g_new(histo_IconStruct,1);
+
+ icon_info->pixmap = gdk_pixmap_create_from_xpm(draw_context->drawable,
+ &icon_info->mask, NULL, properties->icon_name);
+ }
+ else
+ {
+ icon_info = *(value.v_pointer);
+ }
+
+ gint x=0, y=0;
+ gint *offset=NULL;
+ gboolean enough_space = FALSE;
+ gint width = properties->width;
+
+ switch(properties->histo_position.x) {
+ case POS_START:
+ x = draw_context->histo_drawinfo.start.x;
+ switch(properties->histo_position.y) {
+ case OVER:
+ offset = &draw_context->histo_drawinfo.start.offset.over;
+ x += draw_context->histo_drawinfo.start.offset.over;
+ y = draw_context->histo_drawinfo.y.over;
+ break;
+ case MIDDLE:
+ offset = &draw_context->histo_drawinfo.start.offset.middle;
+ x += draw_context->histo_drawinfo.start.offset.middle;
+ y = draw_context->histo_drawinfo.y.middle;
+ break;
+ case UNDER:
+ offset = &draw_context->histo_drawinfo.start.offset.under;
+ x += draw_context->histo_drawinfo.start.offset.under;
+ y = draw_context->histo_drawinfo.y.under;
+ break;
+ }
+ /* verify if there is enough space to draw */
+ if(unlikely(x + width <= draw_context->histo_drawinfo.end.x)) {
+ enough_space = TRUE;
+ *offset += width;
+ }
+ break;
+ case POS_END:
+ x = draw_context->histo_drawinfo.end.x;
+ switch(properties->histo_position.y) {
+ case OVER:
+ offset = &draw_context->histo_drawinfo.end.offset.over;
+ x += draw_context->histo_drawinfo.end.offset.over;
+ y = draw_context->histo_drawinfo.y.over;
+ break;
+ case MIDDLE:
+ offset = &draw_context->histo_drawinfo.end.offset.middle;
+ x += draw_context->histo_drawinfo.end.offset.middle;
+ y = draw_context->histo_drawinfo.y.middle;
+ break;
+ case UNDER:
+ offset = &draw_context->histo_drawinfo.end.offset.under;
+ x += draw_context->histo_drawinfo.end.offset.under;
+ y = draw_context->histo_drawinfo.y.under;
+ break;
+ }
+ /* verify if there is enough space to draw */
+ if(unlikely(x - width >= draw_context->histo_drawinfo.start.x)) {
+ enough_space = TRUE;
+ *offset -= width;
+ }
+ break;
+ }
+
+ if(unlikely(enough_space)) {
+ gdk_gc_set_clip_mask(draw_context->gc, icon_info->mask);
+
+ gdk_gc_set_clip_origin(
+ draw_context->gc,
+ x,
+ y);
+ gdk_draw_drawable(draw_context->drawable,
+ draw_context->gc,
+ icon_info->pixmap,
+ 0, 0,
+ x,
+ y,
+ properties->width, properties->height);
+
+ gdk_gc_set_clip_origin(draw_context->gc, 0, 0);
+ gdk_gc_set_clip_mask(draw_context->gc, NULL);
+ }
+ return 0;
+}
+
+gboolean histo_draw_line( void *hook_data, void *call_data)
+{
+ histo_PropertiesLine *properties = (histo_PropertiesLine*)hook_data;
+ histo_DrawContext *draw_context = (histo_DrawContext*)call_data;
+
+ gdk_gc_set_foreground(draw_context->gc, &properties->color);
+ //gdk_gc_set_rgb_fg_color(draw_context->gc, &properties->color);
+ gdk_gc_set_line_attributes( draw_context->gc,
+ properties->line_width,
+ properties->style,
+ GDK_CAP_BUTT,
+ GDK_JOIN_MITER);
+ //g_critical("DRAWING LINE : x1: %i, y1: %i, x2:%i, y2:%i",
+ // draw_context->previous->middle->x,
+ // draw_context->previous->middle->y,
+ // draw_context->drawinfo.middle.x,
+ // draw_context->drawinfo.middle.y);
+
+ gint x_begin=0, x_end=0, y=0;
+
+ x_begin = draw_context->histo_drawinfo.start.x;
+ x_end = draw_context->histo_drawinfo.end.x;
+
+ switch(properties->y) {
+ case OVER:
+ y = draw_context->histo_drawinfo.y.over;
+ break;
+ case MIDDLE:
+ y = draw_context->histo_drawinfo.y.middle;
+ break;
+ case UNDER:
+ y = draw_context->histo_drawinfo.y.under;
+ break;
+ }
+
+ histo_drawing_draw_line(
+ NULL, draw_context->drawable,
+ x_begin,
+ y,
+ x_end,
+ y,
+ draw_context->gc);
+
+ return 0;
+}
+
+gboolean histo_draw_arc( void *hook_data, void *call_data)
+{
+ histo_PropertiesArc *properties = (histo_PropertiesArc*)hook_data;
+ histo_DrawContext *draw_context = (histo_DrawContext*)call_data;
+
+ gdk_gc_set_foreground(draw_context->gc, properties->color);
+ //gdk_gc_set_rgb_fg_color(draw_context->gc, properties->color);
+
+ gint x=0, y=0;
+ gint *offset=NULL;
+ gboolean enough_space = FALSE;
+ gint width = properties->size;
+
+ switch(properties->histo_position.x) {
+ case POS_START:
+ x = draw_context->histo_drawinfo.start.x;
+ switch(properties->histo_position.y) {
+ case OVER:
+ offset = &draw_context->histo_drawinfo.start.offset.over;
+ x += draw_context->histo_drawinfo.start.offset.over;
+ y = draw_context->histo_drawinfo.y.over;
+ break;
+ case MIDDLE:
+ offset = &draw_context->histo_drawinfo.start.offset.middle;
+ x += draw_context->histo_drawinfo.start.offset.middle;
+ y = draw_context->histo_drawinfo.y.middle;
+ break;
+ case UNDER:
+ offset = &draw_context->histo_drawinfo.start.offset.under;
+ x += draw_context->histo_drawinfo.start.offset.under;
+ y = draw_context->histo_drawinfo.y.under;
+ break;
+ }
+ /* verify if there is enough space to draw */
+ if(unlikely(x + width <= draw_context->histo_drawinfo.end.x)) {
+ enough_space = TRUE;
+ *offset += width;
+ }
+ break;
+ case POS_END:
+ x = draw_context->histo_drawinfo.end.x;
+ switch(properties->histo_position.y) {
+ case OVER:
+ offset = &draw_context->histo_drawinfo.end.offset.over;
+ x += draw_context->histo_drawinfo.end.offset.over;
+ y = draw_context->histo_drawinfo.y.over;
+ break;
+ case MIDDLE:
+ offset = &draw_context->histo_drawinfo.end.offset.middle;
+ x += draw_context->histo_drawinfo.end.offset.middle;
+ y = draw_context->histo_drawinfo.y.middle;
+ break;
+ case UNDER:
+ offset = &draw_context->histo_drawinfo.end.offset.under;
+ x += draw_context->histo_drawinfo.end.offset.under;
+ y = draw_context->histo_drawinfo.y.under;
+ break;
+ }
+ /* verify if there is enough space to draw */
+ if(unlikely(x - width >= draw_context->histo_drawinfo.start.x)) {
+ enough_space = TRUE;
+ *offset -= width;
+ }
+ break;
+ }
+
+ if(unlikely(enough_space))
+ gdk_draw_arc(draw_context->drawable, draw_context->gc,
+ properties->filled,
+ x,
+ y,
+ properties->size, properties->size, 0, 360*64);
+
+ return 0;
+}
+
+gboolean histo_draw_bg( void *hook_data, void *call_data)
+{
+ histo_PropertiesBG *properties = (histo_PropertiesBG*)hook_data;
+ histo_DrawContext *draw_context = (histo_DrawContext*)call_data;
+
+ gdk_gc_set_foreground(draw_context->gc, properties->color);
+ //gdk_gc_set_rgb_fg_color(draw_context->gc, properties->color);
+
+ //g_critical("DRAWING RECT : x: %i, y: %i, w:%i, h:%i, val1 :%i, val2:%i ",
+ // draw_context->previous->over->x,
+ // draw_context->previous->over->y,
+ // draw_context->drawinfo.over.x - draw_context->previous->over->x,
+ // draw_context->previous->under->y-draw_context->previous->over->y,
+ // draw_context->drawinfo.over.x,
+ // draw_context->previous->over->x);
+ gdk_draw_rectangle(draw_context->drawable, draw_context->gc,
+ TRUE,
+ draw_context->histo_drawinfo.start.x,
+ draw_context->histo_drawinfo.y.over,
+ draw_context->histo_drawinfo.end.x - draw_context->histo_drawinfo.start.x,
+ draw_context->histo_drawinfo.y.under - draw_context->histo_drawinfo.y.over);
+
+ return 0;
+}
+
+
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Mathieu Desnoyers
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+
+#ifndef _DRAW_ITEM_H
+#define _DRAW_ITEM_H
+
+#include <lttv/state.h>
+
+typedef struct _histo_DrawContext histo_DrawContext;
+typedef struct _histo_DrawInfo histo_DrawInfo;
+typedef struct _histo_ItemInfo histo_ItemInfo;
+
+typedef struct _histo_IconStruct histo_IconStruct;
+
+typedef struct _histo_DrawOperation histo_DrawOperation;
+
+
+typedef struct _histo_PropertiesText histo_PropertiesText;
+typedef struct _histo_PropertiesIcon histo_PropertiesIcon;
+typedef struct _histo_PropertiesLine histo_PropertiesLine;
+typedef struct _histo_PropertiesArc histo_PropertiesArc;
+typedef struct _histo_PropertiesBG histo_PropertiesBG;
+
+typedef enum _histo_DrawableItems histo_DrawableItems;
+enum _histo_DrawableItems {
+ ITEM_TEXT, ITEM_ICON, ITEM_LINE, ITEM_POINT, ITEM_BACKGROUND
+};
+
+typedef enum _histo_RelPosX {
+ POS_START, POS_END
+} histo_RelPosX;
+
+typedef enum _histo_RelPosY {
+ OVER, MIDDLE, UNDER
+} histo_RelPosY;
+
+
+/* The DrawContext keeps information about the current drawing position and
+ * the previous one, so we can use both to draw lines.
+ *
+ * over : position for drawing over the middle line.
+ * middle : middle line position.
+ * under : position for drawing under the middle line.
+ *
+ * the modify_* are used to take into account that we should go forward
+ * when we draw a text, an arc or an icon, while it's unneeded when we
+ * draw a line or background.
+ *
+ * The modify_* positions are altered by the draw item functions.
+ *
+ */
+
+
+struct _histo_DrawContext {
+ GdkDrawable *drawable;
+ GdkGC *gc;
+ PangoLayout *pango_layout;
+
+ struct {
+ struct {
+ gint x;
+ struct {
+ gint over;
+ gint middle;
+ gint under;
+ } offset;
+ } start;
+
+ struct {
+ gint x;
+ struct {
+ gint over;
+ gint middle;
+ gint under;
+ } offset;
+ } end;
+
+ struct {
+ gint over;
+ gint middle;
+ gint under;
+ } y;
+
+ } histo_drawinfo;
+};
+
+
+
+
+/*
+ * Structure used to keep information about icons.
+ */
+struct _histo_IconStruct {
+ GdkPixmap *pixmap;
+ GdkBitmap *mask;
+};
+
+
+/*
+ * The Item element is only used so the DrawOperation is modifiable by users.
+ * During drawing, only the Hook is needed.
+ */
+struct _histo_DrawOperation {
+ histo_DrawableItems item;
+ LttvHooks *hook;
+};
+#if 0
+/*
+ * We define here each items that can be drawn, together with their
+ * associated priority. Many item types can have the same priority,
+ * it's only used for quicksorting the operations when we add a new one
+ * to the array of operations to perform. Lower priorities are executed
+ * first. So, for example, we may want to give background color a value
+ * of 10 while a line would have 20, so the background color, which
+ * is in fact a rectangle, does not hide the line.
+ */
+
+static int Items_Priorities[] = {
+ 50, /* ITEM_TEXT */
+ 40, /* ITEM_ICON */
+ 20, /* ITEM_LINE */
+ 30, /* ITEM_POINT */
+ 10 /* ITEM_BACKGROUND */
+};
+#endif //0
+
+/*
+ * Here are the different structures describing each item type that can be
+ * drawn. They contain the information necessary to draw the item : not the
+ * position (this is provided by the DrawContext), but the text, icon name,
+ * line width, color; all the properties of the specific items.
+ */
+
+struct _histo_PropertiesText {
+ GdkColor *foreground;
+ GdkColor *background;
+ gint size;
+ gchar *text;
+ struct {
+ histo_RelPosX x;
+ histo_RelPosY y;
+ } histo_position;
+};
+
+
+struct _histo_PropertiesIcon {
+ gchar *icon_name;
+ gint width;
+ gint height;
+ struct {
+ histo_RelPosX x;
+ histo_RelPosY y;
+ } histo_position;
+};
+
+struct _histo_PropertiesLine {
+ GdkColor color;
+ gint line_width;
+ GdkLineStyle style;
+ histo_RelPosY y;
+};
+
+struct _histo_PropertiesArc {
+ GdkColor *color;
+ gint size; /* We force circle by width = height */
+ gboolean filled;
+ struct {
+ histo_RelPosX x;
+ histo_RelPosY y;
+ } histo_position;
+};
+
+struct _histo_PropertiesBG {
+ GdkColor *color;
+};
+
+
+
+void histo_draw_item( GdkDrawable *drawable,
+ gint x,
+ gint y,
+ LttvTraceState *ts,
+ LttvTracefileState *tfs,
+ LttvIAttribute *attributes);
+
+/*
+ * The tree of attributes used to store drawing operations goes like this :
+ *
+ * event_types/
+ * "facility-event_type"
+ * cpus/
+ * "cpu name"
+ * mode_types/
+ * "execution mode"/
+ * submodes/
+ * "submode"
+ * process_states/
+ * "state name"
+ *
+ * So if, for example, we want to add a hook to get called each time we
+ * receive an event that is in state LTTV_STATE_SYSCALL, we put the
+ * pointer to the GArray of DrawOperation in
+ * process_states/ "name associated with LTTV_STATE_SYSCALL"
+ */
+
+
+#if 0
+/*
+ * The add_operation has to do a quick sort by priority to keep the operations
+ * in the right order.
+ */
+void add_operation( LttvIAttribute *attributes,
+ gchar *pathname,
+ DrawOperation *operation);
+
+/*
+ * The del_operation seeks the array present at pathname (if any) and
+ * removes the DrawOperation if present. It returns 0 on success, -1
+ * if it fails.
+ */
+gint del_operation( LttvIAttribute *attributes,
+ gchar *pathname,
+ DrawOperation *operation);
+
+/*
+ * The clean_operations removes all operations present at a pathname.
+ * returns 0 on success, -1 if it fails.
+ */
+gint clean_operations( LttvIAttribute *attributes,
+ gchar *pathname );
+
+
+/*
+ * The list_operations gives a pointer to the operation array associated
+ * with the pathname. It will be NULL if no operation is present.
+ */
+void list_operations( LttvIAttribute *attributes,
+ gchar *pathname,
+ GArray **operation);
+
+
+
+/*
+ * exec_operation executes the operations if present in the attributes, or
+ * do nothing if not present.
+ */
+void exec_operations( LttvIAttribute *attributes,
+ gchar *pathname);
+#endif //0
+
+/*
+ * Here follow the prototypes of the hook functions used to draw the
+ * different items.
+ */
+
+gboolean histo_draw_text( void *hook_data, void *call_data);
+gboolean histo_draw_icon( void *hook_data, void *call_data);
+gboolean histo_draw_line( void *hook_data, void *call_data);
+gboolean histo_draw_arc( void *hook_data, void *call_data);
+gboolean histo_draw_bg( void *hook_data, void *call_data);
+
+
+#endif // _DRAW_ITEM_H
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2006 Parisa heidari (inspired from CFV by Mathieu Desnoyers)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+
+/*****************************************************************************
+ * Hooks to be called by the main window *
+ *****************************************************************************/
+
+
+/* Event hooks are the drawing hooks called during traceset read. They draw the
+ * icons, text, lines and background color corresponding to the events read.
+ *
+ * Two hooks are used for drawing : before_schedchange and after_schedchange hooks. The
+ * before_schedchange is called before the state update that occurs with an event and
+ * the after_schedchange hook is called after this state update.
+ *
+ * The before_schedchange hooks fulfill the task of drawing the visible objects that
+ * corresponds to the data accumulated by the after_schedchange hook.
+ *
+ * The after_schedchange hook accumulates the data that need to be shown on the screen
+ * (items) into a queue. Then, the next before_schedchange hook will draw what that
+ * queue contains. That's the Right Way (TM) of drawing items on the screen,
+ * because we need to draw the background first (and then add icons, text, ...
+ * over it), but we only know the length of a background region once the state
+ * corresponding to it is over, which happens to be at the next before_schedchange
+ * hook.
+ *
+ * We also have a hook called at the end of a chunk to draw the information left
+ * undrawn in each process queue. We use the current time as end of
+ * line/background.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+//#define PANGO_ENABLE_BACKEND
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <glib.h>
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+
+//#include <pango/pango.h>
+
+#include <ltt/event.h>
+#include <ltt/time.h>
+#include <ltt/type.h>
+#include <ltt/trace.h>
+
+#include <lttv/lttv.h>
+#include <lttv/hook.h>
+#include <lttv/state.h>
+#include <lttvwindow/lttvwindow.h>
+#include <lttvwindow/lttvwindowtraces.h>
+#include <lttvwindow/support.h>
+
+
+#include "histoeventhooks.h"
+#include "histocfv.h"
+#include "histobuttonwidget.h"
+#include "histodrawing.h"
+
+
+#define MAX_PATH_LEN 256
+#define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
+//FIXME
+#define TRACE_NUMBER 0
+#define EXTRA_ALLOC 1024 // pixels
+
+/* Action to do when background computation completed.
+ *
+ * Wait for all the awaited computations to be over.
+ */
+
+static gint histo_background_ready(void *hook_data, void *call_data)
+{
+ HistoControlFlowData *histocontrol_flow_data = (HistoControlFlowData *)hook_data;
+ LttvTrace *trace = (LttvTrace*)call_data;
+
+ histoDrawing_t *drawing = histocontrol_flow_data->drawing;
+ histocontrol_flow_data->background_info_waiting--;
+
+ if(histocontrol_flow_data->background_info_waiting == 0) {
+ g_message("Histocontrol flow viewer : background computation data ready.");
+
+ histo_drawing_clear(drawing,0,drawing->width);
+
+ gtk_widget_set_size_request(drawing->drawing_area,
+ -1, -1);
+ histo_redraw_notify(histocontrol_flow_data, NULL);
+ }
+
+ return 0;
+}
+
+
+/* Request background computation. Verify if it is in progress or ready first.
+ * Only for each trace in the tab's traceset.
+ */
+static void histo_request_background_data(HistoControlFlowData *histocontrol_flow_data)
+{
+ LttvTracesetContext * tsc =
+ lttvwindow_get_traceset_context(histocontrol_flow_data->tab);
+ gint num_traces = lttv_traceset_number(tsc->ts);
+ gint i;
+ LttvTrace *trace;
+
+ LttvHooks *histo_background_ready_hook =
+ lttv_hooks_new();
+ lttv_hooks_add(histo_background_ready_hook, histo_background_ready, histocontrol_flow_data,
+ LTTV_PRIO_DEFAULT);
+ histocontrol_flow_data->background_info_waiting = 0;
+
+ for(i=0;i<num_traces;i++) {
+ trace = lttv_traceset_get(tsc->ts, i);
+
+ if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace)==FALSE) {
+
+ if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"),
+ trace) == FALSE) {
+ /* We first remove requests that could have been done for the same
+ * information. Happens when two viewers ask for it before servicing
+ * starts.
+ */
+ if(!lttvwindowtraces_background_request_find(trace, "state"))
+ lttvwindowtraces_background_request_queue(
+ main_window_get_widget(histocontrol_flow_data->tab), trace, "state");
+ lttvwindowtraces_background_notify_queue(histocontrol_flow_data,
+ trace,
+ ltt_time_infinite,
+ NULL,
+ histo_background_ready_hook);
+ histocontrol_flow_data->background_info_waiting++;
+ } else { /* in progress */
+
+ lttvwindowtraces_background_notify_current(histocontrol_flow_data,
+ trace,
+ ltt_time_infinite,
+ NULL,
+ histo_background_ready_hook);
+ histocontrol_flow_data->background_info_waiting++;
+ }
+ } else {
+ /* Data ready. Be its nature, this viewer doesn't need to have
+ * its data ready hook called there, because a background
+ * request is always linked with a redraw.
+ */
+ }
+
+ }
+
+ lttv_hooks_destroy(histo_background_ready_hook);
+}
+
+/**
+ * Histogram Viewer's constructor hook
+ *
+ * This constructor is given as a parameter to the menuitem and toolbar button
+ * registration. It creates the list.
+ * @param tab A pointer to the parent tab.
+ * @return The widget created.
+ */
+GtkWidget *
+h_guihistocontrolflow(Tab *tab)
+{
+ g_info("h_guihistocontrolflow, %p", tab);
+ HistoControlFlowData *histocontrol_flow_data = guihistocontrolflow(tab) ;
+
+ histocontrol_flow_data->tab = tab;
+
+ // Unreg done in the GuiHistoControlFlow_Destructor
+ lttvwindow_register_traceset_notify(tab,
+ histo_traceset_notify,
+ histocontrol_flow_data);
+
+ lttvwindow_register_time_window_notify(tab,
+ histo_update_time_window_hook,
+ histocontrol_flow_data);
+ lttvwindow_register_current_time_notify(tab,
+ histo_update_current_time_hook,
+ histocontrol_flow_data);
+ lttvwindow_register_redraw_notify(tab,
+ histo_redraw_notify,
+ histocontrol_flow_data);
+ lttvwindow_register_continue_notify(tab,
+ histo_continue_notify,
+ histocontrol_flow_data);
+ //added for histogram, enable filter:
+ lttvwindow_register_filter_notify(tab,
+ histo_filter_changed,histocontrol_flow_data );
+ histocontrol_flow_data->histo_main_win_filter = lttvwindow_get_filter(tab);
+
+// histo_request_background_data(histocontrol_flow_data);
+
+ return guihistocontrolflow_get_widget(histocontrol_flow_data) ;
+
+}
+
+
+
+/// added for histogram.
+void histo_request_event( HistoControlFlowData *histocontrol_flow_data, guint x, guint width)
+{
+ if(width < 0) return ;
+
+ guint i, nb_trace;
+ Tab *tab = histocontrol_flow_data->tab;
+ TimeWindow time_window = lttvwindow_get_time_window( tab );
+ LttTime time_start, time_end;
+
+ LttvTraceState *ts;
+
+ //find the tracehooks
+ LttvTracesetContext *tsc = lttvwindow_get_traceset_context(tab);
+
+ LttvTraceset *traceset = tsc->ts;
+ nb_trace = lttv_traceset_number(traceset);
+ guint drawing_width= histocontrol_flow_data->drawing->width;
+//start time for chunk.
+ histo_convert_pixels_to_time(drawing_width, /*0*/x, time_window,
+ &time_start);
+//end time for chunk.
+ histo_convert_pixels_to_time(drawing_width,
+ /*width*/x+width,time_window,
+ &time_end);
+ time_end = ltt_time_add(time_end, ltt_time_one); // because main window
+ // doesn't deliver end time.
+
+ lttvwindow_events_request_remove_all(tab,
+ histocontrol_flow_data);
+
+
+ // LttvHooksById *histo_event_by_id = lttv_hooks_by_id_new();//if necessary for filter!
+ // FIXME : eventually request for more traces
+ for(i = 0; i<MIN(TRACE_NUMBER+1, nb_trace);i++)
+ {
+ //should be in the loop or before?
+ EventsRequest *histo_events_request = g_new(EventsRequest, 1);
+
+ LttvHooks *histo_before_trace_hooks = lttv_hooks_new();
+ lttv_hooks_add(histo_before_trace_hooks, histo_before_trace,
+ histo_events_request, LTTV_PRIO_DEFAULT);
+
+ LttvHooks *histo_count_event_hooks = lttv_hooks_new();
+ lttv_hooks_add(histo_count_event_hooks, histo_count_event,
+ histo_events_request, LTTV_PRIO_DEFAULT);
+
+ LttvHooks *histo_after_trace_hooks = lttv_hooks_new();
+ lttv_hooks_add(histo_after_trace_hooks, histo_after_trace,
+ histo_events_request, LTTV_PRIO_DEFAULT);
+
+ //for chunk:
+ LttvHooks *histo_before_chunk_traceset = lttv_hooks_new();
+ LttvHooks *histo_after_chunk_traceset = lttv_hooks_new();
+
+ lttv_hooks_add(histo_before_chunk_traceset,
+ histo_before_chunk,
+ histo_events_request,
+ LTTV_PRIO_DEFAULT);
+
+ lttv_hooks_add(histo_after_chunk_traceset,
+ histo_after_chunk,
+ histo_events_request,
+ LTTV_PRIO_DEFAULT);
+ ts = (LttvTraceState *)tsc->traces[i];
+ // Fill the events request
+ histo_events_request->owner = histocontrol_flow_data;
+ histo_events_request->viewer_data = histocontrol_flow_data;
+ histo_events_request->servicing = FALSE;
+ histo_events_request->start_time = time_start;//time_window.start_time;
+
+ histo_events_request->start_position = NULL;
+ histo_events_request->stop_flag = FALSE;
+ histo_events_request->end_time = time_end;//time_window.end_time;
+
+ histo_events_request->num_events = G_MAXUINT;
+ histo_events_request->end_position = NULL;
+ histo_events_request->trace = i;
+ histo_events_request->hooks = NULL;
+ histo_events_request->before_chunk_traceset = histo_before_chunk_traceset;//NULL;
+ histo_events_request->before_chunk_trace = NULL;
+ histo_events_request->before_chunk_tracefile= NULL;
+ histo_events_request->event = histo_count_event_hooks;
+ histo_events_request->event_by_id = NULL;//histo_event_by_id;//NULL;
+ histo_events_request->after_chunk_tracefile = NULL;
+ histo_events_request->after_chunk_trace = NULL;
+ histo_events_request->after_chunk_traceset = histo_after_chunk_traceset;//NULL;
+ histo_events_request->before_request = histo_before_trace_hooks;
+ histo_events_request->after_request = histo_after_trace_hooks;
+
+ lttvwindow_events_request(histocontrol_flow_data->tab, histo_events_request);
+ }
+return;
+}
+
+//hook,added for histogram
+int histo_count_event(void *hook_data, void *call_data){
+
+ guint x;//time to pixel
+ guint i;// number of events
+ LttTime event_time;
+ LttEvent *e;
+ guint *element;
+
+ EventsRequest *events_request = (EventsRequest*)hook_data;
+ HistoControlFlowData *histocontrol_flow_data = events_request->viewer_data;
+
+ histoDrawing_t *drawing = histocontrol_flow_data->drawing;
+ int width = drawing->width;
+
+ g_info("Histogram: count_event() \n");
+
+
+ LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
+ LttvTracefileState *tfs = (LttvTracefileState *)call_data;
+
+ e = ltt_tracefile_get_event(tfc->tf);
+
+ LttvFilter *histo_filter = histocontrol_flow_data->histo_main_win_filter;
+ if(histo_filter != NULL && histo_filter->head != NULL)
+ if(!lttv_filter_tree_parse(histo_filter->head,e,tfc->tf,
+ tfc->t_context->t,tfc))
+ return FALSE;
+
+ TimeWindow time_window = lttvwindow_get_time_window(histocontrol_flow_data->tab);
+ event_time = ltt_event_time(e);
+
+ histo_convert_time_to_pixels(
+ time_window,
+ event_time,
+ width,
+ &x);
+ element = &g_array_index(histocontrol_flow_data->number_of_process, guint, x);
+ (*element)++;
+
+ return 0;
+}
+///befor hook:Added for histogram
+int histo_before_trace(void *hook_data, void *call_data){
+
+ EventsRequest *events_request = (EventsRequest*)hook_data;
+ HistoControlFlowData *histocontrol_flow_data = events_request->viewer_data;
+
+ histoDrawing_t *drawing = histocontrol_flow_data->drawing;
+
+//in order to reset all of the array elements.
+ guint i,end;
+ end = MIN(histocontrol_flow_data->number_of_process->len,drawing->damage_end);
+ for(i=drawing->damage_begin/*0*/;
+ i < end/*histocontrol_flow_data->number_of_process->len*/;i++)
+ {
+ g_array_index(histocontrol_flow_data->number_of_process, guint, i) = 0;
+ }
+ histo_drawing_clear(drawing,drawing->damage_begin/*0*/,
+ drawing->damage_end - drawing->damage_begin/*drawing->width*/);
+ //g_array_free(histocontrol_flow_data->number_of_process,TRUE);
+ //histocontrol_flow_data->number_of_process =g_array_new (FALSE,
+ // TRUE,
+ // sizeof(guint));//4 byte for guint
+ //g_array_set_size (histocontrol_flow_data->number_of_process,
+ // drawing->drawing_area->allocation.width);
+// gtk_widget_set_size_request(drawing->drawing_area,-1,-1);
+ gtk_widget_queue_draw(drawing->drawing_area);
+ return 0;
+}
+//after hook,added for histogram
+int histo_after_trace(void *hook_data, void *call_data){
+
+ EventsRequest *events_request = (EventsRequest*)hook_data;
+ HistoControlFlowData *histocontrol_flow_data = events_request->viewer_data;
+ histoDrawing_t *drawing = histocontrol_flow_data->drawing;
+ guint x, x_end, width;
+ LttTime end_time = events_request->end_time;
+ TimeWindow time_window =
+ lttvwindow_get_time_window(histocontrol_flow_data->tab);
+
+ g_debug("histo after trace");
+
+ histo_convert_time_to_pixels(
+ time_window,
+ end_time,
+ drawing->width,
+ &x_end);
+ x = drawing->damage_begin;
+ width = x_end - x;
+ drawing->damage_begin = x+width;
+ histogram_show (histocontrol_flow_data,x,x_end);
+
+ return 0;
+}
+
+void histogram_show(HistoControlFlowData *histocontrol_flow_data,guint draw_begin,
+ guint draw_end)
+{
+ histoDrawing_t *drawing = histocontrol_flow_data->drawing;
+ GtkWidget *drawingarea= histo_drawing_get_drawing_area(drawing);
+ guint width = drawing->width;
+ guint height= drawing->height;//drawingarea->allocation.height;
+
+ /* gdk_gc_set_line_attributes(drawing->gc,
+ 2,
+ GDK_LINE_SOLID,
+ GDK_CAP_BUTT,
+ GDK_JOIN_MITER);*/
+//clean the area!
+ histo_drawing_clear(drawing,draw_begin,draw_end);
+ LttTime t1,t2;
+ TimeWindow time_window =
+ lttvwindow_get_time_window(histocontrol_flow_data->tab);
+
+ guint val,h_val;
+
+ guint i,line_src,line_end;
+ guint end_chunk=MIN(draw_end,(histocontrol_flow_data->number_of_process)->len);
+
+ for (i=draw_begin/*0*/;i<end_chunk/* (histocontrol_flow_data->number_of_process)->len*/;i++){
+ val=g_array_index(histocontrol_flow_data->number_of_process,guint,i);
+ h_val= height-((height*val)/histocontrol_flow_data->max_height);
+
+ histo_convert_pixels_to_time(width, i,
+ time_window,
+ &t1);
+ histo_convert_pixels_to_time(width, i+1,
+ time_window,
+ &t2);
+ line_src=i;
+
+//check if zoom in is used and more than 1 pixel correspond to each 1nsec
+//used for drawing point (not line) on the screen.
+/* while (ltt_time_compare(t1,t2)==0)
+ {
+ histo_convert_pixels_to_time(width, i++,
+ time_window,
+ &t1);
+ histo_convert_pixels_to_time(width, i+1,
+ time_window,
+ &t2);
+
+
+ }//while (t1==t2)
+*/ //replaced later for lines.
+
+ if(val > drawing->histo_control_flow_data->max_height){
+ //overlimit, yellow color
+ gdk_gc_set_foreground(drawing->gc,&histo_drawing_colors[COL_WHITE] );//COL_RUN_TRAP
+ gdk_draw_line (drawing->pixmap,
+ drawing->gc,
+ i/*line_src*/,1,
+ i,/*1*/height);
+ }
+ else{
+ gdk_gc_set_foreground(drawing->gc,&histo_drawing_colors[COL_RUN_USER_MODE] );
+ gdk_draw_line (drawing->pixmap,
+ drawing->gc,
+ i/*line_src*/,h_val,
+ i,/*h_val*/height);
+ }
+
+ while ((ltt_time_compare(t1,t2)==0)&&(i<end_chunk))//-1 , i to be incremented later
+ {////
+ i++;
+
+ if(val > drawing->histo_control_flow_data->max_height){
+ //overlimit, yellow color
+ gdk_gc_set_foreground(drawing->gc,
+ &histo_drawing_colors[COL_RUN_TRAP] );
+ gdk_draw_line (drawing->pixmap,
+ drawing->gc,
+ i,1,
+ i,height);
+ }
+ else{
+ gdk_gc_set_foreground(drawing->gc,&histo_drawing_colors[COL_RUN_USER_MODE] );
+ gdk_draw_line (drawing->pixmap,
+ drawing->gc,
+ i,h_val,
+ i,height);
+ }
+ histo_convert_pixels_to_time(width, i,
+ time_window,
+ &t1);
+ if(i<end_chunk-1){
+ histo_convert_pixels_to_time(width, i+1,
+ time_window,
+ &t2);
+ }
+ }//while (t1==t2)////
+
+ }
+
+ histo_drawing_update_vertical_ruler(drawing);
+ gtk_widget_queue_draw_area ( drawing->drawing_area,
+ draw_begin, 0,
+ draw_end-draw_begin, drawing->height);
+ gdk_window_process_updates(drawingarea->window,TRUE);
+}
+
+int histo_event_selected_hook(void *hook_data, void *call_data)
+{
+ HistoControlFlowData *histocontrol_flow_data = (HistoControlFlowData*) hook_data;
+ guint *event_number = (guint*) call_data;
+
+ g_debug("DEBUG : event selected by main window : %u", *event_number);
+
+ return 0;
+}
+
+
+
+/* histo_before_schedchange_hook
+ *
+ * This function basically draw lines and icons. Two types of lines are drawn :
+ * one small (3 pixels?) representing the state of the process and the second
+ * type is thicker (10 pixels?) representing on which CPU a process is running
+ * (and this only in running state).
+ *
+ * Extremums of the lines :
+ * x_min : time of the last event context for this process kept in memory.
+ * x_max : time of the current event.
+ * y : middle of the process in the process list. The process is found in the
+ * list, therefore is it's position in pixels.
+ *
+ * The choice of lines'color is defined by the context of the last event for this
+ * process.
+ */
+
+/*
+int histo_before_schedchange_hook(void *hook_data, void *call_data)
+{
+ return 0;
+}
+*/
+
+gint histo_update_time_window_hook(void *hook_data, void *call_data)
+{
+ HistoControlFlowData *histocontrol_flow_data = (HistoControlFlowData*) hook_data;
+ histoDrawing_t *drawing = histocontrol_flow_data->drawing;
+
+ const TimeWindowNotifyData *histo_time_window_nofify_data =
+ ((const TimeWindowNotifyData *)call_data);
+
+ TimeWindow *histo_old_time_window =
+ histo_time_window_nofify_data->old_time_window;
+ TimeWindow *histo_new_time_window =
+ histo_time_window_nofify_data->new_time_window;
+
+ // Update the ruler
+ histo_drawing_update_ruler(drawing,
+ histo_new_time_window);
+
+ /* Two cases : zoom in/out or scrolling */
+
+ /* In order to make sure we can reuse the old drawing, the scale must
+ * be the same and the new time interval being partly located in the
+ * currently shown time interval. (reuse is only for scrolling)
+ */
+
+ g_info("Old time window HOOK : %lu, %lu to %lu, %lu",
+ histo_old_time_window->start_time.tv_sec,
+ histo_old_time_window->start_time.tv_nsec,
+ histo_old_time_window->time_width.tv_sec,
+ histo_old_time_window->time_width.tv_nsec);
+
+ g_info("New time window HOOK : %lu, %lu to %lu, %lu",
+ histo_new_time_window->start_time.tv_sec,
+ histo_new_time_window->start_time.tv_nsec,
+ histo_new_time_window->time_width.tv_sec,
+ histo_new_time_window->time_width.tv_nsec);
+
+ //For Histo,redraw always except if zoom fit is pushed 2 times consequently
+ if( histo_new_time_window->start_time.tv_sec == histo_old_time_window->start_time.tv_sec
+ && histo_new_time_window->start_time.tv_nsec == histo_old_time_window->start_time.tv_nsec
+ && histo_new_time_window->time_width.tv_sec == histo_old_time_window->time_width.tv_sec
+ && histo_new_time_window->time_width.tv_nsec == histo_old_time_window->time_width.tv_nsec)
+ {
+ return 0;
+ }
+ histo_rectangle_pixmap (drawing->drawing_area->style->black_gc,
+ TRUE,
+ 0, 0,
+ drawing->width,//+SAFETY, // do not overlap
+ -1,drawing);
+
+ drawing->damage_begin = 0;
+ drawing->damage_end = drawing->width;
+
+ gtk_widget_queue_draw(drawing->drawing_area);
+ histo_request_event(histocontrol_flow_data,drawing->damage_begin,
+ drawing->damage_end- drawing->damage_begin);
+
+ gdk_window_process_updates(drawing->drawing_area->window,TRUE);
+
+//show number of event at current time
+
+ histo_drawing_update_vertical_ruler(drawing);
+
+
+
+/*// if( histo_new_time_window->time_width.tv_sec == histo_old_time_window->time_width.tv_sec
+ && histo_new_time_window->time_width.tv_nsec == histo_old_time_window->time_width.tv_nsec)
+ {
+ // Same scale (scrolling)
+ g_info("scrolling");
+ /* For histogram,
+ while scrolling no matter far or near ,
+ right or left it's necessary to redraw whole screen!*/
+/*// LttTime *ns = &histo_new_time_window->start_time;
+ LttTime *nw = &histo_new_time_window->time_width;
+ LttTime *os = &histo_old_time_window->start_time;
+ LttTime *ow = &histo_old_time_window->time_width;
+ LttTime histo_old_end = histo_old_time_window->end_time;
+ LttTime histo_new_end = histo_new_time_window->end_time;
+ //if(ns<os+w<ns+w)
+ //if(ns<os+w && os+w<ns+w)
+ //if(ns<histo_old_end && os<ns)
+
+ //added for histogram
+ gtk_widget_queue_draw(drawing->drawing_area);
+
+ drawing->damage_begin = 0;
+ drawing->damage_end = drawing->width;
+
+ //replaced for hisogram
+ histo_request_event(histocontrol_flow_data,drawing->damage_begin,
+ drawing->damage_end- drawing->damage_begin);
+/*
+ if(ltt_time_compare(*ns, histo_old_end) == -1
+ && ltt_time_compare(*os, *ns) == -1)
+ {
+ g_info("scrolling near right");
+ // Scroll right, keep right part of the screen
+ guint x = 0;
+ guint width = drawing->width;
+ histo_convert_time_to_pixels(
+ *histo_old_time_window,
+ *ns,
+ width,
+ &x);
+
+ // Copy old data to new location
+ //replaced for histogram:
+ histo_copy_pixmap_region(drawing,NULL,
+ drawing->drawing_area->style->black_gc,//drawing->gc,
+ NULL,
+ x, 0,
+ 0, 0, (drawing->width-x)
+ , -1);
+
+ if(drawing->damage_begin == drawing->damage_end)
+ drawing->damage_begin = drawing->width-x;
+ else
+ drawing->damage_begin = 0;
+
+ drawing->damage_end = drawing->width;
+
+//(histo) copy corresponding array region too:
+ guint i;
+
+ for(i=0; i < histocontrol_flow_data->number_of_process->len-x;i++)
+ {
+ g_array_index(histocontrol_flow_data->number_of_process, guint, i) =
+ g_array_index(histocontrol_flow_data->number_of_process, guint, i+x);
+ }
+
+ // Clear the data request background, but not SAFETY
+
+
+//not necessary for histo, because in before chunk ,it clears the area
+/* histo_rectangle_pixmap (
+ drawing->drawing_area->style->black_gc,
+ TRUE,
+ drawing->damage_begin, 0,
+ drawing->damage_end - drawing->damage_begin, // do not overlap
+ -1,drawing);
+*/
+ /* gtk_widget_queue_draw(drawing->drawing_area);
+ //gtk_widget_queue_draw_area (drawing->drawing_area,
+ // 0,0,
+ // histocontrol_flow_data->drawing->width,
+ // histocontrol_flow_data->drawing->height);
+
+ // Get new data for the rest.
+ //replaced for hisogram
+ histo_request_event(histocontrol_flow_data,drawing->damage_begin,
+ drawing->damage_end- drawing->damage_begin);
+ } else {
+ //if(ns<os<ns+w)
+ //if(ns<os && os<ns+w)
+ //if(ns<os && os<histo_new_end)
+ if(ltt_time_compare(*ns,*os) == -1
+ && ltt_time_compare(*os,histo_new_end) == -1)
+ {
+ g_info("scrolling near left");
+ // Scroll left, keep left part of the screen
+ guint x = 0;
+ guint width = drawing->width;
+ histo_convert_time_to_pixels(
+ *histo_new_time_window,
+ *os,
+ width,
+ &x);
+
+ // Copy old data to new location
+ //replaced for histogram
+
+ histo_copy_pixmap_region(drawing,NULL,
+ drawing->drawing_area->style->black_gc,//drawing->gc,
+ NULL,
+ 0, 0,
+ x, 0, -1, -1);
+ //(histo) copy corresponding array region too:
+ guint i;
+ for(i=histocontrol_flow_data->number_of_process->len; i > x-1;i--)
+ {
+ g_array_index(histocontrol_flow_data->number_of_process, guint, i) =
+ g_array_index(histocontrol_flow_data->number_of_process, guint, i-x);
+ }
+
+ if(drawing->damage_begin == drawing->damage_end)
+ drawing->damage_end = x;
+ else
+ drawing->damage_end =
+ drawing->width;
+
+ drawing->damage_begin = 0;
+
+
+//not necessary for histo, because in before chunk ,it clears the area
+ /* histo_rectangle_pixmap (drawing->drawing_area->style->black_gc,
+ TRUE,
+ drawing->damage_begin, 0,
+ drawing->damage_end - drawing->damage_begin, // do not overlap
+ -1,drawing);
+*/
+ /* gtk_widget_queue_draw(drawing->drawing_area);
+ //gtk_widget_queue_draw_area (drawing->drawing_area,
+ // 0,0,
+ // histocontrol_flow_data->drawing->width,
+ // histocontrol_flow_data->drawing->height);
+
+
+ // Get new data for the rest.
+
+//replaced for hisogram
+ histo_request_event(histocontrol_flow_data,drawing->damage_begin,
+ drawing->damage_end- drawing->damage_begin);
+
+ } else {
+ if(ltt_time_compare(*ns,*os) == 0)
+ {
+ g_info("not scrolling");
+ } else {
+ g_info("scrolling far");
+ // Cannot reuse any part of the screen : far jump
+
+ //not necessary for histo, because in before chunk ,it clears the area
+ /* histo_rectangle_pixmap (histocontrol_flow_data->drawing->drawing_area->style->black_gc,
+ TRUE,
+ 0, 0,
+ histocontrol_flow_data->drawing->width,//+SAFETY, // do not overlap
+ -1,drawing);
+*/
+ //gtk_widget_queue_draw_area (drawing->drawing_area,
+ // 0,0,
+ // histocontrol_flow_data->drawing->width,
+ // histocontrol_flow_data->drawing->height);
+/* gtk_widget_queue_draw(drawing->drawing_area);
+
+ drawing->damage_begin = 0;
+ drawing->damage_end = histocontrol_flow_data->drawing->width;
+/*
+ histo_drawing_data_request(histocontrol_flow_data->drawing,
+ 0, 0,
+ histocontrol_flow_data->drawing->width,
+ histocontrol_flow_data->drawing->height);*/
+ //replaced for hisogram
+ /* histo_request_event(histocontrol_flow_data,drawing->damage_begin,
+ drawing->damage_end- drawing->damage_begin);
+ }
+ }
+ }
+ } else {
+ // Different scale (zoom)
+ g_info("zoom");
+
+ //not necessary for histo, because in before chunk ,it clears the area
+ /*
+ histo_rectangle_pixmap (drawing->drawing_area->style->black_gc,
+ TRUE,
+ 0, 0,
+ histocontrol_flow_data->drawing->width+SAFETY, // do not overlap
+ -1,drawing);
+*/
+ //gtk_widget_queue_draw_area (drawing->drawing_area,
+ // 0,0,
+ // histocontrol_flow_data->drawing->width,
+ // histocontrol_flow_data->drawing->height);
+/*// gtk_widget_queue_draw(drawing->drawing_area);
+
+ drawing->damage_begin = 0;
+ drawing->damage_end = drawing->width;
+
+ //replaced for hisogram
+ histo_request_event(histocontrol_flow_data,drawing->damage_begin,
+ drawing->damage_end- drawing->damage_begin);
+ }
+
+ // Update directly when scrolling
+ gdk_window_process_updates(drawing->drawing_area->window,
+ TRUE);
+
+ //show number of event at current time
+
+ histo_drawing_update_vertical_ruler(drawing);
+*/
+//disabled for histogram, always redraw whole screen.
+ return 0;
+}
+
+gint histo_traceset_notify(void *hook_data, void *call_data)
+{
+ HistoControlFlowData *histocontrol_flow_data = (HistoControlFlowData*) hook_data;
+ histoDrawing_t *drawing = histocontrol_flow_data->drawing;
+
+ if(unlikely(drawing->gc == NULL)) {
+ return FALSE;
+ }
+ if(drawing->dotted_gc == NULL) {
+ return FALSE;
+ }
+
+ histo_drawing_clear(drawing,0,drawing->width);
+
+ guint i;
+ for(i=0;i < histocontrol_flow_data->number_of_process->len;i++)
+ {
+ g_array_index(histocontrol_flow_data->number_of_process, guint, i) = 0;
+ }
+ gtk_widget_set_size_request(
+ drawing->drawing_area,
+ -1, -1);
+ histo_redraw_notify(histocontrol_flow_data, NULL);
+
+ ///histo_request_background_data(histocontrol_flow_data);
+
+ return FALSE;
+}
+
+gint histo_redraw_notify(void *hook_data, void *call_data)
+{
+ HistoControlFlowData *histocontrol_flow_data = (HistoControlFlowData*) hook_data;
+ histoDrawing_t *drawing = histocontrol_flow_data->drawing;
+ GtkWidget *widget = drawing->drawing_area;
+
+ drawing->damage_begin = 0;
+ drawing->damage_end = drawing->width;
+
+ // fun feature, to be separated someday...
+
+ histo_drawing_clear(drawing,0,drawing->width);
+
+ gtk_widget_set_size_request(
+ drawing->drawing_area,
+ -1, -1);
+ // Clear the images
+
+ histo_rectangle_pixmap (widget->style->black_gc,
+ TRUE,
+ 0, 0,
+ drawing->alloc_width,
+ -1,drawing);
+ gtk_widget_queue_draw(widget);
+
+
+ if(drawing->damage_begin < drawing->damage_end)
+ {
+ //replaced for histogram
+ histo_request_event(histocontrol_flow_data,0,drawing->width);
+ }
+
+
+ //gtk_widget_queue_draw_area(drawing->drawing_area,
+ // 0,0,
+ // drawing->width,
+ // drawing->height);
+ return FALSE;
+
+}
+
+
+gint histo_continue_notify(void *hook_data, void *call_data)
+{
+ HistoControlFlowData *histocontrol_flow_data = (HistoControlFlowData*) hook_data;
+ histoDrawing_t *drawing = histocontrol_flow_data->drawing;
+
+ //g_assert(widget->allocation.width == drawing->damage_end);
+
+ if(drawing->damage_begin < drawing->damage_end)
+ {
+ histo_request_event(histocontrol_flow_data,drawing->damage_begin,
+ drawing->damage_end-drawing->damage_begin);
+ }
+
+ return FALSE;
+}
+
+
+gint histo_update_current_time_hook(void *hook_data, void *call_data)
+{
+ HistoControlFlowData *histocontrol_flow_data = (HistoControlFlowData*)hook_data;
+ histoDrawing_t *drawing = histocontrol_flow_data->drawing;
+
+ LttTime current_time = *((LttTime*)call_data);
+
+ TimeWindow time_window =
+ lttvwindow_get_time_window(histocontrol_flow_data->tab);
+
+ LttTime time_begin = time_window.start_time;
+ LttTime width = time_window.time_width;
+ LttTime half_width;
+ {
+ guint64 time_ll = ltt_time_to_uint64(width);
+ time_ll = time_ll >> 1; /* divide by two */
+ half_width = ltt_time_from_uint64(time_ll);
+ }
+ LttTime time_end = ltt_time_add(time_begin, width);
+
+ LttvTracesetContext * tsc =
+ lttvwindow_get_traceset_context(histocontrol_flow_data->tab);
+
+ LttTime trace_start = tsc->time_span.start_time;
+ LttTime trace_end = tsc->time_span.end_time;
+
+ g_info("Histogram: New current time HOOK : %lu, %lu", current_time.tv_sec,
+ current_time.tv_nsec);
+
+
+
+ /* If current time is inside time interval, just move the highlight
+ * bar */
+
+ /* Else, we have to change the time interval. We have to tell it
+ * to the main window. */
+ /* The time interval change will take care of placing the current
+ * time at the center of the visible area, or nearest possible if we are
+ * at one end of the trace. */
+
+
+ if(ltt_time_compare(current_time, time_begin) < 0)
+ {
+ TimeWindow histo_new_time_window;
+
+ if(ltt_time_compare(current_time,
+ ltt_time_add(trace_start,half_width)) < 0)
+ time_begin = trace_start;
+ else
+ time_begin = ltt_time_sub(current_time,half_width);
+
+ histo_new_time_window.start_time = time_begin;
+ histo_new_time_window.time_width = width;
+ histo_new_time_window.time_width_double = ltt_time_to_double(width);
+ histo_new_time_window.end_time = ltt_time_add(time_begin, width);
+
+ lttvwindow_report_time_window(histocontrol_flow_data->tab, histo_new_time_window);
+ }
+ else if(ltt_time_compare(current_time, time_end) > 0)
+ {
+ TimeWindow histo_new_time_window;
+
+ if(ltt_time_compare(current_time, ltt_time_sub(trace_end, half_width)) > 0)
+ time_begin = ltt_time_sub(trace_end,width);
+ else
+ time_begin = ltt_time_sub(current_time,half_width);
+
+ histo_new_time_window.start_time = time_begin;
+ histo_new_time_window.time_width = width;
+ histo_new_time_window.time_width_double = ltt_time_to_double(width);
+ histo_new_time_window.end_time = ltt_time_add(time_begin, width);
+
+ lttvwindow_report_time_window(histocontrol_flow_data->tab, histo_new_time_window);
+
+ }
+ gtk_widget_queue_draw(drawing->drawing_area);
+
+ /* Update directly when scrolling */
+ gdk_window_process_updates(drawing->drawing_area->window,
+ TRUE);
+
+ histo_drawing_update_vertical_ruler(drawing);
+
+ return 0;
+}
+
+gboolean histo_filter_changed(void * hook_data, void * call_data)
+{
+ HistoControlFlowData *histocontrol_flow_data = (HistoControlFlowData*)hook_data;
+ histoDrawing_t *drawing =histocontrol_flow_data->drawing;
+
+ LttvTracesetContext * tsc =
+ lttvwindow_get_traceset_context(histocontrol_flow_data->tab);
+
+ histocontrol_flow_data->histo_main_win_filter =
+ (LttvFilter*)call_data;
+ //get_events(event_viewer_data->vadjust_c->value, event_viewer_data);
+ gtk_widget_set_size_request(
+ drawing->drawing_area,
+ -1, -1);
+ drawing->damage_begin = 0;
+ drawing->damage_end = drawing->width;
+
+ /* //done in, before request!
+ histo_drawing_clear(drawing,0,drawing->width);
+ guint i;
+ for(i=0;i < histocontrol_flow_data->number_of_process->len;i++)
+ {
+ g_array_index(histocontrol_flow_data->number_of_process, guint, i) = 0;
+ }*/
+
+ histo_request_event(histocontrol_flow_data,0,drawing->width);
+
+ return FALSE;
+}
+
+typedef struct _histo_ClosureData {
+ EventsRequest *events_request;
+ LttvTracesetState *tss;
+ LttTime end_time;
+ guint x_end;
+} histo_ClosureData;
+
+
+
+int histo_before_chunk(void *hook_data, void *call_data)
+{
+ EventsRequest *histo_events_request = (EventsRequest*)hook_data;
+ LttvTracesetState *histo_tss = (LttvTracesetState*)call_data;
+ HistoControlFlowData *histo_cfd = (HistoControlFlowData*)histo_events_request->viewer_data;
+#if 0
+ /* Desactivate sort */
+ gtk_tree_sortable_set_sort_column_id(
+ GTK_TREE_SORTABLE(cfd->process_list->list_store),
+ TRACE_COLUMN,
+ GTK_SORT_ASCENDING);
+#endif //0
+ histo_drawing_chunk_begin(histo_events_request, histo_tss);
+
+ return 0;
+}
+
+/*int histo_before_request(void *hook_data, void *call_data)
+{
+ EventsRequest *events_request = (EventsRequest*)hook_data;
+ LttvTracesetState *tss = (LttvTracesetState*)call_data;
+
+ histo_drawing_data_request_begin(events_request, tss);
+
+ return 0;
+}
+*/
+
+
+/*
+ * after request is necessary in addition of after chunk in order to draw
+ * lines until the end of the screen. after chunk just draws lines until
+ * the last event.
+ *
+ * for each process
+ * draw closing line
+ * expose
+ */
+/*int histo_after_request(void *hook_data, void *call_data)
+{
+ return 0;
+}
+*/
+/*
+ * for each process
+ * draw closing line
+ * expose
+ */
+
+int histo_after_chunk(void *hook_data, void *call_data)
+{
+ EventsRequest *events_request = (EventsRequest*)hook_data;
+ HistoControlFlowData *histocontrol_flow_data = events_request->viewer_data;
+ LttvTracesetState *tss = (LttvTracesetState*)call_data;
+ LttvTracesetContext *tsc = (LttvTracesetContext*)call_data;
+ LttvTracefileContext *tfc = lttv_traceset_context_get_current_tfc(tsc);
+ LttTime end_time;
+
+ histoDrawing_t *drawing = histocontrol_flow_data->drawing;
+
+ if(tfc != NULL)
+ end_time = LTT_TIME_MIN(tfc->timestamp, events_request->end_time);
+ else /* end of traceset, or position now out of request : end */
+ end_time = events_request->end_time;
+
+ guint x, x_end, width;
+
+ TimeWindow time_window =
+ lttvwindow_get_time_window(histocontrol_flow_data->tab);
+
+ g_debug("histo after chunk");
+
+ histo_convert_time_to_pixels(
+ time_window,
+ end_time,
+ drawing->width,
+ &x_end);
+ x = drawing->damage_begin;
+ width = x_end - x;
+ drawing->damage_begin = x+width;
+
+ histogram_show (histocontrol_flow_data,x,x_end);
+
+ return 0;
+}
+
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2006 Parisa heidari (inspired from CFV by Mathieu Desnoyers)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+
+/* eventhooks.h defines the hooks that are given to processTrace as parameter.
+ * These hooks call the drawing API to draw the information on the screen,
+ * using information from Context, but mostly state (running, waiting...).
+ */
+
+
+#ifndef _EVENT_HOOKS_H
+#define _EVENT_HOOKS_H
+
+#include <gtk/gtk.h>
+#include <lttvwindow/mainwindow.h>
+#include <ltt/time.h>
+
+#include "histobuttonwidget.h"
+#include "histodrawing.h"
+#include "histocfv.h"
+
+
+/* Structure used to store and use information relative to one events refresh
+ * request. Typically filled in by the expose event callback, then passed to the
+ * library call, then used by the drawing hooks. Then, once all the events are
+ * sent, it is freed by the hook called after the reading.
+ */
+//typedef struct _EventRequest
+//{
+// ControlFlowData *control_flow_data;
+// LttTime time_begin, time_end;
+// gint x_begin, x_end;
+ /* Fill the Events_Context during the initial expose, before calling for
+ * events.
+ */
+ //GArray Events_Context; //FIXME
+//} EventRequest ;
+
+
+
+
+
+void send_test_data(ButtonWidget *buttonwidget, histoDrawing_t *drawing);//??
+
+GtkWidget *h_guihistocontrolflow(Tab *tab);
+
+//GtkWidget *h_legend(Tab *tab);
+
+int histo_event_selected_hook(void *hook_data, void *call_data);
+
+/*
+ * The draw event hook is called by the reading API to have a
+ * particular event drawn on the screen.
+ * @param hook_data ControlFlowData structure of the viewer.
+ * @param call_data Event context with state.
+ *
+ * This function basically draw lines and icons. Two types of lines are drawn :
+ * one small (3 pixels?) representing the state of the process and the second
+ * type is thicker (10 pixels?) representing on which CPU a process is running
+ * (and this only in running state).
+ *
+ * Extremums of the lines :
+ * x_min : time of the last event context for this process kept in memory.
+ * x_max : time of the current event.
+ * y : middle of the process in the process list. The process is found in the
+ * list, therefore is it's position in pixels.
+ *
+ * The choice of lines'color is defined by the context of the last event for this
+ * process.
+ */
+//int histo_before_schedchange_hook(void *hook_data, void *call_data);
+int histo_after_schedchange_hook(void *hook_data, void *call_data);
+int histo_before_execmode_hook(void *hook_data, void *call_data);
+int histo_after_execmode_hook(void *hook_data, void *call_data);
+
+
+int histo_before_process_exit_hook(void *hook_data, void *call_data);
+int histo_before_process_release_hook(void *hook_data, void *call_data);
+int histo_after_process_exit_hook(void *hook_data, void *call_data);
+int histo_after_process_fork_hook(void *hook_data, void *call_data);
+int histo_after_fs_exec_hook(void *hook_data, void *call_data);
+
+
+#if 0
+int before_process_hook(void *hook_data, void *call_data);
+int after_process_hook(void *hook_data, void *call_data);
+#endif //0
+
+//void histo_draw_closure(guint key, gpointer value, gpointer user_data);
+
+int histo_before_chunk(void *hook_data, void *call_data);
+int histo_after_chunk(void *hook_data, void *call_data);
+//int histo_before_request(void *hook_data, void *call_data);
+//int histo_after_request(void *hook_data, void *call_data);
+
+
+
+gint histo_update_time_window_hook(void *hook_data, void *call_data);
+gint histo_update_current_time_hook(void *hook_data, void *call_data);
+gint histo_traceset_notify(void *hook_data, void *call_data);
+gint histo_redraw_notify(void *hook_data, void *call_data);
+gint histo_continue_notify(void *hook_data, void *call_data);
+
+//just for histogram
+void histo_request_event( HistoControlFlowData *histocontrol_flow_data,guint x, guint width);
+int histo_count_event(void *hook_data, void *call_data);
+int histo_before_trace(void *hook_data, void *call_data);//replaced for histo_before_request
+int histo_after_trace(void *hook_data, void *call_data);//replaced for histo_after_request
+
+gboolean histo_filter_changed(void * hook_data, void * call_data);
+
+void histogram_show(HistoControlFlowData *histocontrol_flow_data,guint draw_begin,guint draw_end);
+#endif // _EVENT_HOOKS_H
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2006 Parisa heidari (inspired from CFV by Mathieu Desnoyers)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <lttv/lttv.h>
+#include <lttv/module.h>
+#include <lttvwindow/lttvwindow.h>
+
+#include "histocfv.h"
+#include "histoeventhooks.h"
+
+#include "hHistogramInsert.xpm"
+
+
+GQuark LTT_NAME_CPU;
+
+/** Array containing instanced objects. Used when module is unloaded */
+GSList *g_histo_control_flow_data_list = NULL ;
+
+/*****************************************************************************
+ * Functions for module loading/unloading *
+ *****************************************************************************/
+/**
+ * plugin's init function
+ *
+ * This function initializes the Histogram Control Flow Viewer functionnality through the
+ * gtkTraceSet API.
+ */
+static void histo_init() {
+
+ g_info("GUI ControlFlow Viewer init()");
+
+ /* Register the toolbar insert button and menu entry*/
+ lttvwindow_register_constructor("histogram",
+ "/",
+ "Insert Histogram Viewer",
+ hHistogramInsert_xpm,
+ "Insert Histogram Viewer",
+ h_guihistocontrolflow);
+
+ LTT_NAME_CPU = g_quark_from_string("/cpu");
+}
+
+void histo_destroy_walk(gpointer data, gpointer user_data)
+{
+ g_info("Walk destroy GUI Histogram Control Flow Viewer");
+ guihistocontrolflow_destructor_full((HistoControlFlowData*)data);
+}
+
+
+
+/**
+ * plugin's destroy function
+ *
+ * This function releases the memory reserved by the module and unregisters
+ * everything that has been registered in the gtkTraceSet API.
+ */
+static void histo_destroy() {
+ g_info("GUI Histogram Control Flow Viewer destroy()");
+
+ g_slist_foreach(g_histo_control_flow_data_list, histo_destroy_walk, NULL );
+
+ g_slist_free(g_histo_control_flow_data_list);
+
+ /* Unregister the toolbar insert button and menu entry */
+ lttvwindow_unregister_constructor(h_guihistocontrolflow);
+
+}
+
+
+LTTV_MODULE("guihistogram", "Event Histogram viewer", \
+ "Graphical module to view events' density histogram", \
+ histo_init, histo_destroy, "lttvwindow")
--- /dev/null
+/* XPM */
+static char *stock_zoom_fit_24[]={
+"24 24 189 2",
+"Qt c None",
+"ae c #000000",
+"aF c #000000",
+"an c #050505",
+".U c #242424",
+".s c #373737",
+".G c #4f4f4f",
+".h c #5d5d5d",
+"aS c #000000",
+"a6 c #000000",
+"at c #000000",
+"aQ c #000000",
+"ad c #000000",
+"au c #030303",
+"#8 c #0c0c0c",
+"#j c #121212",
+".F c #232323",
+"#. c #303030",
+".g c #353535",
+".t c #404040",
+".# c #494949",
+"aE c #000000",
+"#7 c #000000",
+"#s c #090909",
+"#1 c #0a0a0a",
+"#k c #1b1b1b",
+".f c #262626",
+".a c #343434",
+"am c #000000",
+"aG c #010101",
+"af c #060606",
+".9 c #0f0f0f",
+".r c #1c1c1c",
+".V c #212121",
+".i c #2e2e2e",
+"aR c #000000",
+"#0 c #020202",
+"#A c #060606",
+"#V c #0b0b0b",
+"#t c #141414",
+".e c #262626",
+".b c #2d2d2d",
+"aN c #000000",
+"a4 c #000000",
+"aW c #000000",
+"aO c #000000",
+"aC c #000000",
+"aD c #000000",
+"aP c #000000",
+"aT c #202020",
+"a1 c #000000",
+"aU c #202020",
+"aV c #000000",
+"aY c #343434",
+"a2 c #000000",
+"as c #000000",
+"av c #030303",
+"#U c #050505",
+"#J c #060606",
+"#K c #0e0e0e",
+".T c #101010",
+"#B c #111111",
+".E c #131313",
+"a3 c #1f1f1f",
+".H c #222222",
+".d c #262626",
+".u c #272727",
+".c c #292929",
+"aX c #686868",
+"a0 c #3a3a3a",
+"a5 c #000000",
+"aZ c #797979",
+"aM c #000000",
+"ac c #020202",
+"aH c #030303",
+"#9 c #0a0a0a",
+"#i c #0e0e0e",
+"## c #1f1f1f",
+".q c #202020",
+"aB c #2b2b2b",
+"al c #2e2e2e",
+".j c #303030",
+"aw c #313131",
+"ag c #3b3b3b",
+"aL c #3c3c3c",
+"aj c #414141",
+".8 c #434343",
+"ai c #444444",
+"aa c #454545",
+".Y c #464646",
+"a# c #474747",
+"#5 c #484848",
+"a. c #494949",
+".6 c #4a4a4a",
+".Z c #4b4b4b",
+".D c #4c4c4c",
+"#f c #4d4d4d",
+"#p c #4e4e4e",
+".5 c #4f4f4f",
+".0 c #505050",
+".4 c #515151",
+".1 c #525252",
+"#c c #535353",
+"#r c #575757",
+".W c #5b5b5b",
+".S c #5e5e5e",
+"#2 c #5f5f5f",
+".v c #616161",
+".p c #676767",
+"#l c #6d6d6d",
+".k c #737373",
+".I c #757575",
+"aK c #777777",
+"aI c #7a7a7a",
+"aA c #909090",
+"#Z c #939393",
+"ax c #999999",
+"aJ c #9a9a9a",
+"#z c #9b9b9b",
+".o c #9d9d9d",
+".l c #a1a1a1",
+"#W c #a5a5a5",
+".C c #a7a7a7",
+"#u c #a8a8a8",
+"#h c #ababab",
+".n c #b2b2b2",
+".m c #b4b4b4",
+"az c #b6b6b6",
+"ar c #b8b8b8",
+"#a c #b9b9b9",
+"#T c #bababa",
+"ay c #bbbbbb",
+".R c #bcbcbc",
+"ak c #bdbdbd",
+"#I c #bfbfbf",
+".B c #c1c1c1",
+".7 c #c2c2c2",
+"#C c #c5c5c5",
+"#L c #c6c6c6",
+"ao c #c7c7c7",
+"aq c #c8c8c8",
+".A c #c9c9c9",
+".w c #cacaca",
+"ab c #cbcbcb",
+".X c #cccccc",
+"ap c #cdcdcd",
+".z c #cecece",
+".x c #cfcfcf",
+".y c #d0d0d0",
+"#Y c #d1d1d1",
+".Q c #d2d2d2",
+".J c #d3d3d3",
+"#6 c #d4d4d4",
+"#b c #d6d6d6",
+"#S c #d7d7d7",
+"#v c #d8d8d8",
+"#3 c #d9d9d9",
+"ah c #dadada",
+".K c #dbdbdb",
+"#y c #dcdcdc",
+"#D c #dfdfdf",
+"#R c #e0e0e0",
+"#m c #e1e1e1",
+"#M c #e3e3e3",
+"#g c #e4e4e4",
+".P c #e5e5e5",
+"#q c #e6e6e6",
+".L c #e7e7e7",
+"#4 c #e9e9e9",
+"#Q c #eaeaea",
+"#N c #ececec",
+"#H c #ededed",
+"#w c #eeeeee",
+".M c #efefef",
+"#P c #f0f0f0",
+".O c #f1f1f1",
+"#G c #f2f2f2",
+".N c #f3f3f3",
+"#O c #f4f4f4",
+"#E c #f5f5f5",
+"#X c #f6f6f6",
+"#F c #f7f7f7",
+"#x c #f8f8f8",
+"#o c #f9f9f9",
+".3 c #fafafa",
+".2 c #fbfbfb",
+"#e c #fcfcfc",
+"#d c #fdfdfd",
+"#n c #fefefe",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQt.#.a.b.c.d.e.f.gQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQt.h.i.j.k.l.m.n.o.p.q.r.sQtQtQtQtQtQtQtQt",
+"QtQtQt.t.u.v.m.w.x.y.z.A.B.C.D.E.FQtQtQtQtQtQtQt",
+"QtQt.G.H.I.w.J.K.L.M.N.O.P.Q.R.S.T.UQtQtQtQtQtQt",
+"QtQt.V.W.X.Y.Z.0.1.2.3.4.0.5.6.7.8.9QtQtQtQtQtQt",
+"Qt#.###a#b.D.1.1#c#d#e.1.4.5#f#g#h#i#jQtQtQtQtQt",
+"Qt#k#l.Q#m.0.1#d#n#n#d#e#o.0#p#q.K#r#sQtQtQtQtQt",
+"Qt#t#u#v#w.4.1#e#n#n#d.2#x.0#p#q#y#z#AQtQtQtQtQt",
+"Qt#B#C#D.M#E#x.2#d#d#e.3#F#G#H.P.K#I#JQtQtQtQtQt",
+"Qt#K#L#M#N#G#E#x.3.3.3#F#O#P#Q#R#S#T#UQtQtQtQtQt",
+"Qt#V#W#m.L#p.5#O#X#X#E.N.M#f.Z.K#Y#Z#0QtQtQtQtQt",
+"Qt#1#2#3#m.Z#f#w.M.M#w#H#4.Z#5#6.w.D#7QtQtQtQtQt",
+"Qt#8#9.m#v#5.6.Z.Z#q.L.6a.a#aaab.lacadQtQtQtQtQt",
+"Qtaeafag.Xaaaaa##5ah.Ka#.YaiajakalamQtQtQtQtQtQt",
+"QtQtan#U.4.7aoab.Xapababaq.7araaasatQtQtQtQtQtQt",
+"QtQtaeauavawaxayak.R.R.RazaAaBasaCaDaEQtQtQtQtQt",
+"QtQtQtaeaFaGaHajaIaJaJaKaLaMamaFaNaOaPaNaQQtQtQt",
+"QtQtQtQtQtaead#7aRasasaR#7adaSaeaeaTaUaVaCaSQtQt",
+"QtQtQtQtQtQtQtaeaeaeaeaeaeaeQtQtaeaWaXaYaDaVaeQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtaeaPaZa0aPa1ae",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtaeaea2aXa3a1ae",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtaeaea4a5a6ae",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtaeaeaeQtQt"};
--- /dev/null
+/* XPM */
+static char *stock_zoom_in_24[]={
+"24 24 142 2",
+"Qt c None",
+"#V c #000000",
+"ae c #010101",
+"#O c #020202",
+"#9 c #030303",
+"#J c #050505",
+"#v c #060606",
+"#n c #090909",
+"#P c #0a0a0a",
+"#K c #0b0b0b",
+"#W c #0c0c0c",
+"#e c #0e0e0e",
+".5 c #0f0f0f",
+".R c #101010",
+"#w c #111111",
+"#f c #121212",
+".C c #131313",
+"#o c #141414",
+"#g c #1b1b1b",
+".p c #1c1c1c",
+".6 c #1f1f1f",
+".o c #202020",
+".T c #212121",
+".F c #222222",
+".D c #232323",
+".S c #242424",
+".d c #262626",
+".s c #272727",
+".c c #292929",
+"ad c #2b2b2b",
+".b c #2d2d2d",
+".g c #2e2e2e",
+".h c #303030",
+"a. c #313131",
+".a c #343434",
+".e c #353535",
+".q c #373737",
+"al c #3a3a3a",
+"#1 c #3b3b3b",
+"ai c #3c3c3c",
+"#Y c #3f3f3f",
+".r c #404040",
+"#F c #414141",
+"#A c #424242",
+".4 c #434343",
+"#z c #444444",
+"## c #454545",
+".# c #494949",
+".B c #4c4c4c",
+".E c #4f4f4f",
+"#5 c #515151",
+"#m c #575757",
+".U c #5b5b5b",
+".f c #5d5d5d",
+".Q c #5e5e5e",
+"#Q c #5f5f5f",
+".t c #616161",
+".n c #676767",
+"aj c #686868",
+"#h c #6d6d6d",
+".i c #737373",
+".G c #757575",
+"ah c #777777",
+"ak c #797979",
+"af c #7a7a7a",
+"ac c #909090",
+"#N c #939393",
+"a# c #999999",
+"ag c #9a9a9a",
+"#u c #9b9b9b",
+".m c #9d9d9d",
+".j c #a1a1a1",
+"#L c #a5a5a5",
+".A c #a7a7a7",
+"#p c #a8a8a8",
+"#d c #ababab",
+".l c #b2b2b2",
+".k c #b4b4b4",
+"ab c #b6b6b6",
+"#8 c #b8b8b8",
+".7 c #b9b9b9",
+"#I c #bababa",
+"aa c #bbbbbb",
+".P c #bcbcbc",
+"#4 c #bdbdbd",
+"#C c #bfbfbf",
+".z c #c1c1c1",
+".3 c #c2c2c2",
+"#x c #c5c5c5",
+"#D c #c6c6c6",
+"#6 c #c7c7c7",
+"#3 c #c8c8c8",
+".y c #c9c9c9",
+".u c #cacaca",
+"#0 c #cbcbcb",
+".V c #cccccc",
+"#7 c #cdcdcd",
+".x c #cecece",
+".v c #cfcfcf",
+".w c #d0d0d0",
+"#M c #d1d1d1",
+".O c #d2d2d2",
+".H c #d3d3d3",
+"#U c #d4d4d4",
+"#2 c #d5d5d5",
+".8 c #d6d6d6",
+".W c #d7d7d7",
+"#q c #d8d8d8",
+"#R c #d9d9d9",
+"#Z c #dadada",
+".I c #dbdbdb",
+"#t c #dcdcdc",
+"#y c #dfdfdf",
+"#H c #e0e0e0",
+".2 c #e1e1e1",
+"#X c #e2e2e2",
+"#E c #e3e3e3",
+"#c c #e4e4e4",
+".N c #e5e5e5",
+"#l c #e6e6e6",
+".J c #e7e7e7",
+"#T c #e9e9e9",
+"#G c #eaeaea",
+"#S c #ebebeb",
+"#b c #ececec",
+"#B c #ededed",
+"#k c #eeeeee",
+".K c #efefef",
+".1 c #f0f0f0",
+".M c #f1f1f1",
+"#a c #f2f2f2",
+".L c #f3f3f3",
+"#s c #f4f4f4",
+".X c #f5f5f5",
+"#r c #f6f6f6",
+".0 c #f8f8f8",
+".9 c #f9f9f9",
+".Y c #fafafa",
+".Z c #fbfbfb",
+"#j c #fcfcfc",
+"#. c #fdfdfd",
+"#i c #fefefe",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQt.#.a.b.c.d.d.d.eQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQt.f.g.h.i.j.k.l.m.n.o.p.qQtQtQtQtQtQtQtQt",
+"QtQtQt.r.s.t.k.u.v.w.x.y.z.A.B.C.DQtQtQtQtQtQtQt",
+"QtQt.E.F.G.u.H.I.J.K.L.M.N.O.P.Q.R.SQtQtQtQtQtQt",
+"QtQt.T.U.V.W.N.X.Y.Z.Y.0.X.1.2.3.4.5QtQtQtQtQtQt",
+"Qt.h.6.7.8.J.9.Z#.####.Z.0#a#b#c#d#e#fQtQtQtQtQt",
+"Qt#g#h.O.2.X.Y#.#i#####j.9.X#k#l.I#m#nQtQtQtQtQt",
+"Qt#o#p#q#k#r.9#j#i####.Z.0#s#k#l#t#u#vQtQtQtQtQt",
+"Qt#w#x#y.K.X#z#z#######z.4#A#B.N.I#C#vQtQtQtQtQt",
+"Qt#e#D#E#b#a.4#z#z#z#z.4#A#F#G#H.W#I#JQtQtQtQtQt",
+"Qt#K#L.2.J#B.M#s#r.4.4.L.K#b#c.I#M#N#OQtQtQtQtQt",
+"Qt#P#Q#R.2#l#S#k.K#F#F#B#T#c.I#U.u.B#VQtQtQtQtQt",
+"Qt#W#P.k#q#t#X.N#l#Y#Y#E#y#Z#U#0.j#O#VQtQtQtQtQt",
+"Qt#V#v#1.V.O#U#Z.I#Z.I#q#2.w#3#4.g#VQtQtQtQtQtQt",
+"QtQt#J#J#5.3#6#0.V#7#0#0#3.3#8###V#VQtQtQtQtQtQt",
+"QtQt#V#9#9a.a#aa#4.P.P.Pabacad#V#V#V#VQtQtQtQtQt",
+"QtQtQt#V#Vae#9#Fafagagahai#V#V#V#V#V#V#V#VQtQtQt",
+"QtQtQtQtQt#V#V#V#V#V#V#V#V#V#V#V#V.o.o#V#V#VQtQt",
+"QtQtQtQtQtQtQt#V#V#V#V#V#V#VQtQt#V#Vaj.a#V#V#VQt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt#V#Vakal#V#V#V",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt#V#V#Vaj.6#V#V",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt#V#V#V#V#V#V",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt#V#V#VQtQt"};
--- /dev/null
+/* XPM */
+static char *stock_zoom_out_24[]={
+"24 24 180 2",
+"Qt c None",
+"#8 c #000000",
+"aw c #000000",
+"ae c #050505",
+".U c #242424",
+".s c #373737",
+".G c #4f4f4f",
+".h c #5d5d5d",
+"aJ c #000000",
+"aX c #000000",
+"ak c #000000",
+"aH c #000000",
+"#7 c #000000",
+"al c #030303",
+"#1 c #0c0c0c",
+"#i c #121212",
+".F c #232323",
+".8 c #303030",
+".g c #353535",
+".t c #404040",
+".# c #494949",
+"av c #000000",
+"#0 c #000000",
+"#p c #090909",
+"#U c #0a0a0a",
+"#j c #1b1b1b",
+".f c #262626",
+".a c #343434",
+"ad c #000000",
+"ax c #010101",
+"#9 c #060606",
+".7 c #0f0f0f",
+".r c #1c1c1c",
+".V c #212121",
+".i c #2e2e2e",
+"aI c #000000",
+"#T c #020202",
+"#x c #060606",
+"#P c #0b0b0b",
+"#q c #141414",
+".e c #262626",
+".b c #2d2d2d",
+"aE c #000000",
+"aV c #000000",
+"aN c #000000",
+"aF c #000000",
+"at c #000000",
+"au c #000000",
+"aG c #000000",
+"aK c #202020",
+"aS c #000000",
+"aL c #202020",
+"aM c #000000",
+"aP c #343434",
+"aT c #000000",
+"aj c #000000",
+"am c #030303",
+"#O c #050505",
+"#G c #060606",
+"#H c #0e0e0e",
+".T c #101010",
+"#y c #111111",
+".E c #131313",
+"aU c #1f1f1f",
+".H c #222222",
+".d c #262626",
+".u c #272727",
+".c c #292929",
+"aO c #686868",
+"aR c #3a3a3a",
+"aW c #000000",
+"aQ c #797979",
+"aD c #000000",
+"#6 c #020202",
+"ay c #030303",
+"#2 c #0a0a0a",
+"#h c #0e0e0e",
+".9 c #1f1f1f",
+".q c #202020",
+"as c #2b2b2b",
+"ac c #2e2e2e",
+".j c #303030",
+"an c #313131",
+"a. c #3b3b3b",
+"aC c #3c3c3c",
+"#K c #414141",
+"#D c #424242",
+".6 c #434343",
+"#B c #444444",
+"#C c #454545",
+".D c #4c4c4c",
+"af c #515151",
+"#o c #575757",
+".W c #5b5b5b",
+".S c #5e5e5e",
+"#V c #5f5f5f",
+".v c #616161",
+".p c #676767",
+"#k c #6d6d6d",
+".k c #737373",
+".I c #757575",
+"aB c #777777",
+"az c #7a7a7a",
+"ar c #909090",
+"#S c #939393",
+"ao c #999999",
+"aA c #9a9a9a",
+"#w c #9b9b9b",
+".o c #9d9d9d",
+".l c #a1a1a1",
+"#Q c #a5a5a5",
+".C c #a7a7a7",
+"#r c #a8a8a8",
+"#g c #ababab",
+".n c #b2b2b2",
+".m c #b4b4b4",
+"aq c #b6b6b6",
+"ai c #b8b8b8",
+"#. c #b9b9b9",
+"#N c #bababa",
+"ap c #bbbbbb",
+".R c #bcbcbc",
+"ab c #bdbdbd",
+"#F c #bfbfbf",
+".B c #c1c1c1",
+".5 c #c2c2c2",
+"#z c #c5c5c5",
+"#I c #c6c6c6",
+"ag c #c7c7c7",
+"aa c #c8c8c8",
+".A c #c9c9c9",
+".w c #cacaca",
+"#5 c #cbcbcb",
+".X c #cccccc",
+"ah c #cdcdcd",
+".z c #cecece",
+".x c #cfcfcf",
+".y c #d0d0d0",
+"#R c #d1d1d1",
+".Q c #d2d2d2",
+".J c #d3d3d3",
+"#Z c #d4d4d4",
+"a# c #d5d5d5",
+"## c #d6d6d6",
+".Y c #d7d7d7",
+"#s c #d8d8d8",
+"#W c #d9d9d9",
+"#4 c #dadada",
+".K c #dbdbdb",
+"#v c #dcdcdc",
+"#A c #dfdfdf",
+"#M c #e0e0e0",
+".4 c #e1e1e1",
+"#3 c #e2e2e2",
+"#J c #e3e3e3",
+"#f c #e4e4e4",
+".P c #e5e5e5",
+"#n c #e6e6e6",
+".L c #e7e7e7",
+"#Y c #e9e9e9",
+"#L c #eaeaea",
+"#X c #ebebeb",
+"#e c #ececec",
+"#E c #ededed",
+"#m c #eeeeee",
+".M c #efefef",
+".3 c #f0f0f0",
+".O c #f1f1f1",
+"#d c #f2f2f2",
+".N c #f3f3f3",
+"#u c #f4f4f4",
+".Z c #f5f5f5",
+"#t c #f6f6f6",
+".2 c #f8f8f8",
+"#a c #f9f9f9",
+".0 c #fafafa",
+".1 c #fbfbfb",
+"#c c #fcfcfc",
+"#b c #fdfdfd",
+"#l c #fefefe",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQtQtQt.#.a.b.c.d.e.f.gQtQtQtQtQtQtQtQtQtQt",
+"QtQtQtQt.h.i.j.k.l.m.n.o.p.q.r.sQtQtQtQtQtQtQtQt",
+"QtQtQt.t.u.v.m.w.x.y.z.A.B.C.D.E.FQtQtQtQtQtQtQt",
+"QtQt.G.H.I.w.J.K.L.M.N.O.P.Q.R.S.T.UQtQtQtQtQtQt",
+"QtQt.V.W.X.Y.P.Z.0.1.0.2.Z.3.4.5.6.7QtQtQtQtQtQt",
+"Qt.8.9#.##.L#a.1#b#b#c.1.2#d#e#f#g#h#iQtQtQtQtQt",
+"Qt#j#k.Q.4.Z.0#b#l#l#b#c#a.Z#m#n.K#o#pQtQtQtQtQt",
+"Qt#q#r#s#m#t#a#c#l#l#b.1.2#u#m#n#v#w#xQtQtQtQtQt",
+"Qt#y#z#A.M.Z#B#B#C#C#C#B.6#D#E.P.K#F#GQtQtQtQtQt",
+"Qt#H#I#J#e#d.6#B#B#B#B.6#D#K#L#M.Y#N#OQtQtQtQtQt",
+"Qt#P#Q.4.L#E.O#u#t#t.Z.N.M#e#f.K#R#S#TQtQtQtQtQt",
+"Qt#U#V#W.4#n#X#m.M.M#m#E#Y#f.K#Z.w.D#0QtQtQtQtQt",
+"Qt#1#2.m#s#v#3.P#n#n.L#J#A#4#Z#5.l#6#7QtQtQtQtQt",
+"Qt#8#9a..X.Q#Z#4.K#4.K#sa#.yaaabacadQtQtQtQtQtQt",
+"QtQtae#Oaf.5ag#5.Xah#5#5aa.5ai#CajakQtQtQtQtQtQt",
+"QtQt#8alamanaoapab.R.R.RaqarasajatauavQtQtQtQtQt",
+"QtQtQt#8awaxay#KazaAaAaBaCaDadawaEaFaGaEaHQtQtQt",
+"QtQtQtQtQt#8#7#0aIajajaI#0#7aJ#8#8aKaLaMataJQtQt",
+"QtQtQtQtQtQtQt#8#8#8#8#8#8#8QtQt#8aNaOaPauaM#8Qt",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt#8aGaQaRaGaS#8",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt#8#8aTaOaUaS#8",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt#8#8aVaWaX#8",
+"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt#8#8#8QtQt"};