static void gtk_math_view_clicked(GtkMathView*, GdomeNode*); static void gtk_math_view_selection_changed(GtkMathView*, GdomeNode*); static void gtk_math_view_element_changed(GtkMathView*, GdomeNode*);
static void gtk_math_view_clicked(GtkMathView*, GdomeElement*); static void gtk_math_view_selection_changed(GtkMathView*, GdomeElement*); static void gtk_math_view_element_changed(GtkMathView*, GdomeElement*);
static void gtk_math_view_destroy(GtkObject*);/* GtkWidget functions */static gboolean gtk_math_view_configure_event(GtkWidget*, GdkEventConfigure*, GtkMathView*);static gboolean gtk_math_view_expose_event(GtkWidget*, GdkEventExpose*, GtkMathView*);static gboolean gtk_math_view_button_press_event(GtkWidget*, GdkEventButton*, GtkMathView*);static gboolean gtk_math_view_button_release_event(GtkWidget*, GdkEventButton*, GtkMathView*);static gboolean gtk_math_view_motion_notify_event(GtkWidget*, GdkEventMotion*, GtkMathView*);static gboolean gtk_math_view_key_press_event(GtkWidget*, GdkEventKey*, GtkMathView*);static void     gtk_math_view_realize(GtkWidget*, GtkMathView*);static void     gtk_math_view_size_request(GtkWidget*, GtkRequisition*);/* GtkMathView signals */#if defined(HAVE_MINIDOM)static void gtk_math_view_clicked(GtkMathView*, mDOMNodeRef);static void gtk_math_view_selection_changed(GtkMathView*, mDOMNodeRef);static void gtk_math_view_element_changed(GtkMathView*, mDOMNodeRef);#elif defined(HAVE_GMETADOM)static void gtk_math_view_clicked(GtkMathView*, GdomeNode*);static void gtk_math_view_selection_changed(GtkMathView*, GdomeNode*);static void gtk_math_view_element_changed(GtkMathView*, GdomeNode*);#endif/* auxiliary functions */static void setup_adjustment(GtkAdjustment*, gfloat, gfloat);static void setup_adjustments(GtkMathView*);static void reset_adjustments(GtkMathView*);/* Local data */static GtkEventBoxClass* parent_class = NULL;static guint clicked_signal = 0;static guint selection_changed_signal = 0;static guint element_changed_signal = 0;static guint action_changed_signal = 0;/* widget implementation */static voidpaint_widget_area(GtkMathView* math_view, gint x, gint y, gint width, gint height){  GtkWidget* widget;  g_return_if_fail(math_view != NULL);  g_return_if_fail(math_view->area != NULL);  g_return_if_fail(math_view->interface != NULL);  widget = math_view->area;  gdk_draw_rectangle(math_view->pixmap, widget->style->white_gc, TRUE, x, y, width, height);  Rectangle rect;  rect.x = px2sp(x) + float2sp(math_view->top_x);  rect.y = px2sp(y) + float2sp(math_view->top_y);  rect.width = px2sp(width);  rect.height = px2sp(height);  math_view->interface->Render(&rect);}static voidpaint_widget(GtkMathView* math_view){  GtkWidget* widget;  g_return_if_fail(math_view != NULL);  g_return_if_fail(math_view->area != NULL);  widget = math_view->area;  paint_widget_area(math_view, 0, 0, widget->allocation.width, widget->allocation.height);}static voidhadjustment_value_changed(GtkAdjustment* adj, GtkMathView* math_view){  g_return_if_fail(adj != NULL);  g_return_if_fail(math_view != NULL);  g_return_if_fail(math_view->drawing_area != NULL);  if (adj->value > adj->upper - adj->page_size) adj->value = adj->upper - adj->page_size;  if (adj->value < adj->lower) adj->value = adj->lower;  math_view->old_top_x = math_view->top_x;  math_view->top_x = adj->value;  math_view->drawing_area->SetTopX(float2sp(adj->value));  if (math_view->old_top_x != math_view->top_x) {#if 0    gint change = sp2ipx(float2sp(fabs(math_view->old_top_x - math_view->top_x)));    GtkWidget* widget = math_view->area;    if (change < widget->allocation.width) {      if (math_view->old_top_x < math_view->top_x) {	// the window scrolled right	gdk_draw_pixmap(math_view->pixmap,			widget->style->white_gc,			math_view->pixmap,			change, 0, 0, 0,			widget->allocation.width - change,			widget->allocation.height);	paint_widget_area(math_view,			  widget->allocation.width - change, 0,			  change, widget->allocation.height);      } else {	// the window scrolled left	gdk_draw_pixmap(math_view->pixmap,			widget->style->white_gc,			math_view->pixmap,			0, 0, change, 0,			widget->allocation.width - change,			widget->allocation.height);	paint_widget_area(math_view,			  0, 0,			  change, widget->allocation.height);      }            gtk_widget_draw(math_view->area, NULL);    } else#endif      paint_widget(math_view);  }}static voidvadjustment_value_changed(GtkAdjustment* adj, GtkMathView* math_view){  g_return_if_fail(adj != NULL);  g_return_if_fail(math_view != NULL);  if (adj->value > adj->upper - adj->page_size) adj->value = adj->upper - adj->page_size;  if (adj->value < adj->lower) adj->value = adj->lower;  math_view->old_top_y = math_view->top_y;  math_view->top_y = adj->value;  math_view->drawing_area->SetTopY(float2sp(adj->value));    if (math_view->old_top_y != math_view->top_y) {#if 0    gint change = sp2ipx(float2sp(fabs(math_view->old_top_y - math_view->top_y)));    GtkWidget* widget = math_view->area;    if (change < widget->allocation.height) {      if (math_view->old_top_y < math_view->top_y) {	// the window scrolled down	gdk_draw_pixmap(math_view->pixmap,			widget->style->white_gc,			math_view->pixmap,			0, change, 0, 0,			widget->allocation.width,			widget->allocation.height - change);	paint_widget_area(math_view,			  0, widget->allocation.height - change,			  widget->allocation.width, change);      } else {	// the window scrolled up	gdk_draw_pixmap(math_view->pixmap,			widget->style->white_gc,			math_view->pixmap,			0, 0, 0, change,			widget->allocation.width,			widget->allocation.height - change);	paint_widget_area(math_view,			  0, 0,			  widget->allocation.width, change);      }      gtk_widget_draw(math_view->area, NULL);    } else#endif      paint_widget(math_view);  }}extern "C" GtkTypegtk_math_view_get_type(){  static guint math_view_type = 0;  if (math_view_type == 0) {    GtkTypeInfo math_view_info = {      "GtkMathView",      sizeof(GtkMathView),      sizeof(GtkMathViewClass),      (GtkClassInitFunc) gtk_math_view_class_init,      (GtkObjectInitFunc) gtk_math_view_init,      NULL,      NULL,      NULL    };    math_view_type = gtk_type_unique(gtk_event_box_get_type(), &math_view_info);  }  return math_view_type;}static voidgtk_math_view_class_init(GtkMathViewClass* klass){  GtkObjectClass* object_class = (GtkObjectClass*) klass;  GtkWidgetClass* widget_class = (GtkWidgetClass*) klass;  klass->clicked            = gtk_math_view_clicked;  klass->selection_changed  = gtk_math_view_selection_changed;  klass->element_changed    = gtk_math_view_element_changed;  klass->set_scroll_adjustments = gtk_math_view_set_adjustments;  parent_class = (GtkEventBoxClass*) gtk_type_class(gtk_event_box_get_type());  object_class->destroy = gtk_math_view_destroy;  widget_class->size_request = gtk_math_view_size_request;  widget_class->set_scroll_adjustments_signal =    gtk_signal_new("set_scroll_adjustments",		   GTK_RUN_LAST,		   object_class->type,		   GTK_SIGNAL_OFFSET (GtkMathViewClass, set_scroll_adjustments),		   gtk_marshal_NONE__POINTER_POINTER,		   GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);  clicked_signal =    gtk_signal_new("clicked",		   GTK_RUN_FIRST,		   object_class->type,		   GTK_SIGNAL_OFFSET (GtkMathViewClass, clicked),		   gtk_marshal_NONE__POINTER,		   GTK_TYPE_NONE, 1, GTK_TYPE_POINTER);  gtk_object_class_add_signals(object_class, &clicked_signal, 1);  selection_changed_signal =    gtk_signal_new("selection_changed",		   GTK_RUN_FIRST,		   object_class->type,		   GTK_SIGNAL_OFFSET (GtkMathViewClass, selection_changed),		   gtk_marshal_NONE__POINTER,		   GTK_TYPE_NONE, 1, GTK_TYPE_POINTER);  gtk_object_class_add_signals(object_class, &selection_changed_signal, 1);  element_changed_signal =    gtk_signal_new("element_changed",		   GTK_RUN_FIRST,		   object_class->type,		   GTK_SIGNAL_OFFSET (GtkMathViewClass, element_changed),		   gtk_marshal_NONE__POINTER,		   GTK_TYPE_NONE, 1, GTK_TYPE_POINTER);  gtk_object_class_add_signals(object_class, &element_changed_signal, 1);  action_changed_signal =    gtk_signal_new("action_changed",		   GTK_RUN_FIRST,		   object_class->type,		   GTK_SIGNAL_OFFSET (GtkMathViewClass, action_changed),		   gtk_marshal_NONE__POINTER,		   GTK_TYPE_NONE, 1, GTK_TYPE_POINTER);  gtk_object_class_add_signals(object_class, &action_changed_signal, 1);  MathEngine::InitGlobalData(getenv("MATHENGINECONF"));}static voidgtk_math_view_init(GtkMathView* math_view){  g_return_if_fail(math_view != NULL);  math_view->pixmap          = NULL;  math_view->font_manager_id = FONT_MANAGER_UNKNOWN;  math_view->font_manager    = NULL;  math_view->drawing_area    = NULL;  math_view->interface       = NULL;  math_view->select          = FALSE;  math_view->button_press    = FALSE;  math_view->frame = gtk_frame_new(NULL);  gtk_frame_set_shadow_type(GTK_FRAME(math_view->frame), GTK_SHADOW_IN);  gtk_container_add(GTK_CONTAINER(math_view), math_view->frame);  gtk_widget_show(math_view->frame);  math_view->area = gtk_drawing_area_new();  GTK_WIDGET_SET_FLAGS(GTK_WIDGET(math_view->area), GTK_CAN_FOCUS);  gtk_container_add(GTK_CONTAINER(math_view->frame), math_view->area);  gtk_widget_show(math_view->area);  gtk_signal_connect(GTK_OBJECT(math_view->area), "configure_event",		     GTK_SIGNAL_FUNC(gtk_math_view_configure_event), math_view);  gtk_signal_connect(GTK_OBJECT(math_view->area), "expose_event",		     GTK_SIGNAL_FUNC(gtk_math_view_expose_event), math_view);  gtk_signal_connect(GTK_OBJECT(math_view->area), "button_press_event",		     GTK_SIGNAL_FUNC(gtk_math_view_button_press_event), math_view);  gtk_signal_connect(GTK_OBJECT(math_view->area), "button_release_event",		     GTK_SIGNAL_FUNC(gtk_math_view_button_release_event), math_view);  gtk_signal_connect(GTK_OBJECT(math_view->area), "motion_notify_event",		     GTK_SIGNAL_FUNC(gtk_math_view_motion_notify_event), math_view);  gtk_signal_connect(GTK_OBJECT(math_view->area), "key_press_event",		     GTK_SIGNAL_FUNC(gtk_math_view_key_press_event), math_view);  gtk_signal_connect(GTK_OBJECT(math_view->area), "realize",		     GTK_SIGNAL_FUNC(gtk_math_view_realize), math_view);  math_view->hadjustment = NULL;  math_view->vadjustment = NULL;  gtk_widget_add_events(GTK_WIDGET(math_view->area),			GDK_BUTTON_PRESS_MASK			| GDK_BUTTON_RELEASE_MASK			| GDK_POINTER_MOTION_MASK			| GDK_KEY_PRESS_MASK);}extern "C" GtkWidget*gtk_math_view_new(GtkAdjustment* hadj, GtkAdjustment* vadj){  GtkMathView* math_view = (GtkMathView*) gtk_type_new(gtk_math_view_get_type());    g_return_val_if_fail(math_view != NULL, NULL);  math_view->top_x = math_view->top_y = 0;  math_view->old_top_x = math_view->old_top_y = 0;  math_view->interface = new MathEngine();  gtk_math_view_set_font_manager_type(math_view, FONT_MANAGER_GTK);  return GTK_WIDGET(math_view);}static voidgtk_math_view_destroy(GtkObject* object){  GtkMathView* math_view;  g_return_if_fail(object != NULL);  g_return_if_fail(GTK_IS_MATH_VIEW(object));  math_view = GTK_MATH_VIEW(object);  g_assert(math_view != NULL);  g_return_if_fail(math_view->interface != NULL);  MathMLElement* root = math_view->interface->GetRoot();  if (root != NULL) root->ReleaseGCs();  MathEngine::logger(LOG_DEBUG, "destroying the widget");  delete math_view->interface;  delete math_view->font_manager;  delete math_view->drawing_area;  /* FIXME: sometimes the frame has been destroyed already   * if you disable the delete_event and close the window you'll see   * some messages   */  /* ATTEMPT: since this class is derived from a container   * then contained object will be destroyed by the parent class'   * method   */  gtk_signal_disconnect_by_data(GTK_OBJECT(math_view->hadjustment), math_view);  gtk_signal_disconnect_by_data(GTK_OBJECT(math_view->vadjustment), math_view);  if (GTK_OBJECT_CLASS(parent_class)->destroy != NULL)    (*GTK_OBJECT_CLASS(parent_class)->destroy)(object);}