enum PatternColumnType{ PCT_NOTE, PCT_SWITCH, PCT_BYTE, PCT_WORD};typedef struct _PatternColumn{ enum PatternColumnType type; float def, min, max; gpointer user_data;} PatternColumn;typedef struct _PatternColumnGroup{ // just an id to tell groups apart (wire, global, voice) int type; // can be used for the headline above the group char *name; int num_columns; PatternColumn *columns; gpointer user_data; } PatternColumnGroup;typedef struct _BtPatternEditorCallbacks{ /* FIXME: what about supplying * - PatternColumn instead of PatternColumn->user_data * - PatternColumnGroup instead of track; */ float (*get_data_func)(gpointer pattern_data, gpointer column_data, int row, int track, int param); void (*set_data_func)(gpointer pattern_data, gpointer column_data, int row, int track, int param, float value); void (*notify_cursor_func)(gpointer pattern_data, int row, int track, int param, int digit);} BtPatternEditorCallbacks;typedef struct _BtPatternEditor{ GtkWidget parent; /* cursor position * FIXME: {track, parameter} needs to become {group, parameter} */ int row; int track; int parameter; int digit; /* scroll location */ // FIXME: why, gtk+ is doing the scrolling for us int ofs_x, ofs_y; /* pattern data * FIXME: need to use num_groups and PatternColumnGroup* here */ int num_lines, num_tracks, num_globals, num_locals, num_rows; PatternColumn *globals; PatternColumn *locals; BtPatternEditorCallbacks *callbacks; gpointer pattern_data; /* font metrics */ int cw, ch; /* pixel widths of global section, a single track and the row-number column * FIXME: need rowhdr_width, group_width[num_groups] */ int global_width, local_width, rowhdr_width; gboolean size_changed; /* current octave number */ int octave;} BtPatternEditor;