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