1/****************************************************************************
2 * Copyright (c) 1998-2005,2006 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#if HAVE_WCTYPE_H
43#include <wctype.h>
44#endif
45#endif
46
47MODULE_ID("$Id: m_item_new.c,v 1.27 2006/12/17 19:47:09 tom Exp $")
48
49/*---------------------------------------------------------------------------
50|   Facility      :  libnmenu
51|   Function      :  bool Is_Printable_String(const char *s)
52|
53|   Description   :  Checks whether or not the string contains only printable
54|                    characters.
55|
56|   Return Values :  TRUE     - if string is printable
57|                    FALSE    - if string contains non-printable characters
58+--------------------------------------------------------------------------*/
59static bool
60Is_Printable_String(const char *s)
61{
62  int result = TRUE;
63
64#if USE_WIDEC_SUPPORT
65  int count = mbstowcs(0, s, 0);
66  wchar_t *temp = 0;
67
68  assert(s);
69
70  if (count > 0
71      && (temp = typeCalloc(wchar_t, (2 + (unsigned)count))) != 0)
72    {
73      int n;
74
75      mbstowcs(temp, s, (unsigned)count);
76      for (n = 0; n < count; ++n)
77	if (!iswprint((wint_t) temp[n]))
78	  {
79	    result = FALSE;
80	    break;
81	  }
82      free(temp);
83    }
84#else
85  assert(s);
86  while (*s)
87    {
88      if (!isprint(UChar(*s)))
89	{
90	  result = FALSE;
91	  break;
92	}
93      s++;
94    }
95#endif
96  return result;
97}
98
99/*---------------------------------------------------------------------------
100|   Facility      :  libnmenu
101|   Function      :  ITEM *new_item(char *name, char *description)
102|
103|   Description   :  Create a new item with name and description. Return
104|                    a pointer to this new item.
105|                    N.B.: an item must(!) have a name.
106|
107|   Return Values :  The item pointer or NULL if creation failed.
108+--------------------------------------------------------------------------*/
109NCURSES_EXPORT(ITEM *)
110new_item(const char *name, const char *description)
111{
112  ITEM *item;
113
114  T((T_CALLED("new_item(\"%s\", \"%s\")"),
115     name ? name : "",
116     description ? description : ""));
117
118  if (!name || (*name == '\0') || !Is_Printable_String(name))
119    {
120      item = (ITEM *) 0;
121      SET_ERROR(E_BAD_ARGUMENT);
122    }
123  else
124    {
125      item = (ITEM *) calloc(1, sizeof(ITEM));
126      if (item)
127	{
128	  *item = _nc_Default_Item;	/* hope we have struct assignment */
129
130	  item->name.length = strlen(name);
131	  item->name.str = name;
132
133	  if (description && (*description != '\0') &&
134	      Is_Printable_String(description))
135	    {
136	      item->description.length = strlen(description);
137	      item->description.str = description;
138	    }
139	  else
140	    {
141	      item->description.length = 0;
142	      item->description.str = (char *)0;
143	    }
144	}
145      else
146	SET_ERROR(E_SYSTEM_ERROR);
147    }
148  returnItem(item);
149}
150
151/*---------------------------------------------------------------------------
152|   Facility      :  libnmenu
153|   Function      :  int free_item(ITEM *item)
154|
155|   Description   :  Free the allocated storage for this item.
156|                    N.B.: a connected item can't be freed.
157|
158|   Return Values :  E_OK              - success
159|                    E_BAD_ARGUMENT    - invalid value has been passed
160|                    E_CONNECTED       - item is still connected to a menu
161+--------------------------------------------------------------------------*/
162NCURSES_EXPORT(int)
163free_item(ITEM * item)
164{
165  T((T_CALLED("free_item(%p)"), item));
166
167  if (!item)
168    RETURN(E_BAD_ARGUMENT);
169
170  if (item->imenu)
171    RETURN(E_CONNECTED);
172
173  free(item);
174
175  RETURN(E_OK);
176}
177
178/*---------------------------------------------------------------------------
179|   Facility      :  libnmenu
180|   Function      :  int set_menu_mark( MENU *menu, const char *mark )
181|
182|   Description   :  Set the mark string used to indicate the current
183|                    item (single-valued menu) or the selected items
184|                    (multi-valued menu).
185|                    The mark argument may be NULL, in which case no
186|                    marker is used.
187|                    This might be a little bit tricky, because this may
188|                    affect the geometry of the menu, which we don't allow
189|                    if it is already posted.
190|
191|   Return Values :  E_OK               - success
192|                    E_BAD_ARGUMENT     - an invalid value has been passed
193|                    E_SYSTEM_ERROR     - no memory to store mark
194+--------------------------------------------------------------------------*/
195NCURSES_EXPORT(int)
196set_menu_mark(MENU * menu, const char *mark)
197{
198  unsigned l;
199
200  T((T_CALLED("set_menu_mark(%p,%s)"), menu, _nc_visbuf(mark)));
201
202  if (mark && (*mark != '\0') && Is_Printable_String(mark))
203    l = strlen(mark);
204  else
205    l = 0;
206
207  if (menu)
208    {
209      char *old_mark = menu->mark;
210      unsigned short old_status = menu->status;
211
212      if (menu->status & _POSTED)
213	{
214	  /* If the menu is already posted, the geometry is fixed. Then
215	     we can only accept a mark with exactly the same length */
216	  if (menu->marklen != (int)l)
217	    RETURN(E_BAD_ARGUMENT);
218	}
219      menu->marklen = l;
220      if (l)
221	{
222	  menu->mark = (char *)malloc(l + 1);
223	  if (menu->mark)
224	    {
225	      strcpy(menu->mark, mark);
226	      if (menu != &_nc_Default_Menu)
227		menu->status |= _MARK_ALLOCATED;
228	    }
229	  else
230	    {
231	      menu->mark = old_mark;
232	      RETURN(E_SYSTEM_ERROR);
233	    }
234	}
235      else
236	menu->mark = (char *)0;
237
238      if ((old_status & _MARK_ALLOCATED) && old_mark)
239	free(old_mark);
240
241      if (menu->status & _POSTED)
242	{
243	  _nc_Draw_Menu(menu);
244	  _nc_Show_Menu(menu);
245	}
246      else
247	{
248	  /* Recalculate the geometry */
249	  _nc_Calculate_Item_Length_and_Width(menu);
250	}
251    }
252  else
253    {
254      returnCode(set_menu_mark(&_nc_Default_Menu, mark));
255    }
256  RETURN(E_OK);
257}
258
259/*---------------------------------------------------------------------------
260|   Facility      :  libnmenu
261|   Function      :  char *menu_mark(const MENU *menu)
262|
263|   Description   :  Return a pointer to the marker string
264|
265|   Return Values :  The marker string pointer or NULL if no marker defined
266+--------------------------------------------------------------------------*/
267NCURSES_EXPORT(const char *)
268menu_mark(const MENU * menu)
269{
270  T((T_CALLED("menu_mark(%p)"), menu));
271  returnPtr(Normalize_Menu(menu)->mark);
272}
273
274/* m_item_new.c */
275