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 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 *) 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) 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) 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 *) 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