| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 | 
/* * THIS CODE IS SPECIFICALLY EXEMPTED FROM THE NCURSES PACKAGE COPYRIGHT. * You may freely copy it for use as a template for your own field types. * If you develop a field type that might be of general use, please send * it back to the ncurses maintainers for inclusion in the next version. *//****************************************************************************                                                                          **  Author : Juergen Pfeifer, [email protected]                       **                                                                          ****************************************************************************/#include "form.priv.h"MODULE_ID("$Id$")typedef struct {  char **kwds;  int  count;  bool checkcase;  bool checkunique;} enumARG;/*---------------------------------------------------------------------------|   Facility      :  libnform  |   Function      :  static void *Make_Enum_Type( va_list * ap )|   |   Description   :  Allocate structure for enumeration type argument.||   Return Values :  Pointer to argument structure or NULL on error+--------------------------------------------------------------------------*/static void *Make_Enum_Type(va_list * ap){  enumARG *argp = (enumARG *)malloc(sizeof(enumARG));  if (argp)    {      int cnt = 0;      char **kp = (char **)0;      int ccase, cunique;      argp->kwds        = va_arg(*ap,char **);      ccase             = va_arg(*ap,int);      cunique           = va_arg(*ap,int);      argp->checkcase   = ccase   ? TRUE : FALSE;      argp->checkunique = cunique ? TRUE : FALSE;      kp = argp->kwds;      while( kp && (*kp++) ) cnt++;      argp->count = cnt;    }  return (void *)argp;}/*---------------------------------------------------------------------------|   Facility      :  libnform  |   Function      :  static void *Copy_Enum_Type( const void * argp )|   |   Description   :  Copy structure for enumeration type argument.  ||   Return Values :  Pointer to argument structure or NULL on error.+--------------------------------------------------------------------------*/static void *Copy_Enum_Type(const void * argp){  enumARG *result = (enumARG *)0;  if (argp)    {      const enumARG *ap = (const enumARG *)argp;      result = (enumARG *)malloc(sizeof(enumARG));      if (result)	*result = *ap;    }  return (void *)result;}/*---------------------------------------------------------------------------|   Facility      :  libnform  |   Function      :  static void Free_Enum_Type( void * argp )|   |   Description   :  Free structure for enumeration type argument.||   Return Values :  -+--------------------------------------------------------------------------*/static void Free_Enum_Type(void * argp){  if (argp)     free(argp);}#define SKIP_SPACE(x) while(((*(x))!='\0') && (is_blank(*(x)))) (x)++#define NOMATCH 0#define PARTIAL 1#define EXACT   2/*---------------------------------------------------------------------------|   Facility      :  libnform  |   Function      :  static int Compare(const unsigned char * s,  |                                       const unsigned char * buf,|                                       bool  ccase )|   |   Description   :  Check whether or not the text in 'buf' matches the|                    text in 's', at least partial.||   Return Values :  NOMATCH   - buffer doesn't match|                    PARTIAL   - buffer matches partially|                    EXACT     - buffer matches exactly+--------------------------------------------------------------------------*/static int Compare(const unsigned char *s, const unsigned char *buf, 		   bool ccase){  SKIP_SPACE(buf); /* Skip leading spaces in both texts */  SKIP_SPACE(s);  if (*buf=='\0')    {      return (((*s)!='\0') ? NOMATCH : EXACT);    }   else     {      if (ccase)	{	  while(*s++ == *buf)	    {	      if (*buf++=='\0') return EXACT;	    } 	}       else 	{	  while(toupper(*s++)==toupper(*buf))	    {	      if (*buf++=='\0') return EXACT;	    }	}    }  /* At this location buf points to the first character where it no longer     matches with s. So if only blanks are following, we have a partial     match otherwise there is no match */  SKIP_SPACE(buf);  if (*buf)     return NOMATCH;  /* If it happens that the reference buffer is at its end, the partial     match is actually an exact match. */  return ((s[-1]!='\0') ? PARTIAL : EXACT);}/*---------------------------------------------------------------------------|   Facility      :  libnform  |   Function      :  static bool Check_Enum_Field(|                                      FIELD * field,|                                      const void  * argp)|   |   Description   :  Validate buffer content to be a valid enumeration value||   Return Values :  TRUE  - field is valid|                    FALSE - field is invalid+--------------------------------------------------------------------------*/static bool Check_Enum_Field(FIELD * field, const void  * argp){  char **kwds       = ((const enumARG *)argp)->kwds;  bool ccase        = ((const enumARG *)argp)->checkcase;  bool unique       = ((const enumARG *)argp)->checkunique;  unsigned char *bp = (unsigned char *)field_buffer(field,0);  char *s, *t, *p;  int res;    while( kwds && (s=(*kwds++)) )    {      if ((res=Compare((unsigned char *)s,bp,ccase))!=NOMATCH)	{	  p=t=s; /* t is at least a partial match */	  if ((unique && res!=EXACT)) 	    {	      while( kwds && (p = *kwds++) )		{		  if ((res=Compare((unsigned char *)p,bp,ccase))!=NOMATCH)		    {		      if (res==EXACT)			{			  t = p;			  break;			}		      else			t = (char *)0;		    }		}	    }	  	  if (t)	    {	      set_field_buffer(field,0,t);	      return TRUE;	    }	  if (!p)	    break;	}    }  return FALSE;}static const char *dummy[] = { (char *)0 };/*---------------------------------------------------------------------------|   Facility      :  libnform  |   Function      :  static bool Next_Enum(FIELD * field,|                                          const void * argp)|   |   Description   :  Check for the next enumeration value||   Return Values :  TRUE  - next value found and loaded|                    FALSE - no next value loaded+--------------------------------------------------------------------------*/static bool Next_Enum(FIELD * field, const void * argp){  const enumARG *args = (const enumARG *)argp;  char **kwds       = args->kwds;  bool ccase        = args->checkcase;  int cnt           = args->count;  unsigned char *bp = (unsigned char *)field_buffer(field,0);  if (kwds) {    while(cnt--)      {	if (Compare((unsigned char *)(*kwds++),bp,ccase)==EXACT) 	  break;      }    if (cnt<=0)      kwds = args->kwds;    if ((cnt>=0) || (Compare((const unsigned char *)dummy,bp,ccase)==EXACT))      {	set_field_buffer(field,0,*kwds);	return TRUE;      }  }  return FALSE;}/*---------------------------------------------------------------------------|   Facility      :  libnform  |   Function      :  static bool Previous_Enum(|                                          FIELD * field,|                                          const void * argp)|   |   Description   :  Check for the previous enumeration value||   Return Values :  TRUE  - previous value found and loaded|                    FALSE - no previous value loaded+--------------------------------------------------------------------------*/static bool Previous_Enum(FIELD * field, const void * argp){  const enumARG *args = (const enumARG *)argp;  int cnt       = args->count;  char **kwds   = &args->kwds[cnt-1];  bool ccase    = args->checkcase;  unsigned char *bp = (unsigned char *)field_buffer(field,0);  if (kwds) {    while(cnt--)      {	if (Compare((unsigned char *)(*kwds--),bp,ccase)==EXACT) 	  break;      }        if (cnt<=0)      kwds  = &args->kwds[args->count-1];        if ((cnt>=0) || (Compare((const unsigned char *)dummy,bp,ccase)==EXACT))      {	set_field_buffer(field,0,*kwds);	return TRUE;      }  }  return FALSE;}static FIELDTYPE typeENUM = {  _HAS_ARGS | _HAS_CHOICE | _RESIDENT,  1,                           /* this is mutable, so we can't be const */  (FIELDTYPE *)0,  (FIELDTYPE *)0,  Make_Enum_Type,  Copy_Enum_Type,  Free_Enum_Type,  Check_Enum_Field,  NULL,  Next_Enum,  Previous_Enum};FIELDTYPE* TYPE_ENUM = &typeENUM;/* fty_enum.c ends here */
 |