/* formulas.c * geg, a GTK+ Equation Grapher * David Bryant 1998 */ #ifdef HAVE_CONFIG_H #include #endif /* HAVE_CONFIG_H */ #include "formulas.h" #include "log.h" #include "prefs.h" #include "colors.h" /* global data */ extern struct_prefs prefs; extern misc_colors m_colors; /* locally global data */ static gchar **formulas = NULL; static int nformulas = 0; static GtkWidget *wi = NULL; static GtkStyle *style; static void close_event(GtkWidget *widget, gpointer data); static void remove_event(GtkWidget *widget, gpointer data); static void really_remove_event(gpointer data, gpointer user_data); void remove_all_event(GtkWidget *widget, gpointer data) { int i; for(i = 0; i < nformulas; i++) g_free(formulas[i]); if(formulas) g_free(formulas); formulas = NULL; nformulas = 0; } /* formula_foreach, calls the supplied function for each formula in the * array of formulas, called by go_event in app.c */ void formula_foreach(FormulaFunc func) { int i; for(i = 0; i < nformulas; i++) func(formulas[i], i); } /* formula_forall, */ void formula_forall(FormulaAllFunc func, gdouble x1, gdouble x2, gdouble y1, gdouble y2) { func(formulas, nformulas, x1, x2, y1, y2); } /* formula_add, */ gint formula_add(FormulaFunc func, gchar *formula) { if(*formula == '\0') /* check for a real formula */ return(FALSE); if(nformulas >= prefs.maxform) { write_log(NULL, "Maximum Formulas"); return(FALSE); } write_log(NULL, formula); if(!func(formula, nformulas)) { write_log(NULL, "Parse Error!"); return(FALSE); } /* add the formula to the list */ formulas = (gchar **)g_realloc(formulas, ++nformulas * sizeof(gchar **)); formulas[nformulas - 1] = g_strdup(formula); return(TRUE); } /* delete_event, deletes the window, not sure if it would be GTK+ approved */ static gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) { gtk_widget_destroy(wi); wi = NULL; gtk_style_unref(style); return(TRUE); } /* close_event, closes the 'erase' dialog, it is called by the 'Cancel' * and the 'Ok' button */ static void close_event(GtkWidget *widget, gpointer data) { gtk_widget_destroy(wi); wi = NULL; gtk_style_unref(style); } /* erase_event, brings up the 'erase' dialog, it is called by the 'erase' * toolbar button in the main dialog */ void erase_event(GtkWidget *widget, gpointer data) { int i; GtkWidget *temp_bu, *fr, *li; GtkSignalFunc refresh_graph; if(wi && wi->window) { gtk_widget_map(wi); gdk_window_raise(wi->window); return; } refresh_graph = (GtkSignalFunc)data; wi = gtk_dialog_new(); gtk_signal_connect(GTK_OBJECT(wi), "delete_event", GTK_SIGNAL_FUNC(delete_event), NULL); gtk_window_set_wmclass(GTK_WINDOW(wi), "erase", "geg"); gtk_window_set_title(GTK_WINDOW(wi), "Erase"); gtk_window_set_policy(GTK_WINDOW(wi), FALSE, TRUE, FALSE); gtk_window_position(GTK_WINDOW(wi), GTK_WIN_POS_MOUSE); gtk_container_border_width(GTK_CONTAINER(GTK_DIALOG(wi)->vbox), 5); /* the list to delete functions from */ fr = gtk_frame_new("Select functions to erase:"); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(wi)->vbox), fr, TRUE, TRUE, 0); li = gtk_clist_new(1); /* only want 1 column */ /* gtk_clist_set_reorderable(GTK_CLIST(li), TRUE); */ /* style stuff */ style = gtk_style_copy(gtk_widget_get_style(widget)); style->bg[GTK_STATE_PRELIGHT] = *m_colors.back; gtk_widget_set_style(li, style); gtk_clist_set_selection_mode(GTK_CLIST(li), GTK_SELECTION_MULTIPLE); /* add the formulas to the list */ for(i = 0; i < nformulas; i++) { gtk_clist_append(GTK_CLIST(li), &formulas[i]); gtk_clist_set_foreground(GTK_CLIST(li), i, function_color(i)); gtk_clist_set_background(GTK_CLIST(li), i, m_colors.back); } /* make the list a bit bigger than the default size */ gtk_widget_set_usize(li, 200, 200); gtk_container_add(GTK_CONTAINER(fr), li); gtk_widget_show(li); gtk_widget_show(fr); /* Ok button */ temp_bu = gtk_button_new_with_label("Ok"); gtk_signal_connect(GTK_OBJECT(temp_bu), "clicked", GTK_SIGNAL_FUNC(remove_event), li); gtk_signal_connect(GTK_OBJECT(temp_bu), "clicked", GTK_SIGNAL_FUNC(refresh_graph), NULL); gtk_signal_connect(GTK_OBJECT(temp_bu), "clicked", GTK_SIGNAL_FUNC(close_event), NULL); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(wi)->action_area), temp_bu, TRUE, TRUE, 0); gtk_widget_show(temp_bu); /* Cancel button */ temp_bu = gtk_button_new_with_label("Cancel"); gtk_signal_connect(GTK_OBJECT(temp_bu), "clicked", GTK_SIGNAL_FUNC(close_event), NULL); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(wi)->action_area), temp_bu, TRUE, TRUE, 0); gtk_widget_show(temp_bu); gtk_grab_add(wi); gtk_widget_show(wi); /* how do I do this ? */ /* gdk_window_set_decorations(wi->window, GDK_DECOR_BORDER); */ } /* really_remove_event, called for each item in the glist in remove_event */ static void really_remove_event(gpointer data, gpointer user_data) { gint i = 0; gchar *text; gtk_clist_get_text((GtkCList *)user_data, (gint)data, 0, &text); while(strcmp(text, formulas[i++])); g_free(formulas[--i]); nformulas--; /* the next part shuffles the order if we didn't delete the last one */ /* this disturbs the order, ideally this should not happen... maybe later */ if(i != nformulas) formulas[i] = formulas[nformulas]; formulas = (gchar **)g_realloc(formulas, nformulas * sizeof(gchar **)); } /* remove_event, called from the 'ok' button in the 'erase' dialog. it * passes a pointer to the CList, which has selected entries which we * wish to delete */ static void remove_event(GtkWidget *widget, gpointer data) { GtkCList *clist; GList *glist; /* glib doubly linked list */ clist = GTK_CLIST((GtkWidget *)data); glist = clist->selection; if(glist) write_log(NULL, "Erase Formulas"); g_list_foreach(glist, (GFunc)really_remove_event, clist); }