/* * Base pane widget module * See basepane-widget.h about details. * * Copyright INOUE Seiichiro , licensed under the GPL. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "diff.h" #include "gui.h" #include "basepane-widget.h" /* Function table to find difference */ const FindFunc findfn_table[] = { {MOVED_CURRENT, dfiles_get_curl}, {MOVED_CUR_NOSCROLL, dfiles_get_curl}, {MOVED_NEXT, dfiles_find_nextl}, {MOVED_PREV, dfiles_find_prevl}, {MOVED_FIRST, dfiles_get_firstl}, {MOVED_LAST, dfiles_get_lastl}, {0, NULL},/* for error check */ }; const int NUM_FTABLE = sizeof(findfn_table) / sizeof(findfn_table[0]); /* signals */ enum { MOVE_DIFF, SELECT_DLINES, LAST_SIGNAL }; /* Private function declarations */ static void gdiff_basepane_class_init(GdiffBasePaneClass *klass); static void gdiff_basepane_init(GdiffBasePane *basepane); static void gdiff_basepane_finalize(GtkObject *object); static void gdiff_basepane_size_request(GtkWidget *widget, GtkRequisition *requisition); static void gdiff_basepane_size_allocate(GtkWidget *widget, GtkAllocation *allocation); static GtkBinClass *parent_class = NULL; static guint basepane_signals[LAST_SIGNAL] = { 0 }; GtkType gdiff_basepane_get_type(void) { static GtkType basepane_type = 0; if (!basepane_type) { static const GtkTypeInfo basepane_info = { "GdiffBasePane", sizeof(GdiffBasePane), sizeof(GdiffBasePaneClass), (GtkClassInitFunc)gdiff_basepane_class_init, (GtkObjectInitFunc)gdiff_basepane_init, /* reserved_1 */ NULL, /* reserved_2 */ NULL, (GtkClassInitFunc)NULL, }; basepane_type = gtk_type_unique(GTK_TYPE_BIN, &basepane_info); } return basepane_type; } static void gdiff_basepane_class_init(GdiffBasePaneClass *klass) { GtkObjectClass *object_class; GtkWidgetClass *widget_class; object_class = (GtkObjectClass*)klass; widget_class = (GtkWidgetClass*)klass; parent_class = gtk_type_class(GTK_TYPE_BIN); basepane_signals[MOVE_DIFF] = gtk_signal_new("move_diff", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET(GdiffBasePaneClass, move_diff), gtk_marshal_NONE__INT, GTK_TYPE_NONE, 1, GTK_TYPE_INT); basepane_signals[SELECT_DLINES] = gtk_signal_new("select_dlines", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET(GdiffBasePaneClass, select_dlines), gtk_marshal_NONE__INT_INT, GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT); gtk_object_class_add_signals(object_class, basepane_signals, LAST_SIGNAL); object_class->finalize = gdiff_basepane_finalize; widget_class->size_request = gdiff_basepane_size_request; widget_class->size_allocate = gdiff_basepane_size_allocate; klass->display = NULL; klass->show_linenum = NULL; klass->show_fill = NULL; klass->toggle_textwrap = NULL; klass->set_highlight = NULL; klass->move_diff = NULL; klass->select_dlines = NULL; klass->search_string = NULL; } static void gdiff_basepane_init(GdiffBasePane *basepane) { int n; basepane->diffdir = NULL; basepane->dfiles = NULL; basepane->cur_dlines_node = NULL; for (n = 0; n < MAX_NUM_COMPARE_FILES; n++) { basepane->filename[n] = NULL; basepane->mbuf[n] = NULL; } basepane->pref = g_pref.fvpref;/*XXX*/ } static void gdiff_basepane_finalize(GtkObject *object) { GdiffBasePane *basepane; int n; g_return_if_fail(object != NULL); g_return_if_fail(GDIFF_IS_BASEPANE(object)); basepane = GDIFF_BASEPANE(object); for (n = 0; n < MAX_NUM_COMPARE_FILES; n++) { if (basepane->mbuf[n]) mbuf_delete(basepane->mbuf[n]); if (basepane->filename[n]) g_free(basepane->filename[n]); } dfiles_unref(basepane->dfiles);/* leave it */ diffdir_unref(basepane->diffdir);/* leave it */ (*GTK_OBJECT_CLASS(parent_class)->finalize)(object); } static void gdiff_basepane_size_request(GtkWidget *widget, GtkRequisition *requisition) { GtkBin *bin; g_return_if_fail(widget != NULL); g_return_if_fail(GDIFF_IS_BASEPANE(widget)); g_return_if_fail(requisition != NULL); bin = GTK_BIN(widget); if (bin->child && GTK_WIDGET_VISIBLE(bin->child)) { GtkRequisition child_requisition; gtk_widget_size_request(bin->child, &child_requisition); requisition->width = child_requisition.width; requisition->height = child_requisition.height; } } static void gdiff_basepane_size_allocate(GtkWidget *widget, GtkAllocation *allocation) { g_return_if_fail(widget != NULL); g_return_if_fail(GDIFF_IS_BASEPANE(widget)); g_return_if_fail(allocation != NULL); widget->allocation = *allocation; if (GTK_BIN(widget)->child && GTK_WIDGET_VISIBLE(GTK_BIN(widget)->child)) { gtk_widget_size_allocate(GTK_BIN(widget)->child, allocation); } } /* called from a derived type */ void _gdiff_basepane_set_backend(GdiffBasePane *basepane, DiffDir *diffdir, DiffFiles *dfiles) { int n; int num_comp_files; g_return_if_fail(basepane != NULL); g_return_if_fail(GDIFF_IS_BASEPANE(basepane)); g_return_if_fail(basepane->filename[0] == NULL); g_return_if_fail(basepane->mbuf[0] == NULL); basepane->diffdir = diffdir; diffdir_ref(diffdir);/* own it */ basepane->dfiles = dfiles; dfiles_ref(dfiles);/* own it */ num_comp_files = dfiles->is_diff3 ? 3 : 2; for (n = 0; n < num_comp_files; n++) { const FileInfo *fi = dfiles_get_fileinfo(dfiles, n, TRUE); basepane->filename[n] = g_strdup(fi->fname); basepane->mbuf[n] = mbuf_new(fi->buf, fi->lenb, fi->nlines, TRUE); } } /** Interfaces **/ void gdiff_basepane_display(GdiffBasePane *basepane) { GdiffBasePaneClass *klass; g_return_if_fail(basepane != NULL); g_return_if_fail(GDIFF_IS_BASEPANE(basepane)); klass = GDIFF_BASEPANE_CLASS(GTK_OBJECT(basepane)->klass); if (klass->display) klass->display(basepane); } void gdiff_basepane_show_linenum(GdiffBasePane *basepane, gboolean to_show) { GdiffBasePaneClass *klass; g_return_if_fail(basepane != NULL); g_return_if_fail(GDIFF_IS_BASEPANE(basepane)); klass = GDIFF_BASEPANE_CLASS(GTK_OBJECT(basepane)->klass); if (klass->show_linenum) klass->show_linenum(basepane, to_show); } void gdiff_basepane_show_fill(GdiffBasePane *basepane, gboolean to_show) { GdiffBasePaneClass *klass; g_return_if_fail(basepane != NULL); g_return_if_fail(GDIFF_IS_BASEPANE(basepane)); klass = GDIFF_BASEPANE_CLASS(GTK_OBJECT(basepane)->klass); if (klass->show_fill) klass->show_fill(basepane, to_show); } /** * gdiff_basepane_toggle_textwrap: * Return toggle status. I.e. return TRUE if text becomes toggled. **/ gboolean gdiff_basepane_toggle_textwrap(GdiffBasePane *basepane) { GdiffBasePaneClass *klass; g_return_val_if_fail(basepane != NULL, FALSE); g_return_val_if_fail(GDIFF_IS_BASEPANE(basepane), FALSE); klass = GDIFF_BASEPANE_CLASS(GTK_OBJECT(basepane)->klass); if (klass->toggle_textwrap) return klass->toggle_textwrap(basepane); else return FALSE; } /** * gdiff_basepane_set_highlight:: **/ void gdiff_basepane_set_highlight(GdiffBasePane *basepane, gboolean to_highlight) { GdiffBasePaneClass *klass; g_return_if_fail(basepane != NULL); g_return_if_fail(GDIFF_IS_BASEPANE(basepane)); klass = GDIFF_BASEPANE_CLASS(GTK_OBJECT(basepane)->klass); if (klass->set_highlight) klass->set_highlight(basepane, to_highlight); else return; } /** * gdiff_basepane_move_diff: * Move to a difference, such as next, previous, first or last. **/ void gdiff_basepane_move_diff(GdiffBasePane *basepane, MoveDiff mv_diff) { g_return_if_fail(basepane != NULL); g_return_if_fail(GDIFF_IS_BASEPANE(basepane)); gtk_signal_emit(GTK_OBJECT(basepane), basepane_signals[MOVE_DIFF], mv_diff); } /** * gdiff_basepane_select_dlines: * Select specified line for current dlines. **/ void gdiff_basepane_select_dlines(GdiffBasePane *basepane, WhichFile whichfile, int ln) { g_return_if_fail(basepane != NULL); g_return_if_fail(GDIFF_IS_BASEPANE(basepane)); gtk_signal_emit(GTK_OBJECT(basepane), basepane_signals[SELECT_DLINES], whichfile, ln); } /** * gdiff_basepane_search_string: **/ gboolean gdiff_basepane_search_string(GdiffBasePane *basepane, const char *string, WhichFile whichfile) { GdiffBasePaneClass *klass; g_return_val_if_fail(basepane != NULL, FALSE); g_return_val_if_fail(GDIFF_IS_BASEPANE(basepane), FALSE); klass = GDIFF_BASEPANE_CLASS(GTK_OBJECT(basepane)->klass); if (klass->search_string) return klass->search_string(basepane, string, whichfile); else return FALSE; }