xref: /freebsd/contrib/ncurses/form/fty_enum.c (revision 21817992b3314c908ab50f0bb88d2ee750b9c4ac)
14a1a9510SRong-En Fan /****************************************************************************
2*21817992SBaptiste Daroussin  * Copyright 2020,2021 Thomas E. Dickey                                     *
3e1865124SBaptiste Daroussin  * Copyright 1998-2009,2010 Free Software Foundation, Inc.                  *
44a1a9510SRong-En Fan  *                                                                          *
54a1a9510SRong-En Fan  * Permission is hereby granted, free of charge, to any person obtaining a  *
64a1a9510SRong-En Fan  * copy of this software and associated documentation files (the            *
74a1a9510SRong-En Fan  * "Software"), to deal in the Software without restriction, including      *
84a1a9510SRong-En Fan  * without limitation the rights to use, copy, modify, merge, publish,      *
94a1a9510SRong-En Fan  * distribute, distribute with modifications, sublicense, and/or sell       *
104a1a9510SRong-En Fan  * copies of the Software, and to permit persons to whom the Software is    *
114a1a9510SRong-En Fan  * furnished to do so, subject to the following conditions:                 *
124a1a9510SRong-En Fan  *                                                                          *
134a1a9510SRong-En Fan  * The above copyright notice and this permission notice shall be included  *
144a1a9510SRong-En Fan  * in all copies or substantial portions of the Software.                   *
154a1a9510SRong-En Fan  *                                                                          *
164a1a9510SRong-En Fan  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
174a1a9510SRong-En Fan  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
184a1a9510SRong-En Fan  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
194a1a9510SRong-En Fan  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
204a1a9510SRong-En Fan  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
214a1a9510SRong-En Fan  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
224a1a9510SRong-En Fan  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
234a1a9510SRong-En Fan  *                                                                          *
244a1a9510SRong-En Fan  * Except as contained in this notice, the name(s) of the above copyright   *
254a1a9510SRong-En Fan  * holders shall not be used in advertising or otherwise to promote the     *
264a1a9510SRong-En Fan  * sale, use or other dealings in this Software without prior written       *
274a1a9510SRong-En Fan  * authorization.                                                           *
284a1a9510SRong-En Fan  ****************************************************************************/
290e3d5408SPeter Wemm 
300e3d5408SPeter Wemm /***************************************************************************
310e3d5408SPeter Wemm *                                                                          *
324a1a9510SRong-En Fan *  Author : Juergen Pfeifer                                                *
330e3d5408SPeter Wemm *                                                                          *
340e3d5408SPeter Wemm ***************************************************************************/
350e3d5408SPeter Wemm 
360e3d5408SPeter Wemm #include "form.priv.h"
370e3d5408SPeter Wemm 
38*21817992SBaptiste Daroussin MODULE_ID("$Id: fty_enum.c,v 1.33 2021/06/17 21:11:08 tom Exp $")
390e3d5408SPeter Wemm 
404a1a9510SRong-En Fan typedef struct
414a1a9510SRong-En Fan   {
420e3d5408SPeter Wemm     char **kwds;
430e3d5408SPeter Wemm     int count;
440e3d5408SPeter Wemm     bool checkcase;
450e3d5408SPeter Wemm     bool checkunique;
464a1a9510SRong-En Fan   }
474a1a9510SRong-En Fan enumARG;
480e3d5408SPeter Wemm 
4906bfebdeSXin LI typedef struct
5006bfebdeSXin LI   {
5106bfebdeSXin LI     char **kwds;
5206bfebdeSXin LI     int ccase;
5306bfebdeSXin LI     int cunique;
5406bfebdeSXin LI   }
5506bfebdeSXin LI enumParams;
5606bfebdeSXin LI 
5706bfebdeSXin LI /*---------------------------------------------------------------------------
5806bfebdeSXin LI |   Facility      :  libnform
5906bfebdeSXin LI |   Function      :  static void *Generic_Enum_Type(void * arg)
6006bfebdeSXin LI |
6106bfebdeSXin LI |   Description   :  Allocate structure for enumeration type argument.
6206bfebdeSXin LI |
6306bfebdeSXin LI |   Return Values :  Pointer to argument structure or NULL on error
6406bfebdeSXin LI +--------------------------------------------------------------------------*/
6506bfebdeSXin LI static void *
Generic_Enum_Type(void * arg)6606bfebdeSXin LI Generic_Enum_Type(void *arg)
6706bfebdeSXin LI {
6806bfebdeSXin LI   enumARG *argp = (enumARG *)0;
6906bfebdeSXin LI   enumParams *params = (enumParams *)arg;
7006bfebdeSXin LI 
7106bfebdeSXin LI   if (params)
7206bfebdeSXin LI     {
7306bfebdeSXin LI       argp = typeMalloc(enumARG, 1);
7406bfebdeSXin LI 
7506bfebdeSXin LI       if (argp)
7606bfebdeSXin LI 	{
7706bfebdeSXin LI 	  int cnt = 0;
7806bfebdeSXin LI 	  char **kp = (char **)0;
7906bfebdeSXin LI 	  char **kwds = (char **)0;
8006bfebdeSXin LI 	  int ccase, cunique;
8106bfebdeSXin LI 
8206bfebdeSXin LI 	  T((T_CREATE("enumARG %p"), (void *)argp));
8306bfebdeSXin LI 	  kwds = params->kwds;
8406bfebdeSXin LI 	  ccase = params->ccase;
8506bfebdeSXin LI 	  cunique = params->cunique;
8606bfebdeSXin LI 
8706bfebdeSXin LI 	  argp->checkcase = ccase ? TRUE : FALSE;
8806bfebdeSXin LI 	  argp->checkunique = cunique ? TRUE : FALSE;
8906bfebdeSXin LI 	  argp->kwds = (char **)0;
9006bfebdeSXin LI 
9106bfebdeSXin LI 	  kp = kwds;
9206bfebdeSXin LI 	  while (kp && (*kp++))
9306bfebdeSXin LI 	    cnt++;
9406bfebdeSXin LI 	  argp->count = cnt;
9506bfebdeSXin LI 
9606bfebdeSXin LI 	  if (cnt > 0)
9706bfebdeSXin LI 	    {
98*21817992SBaptiste Daroussin 	      char **kptarget;
99*21817992SBaptiste Daroussin 
10006bfebdeSXin LI 	      /* We copy the keywords, because we can't rely on the fact
10106bfebdeSXin LI 	         that the caller doesn't relocate or free the memory used
10206bfebdeSXin LI 	         for the keywords (maybe he has GC)
10306bfebdeSXin LI 	       */
10406bfebdeSXin LI 	      argp->kwds = typeMalloc(char *, cnt + 1);
10506bfebdeSXin LI 
10606bfebdeSXin LI 	      kp = kwds;
10706bfebdeSXin LI 	      if ((kptarget = argp->kwds) != 0)
10806bfebdeSXin LI 		{
10906bfebdeSXin LI 		  while (kp && (*kp))
11006bfebdeSXin LI 		    {
11106bfebdeSXin LI 		      (*kptarget++) = strdup(*kp++);
11206bfebdeSXin LI 		    }
11306bfebdeSXin LI 		  *kptarget = (char *)0;
11406bfebdeSXin LI 		}
11506bfebdeSXin LI 	    }
11606bfebdeSXin LI 	}
11706bfebdeSXin LI     }
11806bfebdeSXin LI   return (void *)argp;
11906bfebdeSXin LI }
12006bfebdeSXin LI 
1210e3d5408SPeter Wemm /*---------------------------------------------------------------------------
1220e3d5408SPeter Wemm |   Facility      :  libnform
1230e3d5408SPeter Wemm |   Function      :  static void *Make_Enum_Type( va_list * ap )
1240e3d5408SPeter Wemm |
1250e3d5408SPeter Wemm |   Description   :  Allocate structure for enumeration type argument.
1260e3d5408SPeter Wemm |
1270e3d5408SPeter Wemm |   Return Values :  Pointer to argument structure or NULL on error
1280e3d5408SPeter Wemm +--------------------------------------------------------------------------*/
1294a1a9510SRong-En Fan static void *
Make_Enum_Type(va_list * ap)1304a1a9510SRong-En Fan Make_Enum_Type(va_list *ap)
1310e3d5408SPeter Wemm {
13206bfebdeSXin LI   enumParams params;
1330e3d5408SPeter Wemm 
13406bfebdeSXin LI   params.kwds = va_arg(*ap, char **);
13506bfebdeSXin LI   params.ccase = va_arg(*ap, int);
13606bfebdeSXin LI   params.cunique = va_arg(*ap, int);
13718259542SPeter Wemm 
13806bfebdeSXin LI   return Generic_Enum_Type((void *)&params);
1390e3d5408SPeter Wemm }
1400e3d5408SPeter Wemm 
1410e3d5408SPeter Wemm /*---------------------------------------------------------------------------
1420e3d5408SPeter Wemm |   Facility      :  libnform
1430e3d5408SPeter Wemm |   Function      :  static void *Copy_Enum_Type( const void * argp )
1440e3d5408SPeter Wemm |
1450e3d5408SPeter Wemm |   Description   :  Copy structure for enumeration type argument.
1460e3d5408SPeter Wemm |
1470e3d5408SPeter Wemm |   Return Values :  Pointer to argument structure or NULL on error.
1480e3d5408SPeter Wemm +--------------------------------------------------------------------------*/
1494a1a9510SRong-En Fan static void *
Copy_Enum_Type(const void * argp)1504a1a9510SRong-En Fan Copy_Enum_Type(const void *argp)
1510e3d5408SPeter Wemm {
1520e3d5408SPeter Wemm   enumARG *result = (enumARG *)0;
1530e3d5408SPeter Wemm 
1540e3d5408SPeter Wemm   if (argp)
1550e3d5408SPeter Wemm     {
15618259542SPeter Wemm       const enumARG *ap = (const enumARG *)argp;
15718259542SPeter Wemm 
1585ca44d1cSRong-En Fan       result = typeMalloc(enumARG, 1);
1594a1a9510SRong-En Fan 
1600e3d5408SPeter Wemm       if (result)
1615ca44d1cSRong-En Fan 	{
16206bfebdeSXin LI 	  T((T_CREATE("enumARG %p"), (void *)result));
1630e3d5408SPeter Wemm 	  *result = *ap;
16406bfebdeSXin LI 
16506bfebdeSXin LI 	  if (ap->count > 0)
16606bfebdeSXin LI 	    {
16706bfebdeSXin LI 	      char **kptarget;
16806bfebdeSXin LI 	      char **kp = ap->kwds;
16906bfebdeSXin LI 	      result->kwds = typeMalloc(char *, 1 + ap->count);
17006bfebdeSXin LI 
17106bfebdeSXin LI 	      if ((kptarget = result->kwds) != 0)
17206bfebdeSXin LI 		{
17306bfebdeSXin LI 		  while (kp && (*kp))
17406bfebdeSXin LI 		    {
17506bfebdeSXin LI 		      (*kptarget++) = strdup(*kp++);
17606bfebdeSXin LI 		    }
17706bfebdeSXin LI 		  *kptarget = (char *)0;
17806bfebdeSXin LI 		}
17906bfebdeSXin LI 	    }
1800e3d5408SPeter Wemm 	}
1815ca44d1cSRong-En Fan     }
1820e3d5408SPeter Wemm   return (void *)result;
1830e3d5408SPeter Wemm }
1840e3d5408SPeter Wemm 
1850e3d5408SPeter Wemm /*---------------------------------------------------------------------------
1860e3d5408SPeter Wemm |   Facility      :  libnform
1870e3d5408SPeter Wemm |   Function      :  static void Free_Enum_Type( void * argp )
1880e3d5408SPeter Wemm |
1890e3d5408SPeter Wemm |   Description   :  Free structure for enumeration type argument.
1900e3d5408SPeter Wemm |
1910e3d5408SPeter Wemm |   Return Values :  -
1920e3d5408SPeter Wemm +--------------------------------------------------------------------------*/
1934a1a9510SRong-En Fan static void
Free_Enum_Type(void * argp)1944a1a9510SRong-En Fan Free_Enum_Type(void *argp)
1950e3d5408SPeter Wemm {
1960e3d5408SPeter Wemm   if (argp)
19706bfebdeSXin LI     {
19806bfebdeSXin LI       const enumARG *ap = (const enumARG *)argp;
19906bfebdeSXin LI 
20006bfebdeSXin LI       if (ap->kwds && ap->count > 0)
20106bfebdeSXin LI 	{
20206bfebdeSXin LI 	  char **kp = ap->kwds;
20306bfebdeSXin LI 	  int cnt = 0;
20406bfebdeSXin LI 
20506bfebdeSXin LI 	  while (kp && (*kp))
20606bfebdeSXin LI 	    {
20706bfebdeSXin LI 	      free(*kp++);
20806bfebdeSXin LI 	      cnt++;
20906bfebdeSXin LI 	    }
21006bfebdeSXin LI 	  assert(cnt == ap->count);
21106bfebdeSXin LI 	  free(ap->kwds);
21206bfebdeSXin LI 	}
2130e3d5408SPeter Wemm       free(argp);
2140e3d5408SPeter Wemm     }
21506bfebdeSXin LI }
2160e3d5408SPeter Wemm 
2170e3d5408SPeter Wemm #define SKIP_SPACE(x) while(((*(x))!='\0') && (is_blank(*(x)))) (x)++
2180e3d5408SPeter Wemm #define NOMATCH 0
2190e3d5408SPeter Wemm #define PARTIAL 1
2200e3d5408SPeter Wemm #define EXACT   2
2210e3d5408SPeter Wemm 
2220e3d5408SPeter Wemm /*---------------------------------------------------------------------------
2230e3d5408SPeter Wemm |   Facility      :  libnform
2240e3d5408SPeter Wemm |   Function      :  static int Compare(const unsigned char * s,
2250e3d5408SPeter Wemm |                                       const unsigned char * buf,
2260e3d5408SPeter Wemm |                                       bool  ccase )
2270e3d5408SPeter Wemm |
2284a1a9510SRong-En Fan |   Description   :  Check whether or not the text in 'buf' matches the
2290e3d5408SPeter Wemm |                    text in 's', at least partial.
2300e3d5408SPeter Wemm |
2310e3d5408SPeter Wemm |   Return Values :  NOMATCH   - buffer doesn't match
2320e3d5408SPeter Wemm |                    PARTIAL   - buffer matches partially
2330e3d5408SPeter Wemm |                    EXACT     - buffer matches exactly
2340e3d5408SPeter Wemm +--------------------------------------------------------------------------*/
2354a1a9510SRong-En Fan static int
Compare(const unsigned char * s,const unsigned char * buf,bool ccase)2364a1a9510SRong-En Fan Compare(const unsigned char *s, const unsigned char *buf,
2370e3d5408SPeter Wemm 	bool ccase)
2380e3d5408SPeter Wemm {
2390e3d5408SPeter Wemm   SKIP_SPACE(buf);		/* Skip leading spaces in both texts */
2400e3d5408SPeter Wemm   SKIP_SPACE(s);
2410e3d5408SPeter Wemm 
2420e3d5408SPeter Wemm   if (*buf == '\0')
2430e3d5408SPeter Wemm     {
2440e3d5408SPeter Wemm       return (((*s) != '\0') ? NOMATCH : EXACT);
2450e3d5408SPeter Wemm     }
2460e3d5408SPeter Wemm   else
2470e3d5408SPeter Wemm     {
2480e3d5408SPeter Wemm       if (ccase)
2490e3d5408SPeter Wemm 	{
2500e3d5408SPeter Wemm 	  while (*s++ == *buf)
2510e3d5408SPeter Wemm 	    {
2524a1a9510SRong-En Fan 	      if (*buf++ == '\0')
2534a1a9510SRong-En Fan 		return EXACT;
2540e3d5408SPeter Wemm 	    }
2550e3d5408SPeter Wemm 	}
2560e3d5408SPeter Wemm       else
2570e3d5408SPeter Wemm 	{
2580e3d5408SPeter Wemm 	  while (toupper(*s++) == toupper(*buf))
2590e3d5408SPeter Wemm 	    {
2604a1a9510SRong-En Fan 	      if (*buf++ == '\0')
2614a1a9510SRong-En Fan 		return EXACT;
2620e3d5408SPeter Wemm 	    }
2630e3d5408SPeter Wemm 	}
2640e3d5408SPeter Wemm     }
2650e3d5408SPeter Wemm   /* At this location buf points to the first character where it no longer
2660e3d5408SPeter Wemm      matches with s. So if only blanks are following, we have a partial
2670e3d5408SPeter Wemm      match otherwise there is no match */
2680e3d5408SPeter Wemm   SKIP_SPACE(buf);
2690e3d5408SPeter Wemm   if (*buf)
2700e3d5408SPeter Wemm     return NOMATCH;
2710e3d5408SPeter Wemm 
2720e3d5408SPeter Wemm   /* If it happens that the reference buffer is at its end, the partial
2730e3d5408SPeter Wemm      match is actually an exact match. */
2740e3d5408SPeter Wemm   return ((s[-1] != '\0') ? PARTIAL : EXACT);
2750e3d5408SPeter Wemm }
2760e3d5408SPeter Wemm 
2770e3d5408SPeter Wemm /*---------------------------------------------------------------------------
2780e3d5408SPeter Wemm |   Facility      :  libnform
2790e3d5408SPeter Wemm |   Function      :  static bool Check_Enum_Field(
2800e3d5408SPeter Wemm |                                      FIELD * field,
2810e3d5408SPeter Wemm |                                      const void  * argp)
2820e3d5408SPeter Wemm |
2830e3d5408SPeter Wemm |   Description   :  Validate buffer content to be a valid enumeration value
2840e3d5408SPeter Wemm |
2850e3d5408SPeter Wemm |   Return Values :  TRUE  - field is valid
2860e3d5408SPeter Wemm |                    FALSE - field is invalid
2870e3d5408SPeter Wemm +--------------------------------------------------------------------------*/
2884a1a9510SRong-En Fan static bool
Check_Enum_Field(FIELD * field,const void * argp)2894a1a9510SRong-En Fan Check_Enum_Field(FIELD *field, const void *argp)
2900e3d5408SPeter Wemm {
2910e3d5408SPeter Wemm   char **kwds = ((const enumARG *)argp)->kwds;
2920e3d5408SPeter Wemm   bool ccase = ((const enumARG *)argp)->checkcase;
2930e3d5408SPeter Wemm   bool unique = ((const enumARG *)argp)->checkunique;
2940e3d5408SPeter Wemm   unsigned char *bp = (unsigned char *)field_buffer(field, 0);
2950e3d5408SPeter Wemm   char *s, *t, *p;
2960e3d5408SPeter Wemm 
29718259542SPeter Wemm   while (kwds && (s = (*kwds++)))
2980e3d5408SPeter Wemm     {
299*21817992SBaptiste Daroussin       int res;
300*21817992SBaptiste Daroussin 
3010e3d5408SPeter Wemm       if ((res = Compare((unsigned char *)s, bp, ccase)) != NOMATCH)
3020e3d5408SPeter Wemm 	{
3030e3d5408SPeter Wemm 	  p = t = s;		/* t is at least a partial match */
3040e3d5408SPeter Wemm 	  if ((unique && res != EXACT))
3050e3d5408SPeter Wemm 	    {
30618259542SPeter Wemm 	      while (kwds && (p = *kwds++))
3070e3d5408SPeter Wemm 		{
3080e3d5408SPeter Wemm 		  if ((res = Compare((unsigned char *)p, bp, ccase)) != NOMATCH)
3090e3d5408SPeter Wemm 		    {
3100e3d5408SPeter Wemm 		      if (res == EXACT)
3110e3d5408SPeter Wemm 			{
3120e3d5408SPeter Wemm 			  t = p;
3130e3d5408SPeter Wemm 			  break;
3140e3d5408SPeter Wemm 			}
3150e3d5408SPeter Wemm 		      else
3160e3d5408SPeter Wemm 			t = (char *)0;
3170e3d5408SPeter Wemm 		    }
3180e3d5408SPeter Wemm 		}
3190e3d5408SPeter Wemm 	    }
3200e3d5408SPeter Wemm 	  if (t)
3210e3d5408SPeter Wemm 	    {
3220e3d5408SPeter Wemm 	      set_field_buffer(field, 0, t);
3230e3d5408SPeter Wemm 	      return TRUE;
3240e3d5408SPeter Wemm 	    }
3250e3d5408SPeter Wemm 	  if (!p)
3260e3d5408SPeter Wemm 	    break;
3270e3d5408SPeter Wemm 	}
3280e3d5408SPeter Wemm     }
3290e3d5408SPeter Wemm   return FALSE;
3300e3d5408SPeter Wemm }
3310e3d5408SPeter Wemm 
3324a1a9510SRong-En Fan static const char *dummy[] =
3334a1a9510SRong-En Fan {(char *)0};
3340e3d5408SPeter Wemm 
3350e3d5408SPeter Wemm /*---------------------------------------------------------------------------
3360e3d5408SPeter Wemm |   Facility      :  libnform
3370e3d5408SPeter Wemm |   Function      :  static bool Next_Enum(FIELD * field,
3380e3d5408SPeter Wemm |                                          const void * argp)
3390e3d5408SPeter Wemm |
3400e3d5408SPeter Wemm |   Description   :  Check for the next enumeration value
3410e3d5408SPeter Wemm |
3420e3d5408SPeter Wemm |   Return Values :  TRUE  - next value found and loaded
3430e3d5408SPeter Wemm |                    FALSE - no next value loaded
3440e3d5408SPeter Wemm +--------------------------------------------------------------------------*/
3454a1a9510SRong-En Fan static bool
Next_Enum(FIELD * field,const void * argp)3464a1a9510SRong-En Fan Next_Enum(FIELD *field, const void *argp)
3470e3d5408SPeter Wemm {
3480e3d5408SPeter Wemm   const enumARG *args = (const enumARG *)argp;
3490e3d5408SPeter Wemm   char **kwds = args->kwds;
3500e3d5408SPeter Wemm   bool ccase = args->checkcase;
3510e3d5408SPeter Wemm   int cnt = args->count;
3520e3d5408SPeter Wemm   unsigned char *bp = (unsigned char *)field_buffer(field, 0);
3530e3d5408SPeter Wemm 
3544a1a9510SRong-En Fan   if (kwds)
3554a1a9510SRong-En Fan     {
3560e3d5408SPeter Wemm       while (cnt--)
3570e3d5408SPeter Wemm 	{
3580e3d5408SPeter Wemm 	  if (Compare((unsigned char *)(*kwds++), bp, ccase) == EXACT)
3590e3d5408SPeter Wemm 	    break;
3600e3d5408SPeter Wemm 	}
3610e3d5408SPeter Wemm       if (cnt <= 0)
3620e3d5408SPeter Wemm 	kwds = args->kwds;
36315589c42SPeter Wemm       if ((cnt >= 0) || (Compare((const unsigned char *)dummy, bp, ccase) == EXACT))
3640e3d5408SPeter Wemm 	{
3650e3d5408SPeter Wemm 	  set_field_buffer(field, 0, *kwds);
3660e3d5408SPeter Wemm 	  return TRUE;
3670e3d5408SPeter Wemm 	}
36818259542SPeter Wemm     }
3690e3d5408SPeter Wemm   return FALSE;
3700e3d5408SPeter Wemm }
3710e3d5408SPeter Wemm 
3720e3d5408SPeter Wemm /*---------------------------------------------------------------------------
3730e3d5408SPeter Wemm |   Facility      :  libnform
3740e3d5408SPeter Wemm |   Function      :  static bool Previous_Enum(
3750e3d5408SPeter Wemm |                                          FIELD * field,
3760e3d5408SPeter Wemm |                                          const void * argp)
3770e3d5408SPeter Wemm |
3780e3d5408SPeter Wemm |   Description   :  Check for the previous enumeration value
3790e3d5408SPeter Wemm |
3800e3d5408SPeter Wemm |   Return Values :  TRUE  - previous value found and loaded
3810e3d5408SPeter Wemm |                    FALSE - no previous value loaded
3820e3d5408SPeter Wemm +--------------------------------------------------------------------------*/
3834a1a9510SRong-En Fan static bool
Previous_Enum(FIELD * field,const void * argp)3844a1a9510SRong-En Fan Previous_Enum(FIELD *field, const void *argp)
3850e3d5408SPeter Wemm {
3860e3d5408SPeter Wemm   const enumARG *args = (const enumARG *)argp;
3870e3d5408SPeter Wemm   int cnt = args->count;
3880e3d5408SPeter Wemm   char **kwds = &args->kwds[cnt - 1];
3890e3d5408SPeter Wemm   bool ccase = args->checkcase;
3900e3d5408SPeter Wemm   unsigned char *bp = (unsigned char *)field_buffer(field, 0);
3910e3d5408SPeter Wemm 
3924a1a9510SRong-En Fan   if (kwds)
3934a1a9510SRong-En Fan     {
3940e3d5408SPeter Wemm       while (cnt--)
3950e3d5408SPeter Wemm 	{
3960e3d5408SPeter Wemm 	  if (Compare((unsigned char *)(*kwds--), bp, ccase) == EXACT)
3970e3d5408SPeter Wemm 	    break;
3980e3d5408SPeter Wemm 	}
3990e3d5408SPeter Wemm 
4000e3d5408SPeter Wemm       if (cnt <= 0)
4010e3d5408SPeter Wemm 	kwds = &args->kwds[args->count - 1];
4020e3d5408SPeter Wemm 
40315589c42SPeter Wemm       if ((cnt >= 0) || (Compare((const unsigned char *)dummy, bp, ccase) == EXACT))
4040e3d5408SPeter Wemm 	{
4050e3d5408SPeter Wemm 	  set_field_buffer(field, 0, *kwds);
4060e3d5408SPeter Wemm 	  return TRUE;
4070e3d5408SPeter Wemm 	}
40818259542SPeter Wemm     }
4090e3d5408SPeter Wemm   return FALSE;
4100e3d5408SPeter Wemm }
4110e3d5408SPeter Wemm 
4124a1a9510SRong-En Fan static FIELDTYPE typeENUM =
4134a1a9510SRong-En Fan {
4140e3d5408SPeter Wemm   _HAS_ARGS | _HAS_CHOICE | _RESIDENT,
4150e3d5408SPeter Wemm   1,				/* this is mutable, so we can't be const */
4160e3d5408SPeter Wemm   (FIELDTYPE *)0,
4170e3d5408SPeter Wemm   (FIELDTYPE *)0,
4180e3d5408SPeter Wemm   Make_Enum_Type,
4190e3d5408SPeter Wemm   Copy_Enum_Type,
4200e3d5408SPeter Wemm   Free_Enum_Type,
42106bfebdeSXin LI   INIT_FT_FUNC(Check_Enum_Field),
42206bfebdeSXin LI   INIT_FT_FUNC(NULL),
42306bfebdeSXin LI   INIT_FT_FUNC(Next_Enum),
42406bfebdeSXin LI   INIT_FT_FUNC(Previous_Enum),
42506bfebdeSXin LI #if NCURSES_INTEROP_FUNCS
42606bfebdeSXin LI   Generic_Enum_Type
42706bfebdeSXin LI #endif
4280e3d5408SPeter Wemm };
4290e3d5408SPeter Wemm 
4307a656419SBaptiste Daroussin FORM_EXPORT_VAR(FIELDTYPE *) TYPE_ENUM = &typeENUM;
4310e3d5408SPeter Wemm 
43206bfebdeSXin LI #if NCURSES_INTEROP_FUNCS
43306bfebdeSXin LI /* The next routines are to simplify the use of ncurses from
4347a656419SBaptiste Daroussin    programming languages with restrictions on interop with C level
43506bfebdeSXin LI    constructs (e.g. variable access or va_list + ellipsis constructs)
43606bfebdeSXin LI */
4377a656419SBaptiste Daroussin FORM_EXPORT(FIELDTYPE *)
_nc_TYPE_ENUM(void)43806bfebdeSXin LI _nc_TYPE_ENUM(void)
43906bfebdeSXin LI {
44006bfebdeSXin LI   return TYPE_ENUM;
44106bfebdeSXin LI }
44206bfebdeSXin LI #endif
44306bfebdeSXin LI 
4440e3d5408SPeter Wemm /* fty_enum.c ends here */
445