0d0e98441b8897bc29655c2c8fae1bdbcd566241
[ncurses.git] / menu / m_item_new.c
1 /*-----------------------------------------------------------------------------+
2 |           The ncurses menu library is  Copyright (C) 1995-1997               |
3 |             by Juergen Pfeifer <Juergen.Pfeifer@T-Online.de>                 |
4 |                          All Rights Reserved.                                |
5 |                                                                              |
6 | Permission to use, copy, modify, and distribute this software and its        |
7 | documentation for any purpose and without fee is hereby granted, provided    |
8 | that the above copyright notice appear in all copies and that both that      |
9 | copyright notice and this permission notice appear in supporting             |
10 | documentation, and that the name of the above listed copyright holder(s) not |
11 | be used in advertising or publicity pertaining to distribution of the        |
12 | software without specific, written prior permission.                         | 
13 |                                                                              |
14 | THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD TO  |
15 | THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-  |
16 | NESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR   |
17 | ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RE- |
18 | SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
19 | NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH    |
20 | THE USE OR PERFORMANCE OF THIS SOFTWARE.                                     |
21 +-----------------------------------------------------------------------------*/
22
23 /***************************************************************************
24 * Module menu_item_new                                                     *
25 * Create and destroy menu items                                            *
26 * Set and get marker string for menu
27 ***************************************************************************/
28
29 #include "menu.priv.h"
30
31 MODULE_ID("$Id: m_item_new.c,v 1.5 1997/05/01 16:47:26 juergen Exp $")
32
33 /*---------------------------------------------------------------------------
34 |   Facility      :  libnmenu  
35 |   Function      :  bool Is_Printable_String(const char *s)
36 |   
37 |   Description   :  Checks whether or not the string contains only printable
38 |                    characters.
39 |
40 |   Return Values :  TRUE     - if string is printable
41 |                    FALSE    - if string contains non-printable characters
42 +--------------------------------------------------------------------------*/
43 static bool Is_Printable_String(const char *s)
44 {
45   assert(s);
46   while(*s)
47     {
48       if (!isprint((unsigned char)*s))
49         return FALSE;
50       s++;
51     }
52   return TRUE;
53 }
54
55 /*---------------------------------------------------------------------------
56 |   Facility      :  libnmenu  
57 |   Function      :  ITEM *new_item(char *name, char *description)
58 |   
59 |   Description   :  Create a new item with name and description. Return
60 |                    a pointer to this new item.
61 |                    N.B.: an item must(!) have a name.
62 |
63 |   Return Values :  The item pointer or NULL if creation failed.
64 +--------------------------------------------------------------------------*/
65 ITEM *new_item(const char *name, const char *description)
66 {
67   ITEM *item;
68   
69   if ( !name || (*name == '\0') || !Is_Printable_String(name) )
70     {
71       item = (ITEM *)0;
72       SET_ERROR( E_BAD_ARGUMENT );
73     }
74   else
75     {
76       item = (ITEM *)calloc(1,sizeof(ITEM));
77       if (item)
78         {
79           *item  = _nc_Default_Item; /* hope we have struct assignment */
80           
81           item->name.length        = strlen(name);
82           item->name.str           = (char *)malloc(1 + item->name.length);
83           if (item->name.str)
84             {
85               strcpy(item->name.str, name);
86             }
87           else
88             {
89               free(item);
90               SET_ERROR( E_SYSTEM_ERROR );
91               return (ITEM *)0;
92             }
93           
94           if (description && (*description != '\0') && 
95               Is_Printable_String(description))
96             {
97               item->description.length = strlen(description);         
98               item->description.str    = 
99                 (char *)malloc(1 + item->description.length);
100               if (item->description.str)
101                 {
102                   strcpy(item->description.str, description);
103                 }
104               else
105                 {
106                   free(item->name.str);
107                   free(item);
108                   SET_ERROR( E_SYSTEM_ERROR );
109                   return (ITEM *)0;
110                 }
111             }
112           else
113             {
114               item->description.length = 0;
115               item->description.str    = (char *)0;
116             }
117         }
118       else
119         SET_ERROR( E_SYSTEM_ERROR );
120     }  
121   return(item);
122 }
123
124 /*---------------------------------------------------------------------------
125 |   Facility      :  libnmenu  
126 |   Function      :  int free_item(ITEM *item)
127 |   
128 |   Description   :  Free the allocated storage for this item. 
129 |                    N.B.: a connected item can't be freed.
130 |
131 |   Return Values :  E_OK              - success
132 |                    E_BAD_ARGUMENT    - invalid value has been passed
133 |                    E_CONNECTED       - item is still connected to a menu    
134 +--------------------------------------------------------------------------*/
135 int free_item(ITEM * item)
136 {
137   if (!item)
138     RETURN( E_BAD_ARGUMENT );
139
140   if (item->imenu)
141     RETURN( E_CONNECTED );
142   
143   if (item->name.str)
144     free(item->name.str);
145   if (item->description.str)
146     free (item->description.str);
147   free(item);
148
149   RETURN( E_OK );
150 }
151
152 /*---------------------------------------------------------------------------
153 |   Facility      :  libnmenu  
154 |   Function      :  int set_menu_mark( MENU *menu, const char *mark )
155 |   
156 |   Description   :  Set the mark string used to indicate the current
157 |                    item (single-valued menu) or the selected items
158 |                    (multi-valued menu).
159 |                    The mark argument may be NULL, in which case no 
160 |                    marker is used.
161 |                    This might be a little bit tricky, because this may 
162 |                    affect the geometry of the menu, which we don't allow 
163 |                    if it is already posted.
164 |
165 |   Return Values :  E_OK               - success
166 |                    E_BAD_ARGUMENT     - an invalid value has been passed
167 |                    E_SYSTEM_ERROR     - no memory to store mark
168 +--------------------------------------------------------------------------*/
169 int set_menu_mark(MENU * menu, const char * mark)
170 {
171   int l;
172
173   if ( mark && (*mark != '\0') && Is_Printable_String(mark) )
174     l = strlen(mark);
175   else
176     l = 0;
177
178   if ( menu )
179     {
180       char *old_mark = menu->mark;
181       unsigned short old_status = menu->status;
182
183       if (menu->status & _POSTED)
184         {
185           /* If the menu is already posted, the geometry is fixed. Then
186              we can only accept a mark with exactly the same length */
187           if (menu->marklen != l) 
188             RETURN(E_BAD_ARGUMENT);
189         }       
190       menu->marklen = l;
191       if (l)
192         {
193           menu->mark = (char *)malloc(l+1);
194           if (menu->mark)
195             {
196               strcpy(menu->mark, mark);
197               menu->status |= _MARK_ALLOCATED;
198             }
199           else
200             {
201               menu->mark = old_mark;
202               RETURN(E_SYSTEM_ERROR);
203             }
204         }
205       else
206         menu->mark = (char *)0;
207       
208       if ((old_status & _MARK_ALLOCATED) && old_mark)
209         free(old_mark);
210
211       if (menu->status & _POSTED)
212         {
213           _nc_Draw_Menu( menu );
214           _nc_Show_Menu( menu );
215         }
216       else
217         {
218           /* Recalculate the geometry */
219           _nc_Calculate_Item_Length_and_Width( menu );                  
220         }
221     }
222   else
223     {
224       return set_menu_mark(&_nc_Default_Menu, mark);
225     }
226   RETURN(E_OK);
227 }
228
229 /*---------------------------------------------------------------------------
230 |   Facility      :  libnmenu  
231 |   Function      :  char *menu_mark(const MENU *menu)
232 |   
233 |   Description   :  Return a pointer to the marker string
234 |
235 |   Return Values :  The marker string pointer or NULL if no marker defined
236 +--------------------------------------------------------------------------*/
237 const char *menu_mark(const MENU * menu)
238 {
239   return Normalize_Menu( menu )->mark;
240 }
241
242 /* m_item_new.c */