DOC HOME SITE MAP MAN PAGES GNU INFO SEARCH PRINT BOOK
 
ETI forms

Supporting programmer-defined field types

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.

Argument support for field types

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) ();
   

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;

You must write the functions referenced by pointers make_arg, copy_arg, and free_arg. These functions should do the following:

make_arg
allocate a structure for the field specific parameters to set_field_type and return a pointer to the saved data

copy_arg
duplicate the structure created by make_arg

free_arg
free any storage allocated by make_arg or copy_arg
Function make_arg is called automatically when your application program calls set_field_type. It takes one argument, a va_list *. (See varargs(5) for details.) Function make_arg in turn should call va_arg for each additional argument to set_field_type associated with the field type. Note that function va_start is called by set_field_type before make_arg gains control, while function va_end is called by set_field_type after make_arg returns.

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

If successful, function set_fieldtype_arg returns E_OK. If an error occurs, it returns one of the following:

E_SYSTEM_ERROR -
system error

E_BAD_ARGUMENT -
field type, make_arg, copy_arg, or free_arg is NULL

Supporting next and previous choice functions

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) ();
   

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;

These functions enable the ETI form driver to support the REQ_NEXT_CHOICE and REQ_PREV_CHOICE requests mentioned in ``Form driver processing''.

To support these requests, your application-defined functions next_choice and prev_choice must

Both functions can be quite similar.

``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:


E_SYSTEM_ERROR -
system error

E_BAD_ARGUMENT -
field type, next_choice, or prev_choice is NULL

Previous topic: Freeing programmer-defined field types

© 2004 The SCO Group, Inc. All rights reserved.
UnixWare 7 Release 7.1.4 - 27 April 2004