|
|
You may want to support some programmer-defined field types with additional arguments or with previous and next choice functions. This section explains how to do so.
Some field types may require additional arguments to the set_field_type routine, which sets the field type of a field. Function set_fieldtype_arg takes as arguments pointers to functions that manage storage for the additional arguments.
SYNOPSIS
typedef char ( PTF_charP) (); typedef void ( PTF_void) ();You must write the functions referenced by pointers make_arg, copy_arg, and free_arg. These functions should do the following:int set_fieldtype_arg (fieldtype, make_arg, copy_arg, free_arg) FIELDTYPE * fieldtype; PTF_charP make_arg; PTF_charP copy_arg; PTF_void free_arg;
Function make_arg must allocate space for the information associated with the additional arguments, save the information, and return the pointer to the information cast to a character pointer. It is this character pointer that is the argument arg to the other functions associated with the field type, namely copy_arg, free_arg, f_check, c_check, next_choice, and prev_choice.
Function copy_arg takes as its sole argument a pointer to existing argument information. It returns a pointer to a copy of this information. Function free_arg takes as its sole argument a pointer to existing argument information. It should free any space allocated by make_arg.
``Creating TYPE_HEX with padding and range arguments'' illustrates how you can add padding and range arguments to our TYPE_HEX defined above.
/* TYPE_HEX set_field_type (f, TYPE_HEX, padding, vmin, vmax);int padding; for padding with leading zeros long vmin; minimum acceptable value long vmax; maximum acceptable value */
#include <form.h> #include <ctype.h> #include <varargs.h> extern long strtol ();
#define isblank(c) ((c) == ' ')
typedef struct { int padding; long vmin, vmax; } HEX; static char * make_hex (ap) va_list * ap; { HEX * n = (HEX *) malloc (sizeof (HEX)); if (n) { n -> padding = va_arg (*ap, int); n -> vmin = va_arg (*ap, long); n -> vmax = va_arg (*ap, long); } return (char *) n; } static char * copy_hex (arg) char * arg; { HEX * n = (HEX *) malloc (sizeof (HEX)); if (n) *n = *((HEX *) arg); return (char *) n; } static void free_hex (arg) char * arg; { free (arg); }
static int fcheck_hex (f, arg) FIELD * f; char * arg; { HEX * n = (HEX *) arg; int padding = n -> padding; long vmin = n -> vmin; long vmax = n -> vmax; char buf[80]; char * x = field_buffer (f, 0); while (*x && isblank (*x)) ++x;
if (*x) { char * t = x; while (*x && isxdigit (*x)) ++x; while (*x && isblank (*x)) ++x;
if (! *x) { long v = strtol (t, (char **) 0, 16); if (v >= vmin && v <= vmax) { sprintf (buf, "%.*lx", padding, v); set_field_buffer (f, 0, buf); return TRUE; } } } return FALSE; } static int ccheck_hex (c, arg) int c; char * arg; { return isxdigit (c); } FIELDTYPE * TYPE_HEX = new_fieldtype (fcheck_hex, ccheck_hex); set_fieldtype_arg (TYPE_HEX, make_hex, copy_hex, free_hex);
Creating TYPE_HEX with padding and range arguments
Later, to create a field that stores a hex number between 0x0000 and 0xffff, we have:
set_field_type (field, TYPE_HEX, 4, 0x0000L, 0xffffL);
From this example, note that
Some field types
comprise a set of values from which your user
chooses (enters) one.
The following functions support those types that have a set of choices.
SYNOPSIS
typedef char ( PTF_charP) ();These functions enable the ETI form driver to support the REQ_NEXT_CHOICE and REQ_PREV_CHOICE requests mentioned in ``Form driver processing''.int set_fieldtype_choice (type, next_choice, prev_choice) FIELDTYPE type; PTF_int next_choice; PTF_int prev_choice;
int next_choice(f,arg); FIELD f; char arg;
int prev_choice(f,arg); FIELD f; char arg;
To support these requests, your application-defined functions next_choice and prev_choice must
``Creating a next choice function for a field type'' shows an implementation of function next_choice for the field type TYPE_HEX as defined above, such that REQ_NEXT_CHOICE increments the current value and REG_PREV_CHOICE decrements the current value.
static int next_hex (f, arg) FIELD * f; char * arg; { HEX * n = (HEX *) arg; long v = n -> vmin; char buf[80]; char * x = field_buffer (f, 0);while (*x && isblank (*x)) ++x;
if (*x) { v = strtol (x, (char **) 0, 16); if (v >= n -> vmin && v < n -> vmax) ++v; } sprintf (buf, "%.*lx", n -> padding, v); set_field_buffer (f, 0, buf); return TRUE; } static int prev_hex (f, arg) FIELD * f; char * arg; { HEX * n = (HEX *) arg; long v = n -> vmax; char buf[80]; char * x = field_buffer (f, 0);
while (*x && isblank (*x)) ++x;
if (*x) { v = strtol (x, (char **) 0, 16); if (v > n -> vmin && v <= n -> vmax) --v; } sprintf (buf, "%.*lx", v -> padding, v); set_field_buffer (f, 0, buf); return TRUE; }
/* associate previous and next choice functions */ set_fieldtype_choice (TYPE_HEX, next_hex, prev_hex);
Creating a next choice function for a field type
If given a blank field, your functions next_choice and prev_choice should, of course, do something reasonable, such as setting the field to the first or last value of the type.
If function set_fieldtype_choice encounters an error, it returns one of the following: