1 /****************************************************************************
2 * Copyright (c) 1998-2002,2003 Free Software Foundation, Inc. *
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: *
12 * The above copyright notice and this permission notice shall be included *
13 * in all copies or substantial portions of the Software. *
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. *
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 *
27 ****************************************************************************/
29 /****************************************************************************
30 * Author: Juergen Pfeifer, 1995,1997 *
31 ****************************************************************************/
33 /***************************************************************************
35 * Globally used internal routines and the default menu and item structures *
36 ***************************************************************************/
38 #include "menu.priv.h"
40 MODULE_ID("$Id: m_global.c,v 1.16 2003/11/08 20:53:01 tom Exp $")
42 static char mark
[] = "-";
44 NCURSES_EXPORT_VAR(MENU
) _nc_Default_Menu
= {
45 16, /* Nr. of chars high */
46 1, /* Nr. of chars wide */
47 16, /* Nr. of items high */
48 1, /* Nr. of items wide */
49 16, /* Nr. of formatted items high */
50 1, /* Nr. of formatted items wide */
51 16, /* Nr. of items high (actual) */
52 0, /* length of widest name */
53 0, /* length of widest description */
54 1, /* length of mark */
55 1, /* length of one item */
56 1, /* Spacing for descriptor */
57 1, /* Spacing for columns */
58 1, /* Spacing for rows */
59 (char *)0, /* buffer used to store match chars */
60 0, /* Index into pattern buffer */
61 (WINDOW
*)0, /* Window containing entire menu */
62 (WINDOW
*)0, /* Portion of menu displayed */
63 (WINDOW
*)0, /* User's window */
64 (WINDOW
*)0, /* User's subwindow */
65 (ITEM
**)0, /* List of items */
66 0, /* Total Nr. of items in menu */
67 (ITEM
*)0, /* Current item */
68 0, /* Top row of menu */
69 (chtype
)A_REVERSE
, /* Attribute for selection */
70 (chtype
)A_NORMAL
, /* Attribute for nonselection */
71 (chtype
)A_UNDERLINE
, /* Attribute for inactive */
72 ' ', /* Pad character */
73 (Menu_Hook
)0, /* Menu init */
74 (Menu_Hook
)0, /* Menu term */
75 (Menu_Hook
)0, /* Item init */
76 (Menu_Hook
)0, /* Item term */
77 (void *)0, /* userptr */
79 ALL_MENU_OPTS
, /* options */
83 NCURSES_EXPORT_VAR(ITEM
) _nc_Default_Item
= {
84 { (char *)0, 0 }, /* name */
85 { (char *)0, 0 }, /* description */
86 (MENU
*)0, /* Pointer to parent menu */
87 (char *)0, /* Userpointer */
88 ALL_ITEM_OPTS
, /* options */
94 (ITEM
*)0, /* right */
99 /*---------------------------------------------------------------------------
100 | Facility : libnmenu
101 | Function : static void ComputeMaximum_NameDesc_Lenths(MENU *menu)
103 | Description : Calculates the maximum name and description lengths
104 | of the items connected to the menu
107 +--------------------------------------------------------------------------*/
108 INLINE
static void ComputeMaximum_NameDesc_Lengths(MENU
* menu
)
110 unsigned MaximumNameLength
= 0;
111 unsigned MaximumDescriptionLength
= 0;
114 assert(menu
&& menu
->items
);
115 for( items
= menu
->items
; *items
; items
++ )
117 if (items
[0]->name
.length
> MaximumNameLength
)
118 MaximumNameLength
= items
[0]->name
.length
;
120 if (items
[0]->description
.length
> MaximumDescriptionLength
)
121 MaximumDescriptionLength
= items
[0]->description
.length
;
124 menu
->namelen
= MaximumNameLength
;
125 menu
->desclen
= MaximumDescriptionLength
;
128 /*---------------------------------------------------------------------------
129 | Facility : libnmenu
130 | Function : static void ResetConnectionInfo(MENU *, ITEM **)
132 | Description : Reset all informations in the menu and the items in
133 | the item array that indicates a connection
136 +--------------------------------------------------------------------------*/
137 INLINE
static void ResetConnectionInfo(MENU
*menu
, ITEM
**items
)
141 assert(menu
&& items
);
142 for(item
=items
; *item
; item
++)
145 (*item
)->imenu
= (MENU
*)0;
149 menu
->pattern
= (char *)0;
151 menu
->items
= (ITEM
**)0;
155 /*---------------------------------------------------------------------------
156 | Facility : libnmenu
157 | Function : bool _nc_Connect_Items(MENU *menu, ITEM **items)
159 | Description : Connect the items in the item array to the menu.
160 | Decorate all the items with a number and a backward
161 | pointer to the menu.
163 | Return Values : TRUE - successful connection
164 | FALSE - connection failed
165 +--------------------------------------------------------------------------*/
167 _nc_Connect_Items (MENU
*menu
, ITEM
**items
)
170 unsigned int ItemCount
= 0;
174 for(item
=items
; *item
; item
++)
176 if ( (*item
)->imenu
)
178 /* if a item is already connected, reject connection */
183 /* we reached the end, so there was no connected item */
185 for(item
=items
; *item
; item
++)
187 if (menu
->opt
& O_ONEVALUE
)
189 (*item
)->value
= FALSE
;
191 (*item
)->index
= ItemCount
++;
192 (*item
)->imenu
= menu
;
202 menu
->nitems
= ItemCount
;
203 ComputeMaximum_NameDesc_Lengths(menu
);
204 if ( (menu
->pattern
= (char *)malloc( (unsigned)(1 + menu
->namelen
))) )
207 set_menu_format(menu
,menu
->frows
,menu
->fcols
);
208 menu
->curitem
= *items
;
214 /* If we fall through to this point, we have to reset all items connection
215 and inform about a reject connection */
216 ResetConnectionInfo( menu
, items
);
220 /*---------------------------------------------------------------------------
221 | Facility : libnmenu
222 | Function : void _nc_Disconnect_Items(MENU *menu)
224 | Description : Disconnect the menus item array from the menu
227 +--------------------------------------------------------------------------*/
229 _nc_Disconnect_Items (MENU
* menu
)
231 if (menu
&& menu
->items
)
232 ResetConnectionInfo( menu
, menu
->items
);
235 /*---------------------------------------------------------------------------
236 | Facility : libnmenu
237 | Function : void _nc_Calculate_Item_Length_and_Width(MENU *menu)
239 | Description : Calculate the length of an item and the width of the
243 +--------------------------------------------------------------------------*/
245 _nc_Calculate_Item_Length_and_Width (MENU
* menu
)
251 menu
->height
= 1 + menu
->spc_rows
* (menu
->arows
- 1);
253 l
= menu
->namelen
+ menu
->marklen
;
254 if ( (menu
->opt
& O_SHOWDESC
) && (menu
->desclen
> 0) )
255 l
+= (menu
->desclen
+ menu
->spc_desc
);
259 l
+= (menu
->cols
-1)*menu
->spc_cols
; /* for the padding between the columns */
263 /*---------------------------------------------------------------------------
264 | Facility : libnmenu
265 | Function : void _nc_Link_Item(MENU *menu)
267 | Description : Statically calculate for every item its four neighbors.
268 | This depends on the orientation of the menu. This
269 | static approach simplifies navigation in the menu a lot.
272 +--------------------------------------------------------------------------*/
274 _nc_Link_Items (MENU
* menu
)
276 if (menu
&& menu
->items
&& *(menu
->items
))
280 int Number_Of_Items
= menu
->nitems
;
281 int col
= 0, row
= 0;
284 bool cycle
= (menu
->opt
& O_NONCYCLIC
) ? FALSE
: TRUE
;
286 menu
->status
&= ~_LINK_NEEDED
;
288 if (menu
->opt
& O_ROWMAJOR
)
290 int Number_Of_Columns
= menu
->cols
;
292 for(i
=0; i
< Number_Of_Items
; i
++)
294 item
= menu
->items
[i
];
296 Last_in_Row
= row
* Number_Of_Columns
+ (Number_Of_Columns
-1);
299 /* if we are not in the leftmost column, we can use the
300 predecessor in the items array */
302 (cycle
? menu
->items
[(Last_in_Row
>=Number_Of_Items
) ?
307 item
->right
= ( (col
< (Number_Of_Columns
-1)) &&
308 ((i
+1) < Number_Of_Items
)
311 ( cycle
? menu
->items
[row
* Number_Of_Columns
] :
315 Last_in_Column
= (menu
->rows
-1) * Number_Of_Columns
+ col
;
317 item
->up
= (row
) ? menu
->items
[i
-Number_Of_Columns
] :
318 (cycle
? menu
->items
[(Last_in_Column
>=Number_Of_Items
) ?
323 item
->down
= ( (i
+Number_Of_Columns
) < Number_Of_Items
)
325 menu
->items
[i
+ Number_Of_Columns
] :
326 (cycle
? menu
->items
[(row
+1)<menu
->rows
?
327 Number_Of_Items
-1:col
] :
331 if ( ++col
== Number_Of_Columns
)
340 int Number_Of_Rows
= menu
->rows
;
342 for(j
=0; j
<Number_Of_Items
; j
++)
344 item
= menu
->items
[i
=(col
* Number_Of_Rows
+ row
)];
346 Last_in_Column
= (menu
->cols
-1) * Number_Of_Rows
+ row
;
349 menu
->items
[i
- Number_Of_Rows
] :
350 (cycle
? (Last_in_Column
>= Number_Of_Items
) ?
351 menu
->items
[Last_in_Column
-Number_Of_Rows
] :
352 menu
->items
[Last_in_Column
] :
355 item
->right
= ((i
+ Number_Of_Rows
) <Number_Of_Items
)
357 menu
->items
[i
+ Number_Of_Rows
] :
358 (cycle
? menu
->items
[row
] : (ITEM
*)0);
360 Last_in_Row
= col
* Number_Of_Rows
+ (Number_Of_Rows
- 1);
365 menu
->items
[(Last_in_Row
>=Number_Of_Items
) ?
370 item
->down
= (row
< (Number_Of_Rows
-1))
372 (menu
->items
[((i
+1)<Number_Of_Items
) ?
374 (col
-1)*Number_Of_Rows
+ row
+ 1]) :
376 menu
->items
[col
* Number_Of_Rows
] :
382 if ( (++row
) == Number_Of_Rows
)
392 /*---------------------------------------------------------------------------
393 | Facility : libnmenu
394 | Function : void _nc_Show_Menu(const MENU *menu)
396 | Description : Update the window that is associated with the menu
399 +--------------------------------------------------------------------------*/
401 _nc_Show_Menu (const MENU
*menu
)
407 if ( (menu
->status
& _POSTED
) && !(menu
->status
& _IN_DRIVER
) )
409 /* adjust the internal subwindow to start on the current top */
411 mvderwin(menu
->sub
,menu
->spc_rows
* menu
->toprow
,0);
412 win
= Get_Menu_Window(menu
);
417 if (menu
->height
< maxy
)
419 if (menu
->width
< maxx
)
422 copywin(menu
->sub
,win
,0,0,0,0,maxy
-1,maxx
-1,0);
423 pos_menu_cursor(menu
);
427 /*---------------------------------------------------------------------------
428 | Facility : libnmenu
429 | Function : void _nc_New_TopRow_and_CurrentItem(
432 | ITEM *new_current_item)
434 | Description : Redisplay the menu so that the given row becomes the
435 | top row and the given item becomes the new current
439 +--------------------------------------------------------------------------*/
441 _nc_New_TopRow_and_CurrentItem
442 (MENU
*menu
, int new_toprow
, ITEM
*new_current_item
)
445 bool mterm_called
= FALSE
;
446 bool iterm_called
= FALSE
;
449 if (menu
->status
& _POSTED
)
451 if (new_current_item
!= menu
->curitem
)
453 Call_Hook(menu
,itemterm
);
456 if (new_toprow
!= menu
->toprow
)
458 Call_Hook(menu
,menuterm
);
462 cur_item
= menu
->curitem
;
464 menu
->toprow
= new_toprow
;
465 menu
->curitem
= new_current_item
;
469 Call_Hook(menu
,menuinit
);
473 /* this means, move from the old current_item to the new one... */
474 Move_To_Current_Item( menu
, cur_item
);
475 Call_Hook(menu
,iteminit
);
477 if (mterm_called
|| iterm_called
)
482 pos_menu_cursor(menu
);
485 { /* if we are not posted, this is quite simple */
486 menu
->toprow
= new_toprow
;
487 menu
->curitem
= new_current_item
;
491 /* m_global.c ends here */