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