xref: /openbsd/lib/libmenu/m_item_new.c (revision 5af055cd)
1 /* $OpenBSD: m_item_new.c,v 1.9 2010/01/12 23:22:08 nicm Exp $ */
2 
3 /****************************************************************************
4  * Copyright (c) 1998-2005,2006 Free Software Foundation, Inc.              *
5  *                                                                          *
6  * Permission is hereby granted, free of charge, to any person obtaining a  *
7  * copy of this software and associated documentation files (the            *
8  * "Software"), to deal in the Software without restriction, including      *
9  * without limitation the rights to use, copy, modify, merge, publish,      *
10  * distribute, distribute with modifications, sublicense, and/or sell       *
11  * copies of the Software, and to permit persons to whom the Software is    *
12  * furnished to do so, subject to the following conditions:                 *
13  *                                                                          *
14  * The above copyright notice and this permission notice shall be included  *
15  * in all copies or substantial portions of the Software.                   *
16  *                                                                          *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
20  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
21  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
22  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
23  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
24  *                                                                          *
25  * Except as contained in this notice, the name(s) of the above copyright   *
26  * holders shall not be used in advertising or otherwise to promote the     *
27  * sale, use or other dealings in this Software without prior written       *
28  * authorization.                                                           *
29  ****************************************************************************/
30 
31 /****************************************************************************
32  *   Author:  Juergen Pfeifer, 1995,1997                                    *
33  ****************************************************************************/
34 
35 /***************************************************************************
36 * Module m_item_new                                                        *
37 * Create and destroy menu items                                            *
38 * Set and get marker string for menu                                       *
39 ***************************************************************************/
40 
41 #include "menu.priv.h"
42 
43 #if USE_WIDEC_SUPPORT
44 #if HAVE_WCTYPE_H
45 #include <wctype.h>
46 #endif
47 #endif
48 
49 MODULE_ID("$Id: m_item_new.c,v 1.9 2010/01/12 23:22:08 nicm Exp $")
50 
51 /*---------------------------------------------------------------------------
52 |   Facility      :  libnmenu
53 |   Function      :  bool Is_Printable_String(const char *s)
54 |
55 |   Description   :  Checks whether or not the string contains only printable
56 |                    characters.
57 |
58 |   Return Values :  TRUE     - if string is printable
59 |                    FALSE    - if string contains non-printable characters
60 +--------------------------------------------------------------------------*/
61 static bool
62 Is_Printable_String(const char *s)
63 {
64   int result = TRUE;
65 
66 #if USE_WIDEC_SUPPORT
67   int count = mbstowcs(0, s, 0);
68   wchar_t *temp = 0;
69 
70   assert(s);
71 
72   if (count > 0
73       && (temp = typeCalloc(wchar_t, (2 + (unsigned)count))) != 0)
74     {
75       int n;
76 
77       mbstowcs(temp, s, (unsigned)count);
78       for (n = 0; n < count; ++n)
79 	if (!iswprint((wint_t) temp[n]))
80 	  {
81 	    result = FALSE;
82 	    break;
83 	  }
84       free(temp);
85     }
86 #else
87   assert(s);
88   while (*s)
89     {
90       if (!isprint(UChar(*s)))
91 	{
92 	  result = FALSE;
93 	  break;
94 	}
95       s++;
96     }
97 #endif
98   return result;
99 }
100 
101 /*---------------------------------------------------------------------------
102 |   Facility      :  libnmenu
103 |   Function      :  ITEM *new_item(char *name, char *description)
104 |
105 |   Description   :  Create a new item with name and description. Return
106 |                    a pointer to this new item.
107 |                    N.B.: an item must(!) have a name.
108 |
109 |   Return Values :  The item pointer or NULL if creation failed.
110 +--------------------------------------------------------------------------*/
111 NCURSES_EXPORT(ITEM *)
112 new_item(const char *name, const char *description)
113 {
114   ITEM *item;
115 
116   T((T_CALLED("new_item(\"%s\", \"%s\")"),
117      name ? name : "",
118      description ? description : ""));
119 
120   if (!name || (*name == '\0') || !Is_Printable_String(name))
121     {
122       item = (ITEM *) 0;
123       SET_ERROR(E_BAD_ARGUMENT);
124     }
125   else
126     {
127       item = (ITEM *) calloc(1, sizeof(ITEM));
128       if (item)
129 	{
130 	  *item = _nc_Default_Item;	/* hope we have struct assignment */
131 
132 	  item->name.length = strlen(name);
133 	  item->name.str = name;
134 
135 	  if (description && (*description != '\0') &&
136 	      Is_Printable_String(description))
137 	    {
138 	      item->description.length = strlen(description);
139 	      item->description.str = description;
140 	    }
141 	  else
142 	    {
143 	      item->description.length = 0;
144 	      item->description.str = (char *)0;
145 	    }
146 	}
147       else
148 	SET_ERROR(E_SYSTEM_ERROR);
149     }
150   returnItem(item);
151 }
152 
153 /*---------------------------------------------------------------------------
154 |   Facility      :  libnmenu
155 |   Function      :  int free_item(ITEM *item)
156 |
157 |   Description   :  Free the allocated storage for this item.
158 |                    N.B.: a connected item can't be freed.
159 |
160 |   Return Values :  E_OK              - success
161 |                    E_BAD_ARGUMENT    - invalid value has been passed
162 |                    E_CONNECTED       - item is still connected to a menu
163 +--------------------------------------------------------------------------*/
164 NCURSES_EXPORT(int)
165 free_item(ITEM * item)
166 {
167   T((T_CALLED("free_item(%p)"), item));
168 
169   if (!item)
170     RETURN(E_BAD_ARGUMENT);
171 
172   if (item->imenu)
173     RETURN(E_CONNECTED);
174 
175   free(item);
176 
177   RETURN(E_OK);
178 }
179 
180 /*---------------------------------------------------------------------------
181 |   Facility      :  libnmenu
182 |   Function      :  int set_menu_mark( MENU *menu, const char *mark )
183 |
184 |   Description   :  Set the mark string used to indicate the current
185 |                    item (single-valued menu) or the selected items
186 |                    (multi-valued menu).
187 |                    The mark argument may be NULL, in which case no
188 |                    marker is used.
189 |                    This might be a little bit tricky, because this may
190 |                    affect the geometry of the menu, which we don't allow
191 |                    if it is already posted.
192 |
193 |   Return Values :  E_OK               - success
194 |                    E_BAD_ARGUMENT     - an invalid value has been passed
195 |                    E_SYSTEM_ERROR     - no memory to store mark
196 +--------------------------------------------------------------------------*/
197 NCURSES_EXPORT(int)
198 set_menu_mark(MENU * menu, const char *mark)
199 {
200   unsigned l;
201 
202   T((T_CALLED("set_menu_mark(%p,%s)"), menu, _nc_visbuf(mark)));
203 
204   if (mark && (*mark != '\0') && Is_Printable_String(mark))
205     l = strlen(mark);
206   else
207     l = 0;
208 
209   if (menu)
210     {
211       char *old_mark = menu->mark;
212       unsigned short old_status = menu->status;
213 
214       if (menu->status & _POSTED)
215 	{
216 	  /* If the menu is already posted, the geometry is fixed. Then
217 	     we can only accept a mark with exactly the same length */
218 	  if (menu->marklen != (int)l)
219 	    RETURN(E_BAD_ARGUMENT);
220 	}
221       menu->marklen = l;
222       if (l)
223 	{
224 	  menu->mark = (char *)malloc(l + 1);
225 	  if (menu->mark)
226 	    {
227 	      strlcpy(menu->mark, mark, l+1);
228 	      if (menu != &_nc_Default_Menu)
229 		menu->status |= _MARK_ALLOCATED;
230 	    }
231 	  else
232 	    {
233 	      menu->mark = old_mark;
234 	      RETURN(E_SYSTEM_ERROR);
235 	    }
236 	}
237       else
238 	menu->mark = (char *)0;
239 
240       if ((old_status & _MARK_ALLOCATED) && old_mark)
241 	free(old_mark);
242 
243       if (menu->status & _POSTED)
244 	{
245 	  _nc_Draw_Menu(menu);
246 	  _nc_Show_Menu(menu);
247 	}
248       else
249 	{
250 	  /* Recalculate the geometry */
251 	  _nc_Calculate_Item_Length_and_Width(menu);
252 	}
253     }
254   else
255     {
256       returnCode(set_menu_mark(&_nc_Default_Menu, mark));
257     }
258   RETURN(E_OK);
259 }
260 
261 /*---------------------------------------------------------------------------
262 |   Facility      :  libnmenu
263 |   Function      :  char *menu_mark(const MENU *menu)
264 |
265 |   Description   :  Return a pointer to the marker string
266 |
267 |   Return Values :  The marker string pointer or NULL if no marker defined
268 +--------------------------------------------------------------------------*/
269 NCURSES_EXPORT(const char *)
270 menu_mark(const MENU * menu)
271 {
272   T((T_CALLED("menu_mark(%p)"), menu));
273   returnPtr(Normalize_Menu(menu)->mark);
274 }
275 
276 /* m_item_new.c */
277