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 <gdk/gdkkeysyms.h>
48 #include <epan/dfilter/dfilter-macro.h>
49 #include <epan/emem.h>
50 #include <epan/report_err.h>
51 #include <epan/proto.h>
52 #include <epan/packet.h>
53 #include <epan/uat-int.h>
54 #include <epan/value_string.h>
56 #include "../stat_menu.h"
58 #include "gtk/gtkglobals.h"
59 #include "gtk/gui_utils.h"
60 #include "gtk/dlg_utils.h"
61 #include "gtk/help_dlg.h"
62 #include "gtk/stock_icons.h"
63 #include "gtk/gui_stat_menu.h"
65 #include "gtk/uat_gui.h"
68 # define BUTTON_SIZE_X -1
69 # define BUTTON_SIZE_Y -1
74 GtkWidget* scrolledwindow;
85 GtkWidget* unsaved_window;
89 GtkTreeSelection *selection;
97 struct _uat_dlg_data {
104 GPtrArray* tobe_freed;
108 static gboolean unsaved_dialog(GtkWindow *w, GdkEvent* e, gpointer u);
109 static gboolean uat_window_delete_event_cb(GtkWindow *w, GdkEvent* e, gpointer u);
111 static void set_buttons(uat_t* uat, gint row) {
113 if (!uat->rep) return;
116 gtk_widget_set_sensitive (uat->rep->bt_up, TRUE);
118 gtk_widget_set_sensitive (uat->rep->bt_up, FALSE);
121 if (row < (gint)(*uat->nrows_p - 1) && row >= 0) {
122 gtk_widget_set_sensitive (uat->rep->bt_down, TRUE);
124 gtk_widget_set_sensitive (uat->rep->bt_down, FALSE);
128 g_signal_handlers_disconnect_by_func(uat->rep->window, uat_window_delete_event_cb, uat);
129 g_signal_connect(uat->rep->window, "delete_event", G_CALLBACK(unsaved_dialog), uat);
130 g_signal_connect(uat->rep->window, "destroy", G_CALLBACK(unsaved_dialog), uat);
132 g_signal_handlers_disconnect_by_func(uat->rep->window, unsaved_dialog, uat);
133 g_signal_connect(GTK_WINDOW(uat->rep->window), "delete_event", G_CALLBACK(uat_window_delete_event_cb), uat);
134 g_signal_connect(GTK_WINDOW(uat->rep->window), "destroy", G_CALLBACK(uat_window_delete_event_cb), uat);
138 static char* fld_tostr(void* rec, uat_field_t* f) {
143 f->cb.tostr(rec,&ptr,&len,f->cbdata.tostr,f->fld_data);
146 case PT_TXTMOD_STRING:
148 out = ep_strndup(ptr,len);
150 case PT_TXTMOD_HEXBYTES: {
151 GString* s = g_string_sized_new( len*2 + 1 );
154 for (i=0; i<len;i++) g_string_append_printf(s,"%.2X",((guint8*)ptr)[i]);
156 out = ep_strdup_printf(s->str);
158 g_string_free(s,TRUE);
162 g_assert_not_reached();
172 static void append_row(uat_t* uat, guint idx) {
173 GPtrArray* a = g_ptr_array_new();
174 void* rec = UAT_INDEX_PTR(uat,idx);
175 uat_field_t* f = uat->fields;
179 if (! uat->rep) return;
181 gtk_clist_freeze(GTK_CLIST(uat->rep->clist));
183 for ( colnum = 0; colnum < uat->ncols; colnum++ )
184 g_ptr_array_add(a,fld_tostr(rec,&(f[colnum])));
186 rownum = gtk_clist_append(GTK_CLIST(uat->rep->clist), (gchar**)a->pdata);
187 gtk_clist_set_row_data(GTK_CLIST(uat->rep->clist), rownum, rec);
189 gtk_clist_thaw(GTK_CLIST(uat->rep->clist));
191 g_ptr_array_free(a,TRUE);
194 static void reset_row(uat_t* uat, guint idx) {
195 void* rec = UAT_INDEX_PTR(uat,idx);
196 uat_field_t* f = uat->fields;
199 if (! uat->rep) return;
201 gtk_clist_freeze(GTK_CLIST(uat->rep->clist));
203 for ( colnum = 0; colnum < uat->ncols; colnum++ ) {
204 gtk_clist_set_text(GTK_CLIST(uat->rep->clist), idx, colnum, fld_tostr(rec,&(f[colnum])));
207 gtk_clist_thaw(GTK_CLIST(uat->rep->clist));
211 static guint8* unhexbytes(const char* si, guint len, guint* len_p, const char** err) {
214 const guint8* s = (void*)si;
218 *err = "Uneven number of chars hex string";
222 buf = ep_alloc(len/2+1);
225 for (i = 0; i<len ; i += 2) {
229 if (hi >= '0' && hi <= '9') {
231 } else if (hi >= 'a' && hi <= 'f') {
234 } else if (hi >= 'A' && hi <= 'F') {
241 if (lo >= '0' && lo <= '9') {
243 } else if (lo >= 'a' && lo <= 'f') {
246 } else if (lo >= 'A' && lo <= 'F') {
253 *(p++) = (hi*0x10) + lo;
258 if (len_p) *len_p = len;
266 *err = "Error parsing hex string";
271 static gboolean uat_dlg_cb(GtkWidget *win _U_, gpointer user_data) {
272 struct _uat_dlg_data* dd = user_data;
273 guint ncols = dd->uat->ncols;
274 uat_field_t* f = dd->uat->fields;
275 const char* err = NULL;
278 for ( colnum = 0; colnum < ncols; colnum++ ) {
279 void* e = g_ptr_array_index(dd->entries,colnum);
283 switch(f[colnum].mode) {
284 case PT_TXTMOD_STRING:
285 text = gtk_entry_get_text(GTK_ENTRY(e));
288 case PT_TXTMOD_HEXBYTES: {
289 text = gtk_entry_get_text(GTK_ENTRY(e));
291 text = (void*) unhexbytes(text, strlen(text), &len, &err);
294 err = ep_strdup_printf("error in field '%s': %s",f[colnum].name,err);
300 case PT_TXTMOD_ENUM: {
302 text = text ? text : "";
307 g_assert_not_reached();
312 if (f[colnum].cb.chk) {
313 if (! f[colnum].cb.chk(dd->rec, text, len, f[colnum].cbdata.chk, f[colnum].fld_data, &err)) {
314 err = ep_strdup_printf("error in field '%s': %s",f[colnum].name,err);
319 f[colnum].cb.set(dd->rec,text,len, f[colnum].cbdata.set, f[colnum].fld_data);
322 if (dd->uat->update_cb) {
323 dd->uat->update_cb(dd->rec,&err);
326 err = ep_strdup_printf("error updating record: %s",err);
332 void* rec_tmp = dd->rec;
333 dd->rec = uat_add_record(dd->uat, dd->rec);
335 if (dd->uat->free_cb) {
336 dd->uat->free_cb(rec_tmp);
342 dd->uat->changed = TRUE;
344 set_buttons(dd->uat,-1);
347 append_row(dd->uat, (*dd->uat->nrows_p) - 1 );
349 reset_row(dd->uat,dd->row);
352 g_ptr_array_free(dd->entries,TRUE);
353 window_destroy(GTK_WIDGET(dd->win));
356 window_present(GTK_WIDGET(dd->uat->rep->window));
358 while (dd->tobe_freed->len) g_free( g_ptr_array_remove_index_fast(dd->tobe_freed, dd->tobe_freed->len - 1 ) );
365 report_failure("%s",err);
369 static gboolean uat_cancel_dlg_cb(GtkWidget *win _U_, gpointer user_data) {
370 struct _uat_dlg_data* dd = user_data;
373 window_present(GTK_WIDGET(dd->uat->rep->window));
375 if (dd->is_new) g_free(dd->rec);
376 g_ptr_array_free(dd->entries,TRUE);
377 window_destroy(GTK_WIDGET(dd->win));
379 while (dd->tobe_freed->len) g_free( g_ptr_array_remove_index_fast(dd->tobe_freed, dd->tobe_freed->len - 1 ) );
386 struct _fld_menu_item_data_t {
391 static void fld_menu_item_cb(GtkMenuItem *menuitem _U_, gpointer user_data) {
392 struct _fld_menu_item_data_t* md = user_data;
394 *(md->valptr) = md->text;
397 static void fld_menu_item_destroy_cb(GtkMenuItem *menuitem _U_, gpointer user_data) {
401 static void uat_edit_dialog(uat_t* uat, gint row) {
402 GtkWidget *win, *main_tb, *main_vb, *bbox, *bt_cancel, *bt_ok;
403 struct _uat_dlg_data* dd = g_malloc(sizeof(struct _uat_dlg_data));
404 uat_field_t* f = uat->fields;
406 GtkTooltips *tooltips;
408 tooltips = gtk_tooltips_new();
410 dd->entries = g_ptr_array_new();
411 dd->win = dlg_conf_window_new(ep_strdup_printf("%s: %s", uat->name, (row == -1 ? "New" : "Edit")));
413 dd->rec = row < 0 ? g_malloc0(uat->record_size) : UAT_INDEX_PTR(uat,row);
414 dd->is_new = row < 0 ? TRUE : FALSE;
416 dd->tobe_freed = g_ptr_array_new();
420 gtk_window_set_resizable(GTK_WINDOW(win),FALSE);
421 gtk_window_resize(GTK_WINDOW(win),400, 30*(uat->ncols+2));
423 main_vb = gtk_vbox_new(FALSE,5);
424 gtk_container_add(GTK_CONTAINER(win), main_vb);
425 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 6);
427 main_tb = gtk_table_new(uat->ncols+1, 2, FALSE);
428 gtk_box_pack_start(GTK_BOX(main_vb), main_tb, FALSE, FALSE, 0);
429 gtk_table_set_row_spacings(GTK_TABLE(main_tb), 5);
430 gtk_table_set_col_spacings(GTK_TABLE(main_tb), 10);
432 for ( colnum = 0; colnum < uat->ncols; colnum++ ) {
433 GtkWidget *entry, *label, *event_box;
434 char* text = fld_tostr(dd->rec,&(f[colnum]));
436 event_box = gtk_event_box_new();
438 label = gtk_label_new(f[colnum].name);
439 if (f[colnum].desc != NULL)
440 gtk_tooltips_set_tip(tooltips, event_box, f[colnum].desc, NULL);
442 gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
443 gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box, 0, 1, colnum+1, colnum + 2);
444 gtk_container_add(GTK_CONTAINER(event_box), label);
446 switch(f[colnum].mode) {
447 case PT_TXTMOD_STRING:
448 case PT_TXTMOD_HEXBYTES: {
449 entry = gtk_entry_new();
450 g_ptr_array_add(dd->entries,entry);
451 gtk_table_attach_defaults(GTK_TABLE(main_tb), entry, 1, 2, colnum+1, colnum + 2);
453 gtk_entry_set_text(GTK_ENTRY(entry),text);
457 case PT_TXTMOD_ENUM: {
458 GtkWidget *menu, *option_menu;
459 int menu_index, index;
460 const value_string* enum_vals = f[colnum].fld_data;
461 void* valptr = g_malloc0(sizeof(void*));
463 menu = gtk_menu_new();
465 for (index = 0; enum_vals[index].strptr != NULL; index++) {
466 struct _fld_menu_item_data_t* md = g_malloc(sizeof(struct _fld_menu_item_data_t));
467 const char* str = enum_vals[index].strptr;
468 GtkWidget* menu_item = gtk_menu_item_new_with_label(str);
473 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
475 if ( g_str_equal(str, text) ) {
477 *((char const**)valptr) = str;
480 g_signal_connect(menu_item, "activate", G_CALLBACK(fld_menu_item_cb), md);
481 g_signal_connect(menu_item, "destroy", G_CALLBACK(fld_menu_item_destroy_cb), md);
484 g_ptr_array_add(dd->entries,valptr);
485 g_ptr_array_add(dd->tobe_freed,valptr);
487 /* Create the option menu from the menu */
488 option_menu = gtk_option_menu_new();
489 gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), menu);
491 /* Set its current value to the variable's current value */
492 if (menu_index != -1)
493 gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), menu_index);
495 gtk_table_attach_defaults(GTK_TABLE(main_tb), option_menu, 1, 2, colnum+1, colnum + 2);
500 g_assert_not_reached();
505 bbox = dlg_button_row_new(GTK_STOCK_CANCEL,GTK_STOCK_OK, NULL);
506 gtk_box_pack_end(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
508 bt_ok = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
509 g_signal_connect(bt_ok, "clicked", G_CALLBACK(uat_dlg_cb), dd);
511 bt_cancel = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
512 g_signal_connect(bt_cancel, "clicked", G_CALLBACK(uat_cancel_dlg_cb), dd);
513 window_set_cancel_button(win, bt_cancel, NULL);
515 gtk_widget_show_all(win);
524 static void uat_del_cb(GtkButton *button _U_, gpointer u) {
525 struct _uat_del* ud = u;
527 uat_remove_record_idx(ud->uat, ud->idx);
530 gtk_clist_remove(GTK_CLIST(ud->uat->rep->clist),ud->idx);
532 ud->uat->changed = TRUE;
533 set_buttons(ud->uat,-1);
535 window_destroy(GTK_WIDGET(ud->win));
538 window_present(GTK_WIDGET(ud->uat->rep->window));
543 static void uat_cancel_del_cb(GtkButton *button _U_, gpointer u) {
544 struct _uat_del* ud = u;
545 window_destroy(GTK_WIDGET(ud->win));
548 window_present(GTK_WIDGET(ud->uat->rep->window));
552 static void uat_del_dlg(uat_t* uat, int idx) {
553 GtkWidget *win, *main_tb, *main_vb, *bbox, *bt_cancel, *bt_ok;
554 uat_field_t* f = uat->fields;
556 void* rec = UAT_INDEX_PTR(uat,idx);
557 struct _uat_del* ud = g_malloc(sizeof(struct _uat_del));
561 ud->win = win = dlg_conf_window_new(ep_strdup_printf("%s: Confirm Delete", uat->name));
563 gtk_window_set_resizable(GTK_WINDOW(win),FALSE);
564 gtk_window_resize(GTK_WINDOW(win),400,25*(uat->ncols+2));
566 main_vb = gtk_vbox_new(FALSE,5);
567 gtk_container_add(GTK_CONTAINER(win), main_vb);
568 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 6);
570 main_tb = gtk_table_new(uat->ncols+1, 2, FALSE);
571 gtk_box_pack_start(GTK_BOX(main_vb), main_tb, FALSE, FALSE, 0);
572 gtk_table_set_row_spacings(GTK_TABLE(main_tb), 10);
573 gtk_table_set_col_spacings(GTK_TABLE(main_tb), 15);
575 for ( colnum = 0; colnum < uat->ncols; colnum++ ) {
577 char* text = fld_tostr(rec,&(f[colnum]));
579 label = gtk_label_new(f[colnum].name);
580 gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
581 gtk_table_attach_defaults(GTK_TABLE(main_tb), label, 0, 1, colnum+1, colnum + 2);
583 label = gtk_label_new(text);
584 gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
585 gtk_table_attach_defaults(GTK_TABLE(main_tb), label, 1, 2, colnum+1, colnum + 2);
588 bbox = dlg_button_row_new(GTK_STOCK_CANCEL,GTK_STOCK_DELETE, NULL);
589 gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
591 bt_ok = g_object_get_data(G_OBJECT(bbox),GTK_STOCK_DELETE);
592 g_signal_connect(bt_ok, "clicked", G_CALLBACK(uat_del_cb), ud);
594 bt_cancel = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
595 g_signal_connect(bt_cancel, "clicked", G_CALLBACK(uat_cancel_del_cb), ud);
596 window_set_cancel_button( win, bt_cancel, NULL);
598 gtk_widget_show_all(win);
601 static void uat_new_cb(GtkButton *button _U_, gpointer u) {
604 if (! uat->rep) return;
606 uat_edit_dialog(uat, -1);
609 static void uat_edit_cb(GtkButton *button _U_, gpointer u) {
612 if (! uat->rep) return;
614 uat_edit_dialog(uat, uat->rep->selected);
617 static void uat_delete_cb(GtkButton *button _U_, gpointer u) {
620 if (! uat->rep) return;
622 uat_del_dlg(uat,uat->rep->selected);
625 static gboolean uat_window_delete_event_cb(GtkWindow *w _U_, GdkEvent* e _U_, gpointer u) {
629 void* rep = uat->rep;
631 g_signal_handlers_disconnect_by_func(uat->rep->window, uat_window_delete_event_cb, uat);
632 g_signal_handlers_disconnect_by_func(uat->rep->window, unsaved_dialog, uat);
634 gtk_widget_destroy(uat->rep->window);
637 if (rep) g_free(rep);
642 static void uat_up_cb(GtkButton *button _U_, gpointer u) {
644 guint row = uat->rep->selected;
648 uat_swap(uat,row,row-1);
649 gtk_clist_swap_rows(GTK_CLIST(uat->rep->clist),row,row-1);
654 uat->rep->selected = row;
655 set_buttons(uat,row);
658 static void uat_down_cb(GtkButton *button _U_, gpointer u) {
660 guint row = uat->rep->selected;
662 g_assert(row < *uat->nrows_p - 1);
664 uat_swap(uat,row,row+1);
665 gtk_clist_swap_rows(GTK_CLIST(uat->rep->clist),row,row+1);
670 uat->rep->selected = row;
671 set_buttons(uat,row);
674 static void uat_cancel_cb(GtkWidget *button _U_, gpointer u) {
683 report_failure("Error while loading %s: %s",uat->name,err);
686 if (cfile.state == FILE_READ_DONE) cf_reload(&cfile);
689 g_signal_handlers_disconnect_by_func(uat->rep->window, uat_window_delete_event_cb, uat);
690 g_signal_handlers_disconnect_by_func(uat->rep->window, unsaved_dialog, uat);
691 gtk_widget_destroy(uat->rep->window);
696 static void uat_apply_cb(GtkButton *button _U_, gpointer u) {
699 uat_window_delete_event_cb(NULL,NULL,uat);
701 if (uat->changed && cfile.state == FILE_READ_DONE)
705 static void uat_ok_cb(GtkButton *button _U_, gpointer u) {
713 report_failure("Error while saving %s: %s",uat->name,err);
716 if (cfile.state == FILE_READ_DONE) cf_reload(&cfile);
719 g_signal_handlers_disconnect_by_func(uat->rep->window, uat_window_delete_event_cb, uat);
720 g_signal_handlers_disconnect_by_func(uat->rep->window, unsaved_dialog, uat);
721 gtk_widget_destroy(uat->rep->window);
728 static void remember_selected_row(GtkCList *clist _U_, gint row, gint column _U_, GdkEvent *event _U_, gpointer u) {
731 uat->rep->selected = row;
733 gtk_widget_set_sensitive (uat->rep->bt_edit, TRUE);
734 gtk_widget_set_sensitive(uat->rep->bt_delete, TRUE);
736 set_buttons(uat,row);
739 static void uat_yessave_cb(GtkWindow *w _U_, void* u) {
743 window_delete_event_cb(uat->rep->unsaved_window,NULL,NULL);
748 report_failure("Error while saving %s: %s",uat->name,err);
751 g_signal_handlers_disconnect_by_func(uat->rep->window, uat_window_delete_event_cb, uat);
752 g_signal_handlers_disconnect_by_func(uat->rep->window, unsaved_dialog, uat);
753 window_destroy(uat->rep->window);
760 static void uat_nosave_cb(GtkWindow *w _U_, void* u) {
762 window_delete_event_cb(uat->rep->unsaved_window,NULL,NULL);
763 g_signal_handlers_disconnect_by_func(uat->rep->window, uat_window_delete_event_cb, uat);
764 g_signal_handlers_disconnect_by_func(uat->rep->window, unsaved_dialog, uat);
765 window_destroy(uat->rep->window);
771 static gboolean unsaved_dialog(GtkWindow *w _U_, GdkEvent* e _U_, gpointer u) {
772 GtkWidget *win, *vbox, *label, *bbox;
773 GtkWidget *yes_bt, *no_bt;
777 if (uat->rep->unsaved_window) {
778 window_present(uat->rep->unsaved_window);
782 uat->rep->unsaved_window = win = dlg_conf_window_new("Discard Changes?");
783 gtk_window_set_default_size(GTK_WINDOW(win), 360, 140);
785 gtk_window_set_position(GTK_WINDOW(win), GTK_WIN_POS_CENTER_ON_PARENT);
786 vbox = gtk_vbox_new(FALSE, 12);
787 gtk_container_set_border_width(GTK_CONTAINER(vbox), 6);
788 gtk_container_add(GTK_CONTAINER(win), vbox);
790 message = ep_strdup_printf("Changes to '%s' are not being saved!\n"
791 "Do you want to save '%s'?", uat->name, uat->name);
793 label = gtk_label_new(message);
795 bbox = dlg_button_row_new(GTK_STOCK_YES,GTK_STOCK_NO, NULL);
797 yes_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_YES);
798 no_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_NO);
800 g_signal_connect(no_bt, "clicked", G_CALLBACK(uat_nosave_cb), uat);
801 g_signal_connect(yes_bt, "clicked", G_CALLBACK(uat_yessave_cb), uat);
803 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
804 gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
806 gtk_widget_show_all(win);
812 static void uat_help_cb(GtkWidget* w _U_, gpointer u) {
813 help_topic_html(ep_strdup_printf("%s.html",((uat_t*)u)->help));
816 static GtkWidget* uat_window(void* u) {
818 uat_field_t* f = uat->fields;
822 GtkWidget *hbox, *vbox, *move_hbox, *edit_hbox;
825 window_present(uat->rep->window);
826 return uat->rep->window;
828 uat->rep = rep = g_malloc0(sizeof(uat_rep_t));
831 rep->window = dlg_conf_window_new(uat->name);
833 gtk_window_set_resizable(GTK_WINDOW(rep->window),FALSE);
834 gtk_window_resize(GTK_WINDOW(rep->window), 720, 512);
835 gtk_window_set_position(GTK_WINDOW(rep->window), GTK_WIN_POS_CENTER_ON_PARENT);
837 gtk_container_set_border_width(GTK_CONTAINER(rep->window), 6);
839 rep->vbox = gtk_vbox_new(FALSE, 12);
840 gtk_container_set_border_width(GTK_CONTAINER(rep->vbox), 6);
841 gtk_container_add(GTK_CONTAINER(rep->window), rep->vbox);
843 hbox = gtk_hbox_new(FALSE,12);
844 gtk_container_set_border_width(GTK_CONTAINER(hbox), 6);
845 gtk_container_add(GTK_CONTAINER(rep->vbox), hbox);
847 vbox = gtk_vbox_new(FALSE, 12);
848 gtk_container_set_border_width(GTK_CONTAINER(vbox), 6);
849 gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
851 rep->scrolledwindow = scrolled_window_new(NULL, NULL);
852 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(rep->scrolledwindow), GTK_SHADOW_IN);
854 rep->clist = gtk_clist_new(uat->ncols);
855 gtk_container_add(GTK_CONTAINER(rep->scrolledwindow), rep->clist);
856 gtk_box_pack_start(GTK_BOX(hbox), rep->scrolledwindow, TRUE, TRUE, 0);
858 for ( colnum = 0; colnum < uat->ncols; colnum++ ) {
859 gtk_clist_set_column_title(GTK_CLIST(rep->clist), colnum, f[colnum].name);
860 gtk_clist_set_column_auto_resize(GTK_CLIST(rep->clist), colnum, TRUE);
863 gtk_clist_column_titles_show(GTK_CLIST(rep->clist));
864 gtk_clist_freeze(GTK_CLIST(rep->clist));
866 for ( i = 0 ; i < *(uat->nrows_p); i++ ) {
870 gtk_clist_thaw(GTK_CLIST(rep->clist));
872 rep->selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(rep->clist));
873 gtk_tree_selection_set_mode(rep->selection, GTK_SELECTION_SINGLE);
877 rep->bbox = dlg_button_row_new(GTK_STOCK_HELP, GTK_STOCK_OK, GTK_STOCK_APPLY, GTK_STOCK_CANCEL, NULL);
878 help_btn = g_object_get_data(G_OBJECT(rep->bbox),GTK_STOCK_HELP);
879 g_signal_connect(help_btn, "clicked", G_CALLBACK(uat_help_cb), uat);
882 rep->bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_APPLY, GTK_STOCK_CANCEL, NULL);
885 move_hbox = gtk_vbutton_box_new();
886 gtk_box_pack_start(GTK_BOX(vbox), move_hbox, TRUE, FALSE, 0);
888 edit_hbox = gtk_vbutton_box_new();
889 gtk_box_pack_end(GTK_BOX(vbox), edit_hbox, TRUE, FALSE, 0);
892 rep->bt_down = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN);
893 rep->bt_up = gtk_button_new_from_stock(GTK_STOCK_GO_UP);
895 gtk_box_pack_start(GTK_BOX(move_hbox), rep->bt_up, TRUE, FALSE, 5);
896 gtk_box_pack_start(GTK_BOX(move_hbox), rep->bt_down, TRUE, FALSE, 5);
899 rep->bt_new = gtk_button_new_from_stock(GTK_STOCK_NEW);
900 rep->bt_edit = gtk_button_new_from_stock(WIRESHARK_STOCK_EDIT);
901 rep->bt_delete = gtk_button_new_from_stock(GTK_STOCK_DELETE);
903 gtk_box_pack_end(GTK_BOX(edit_hbox), rep->bt_new, TRUE, FALSE, 5);
904 gtk_box_pack_end(GTK_BOX(edit_hbox), rep->bt_edit, TRUE, FALSE, 5);
905 gtk_box_pack_end(GTK_BOX(edit_hbox), rep->bt_delete, TRUE, FALSE, 5);
908 rep->bt_apply = g_object_get_data(G_OBJECT(rep->bbox),GTK_STOCK_APPLY);
909 rep->bt_cancel = g_object_get_data(G_OBJECT(rep->bbox),GTK_STOCK_CANCEL);
910 rep->bt_ok = g_object_get_data(G_OBJECT(rep->bbox),GTK_STOCK_OK);
912 gtk_box_pack_end(GTK_BOX(rep->vbox), rep->bbox, FALSE, FALSE, 0);
914 gtk_widget_set_sensitive (rep->bt_up, FALSE);
915 gtk_widget_set_sensitive (rep->bt_down, FALSE);
916 gtk_widget_set_sensitive (rep->bt_edit, FALSE);
917 gtk_widget_set_sensitive (rep->bt_delete, FALSE);
920 g_signal_connect(rep->selection, "changed", G_CALLBACK(remember_selected_row), uat);
922 g_signal_connect(rep->bt_new, "clicked", G_CALLBACK(uat_new_cb), uat);
923 g_signal_connect(rep->bt_edit, "clicked", G_CALLBACK(uat_edit_cb), uat);
924 g_signal_connect(rep->bt_delete, "clicked", G_CALLBACK(uat_delete_cb), uat);
926 g_signal_connect(rep->bt_up, "clicked", G_CALLBACK(uat_up_cb), uat);
927 g_signal_connect(rep->bt_down, "clicked", G_CALLBACK(uat_down_cb), uat);
929 g_signal_connect(rep->bt_apply, "clicked", G_CALLBACK(uat_apply_cb), uat);
930 g_signal_connect(rep->bt_cancel, "clicked", G_CALLBACK(uat_cancel_cb), uat);
931 g_signal_connect(rep->bt_ok, "clicked", G_CALLBACK(uat_ok_cb), uat);
933 window_set_cancel_button(rep->window, rep->bt_cancel, NULL); /* set esc to activate cancel button */
936 g_signal_connect(GTK_WINDOW(rep->window), "delete_event", G_CALLBACK(unsaved_dialog), uat);
937 g_signal_connect(GTK_WINDOW(rep->window), "destroy", G_CALLBACK(unsaved_dialog), uat);
939 g_signal_connect(GTK_WINDOW(rep->window), "delete_event", G_CALLBACK(uat_window_delete_event_cb), uat);
940 g_signal_connect(GTK_WINDOW(rep->window), "destroy", G_CALLBACK(uat_window_delete_event_cb), uat);
943 gtk_widget_grab_focus(rep->clist);
945 gtk_widget_show_all(rep->window);
946 window_present(rep->window);
951 void uat_window_cb(GtkWidget* u _U_, void* uat) {