aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuis Ontanon <luis.ontanon@gmail.com>2007-02-07 03:39:40 +0000
committerLuis Ontanon <luis.ontanon@gmail.com>2007-02-07 03:39:40 +0000
commitbc2ca610836d19dfc506e484abc3dba07e37a522 (patch)
treefd84057835825c1a29266b7d03e4fa0b6671497f
parentbc09ad6f17f158b4845c9dc9fbcfbeae40f947d8 (diff)
Add ENUM and HEXBYTES modes
svn path=/trunk/; revision=20733
-rw-r--r--epan/uat.c33
-rw-r--r--epan/uat.h85
-rw-r--r--epan/uat_load.l67
-rw-r--r--gtk/uat_gui.c289
4 files changed, 352 insertions, 122 deletions
diff --git a/epan/uat.c b/epan/uat.c
index de8966a329..3f2a560796 100644
--- a/epan/uat.c
+++ b/epan/uat.c
@@ -174,6 +174,7 @@ static void putfld(FILE* fp, void* rec, uat_field_t* f) {
f->cb.tostr(rec,&fld_ptr,&fld_len,f->cbdata.tostr,f->fld_data);
switch(f->mode){
+ case PT_TXTMOD_ENUM:
case PT_TXTMOD_STRING: {
guint i;
@@ -196,7 +197,7 @@ static void putfld(FILE* fp, void* rec, uat_field_t* f) {
guint i;
for(i=0;i<fld_len;i++) {
- fprintf(fp,"%.2x",fld_ptr[i]);
+ fprintf(fp,"%.2x",((guint8*)fld_ptr)[i]);
}
return;
@@ -311,30 +312,20 @@ gboolean uat_fld_chk_proto(void* u1 _U_, const char* strptr, unsigned len, void*
}
}
-gboolean uat_fld_chk_num_dec(void* u1 _U_, const char* strptr, unsigned len, void* u2 _U_, void* u3 _U_, char** err) {
+gboolean uat_fld_chk_enum(void* u1 _U_, const char* strptr, unsigned len, void* v, void* u3 _U_, char** err) {
char* str = ep_strndup(strptr,len);
- long i = strtol(str,&str,10);
+ guint i;
+ value_string* vs = v;
- if ( ( i == 0) && (errno == ERANGE || errno == EINVAL) ) {
- *err = strerror(errno);
- return FALSE;
+ for(i=0;vs[i].strptr;i++) {
+ if (g_str_equal(vs[i].strptr,str)) {
+ *err = NULL;
+ return TRUE;
+ }
}
-
- *err = NULL;
- return TRUE;
-}
-gboolean uat_fld_chk_num_hex(void* u1 _U_, const char* strptr, unsigned len, void* u2 _U_, void* u3 _U_, char** err) {
- char* str = ep_strndup(strptr,len);
- long i = strtol(str,&str,16);
-
- if ( ( i == 0) && (errno == ERANGE || errno == EINVAL) ) {
- *err = strerror(errno);
- return FALSE;
- }
-
- *err = NULL;
- return TRUE;
+ *err = ep_strdup_printf("invalid value: %s",str);
+ return FALSE;
}
CHK_STR_IS_DEF(isprint)
diff --git a/epan/uat.h b/epan/uat.h
index 1b025ea3f3..068622ca49 100644
--- a/epan/uat.h
+++ b/epan/uat.h
@@ -168,6 +168,7 @@ typedef enum _uat_text_mode_t {
"invalid" as NULL,3
"a1b" as NULL, 1
*/
+ PT_TXTMOD_ENUM
} uat_text_mode_t;
/*
@@ -253,6 +254,7 @@ gboolean uat_fld_chk_str(void*, const char*, unsigned, void*,void*, char** err);
gboolean uat_fld_chk_proto(void*, const char*, unsigned, void*,void*, char** err);
gboolean uat_fld_chk_num_dec(void*, const char*, unsigned, void*, void*, char** err);
gboolean uat_fld_chk_num_hex(void*, const char*, unsigned, void*, void*, char** err);
+gboolean uat_fld_chk_enum(void*, const char*, unsigned, void*, void*, char**);
#define CHK_STR_IS_DECL(what) \
gboolean uat_fld_chk_str_ ## what (void*, const char*, unsigned, void*, void*, char**)
@@ -302,6 +304,23 @@ static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr,
#define UAT_FLD_CSTRING_OTHER(basename,field_name,chk) \
{#field_name, PT_TXTMOD_STRING,{ chk ,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{NULL,NULL,NULL},NULL,FLDFILL}
+/*
+ * LSTRING MACROS
+ */
+#define UAT_LSTRING_CB_DEF(basename,field_name,rec_t,ptr_element,len_element) \
+static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, void* u1 _U_, void* u2 _U_) {\
+ if ((((rec_t*)rec)->ptr_element)) g_free((((rec_t*)rec)->ptr_element)); \
+ (((rec_t*)rec)->ptr_element) = g_strndup(buf,len); \
+ (((rec_t*)rec)->len_element) = len; } \
+static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, void* u1 _U_, void* u2 _U_) {\
+ if (((rec_t*)rec)->ptr_element ) { \
+ *out_ptr = (((rec_t*)rec)->ptr_element); *out_len = (((rec_t*)rec)->len_element); \
+ } else { \
+ *out_ptr = ""; *out_len = 0; } }
+
+#define UAT_FLD_LSTRING(basename,field_name) \
+{#field_name, PT_TXTMOD_STRING,{NULL,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{NULL,NULL,NULL},NULL,FLDFILL}
+
/*
* BUFFER macros,
@@ -309,17 +328,17 @@ static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr,
* and its len in (((rec_t*)rec)->(len_name))
* XXX: UNTESTED
*/
-#define UAT_BUFFER_CB_DEF(field_name,len_name,rec_t,ptr_element,len_element) \
-static void basename ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, void* u1 _U_, void* u2 _U_) {\
- if ((((rec_t*)rec)->(field_name))) g_free((((rec_t*)rec)->(field_name))); \
- (((rec_t*)rec)->(field_name)) = g_memdup(buf,len); \
- (((rec_t*)rec)->(len_name)) = len; \ } \
-static void basename ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, void* u1 _U_, void* u2 _U_) {\
- *out_ptr = ep_memdup(((rec_t*)rec)->(field_name),((rec_t*)rec)->(len_name)); \
- *len_ptr = (((rec_t*)rec)->(len_name)); }
+#define UAT_BUFFER_CB_DEF(basename,field_name,rec_t,ptr_element,len_element) \
+static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, void* u1 _U_, void* u2 _U_) {\
+ if ((((rec_t*)rec)->ptr_element) ) g_free((((rec_t*)rec)->ptr_element)); \
+ (((rec_t*)rec)->ptr_element) = len ? g_memdup(buf,len) : NULL; \
+ (((rec_t*)rec)->len_element) = len; } \
+static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, void* u1 _U_, void* u2 _U_) {\
+ *out_ptr = ((rec_t*)rec)->ptr_element ? ep_memdup(((rec_t*)rec)->ptr_element,((rec_t*)rec)->len_element) : ""; \
+ *out_len = ((rec_t*)rec)->len_element; }
#define UAT_FLD_BUFFER(basename,field_name) \
- {#field_name, PT_TXTMOD_HEXBYTES,{NULL,basename ## field_name ## _set_cb,basename ## field_name ## _tostr_cb},{NULL,NULL,NULL},NULL,FLDFILL}
+ {#field_name, PT_TXTMOD_HEXBYTES,{NULL,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{NULL,NULL,NULL},NULL,FLDFILL}
/*
@@ -327,14 +346,14 @@ static void basename ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsig
* a decimal number contained in
*/
#define UAT_DEC_CB_DEF(basename,field_name,rec_t) \
-static void basename ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, void* u1 _U_, void* u2 _U_) {\
+static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, void* u1 _U_, void* u2 _U_) {\
((rec_t*)rec)->(field_name) = strtol(buf,end,10); } \
-static void basename ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, void* u1 _U_, void* u2 _U_) {\
+static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, void* u1 _U_, void* u2 _U_) {\
*out_ptr = ep_strdup_printf("%d",((rec_t*)rec)->(field_name)); \
*out_len = strlen(*out_ptr); }
#define UAT_FLD_DEC(basename,field_name) \
- {#field_name, PT_TXTMOD_STRING,{uat_fld_chk_num_dec,basename ## field_name ## _set_cb,basename ## field_name ## _tostr_cb},{NULL,NULL,NULL},NULL,FLDFILL}
+ {#field_name, PT_TXTMOD_STRING,{uat_fld_chk_num_dec,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{NULL,NULL,NULL},NULL,FLDFILL}
/*
@@ -342,14 +361,14 @@ static void basename ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsig
* an hexadecimal number contained in
*/
#define UAT_HEX_CB_DEF(basename,field_name,rec_t) \
-static void basename ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, void* u1 _U_, void* u2 _U_) {\
+static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, void* u1 _U_, void* u2 _U_) {\
((rec_t*)rec)->(field_name) = strtol(buf,end,16); } \
-static void basename ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, void* u1 _U_, void* u2 _U_) {\
+static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, void* u1 _U_, void* u2 _U_) {\
*out_ptr = ep_strdup_printf("%x",((rec_t*)rec)->(field_name)); \
*out_len = strlen(*out_ptr); }
#define UAT_FLD_HEX(basename,field_name) \
-{#field_name, PT_TXTMOD_STRING,{uat_fld_chk_num_hex,basename ## field_name ## _set_cb,basename ## field_name ## _tostr_cb},{NULL,NULL,NULL},NULL,FLDFILL}
+{#field_name, PT_TXTMOD_STRING,{uat_fld_chk_num_hex,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{NULL,NULL,NULL},NULL,FLDFILL}
/*
@@ -359,25 +378,25 @@ static void basename ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsig
* rec_t:
* value
*/
-#define UAT_SET_ENUM_DEF(basename,field_name,rec_t,enum_t,default) \
-void static void basename ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, void* enum, void* u2 _U_) {\
+#define UAT_VS_DEF(basename,field_name,rec_t,default_val,default_str) \
+static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, void* vs, void* u2 _U_) {\
+ guint i; ((rec_t*)rec)->field_name = default_val; \
char* str = ep_strndup(buf,len); \
- for(;((enum_t*)enum)->strptr;((enum_t*)enum)++) { \
- if (g_strequal(((enum_t*)enum)->strptr,str)) { \
- ((rec_t*)rec)->(field_name) = ((enum_t*)enum)->value; return; } } \
- (rec_t*)rec)->(field_name) = default; \
-}
-
-#define UAT_TOSTR_ENUM_DEF(basename,field_name,rec_t,enum_t) {\
-static void basename ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, void* enum, void* u2 _U_) {\
- for(;((enum_t*)enum)->strptr;((enum_t*)enum)++) { \
- if ( ((enum_t*)enum)->value == ((rec_t*)rec)->(field_name) ) { \
- *out_str = ((enum_t*)enum)->strptr; \
- *out_len = strlen(*out_ptr); } } }
-
-
-#define UAT_FLD_ENUM(basename,field_name,enum_t,enum) \
- {#field_name, PT_TXTMOD_STRING,{uat_fld_chk_enum,basename ## field_name ## _set_cb,basename ## field_name ## _tostr_cb},{&(enum),&(enum),&(enum)},NULL,FLDFILL}
+ char* cstr;\
+ for(i=0; ( cstr = ((value_string*)vs)[i].strptr ) ;i++) { \
+ if (g_str_equal(cstr,str)) { \
+ ((rec_t*)rec)->field_name = ((value_string*)vs)[i].value; return; } } } \
+static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, void* vs, void* u2 _U_) {\
+ guint i; \
+ *out_ptr = default_str; *out_len = strlen(default_str);\
+ for(i=0;((value_string*)vs)[i].strptr;i++) { \
+ if ( ((value_string*)vs)[i].value == ((rec_t*)rec)->field_name ) { \
+ *out_ptr = ep_strdup(((value_string*)vs)[i].strptr); \
+ *out_len = strlen(*out_ptr); return; } } }
+
+
+#define UAT_FLD_VS(basename,field_name,enum) \
+ {#field_name, PT_TXTMOD_ENUM,{uat_fld_chk_enum,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{&(enum),&(enum),&(enum)},&(enum),FLDFILL}
diff --git a/epan/uat_load.l b/epan/uat_load.l
index 9e2cf3f392..b5ef2ff268 100644
--- a/epan/uat_load.l
+++ b/epan/uat_load.l
@@ -1,12 +1,11 @@
%option noyywrap
-%option nounput
%option prefix="uat_load_"
%option never-interactive
-%option yylineno
+%option nounput
%{
/*
- * uat_load.c
+ * uat_load.l
*
* $Id$
*
@@ -55,27 +54,28 @@
static guint len;
static gchar* error;
static void* record;
-
+ static guint linenum;
+
static char* unbinstring(const char* si, guint in_len, guint* len_p);
static char* undquote(const char* si, guint in_len, guint* len_p);
-#define ERROR(fmtd) do { error = ep_strdup_printf("%s:%d: %s",uat->filename,yylineno,ep_strdup_printf fmtd); yyterminate(); } while(0)
+#define ERROR(fmtd) do { error = ep_strdup_printf("%s:%d: %s",uat->filename,linenum,ep_strdup_printf fmtd); yyterminate(); } while(0)
#define SET_FIELD() \
{ gchar* err; \
if (uat->fields[colnum].cb.chk) { \
- if ( ! uat->fields[colnum].cb.chk(record, ptr, len, uat->fields[colnum].cbdata.chk,uat->fields[colnum].fld_data, &err) ) { \
+ if ( ! uat->fields[colnum].cb.chk(record, ptr, len, uat->fields[colnum].cbdata.chk, uat->fields[colnum].fld_data, &err) ) { \
ERROR(("%s",err)); \
}\
}\
- uat->fields[colnum].cb.set(record, ptr, len,uat->fields[colnum].cbdata.chk,uat->fields[colnum].fld_data);\
+ uat->fields[colnum].cb.set(record, ptr, len, uat->fields[colnum].cbdata.chk, uat->fields[colnum].fld_data);\
g_free(ptr);\
colnum++; \
} while(0)
#ifdef DEBUG_UAT_LOAD
#define DUMP_FIELD(str) \
- { guint i; printf("%s: '",str); for(i=0;i<len;i++) putc(ptr[i],stdout); printf("'[%d]\n",len); }
+ { guint i; printf("%s: %s='",str,uat->fields[colnum].name); for(i=0;i<len;i++) if (uat->fields[colnum].mode == PT_TXTMOD_HEXBYTES) { printf("%.2x ",((guint8*)ptr)[i]); } else putc(ptr[i],stdout); printf("'[%d]\n",len); }
#define DUMP(str) printf("%s\n",str)
#else
@@ -90,7 +90,7 @@
%}
quoted_string \042([^\042]|\134\134|\134\042)*\042
-binstring ([0-9a-zA-Z][0-9a-zA-Z])+
+binstring ([0-9a-zA-Z][0-9a-zA-Z])*
separator [ \t]*,
newline [ \t]*[\r]?\n
ws [ \t]+
@@ -99,11 +99,31 @@ comment #[^\n]*\n
%x START_OF_LINE NEXT_FIELD SEPARATOR END_OF_RECORD ERRORED
%%
<START_OF_LINE,NEXT_FIELD>{ws} ;
-<START_OF_LINE>{newline} ;
+<START_OF_LINE>{newline} linenum++;
<START_OF_LINE>{comment} ;
-<NEXT_FIELD>{newline} {
- ERROR(("expecting %s field in previuos line",uat->fields[colnum].name));
- BEGIN START_OF_LINE;
+
+<START_OF_LINE,NEXT_FIELD>{separator} {
+ ptr = g_strdup("");
+ len = 0;
+
+ DUMP_FIELD("empty->next");
+
+ SET_FIELD();
+
+ if ( colnum >= uat->ncols ) {
+ ERROR(("more fields than required"));
+ }
+
+ BEGIN NEXT_FIELD;
+}
+
+<START_OF_LINE,NEXT_FIELD>{newline} {
+ ptr = "";
+ len = 0;
+
+ BEGIN END_OF_RECORD;
+
+ yyless(yyleng);
}
<START_OF_LINE,NEXT_FIELD>{quoted_string} {
@@ -149,12 +169,13 @@ comment #[^\n]*\n
}
<SEPARATOR>{newline} {
+ linenum++;
ERROR(("expecting field %s in previuos line",uat->fields[colnum].name));
BEGIN START_OF_LINE;
}
<SEPARATOR>. {
- ERROR(("unexpected char while looking for field %s",uat->fields[colnum].name));
+ ERROR(("unexpected char '%s' while looking for field %s",yytext,uat->fields[colnum].name));
BEGIN ERRORED;
}
@@ -167,6 +188,8 @@ comment #[^\n]*\n
void* rec;
gchar* err = NULL;
+ linenum++;
+
DUMP_FIELD("newline->start");
SET_FIELD();
@@ -193,10 +216,10 @@ comment #[^\n]*\n
BEGIN ERRORED;
}
-<ERRORED>{newline} BEGIN START_OF_LINE;
+<ERRORED>{newline} { linenum++; BEGIN START_OF_LINE; }
<ERRORED>. ;
-{newline} { ERROR(("incomplete record")); }
+{newline} { linenum++; ERROR(("incomplete record")); BEGIN START_OF_LINE; }
. { ERROR(("unexpected input")); }
%%
@@ -224,7 +247,7 @@ static int xton(char d) {
}
static char* unbinstring(const char* si, guint in_len, guint* len_p) {
- char* buf;
+ guint8* buf;
guint len = in_len/2;
int i = 0;
@@ -232,7 +255,7 @@ static char* unbinstring(const char* si, guint in_len, guint* len_p) {
return NULL;
}
- buf= g_malloc(len); /* wastes one byte for every '\\' in text */
+ buf= g_malloc(len);
*len_p = len;
while(in_len) {
@@ -244,7 +267,7 @@ static char* unbinstring(const char* si, guint in_len, guint* len_p) {
in_len -= 2;
}
- return buf;
+ return (void*)buf;
}
static char* undquote(const char* si, guint in_len, guint* len_p) {
@@ -346,6 +369,7 @@ gboolean uat_load(uat_t* uat_in, char** err) {
UAT_UPDATE(uat);
return TRUE;
}
+
if (!(yyin = fopen(fname,"r"))) {
*err = strerror(errno);
@@ -355,11 +379,14 @@ gboolean uat_load(uat_t* uat_in, char** err) {
error = NULL;
colnum = 0;
record = g_malloc0(uat->record_size);
+ linenum = 1;
BEGIN START_OF_LINE;
+ DUMP(fname);
yylex();
-
+ yyrestart(NULL);
+
uat->changed = FALSE;
if (error) {
diff --git a/gtk/uat_gui.c b/gtk/uat_gui.c
index 7d200e5820..5539986fea 100644
--- a/gtk/uat_gui.c
+++ b/gtk/uat_gui.c
@@ -26,6 +26,14 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+
+/*
+ * TO DO:
+ * + improvements
+ * - field value check (red/green editbox)
+ * - tooltips (add field descriptions)
+ */
+
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
@@ -46,6 +54,7 @@
#include "compat_macros.h"
#include <epan/uat-int.h>
+#include <epan/value_string.h>
#include "uat_gui.h"
#if GTK_MAJOR_VERSION >= 2
@@ -93,6 +102,7 @@ struct _uat_dlg_data {
void* rec;
gboolean is_new;
gint row;
+ GPtrArray* tobe_freed;
};
@@ -136,6 +146,39 @@ static void set_buttons(uat_t* uat, gint row) {
}
}
+static char* fld_tostr(void* rec, uat_field_t* f) {
+ guint len;
+ char* ptr;
+ char* out;
+
+ f->cb.tostr(rec,&ptr,&len,f->cbdata.tostr,f->fld_data);
+
+ switch(f->mode) {
+ case PT_TXTMOD_STRING:
+ case PT_TXTMOD_ENUM:
+ out = ep_strndup(ptr,len);
+ break;
+ case PT_TXTMOD_HEXBYTES: {
+ GString* s = g_string_sized_new( len*2 + 1 );
+ guint i;
+
+ for (i=0; i<len;i++) g_string_sprintfa(s,"%.2X",((guint8*)ptr)[i]);
+
+ out = ep_strdup_printf(s->str);
+
+ g_string_free(s,TRUE);
+ break;
+ }
+ default:
+ g_assert_not_reached();
+ break;
+ }
+
+ return out;
+}
+
+
+
static void append_row(uat_t* uat, guint idx) {
GPtrArray* a = g_ptr_array_new();
void* rec = UAT_INDEX_PTR(uat,idx);
@@ -145,12 +188,8 @@ static void append_row(uat_t* uat, guint idx) {
gtk_clist_freeze(GTK_CLIST(uat->rep->clist));
- for ( colnum = 0; colnum < uat->ncols; colnum++ ) {
- guint len;
- char* ptr;
- f[colnum].cb.tostr(rec,&ptr,&len,f[colnum].cbdata.tostr,f[colnum].fld_data);
- g_ptr_array_add(a,ptr);
- }
+ for ( colnum = 0; colnum < uat->ncols; colnum++ )
+ g_ptr_array_add(a,fld_tostr(rec,&(f[colnum])));
rownum = gtk_clist_append(GTK_CLIST(uat->rep->clist), (gchar**)a->pdata);
gtk_clist_set_row_data(GTK_CLIST(uat->rep->clist), rownum, rec);
@@ -168,16 +207,72 @@ static void reset_row(uat_t* uat, guint idx) {
gtk_clist_freeze(GTK_CLIST(uat->rep->clist));
for ( colnum = 0; colnum < uat->ncols; colnum++ ) {
- guint len;
- char* ptr;
- f[colnum].cb.tostr(rec,&ptr,&len,f[colnum].cbdata.tostr,f[colnum].fld_data);
- gtk_clist_set_text(GTK_CLIST(uat->rep->clist), idx, colnum, ptr);
+ gtk_clist_set_text(GTK_CLIST(uat->rep->clist), idx, colnum, fld_tostr(rec,&(f[colnum])));
}
gtk_clist_thaw(GTK_CLIST(uat->rep->clist));
}
+static guint8* unhexbytes(const char* si, guint len, guint* len_p, char** err) {
+ guint8* buf;
+ guint8* p;
+ const guint8* s = (void*)si;
+ unsigned i;
+
+ if (len % 2) {
+ *err = "Uneven number of chars hex string";
+ return NULL;
+ }
+
+ buf = ep_alloc(len/2+1);
+ p = buf;
+
+ for (i = 0; i<len ; i += 2) {
+ guint8 lo = s[i+1];
+ guint8 hi = s[i];
+
+ if (hi >= '0' && hi <= '9') {
+ hi -= '0';
+ } else if (hi >= 'a' && hi <= 'f') {
+ hi -= 'a';
+ hi += 0xa;
+ } else if (hi >= 'A' && hi <= 'F') {
+ hi -= 'A';
+ hi += 0xa;
+ } else {
+ goto on_error;
+ }
+
+ if (lo >= '0' && lo <= '9') {
+ lo -= '0';
+ } else if (lo >= 'a' && lo <= 'f') {
+ lo -= 'a';
+ lo += 0xa;
+ } else if (lo >= 'A' && lo <= 'F') {
+ lo -= 'A';
+ lo += 0xa;
+ } else {
+ goto on_error;
+ }
+
+ *(p++) = (hi*0x10) + lo;
+ }
+
+ len /= 2;
+
+ if (len_p) *len_p = len;
+
+ buf[len] = '\0';
+
+ *err = NULL;
+ return buf;
+
+on_error:
+ *err = "Error parsing hex string";
+ return NULL;
+}
+
static gboolean uat_dlg_cb(GtkWidget *win _U_, gpointer user_data) {
struct _uat_dlg_data* dd = user_data;
@@ -187,17 +282,48 @@ static gboolean uat_dlg_cb(GtkWidget *win _U_, gpointer user_data) {
guint colnum;
for ( colnum = 0; colnum < ncols; colnum++ ) {
- const gchar* text = gtk_entry_get_text(GTK_ENTRY(g_ptr_array_index(dd->entries,colnum)));
- unsigned len = strlen(text);
+ void* e = g_ptr_array_index(dd->entries,colnum);
+ const char* text;
+ unsigned len = 0;
+
+ switch(f[colnum].mode) {
+ case PT_TXTMOD_STRING:
+ text = gtk_entry_get_text(GTK_ENTRY(e));
+ len = strlen(text);
+ break;
+ case PT_TXTMOD_HEXBYTES: {
+ text = gtk_entry_get_text(GTK_ENTRY(e));
+
+ text = (void*) unhexbytes(text, strlen(text), &len, &err);
+
+ if (err) {
+ err = ep_strdup_printf("error in field '%s': %s",f[colnum].name,err);
+ goto on_failure;
+ }
+
+ break;
+ }
+ case PT_TXTMOD_ENUM: {
+ text = *(char**)e;
+ text = text ? text : "";
+ len = strlen(text);
+ g_ptr_array_add(dd->tobe_freed,e);
+ }
+ break;
+ default:
+ g_assert_not_reached();
+ return FALSE;
+ }
+
if (f[colnum].cb.chk) {
- if (! f[colnum].cb.chk(dd->rec, text, len, f[colnum].cbdata.tostr, f[colnum].fld_data, &err)) {
+ if (! f[colnum].cb.chk(dd->rec, text, len, f[colnum].cbdata.chk, f[colnum].fld_data, &err)) {
err = ep_strdup_printf("error in field '%s': %s",f[colnum].name,err);
goto on_failure;
}
}
- f[colnum].cb.set(dd->rec,text,len, f[colnum].cbdata.tostr, f[colnum].fld_data);
+ f[colnum].cb.set(dd->rec,text,len, f[colnum].cbdata.set, f[colnum].fld_data);
}
if (dd->uat->update_cb) {
@@ -252,10 +378,27 @@ static gboolean uat_cancel_dlg_cb(GtkWidget *win _U_, gpointer user_data) {
window_destroy(GTK_WIDGET(dd->win));
g_free(dd);
+ while (dd->tobe_freed->len) g_free( g_ptr_array_remove_index_fast(dd->tobe_freed, dd->tobe_freed->len - 1 ) );
+
return TRUE;
}
-static void uat_dialog(uat_t* uat, gint row) {
+struct _fld_menu_item_data_t {
+ const char* text;
+ char const** valptr;
+};
+
+static void fld_menu_item_cb(GtkMenuItem *menuitem _U_, gpointer user_data) {
+ struct _fld_menu_item_data_t* md = user_data;
+
+ *(md->valptr) = md->text;
+}
+
+static void fld_menu_item_destroy_cb(GtkMenuItem *menuitem _U_, gpointer user_data) {
+ g_free(user_data);
+}
+
+static void uat_edit_dialog(uat_t* uat, gint row) {
GtkWidget *win, *main_tb, *main_vb, *bbox, *bt_cancel, *bt_ok;
struct _uat_dlg_data* dd = g_malloc(sizeof(struct _uat_dlg_data));
uat_field_t* f = uat->fields;
@@ -267,50 +410,102 @@ static void uat_dialog(uat_t* uat, gint row) {
dd->rec = row < 0 ? g_malloc0(uat->record_size) : UAT_INDEX_PTR(uat,row);
dd->is_new = row < 0 ? TRUE : FALSE;
dd->row = row;
+ dd->tobe_freed = g_ptr_array_new();
win = dd->win;
+ gtk_window_set_resizable(GTK_WINDOW(win),FALSE);
+
#if GTK_MAJOR_VERSION >= 2
- gtk_window_resize(GTK_WINDOW(win),400,15*(uat->ncols+6));
+ gtk_window_resize(GTK_WINDOW(win),400, 30*(uat->ncols+2));
#else
- gtk_window_set_default_size(GTK_WINDOW(win), 400, 15*(uat->ncols+6));
- gtk_widget_set_usize(win, 400, 15*(uat->ncols+6));
+ gtk_window_set_default_size(GTK_WINDOW(win), 400, 30*(uat->ncols+2));
+ gtk_widget_set_usize(win, 400, 30*(uat->ncols+2));
#endif
- main_vb = gtk_vbox_new(TRUE,5);
+ main_vb = gtk_vbox_new(FALSE,5);
gtk_container_add(GTK_CONTAINER(win), main_vb);
gtk_container_border_width(GTK_CONTAINER(main_vb), 6);
main_tb = gtk_table_new(uat->ncols+1, 2, FALSE);
gtk_box_pack_start(GTK_BOX(main_vb), main_tb, FALSE, FALSE, 0);
- gtk_table_set_row_spacings(GTK_TABLE(main_tb), 10);
- gtk_table_set_col_spacings(GTK_TABLE(main_tb), 15);
+ gtk_table_set_row_spacings(GTK_TABLE(main_tb), 5);
+ gtk_table_set_col_spacings(GTK_TABLE(main_tb), 10);
for ( colnum = 0; colnum < uat->ncols; colnum++ ) {
GtkWidget *entry, *label;
-
+ char* text = fld_tostr(dd->rec,&(f[colnum]));
+
label = gtk_label_new(f[colnum].name);
gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
gtk_table_attach_defaults(GTK_TABLE(main_tb), label, 0, 1, colnum+1, colnum + 2);
gtk_widget_show(label);
- entry = gtk_entry_new();
- g_ptr_array_add(dd->entries,entry);
- gtk_table_attach_defaults(GTK_TABLE(main_tb), entry, 1, 2, colnum+1, colnum + 2);
- gtk_widget_show(entry);
-
- if (! dd->is_new) {
- gchar* text;
- unsigned len;
-
- f[colnum].cb.tostr(dd->rec,&text,&len, f[colnum].cbdata.tostr, f[colnum].fld_data);
-
- gtk_entry_set_text(GTK_ENTRY(entry),text);
+
+ switch(f[colnum].mode) {
+ case PT_TXTMOD_STRING:
+ case PT_TXTMOD_HEXBYTES: {
+ entry = gtk_entry_new();
+ g_ptr_array_add(dd->entries,entry);
+ gtk_table_attach_defaults(GTK_TABLE(main_tb), entry, 1, 2, colnum+1, colnum + 2);
+ gtk_widget_show(entry);
+ if (! dd->is_new) {
+ gtk_entry_set_text(GTK_ENTRY(entry),text);
+ }
+ break;
+ }
+ case PT_TXTMOD_ENUM: {
+ GtkWidget *menu, *option_menu;
+ int menu_index, index;
+ const value_string* enum_vals = f[colnum].fld_data;
+ void* valptr = g_malloc0(sizeof(void*));
+
+ menu = gtk_menu_new();
+ menu_index = -1;
+ for (index = 0; enum_vals[index].strptr != NULL; index++) {
+ struct _fld_menu_item_data_t* md = g_malloc(sizeof(struct _fld_menu_item_data_t)); /* XXX: leaked */
+ const char* str = enum_vals[index].strptr;
+ GtkWidget* menu_item = gtk_menu_item_new_with_label(str);
+
+ md->text = str;
+ md->valptr = valptr;
+
+ gtk_menu_append(GTK_MENU(menu), menu_item);
+
+ if ( g_str_equal(str, text) ) {
+ menu_index = index;
+ *((char const**)valptr) = str;
+ }
+
+ gtk_widget_show(menu_item);
+ SIGNAL_CONNECT(menu_item, "activate", fld_menu_item_cb, md);
+ SIGNAL_CONNECT(menu_item, "destroy", fld_menu_item_destroy_cb, md);
+ }
+
+ g_ptr_array_add(dd->entries,valptr);
+ g_ptr_array_add(dd->tobe_freed,valptr);
+
+ /* Create the option menu from the menu */
+ option_menu = gtk_option_menu_new();
+ gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), menu);
+ gtk_widget_show(option_menu);
+
+ /* Set its current value to the variable's current value */
+ if (menu_index != -1)
+ gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), menu_index);
+
+ gtk_table_attach_defaults(GTK_TABLE(main_tb), option_menu, 1, 2, colnum+1, colnum + 2);
+
+ break;
+ }
+ default:
+ g_assert_not_reached();
+ return;
}
}
bbox = dlg_button_row_new(GTK_STOCK_CANCEL,GTK_STOCK_OK, NULL);
- gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
+ gtk_box_pack_end(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
bt_ok = OBJECT_GET_DATA(bbox, GTK_STOCK_OK);
SIGNAL_CONNECT(bt_ok, "clicked", uat_dlg_cb, dd);
@@ -363,14 +558,16 @@ static void uat_del_dlg(uat_t* uat, int idx) {
ud->idx = idx;
ud->win = win = dlg_window_new(ep_strdup_printf("Confirm Delete"));
+ gtk_window_set_resizable(GTK_WINDOW(win),FALSE);
+
#if GTK_MAJOR_VERSION >= 2
- gtk_window_resize(GTK_WINDOW(win),400,15*(uat->ncols+6));
+ gtk_window_resize(GTK_WINDOW(win),400,25*(uat->ncols+2));
#else
- gtk_window_set_default_size(GTK_WINDOW(win), 400, 15*(uat->ncols+6));
- gtk_widget_set_usize(win, 400, 15*(uat->ncols+6));
+ gtk_window_set_default_size(GTK_WINDOW(win), 400, 25*(uat->ncols+2));
+ gtk_widget_set_usize(win, 400, 25*(uat->ncols+2));
#endif
- main_vb = gtk_vbox_new(TRUE,5);
+ main_vb = gtk_vbox_new(FALSE,5);
gtk_container_add(GTK_CONTAINER(win), main_vb);
gtk_container_border_width(GTK_CONTAINER(main_vb), 6);
@@ -381,12 +578,8 @@ static void uat_del_dlg(uat_t* uat, int idx) {
for ( colnum = 0; colnum < uat->ncols; colnum++ ) {
GtkWidget *label;
- gchar* text;
- unsigned len;
-
- f[colnum].cb.tostr(rec,&text,&len, f[colnum].cbdata.tostr, f[colnum].fld_data);
-
-
+ char* text = fld_tostr(rec,&(f[colnum]));
+
label = gtk_label_new(f[colnum].name);
gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
gtk_table_attach_defaults(GTK_TABLE(main_tb), label, 0, 1, colnum+1, colnum + 2);
@@ -416,12 +609,12 @@ static void uat_del_dlg(uat_t* uat, int idx) {
static void uat_new_cb(GtkButton *button _U_, gpointer u) {
uat_t* uat = u;
- uat_dialog(uat, -1);
+ uat_edit_dialog(uat, -1);
}
static void uat_edit_cb(GtkButton *button _U_, gpointer u) {
uat_t* uat = u;
- uat_dialog(uat, uat->rep->selected);
+ uat_edit_dialog(uat, uat->rep->selected);
}
static void uat_delete_cb(GtkButton *button _U_, gpointer u) {
@@ -608,7 +801,7 @@ GtkWidget* uat_window(void* u) {
uat->rep = rep = g_malloc0(sizeof(uat_rep_t));
}
- rep->window = window_new(GTK_WINDOW_TOPLEVEL, "Display Filter Macros");
+ rep->window = window_new(GTK_WINDOW_TOPLEVEL, uat->name);
gtk_window_set_default_size(GTK_WINDOW(rep->window), 480, 320);
#if GTK_MAJOR_VERSION >= 2