6 * User Accessible Tables GUI
7 * Mantain an array of user accessible data strucures
9 * (c) 2007, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
11 * Wireshark - Network traffic analyzer
12 * By Gerald Combs <gerald@wireshark.org>
13 * Copyright 2001 Gerald Combs
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33 * - field value check (red/green editbox)
34 * - tooltips (add field descriptions)
46 #include <epan/dfilter/dfilter-macro.h>
47 #include <epan/emem.h>
48 #include <epan/report_err.h>
49 #include <gdk/gdkkeysyms.h>
50 #include "gtkglobals.h"
51 #include "gui_utils.h"
52 #include "dlg_utils.h"
55 #include "compat_macros.h"
56 #include <epan/proto.h>
57 #include <epan/packet.h>
58 #include "../stat_menu.h"
59 #include "gui_stat_menu.h"
62 #include <epan/uat-int.h>
63 #include <epan/value_string.h>
66 #if GTK_MAJOR_VERSION >= 2
67 # undef GTK_MAJOR_VERSION
68 # define GTK_MAJOR_VERSION 1
69 # define BUTTON_SIZE_X -1
70 # define BUTTON_SIZE_Y -1
72 # define BUTTON_SIZE_X 50
73 # define BUTTON_SIZE_Y 20
79 GtkWidget* scrolledwindow;
90 GtkWidget* unsaved_window;
94 #if GTK_MAJOR_VERSION >= 2
95 GtkTreeSelection *selection;
105 struct _uat_dlg_data {
112 GPtrArray* tobe_freed;
116 static gboolean unsaved_dialog(GtkWindow *w, GdkEvent* e, gpointer u);
117 static gboolean uat_window_delete_event_cb(GtkWindow *w, GdkEvent* e, gpointer u);
119 static void set_buttons(uat_t* uat, gint row) {
121 if (!uat->rep) return;
124 gtk_widget_set_sensitive (uat->rep->bt_up, TRUE);
126 gtk_widget_set_sensitive (uat->rep->bt_up, FALSE);
129 if (row < (gint)(*uat->nrows_p - 1) && row >= 0) {
130 gtk_widget_set_sensitive (uat->rep->bt_down, TRUE);
132 gtk_widget_set_sensitive (uat->rep->bt_down, FALSE);
136 SIGNAL_DISCONNECT_BY_FUNC(uat->rep->window, uat_window_delete_event_cb, uat);
137 SIGNAL_CONNECT(uat->rep->window, "delete_event", unsaved_dialog, uat);
138 SIGNAL_CONNECT(uat->rep->window, "destroy", unsaved_dialog, uat);
140 SIGNAL_DISCONNECT_BY_FUNC(uat->rep->window, unsaved_dialog, uat);
141 SIGNAL_CONNECT(GTK_WINDOW(uat->rep->window), "delete_event", uat_window_delete_event_cb, uat);
142 SIGNAL_CONNECT(GTK_WINDOW(uat->rep->window), "destroy", uat_window_delete_event_cb, uat);
146 static char* fld_tostr(void* rec, uat_field_t* f) {
151 f->cb.tostr(rec,&ptr,&len,f->cbdata.tostr,f->fld_data);
154 case PT_TXTMOD_STRING:
156 out = ep_strndup(ptr,len);
158 case PT_TXTMOD_HEXBYTES: {
159 GString* s = g_string_sized_new( len*2 + 1 );
162 for (i=0; i<len;i++) g_string_sprintfa(s,"%.2X",((guint8*)ptr)[i]);
164 out = ep_strdup_printf(s->str);
166 g_string_free(s,TRUE);
170 g_assert_not_reached();
180 static void append_row(uat_t* uat, guint idx) {
181 GPtrArray* a = g_ptr_array_new();
182 void* rec = UAT_INDEX_PTR(uat,idx);
183 uat_field_t* f = uat->fields;
187 if (! uat->rep) return;
189 gtk_clist_freeze(GTK_CLIST(uat->rep->clist));
191 for ( colnum = 0; colnum < uat->ncols; colnum++ )
192 g_ptr_array_add(a,fld_tostr(rec,&(f[colnum])));
194 rownum = gtk_clist_append(GTK_CLIST(uat->rep->clist), (gchar**)a->pdata);
195 gtk_clist_set_row_data(GTK_CLIST(uat->rep->clist), rownum, rec);
197 gtk_clist_thaw(GTK_CLIST(uat->rep->clist));
199 g_ptr_array_free(a,TRUE);
202 static void reset_row(uat_t* uat, guint idx) {
203 void* rec = UAT_INDEX_PTR(uat,idx);
204 uat_field_t* f = uat->fields;
207 if (! uat->rep) return;
209 gtk_clist_freeze(GTK_CLIST(uat->rep->clist));
211 for ( colnum = 0; colnum < uat->ncols; colnum++ ) {
212 gtk_clist_set_text(GTK_CLIST(uat->rep->clist), idx, colnum, fld_tostr(rec,&(f[colnum])));
215 gtk_clist_thaw(GTK_CLIST(uat->rep->clist));
219 static guint8* unhexbytes(const char* si, guint len, guint* len_p, const char** err) {
222 const guint8* s = (void*)si;
226 *err = "Uneven number of chars hex string";
230 buf = ep_alloc(len/2+1);
233 for (i = 0; i<len ; i += 2) {
237 if (hi >= '0' && hi <= '9') {
239 } else if (hi >= 'a' && hi <= 'f') {
242 } else if (hi >= 'A' && hi <= 'F') {
249 if (lo >= '0' && lo <= '9') {
251 } else if (lo >= 'a' && lo <= 'f') {
254 } else if (lo >= 'A' && lo <= 'F') {
261 *(p++) = (hi*0x10) + lo;
266 if (len_p) *len_p = len;
274 *err = "Error parsing hex string";
279 static gboolean uat_dlg_cb(GtkWidget *win _U_, gpointer user_data) {
280 struct _uat_dlg_data* dd = user_data;
281 guint ncols = dd->uat->ncols;
282 uat_field_t* f = dd->uat->fields;
283 const char* err = NULL;
286 for ( colnum = 0; colnum < ncols; colnum++ ) {
287 void* e = g_ptr_array_index(dd->entries,colnum);
291 switch(f[colnum].mode) {
292 case PT_TXTMOD_STRING:
293 text = gtk_entry_get_text(GTK_ENTRY(e));
296 case PT_TXTMOD_HEXBYTES: {
297 text = gtk_entry_get_text(GTK_ENTRY(e));
299 text = (void*) unhexbytes(text, strlen(text), &len, &err);
302 err = ep_strdup_printf("error in field '%s': %s",f[colnum].name,err);
308 case PT_TXTMOD_ENUM: {
310 text = text ? text : "";
315 g_assert_not_reached();
320 if (f[colnum].cb.chk) {
321 if (! f[colnum].cb.chk(dd->rec, text, len, f[colnum].cbdata.chk, f[colnum].fld_data, &err)) {
322 err = ep_strdup_printf("error in field '%s': %s",f[colnum].name,err);
327 f[colnum].cb.set(dd->rec,text,len, f[colnum].cbdata.set, f[colnum].fld_data);
330 if (dd->uat->update_cb) {
331 dd->uat->update_cb(dd->rec,&err);
334 err = ep_strdup_printf("error updating record: %s",err);
340 void* rec_tmp = dd->rec;
341 dd->rec = uat_add_record(dd->uat, dd->rec);
343 if (dd->uat->free_cb) {
344 dd->uat->free_cb(rec_tmp);
350 dd->uat->changed = TRUE;
352 set_buttons(dd->uat,-1);
355 append_row(dd->uat, (*dd->uat->nrows_p) - 1 );
357 reset_row(dd->uat,dd->row);
360 g_ptr_array_free(dd->entries,TRUE);
361 window_destroy(GTK_WIDGET(dd->win));
364 window_present(GTK_WIDGET(dd->uat->rep->window));
366 while (dd->tobe_freed->len) g_free( g_ptr_array_remove_index_fast(dd->tobe_freed, dd->tobe_freed->len - 1 ) );
373 report_failure("%s",err);
377 static gboolean uat_cancel_dlg_cb(GtkWidget *win _U_, gpointer user_data) {
378 struct _uat_dlg_data* dd = user_data;
381 window_present(GTK_WIDGET(dd->uat->rep->window));
383 if (dd->is_new) g_free(dd->rec);
384 g_ptr_array_free(dd->entries,TRUE);
385 window_destroy(GTK_WIDGET(dd->win));
387 while (dd->tobe_freed->len) g_free( g_ptr_array_remove_index_fast(dd->tobe_freed, dd->tobe_freed->len - 1 ) );
394 struct _fld_menu_item_data_t {
399 static void fld_menu_item_cb(GtkMenuItem *menuitem _U_, gpointer user_data) {
400 struct _fld_menu_item_data_t* md = user_data;
402 *(md->valptr) = md->text;
405 static void fld_menu_item_destroy_cb(GtkMenuItem *menuitem _U_, gpointer user_data) {
409 static void uat_edit_dialog(uat_t* uat, gint row) {
410 GtkWidget *win, *main_tb, *main_vb, *bbox, *bt_cancel, *bt_ok;
411 struct _uat_dlg_data* dd = g_malloc(sizeof(struct _uat_dlg_data));
412 uat_field_t* f = uat->fields;
414 GtkTooltips *tooltips;
416 tooltips = gtk_tooltips_new();
418 dd->entries = g_ptr_array_new();
419 dd->win = dlg_window_new(ep_strdup_printf("%s: %s", uat->name, (row == -1 ? "New" : "Edit")));
421 dd->rec = row < 0 ? g_malloc0(uat->record_size) : UAT_INDEX_PTR(uat,row);
422 dd->is_new = row < 0 ? TRUE : FALSE;
424 dd->tobe_freed = g_ptr_array_new();
428 #if GTK_MAJOR_VERSION >= 2
429 gtk_window_set_resizable(GTK_WINDOW(win),FALSE);
430 gtk_window_resize(GTK_WINDOW(win),400, 30*(uat->ncols+2));
432 gtk_window_set_policy(GTK_WINDOW(win), FALSE, FALSE, TRUE);
433 gtk_window_set_default_size(GTK_WINDOW(win), 400, 30*(uat->ncols+2));
434 gtk_widget_set_usize(win, 400, 30*(uat->ncols+2));
437 main_vb = gtk_vbox_new(FALSE,5);
438 gtk_container_add(GTK_CONTAINER(win), main_vb);
439 gtk_container_border_width(GTK_CONTAINER(main_vb), 6);
441 main_tb = gtk_table_new(uat->ncols+1, 2, FALSE);
442 gtk_box_pack_start(GTK_BOX(main_vb), main_tb, FALSE, FALSE, 0);
443 gtk_table_set_row_spacings(GTK_TABLE(main_tb), 5);
444 gtk_table_set_col_spacings(GTK_TABLE(main_tb), 10);
446 for ( colnum = 0; colnum < uat->ncols; colnum++ ) {
447 GtkWidget *entry, *label, *event_box;
448 char* text = fld_tostr(dd->rec,&(f[colnum]));
450 event_box = gtk_event_box_new();
452 label = gtk_label_new(f[colnum].name);
453 if (f[colnum].desc != NULL)
454 gtk_tooltips_set_tip(tooltips, event_box, f[colnum].desc, NULL);
456 gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
457 gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box, 0, 1, colnum+1, colnum + 2);
458 gtk_container_add(GTK_CONTAINER(event_box), label);
460 switch(f[colnum].mode) {
461 case PT_TXTMOD_STRING:
462 case PT_TXTMOD_HEXBYTES: {
463 entry = gtk_entry_new();
464 g_ptr_array_add(dd->entries,entry);
465 gtk_table_attach_defaults(GTK_TABLE(main_tb), entry, 1, 2, colnum+1, colnum + 2);
467 gtk_entry_set_text(GTK_ENTRY(entry),text);
471 case PT_TXTMOD_ENUM: {
472 GtkWidget *menu, *option_menu;
473 int menu_index, index;
474 const value_string* enum_vals = f[colnum].fld_data;
475 void* valptr = g_malloc0(sizeof(void*));
477 menu = gtk_menu_new();
479 for (index = 0; enum_vals[index].strptr != NULL; index++) {
480 struct _fld_menu_item_data_t* md = g_malloc(sizeof(struct _fld_menu_item_data_t));
481 const char* str = enum_vals[index].strptr;
482 GtkWidget* menu_item = gtk_menu_item_new_with_label(str);
487 gtk_menu_append(GTK_MENU(menu), menu_item);
489 if ( g_str_equal(str, text) ) {
491 *((char const**)valptr) = str;
494 SIGNAL_CONNECT(menu_item, "activate", fld_menu_item_cb, md);
495 SIGNAL_CONNECT(menu_item, "destroy", fld_menu_item_destroy_cb, md);
498 g_ptr_array_add(dd->entries,valptr);
499 g_ptr_array_add(dd->tobe_freed,valptr);
501 /* Create the option menu from the menu */
502 option_menu = gtk_option_menu_new();
503 gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), menu);
505 /* Set its current value to the variable's current value */
506 if (menu_index != -1)
507 gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), menu_index);
509 gtk_table_attach_defaults(GTK_TABLE(main_tb), option_menu, 1, 2, colnum+1, colnum + 2);
514 g_assert_not_reached();
519 bbox = dlg_button_row_new(GTK_STOCK_CANCEL,GTK_STOCK_OK, NULL);
520 gtk_box_pack_end(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
522 bt_ok = OBJECT_GET_DATA(bbox, GTK_STOCK_OK);
523 SIGNAL_CONNECT(bt_ok, "clicked", uat_dlg_cb, dd);
525 bt_cancel = OBJECT_GET_DATA(bbox, GTK_STOCK_CANCEL);
526 SIGNAL_CONNECT(bt_cancel, "clicked", uat_cancel_dlg_cb, dd);
527 window_set_cancel_button(win, bt_cancel, NULL);
529 gtk_widget_show_all(win);
538 static void uat_del_cb(GtkButton *button _U_, gpointer u) {
539 struct _uat_del* ud = u;
541 uat_remove_record_idx(ud->uat, ud->idx);
544 gtk_clist_remove(GTK_CLIST(ud->uat->rep->clist),ud->idx);
546 ud->uat->changed = TRUE;
547 set_buttons(ud->uat,-1);
549 window_destroy(GTK_WIDGET(ud->win));
552 window_present(GTK_WIDGET(ud->uat->rep->window));
557 static void uat_cancel_del_cb(GtkButton *button _U_, gpointer u) {
558 struct _uat_del* ud = u;
559 window_destroy(GTK_WIDGET(ud->win));
562 window_present(GTK_WIDGET(ud->uat->rep->window));
566 static void uat_del_dlg(uat_t* uat, int idx) {
567 GtkWidget *win, *main_tb, *main_vb, *bbox, *bt_cancel, *bt_ok;
568 uat_field_t* f = uat->fields;
570 void* rec = UAT_INDEX_PTR(uat,idx);
571 struct _uat_del* ud = g_malloc(sizeof(struct _uat_del));
575 ud->win = win = dlg_window_new(ep_strdup_printf("%s: Confirm Delete", uat->name));
577 #if GTK_MAJOR_VERSION >= 2
578 gtk_window_set_resizable(GTK_WINDOW(win),FALSE);
579 gtk_window_resize(GTK_WINDOW(win),400,25*(uat->ncols+2));
581 gtk_window_set_policy(GTK_WINDOW(win), FALSE, FALSE, TRUE);
582 gtk_window_set_default_size(GTK_WINDOW(win), 400, 25*(uat->ncols+2));
583 gtk_widget_set_usize(win, 400, 25*(uat->ncols+2));
586 main_vb = gtk_vbox_new(FALSE,5);
587 gtk_container_add(GTK_CONTAINER(win), main_vb);
588 gtk_container_border_width(GTK_CONTAINER(main_vb), 6);
590 main_tb = gtk_table_new(uat->ncols+1, 2, FALSE);
591 gtk_box_pack_start(GTK_BOX(main_vb), main_tb, FALSE, FALSE, 0);
592 gtk_table_set_row_spacings(GTK_TABLE(main_tb), 10);
593 gtk_table_set_col_spacings(GTK_TABLE(main_tb), 15);
595 for ( colnum = 0; colnum < uat->ncols; colnum++ ) {
597 char* text = fld_tostr(rec,&(f[colnum]));
599 label = gtk_label_new(f[colnum].name);
600 gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
601 gtk_table_attach_defaults(GTK_TABLE(main_tb), label, 0, 1, colnum+1, colnum + 2);
603 label = gtk_label_new(text);
604 gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
605 gtk_table_attach_defaults(GTK_TABLE(main_tb), label, 1, 2, colnum+1, colnum + 2);
608 bbox = dlg_button_row_new(GTK_STOCK_CANCEL,GTK_STOCK_DELETE, NULL);
609 gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
611 bt_ok = OBJECT_GET_DATA(bbox,GTK_STOCK_DELETE);
612 SIGNAL_CONNECT(bt_ok, "clicked", uat_del_cb, ud);
614 bt_cancel = OBJECT_GET_DATA(bbox, GTK_STOCK_CANCEL);
615 SIGNAL_CONNECT(bt_cancel, "clicked", uat_cancel_del_cb, ud);
616 window_set_cancel_button( win, bt_cancel, NULL);
618 gtk_widget_show_all(win);
621 static void uat_new_cb(GtkButton *button _U_, gpointer u) {
624 if (! uat->rep) return;
626 uat_edit_dialog(uat, -1);
629 static void uat_edit_cb(GtkButton *button _U_, gpointer u) {
632 if (! uat->rep) return;
634 uat_edit_dialog(uat, uat->rep->selected);
637 static void uat_delete_cb(GtkButton *button _U_, gpointer u) {
640 if (! uat->rep) return;
642 uat_del_dlg(uat,uat->rep->selected);
645 static gboolean uat_window_delete_event_cb(GtkWindow *w _U_, GdkEvent* e _U_, gpointer u) {
649 void* rep = uat->rep;
651 SIGNAL_DISCONNECT_BY_FUNC(uat->rep->window, uat_window_delete_event_cb, uat);
652 SIGNAL_DISCONNECT_BY_FUNC(uat->rep->window, unsaved_dialog, uat);
654 gtk_widget_destroy(uat->rep->window);
657 if (rep) g_free(rep);
662 static void uat_up_cb(GtkButton *button _U_, gpointer u) {
664 guint row = uat->rep->selected;
668 uat_swap(uat,row,row-1);
669 gtk_clist_swap_rows(GTK_CLIST(uat->rep->clist),row,row-1);
674 uat->rep->selected = row;
675 set_buttons(uat,row);
678 static void uat_down_cb(GtkButton *button _U_, gpointer u) {
680 guint row = uat->rep->selected;
682 g_assert(row < *uat->nrows_p - 1);
684 uat_swap(uat,row,row+1);
685 gtk_clist_swap_rows(GTK_CLIST(uat->rep->clist),row,row+1);
690 uat->rep->selected = row;
691 set_buttons(uat,row);
694 static void uat_cancel_cb(GtkWidget *button _U_, gpointer u) {
703 report_failure("Error while loading %s: %s",uat->name,err);
706 if (cfile.state == FILE_READ_DONE) cf_reload(&cfile);
709 SIGNAL_DISCONNECT_BY_FUNC(uat->rep->window, uat_window_delete_event_cb, uat);
710 SIGNAL_DISCONNECT_BY_FUNC(uat->rep->window, unsaved_dialog, uat);
711 gtk_widget_destroy(uat->rep->window);
716 static void uat_apply_cb(GtkButton *button _U_, gpointer u) {
719 uat_window_delete_event_cb(NULL,NULL,uat);
721 if (uat->changed && cfile.state == FILE_READ_DONE)
725 static void uat_ok_cb(GtkButton *button _U_, gpointer u) {
733 report_failure("Error while saving %s: %s",uat->name,err);
736 if (cfile.state == FILE_READ_DONE) cf_reload(&cfile);
739 SIGNAL_DISCONNECT_BY_FUNC(uat->rep->window, uat_window_delete_event_cb, uat);
740 SIGNAL_DISCONNECT_BY_FUNC(uat->rep->window, unsaved_dialog, uat);
741 gtk_widget_destroy(uat->rep->window);
748 static void remember_selected_row(GtkCList *clist _U_, gint row, gint column _U_, GdkEvent *event _U_, gpointer u) {
751 uat->rep->selected = row;
753 gtk_widget_set_sensitive (uat->rep->bt_edit, TRUE);
754 gtk_widget_set_sensitive(uat->rep->bt_delete, TRUE);
756 set_buttons(uat,row);
759 static void unremember_selected_row(GtkCList *clist _U_, gint row _U_, gint column _U_, GdkEvent *event _U_, gpointer u) {
762 uat->rep->selected = -1;
763 gtk_widget_set_sensitive (uat->rep->bt_edit, FALSE);
764 gtk_widget_set_sensitive(uat->rep->bt_delete, FALSE);
765 gtk_widget_set_sensitive (uat->rep->bt_down, FALSE);
766 gtk_widget_set_sensitive (uat->rep->bt_up, FALSE);
769 static void uat_yessave_cb(GtkWindow *w _U_, void* u) {
773 window_delete_event_cb(uat->rep->unsaved_window,NULL,NULL);
778 report_failure("Error while saving %s: %s",uat->name,err);
781 SIGNAL_DISCONNECT_BY_FUNC(uat->rep->window, uat_window_delete_event_cb, uat);
782 SIGNAL_DISCONNECT_BY_FUNC(uat->rep->window, unsaved_dialog, uat);
783 window_destroy(uat->rep->window);
790 static void uat_nosave_cb(GtkWindow *w _U_, void* u) {
792 window_delete_event_cb(uat->rep->unsaved_window,NULL,NULL);
793 SIGNAL_DISCONNECT_BY_FUNC(uat->rep->window, uat_window_delete_event_cb, uat);
794 SIGNAL_DISCONNECT_BY_FUNC(uat->rep->window, unsaved_dialog, uat);
795 window_destroy(uat->rep->window);
801 static gboolean unsaved_dialog(GtkWindow *w _U_, GdkEvent* e _U_, gpointer u) {
802 GtkWidget *win, *vbox, *label, *bbox;
803 GtkWidget *yes_bt, *no_bt;
807 if (uat->rep->unsaved_window) {
808 window_present(uat->rep->unsaved_window);
812 uat->rep->unsaved_window = win = window_new(GTK_WINDOW_TOPLEVEL, "Discard Changes?");
813 gtk_window_set_default_size(GTK_WINDOW(win), 360, 140);
815 #if GTK_MAJOR_VERSION >= 2
816 gtk_window_set_position(GTK_WINDOW(win), GTK_WIN_POS_CENTER_ON_PARENT);
818 gtk_window_set_position(GTK_WINDOW(win), GTK_WIN_POS_CENTER);
820 vbox = gtk_vbox_new(FALSE, 12);
821 gtk_container_border_width(GTK_CONTAINER(vbox), 6);
822 gtk_container_add(GTK_CONTAINER(win), vbox);
824 message = ep_strdup_printf("Changes to '%s' are not being saved!\n"
825 "Do you want to save '%s'?", uat->name, uat->name);
827 label = gtk_label_new(message);
829 bbox = dlg_button_row_new(GTK_STOCK_YES,GTK_STOCK_NO, NULL);
831 yes_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_YES);
832 no_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_NO);
834 SIGNAL_CONNECT(no_bt, "clicked", uat_nosave_cb, uat);
835 SIGNAL_CONNECT(yes_bt, "clicked", uat_yessave_cb, uat);
837 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
838 gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
840 gtk_widget_show_all(win);
846 static void uat_help_cb(GtkWidget* w _U_, gpointer u) {
847 help_topic_html(ep_strdup_printf("%s.html",((uat_t*)u)->help));
850 static GtkWidget* uat_window(void* u) {
852 uat_field_t* f = uat->fields;
856 GtkWidget *hbox, *vbox, *move_hbox, *edit_hbox;
859 window_present(uat->rep->window);
860 return uat->rep->window;
862 uat->rep = rep = g_malloc0(sizeof(uat_rep_t));
865 rep->window = window_new(GTK_WINDOW_TOPLEVEL, uat->name);
867 #if GTK_MAJOR_VERSION >= 2
868 gtk_window_set_resizable(GTK_WINDOW(rep->window),FALSE);
869 gtk_window_resize(GTK_WINDOW(rep->window), 720, 512);
871 gtk_window_set_policy(GTK_WINDOW(rep->window), FALSE, FALSE, TRUE);
872 gtk_window_set_default_size(GTK_WINDOW(rep->window), 720, 512);
873 gtk_widget_set_usize(rep->window, 720, 512);
877 #if GTK_MAJOR_VERSION >= 2
878 gtk_window_set_position(GTK_WINDOW(rep->window), GTK_WIN_POS_CENTER_ON_PARENT);
880 gtk_window_set_position(GTK_WINDOW(rep->window), GTK_WIN_POS_CENTER);
883 gtk_container_border_width(GTK_CONTAINER(rep->window), 6);
885 rep->vbox = gtk_vbox_new(FALSE, 12);
886 gtk_container_border_width(GTK_CONTAINER(rep->vbox), 6);
887 gtk_container_add(GTK_CONTAINER(rep->window), rep->vbox);
889 hbox = gtk_hbox_new(FALSE,12);
890 gtk_container_border_width(GTK_CONTAINER(hbox), 6);
891 gtk_container_add(GTK_CONTAINER(rep->vbox), hbox);
893 vbox = gtk_vbox_new(FALSE, 12);
894 gtk_container_border_width(GTK_CONTAINER(vbox), 6);
895 gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
897 rep->scrolledwindow = scrolled_window_new(NULL, NULL);
899 #if GTK_MAJOR_VERSION >= 2
900 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(rep->scrolledwindow), GTK_SHADOW_IN);
903 rep->clist = gtk_clist_new(uat->ncols);
904 gtk_container_add(GTK_CONTAINER(rep->scrolledwindow), rep->clist);
905 gtk_box_pack_start(GTK_BOX(hbox), rep->scrolledwindow, TRUE, TRUE, 0);
907 for ( colnum = 0; colnum < uat->ncols; colnum++ ) {
908 gtk_clist_set_column_title(GTK_CLIST(rep->clist), colnum, f[colnum].name);
909 gtk_clist_set_column_auto_resize(GTK_CLIST(rep->clist), colnum, TRUE);
912 gtk_clist_column_titles_show(GTK_CLIST(rep->clist));
913 gtk_clist_freeze(GTK_CLIST(rep->clist));
915 for ( i = 0 ; i < *(uat->nrows_p); i++ ) {
919 gtk_clist_thaw(GTK_CLIST(rep->clist));
921 #if GTK_MAJOR_VERSION < 2
922 gtk_clist_set_selection_mode(GTK_CLIST(rep->clist),GTK_SELECTION_SINGLE);
924 rep->selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(rep->clist));
925 gtk_tree_selection_set_mode(rep->selection, GTK_SELECTION_SINGLE);
930 rep->bbox = dlg_button_row_new(GTK_STOCK_HELP, GTK_STOCK_OK, GTK_STOCK_APPLY, GTK_STOCK_CANCEL, NULL);
931 help_btn = OBJECT_GET_DATA(rep->bbox,GTK_STOCK_HELP);
932 SIGNAL_CONNECT(help_btn, "clicked", uat_help_cb, uat);
935 rep->bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_APPLY, GTK_STOCK_CANCEL, NULL);
938 move_hbox = gtk_vbutton_box_new();
939 gtk_box_pack_start(GTK_BOX(vbox), move_hbox, TRUE, FALSE, 0);
941 edit_hbox = gtk_vbutton_box_new();
942 gtk_box_pack_end(GTK_BOX(vbox), edit_hbox, TRUE, FALSE, 0);
945 rep->bt_down = BUTTON_NEW_FROM_STOCK(GTK_STOCK_GO_DOWN);
946 rep->bt_up = BUTTON_NEW_FROM_STOCK(GTK_STOCK_GO_UP);
948 gtk_box_pack_start(GTK_BOX(move_hbox), rep->bt_up, TRUE, FALSE, 5);
949 gtk_box_pack_start(GTK_BOX(move_hbox), rep->bt_down, TRUE, FALSE, 5);
952 rep->bt_new = BUTTON_NEW_FROM_STOCK(GTK_STOCK_NEW);
953 rep->bt_edit = BUTTON_NEW_FROM_STOCK(WIRESHARK_STOCK_EDIT);
954 rep->bt_delete = BUTTON_NEW_FROM_STOCK(GTK_STOCK_DELETE);
956 gtk_box_pack_end(GTK_BOX(edit_hbox), rep->bt_new, TRUE, FALSE, 5);
957 gtk_box_pack_end(GTK_BOX(edit_hbox), rep->bt_edit, TRUE, FALSE, 5);
958 gtk_box_pack_end(GTK_BOX(edit_hbox), rep->bt_delete, TRUE, FALSE, 5);
961 rep->bt_apply = OBJECT_GET_DATA(rep->bbox,GTK_STOCK_APPLY);
962 rep->bt_cancel = OBJECT_GET_DATA(rep->bbox,GTK_STOCK_CANCEL);
963 rep->bt_ok = OBJECT_GET_DATA(rep->bbox,GTK_STOCK_OK);
965 gtk_box_pack_end(GTK_BOX(rep->vbox), rep->bbox, FALSE, FALSE, 0);
967 gtk_widget_set_sensitive (rep->bt_up, FALSE);
968 gtk_widget_set_sensitive (rep->bt_down, FALSE);
969 gtk_widget_set_sensitive (rep->bt_edit, FALSE);
970 gtk_widget_set_sensitive (rep->bt_delete, FALSE);
973 #if GTK_MAJOR_VERSION < 2
974 SIGNAL_CONNECT(rep->clist, "select_row", remember_selected_row, uat);
975 SIGNAL_CONNECT(rep->clist, "unselect_row", unremember_selected_row, uat);
977 SIGNAL_CONNECT(selection, "changed", remember_selected_row, uat);
980 SIGNAL_CONNECT(rep->bt_new, "clicked", uat_new_cb, uat);
981 SIGNAL_CONNECT(rep->bt_edit, "clicked", uat_edit_cb, uat);
982 SIGNAL_CONNECT(rep->bt_delete, "clicked", uat_delete_cb, uat);
984 SIGNAL_CONNECT(rep->bt_up, "clicked", uat_up_cb, uat);
985 SIGNAL_CONNECT(rep->bt_down, "clicked", uat_down_cb, uat);
987 SIGNAL_CONNECT(rep->bt_apply, "clicked", uat_apply_cb, uat);
988 SIGNAL_CONNECT(rep->bt_cancel, "clicked", uat_cancel_cb, uat);
989 SIGNAL_CONNECT(rep->bt_ok, "clicked", uat_ok_cb, uat);
991 window_set_cancel_button(rep->window, rep->bt_cancel, NULL); /* set esc to activate cancel button */
994 SIGNAL_CONNECT(GTK_WINDOW(rep->window), "delete_event", unsaved_dialog, uat);
995 SIGNAL_CONNECT(GTK_WINDOW(rep->window), "destroy", unsaved_dialog, uat);
997 SIGNAL_CONNECT(GTK_WINDOW(rep->window), "delete_event", uat_window_delete_event_cb, uat);
998 SIGNAL_CONNECT(GTK_WINDOW(rep->window), "destroy", uat_window_delete_event_cb, uat);
1001 gtk_widget_grab_focus(rep->clist);
1003 gtk_widget_show_all(rep->window);
1004 window_present(rep->window);
1009 void uat_window_cb(GtkWidget* u _U_, void* uat) {