1 // * This makes emacs happy -*-Mode: C++;-*-
2 /****************************************************************************
3 * Copyright (c) 1998-2012,2014 Free Software Foundation, Inc. *
5 * Permission is hereby granted, free of charge, to any person obtaining a *
6 * copy of this software and associated documentation files (the *
7 * "Software"), to deal in the Software without restriction, including *
8 * without limitation the rights to use, copy, modify, merge, publish, *
9 * distribute, distribute with modifications, sublicense, and/or sell *
10 * copies of the Software, and to permit persons to whom the Software is *
11 * furnished to do so, subject to the following conditions: *
13 * The above copyright notice and this permission notice shall be included *
14 * in all copies or substantial portions of the Software. *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
19 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
22 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
24 * Except as contained in this notice, the name(s) of the above copyright *
25 * holders shall not be used in advertising or otherwise to promote the *
26 * sale, use or other dealings in this Software without prior written *
28 ****************************************************************************/
30 /****************************************************************************
31 * Author: Juergen Pfeifer, 1997 *
32 ****************************************************************************/
34 // $Id: cursesm.h,v 1.30 2014/08/09 22:06:18 Adam.Jiang Exp $
36 #ifndef NCURSES_CURSESM_H_incl
37 #define NCURSES_CURSESM_H_incl 1
45 // -------------------------------------------------------------------------
46 // This wraps the ITEM type of <menu.h>
47 // -------------------------------------------------------------------------
49 class NCURSES_IMPEXP NCursesMenuItem
51 friend class NCursesMenu
;
56 inline void OnError (int err
) const THROW2(NCursesException
const, NCursesMenuException
) {
58 THROW(new NCursesMenuException (err
));
62 NCursesMenuItem (const char* p_name
= NULL
,
63 const char* p_descript
= NULL
)
66 item
= p_name
? ::new_item (p_name
, p_descript
) : STATIC_CAST(ITEM
*)(0);
68 OnError (E_SYSTEM_ERROR
);
70 // Create an item. If you pass both parameters as NULL, a delimiting
71 // item is constructed which can be used to terminate a list of
72 // NCursesMenu objects.
74 NCursesMenuItem
& operator=(const NCursesMenuItem
& rhs
)
82 NCursesMenuItem(const NCursesMenuItem
& rhs
)
88 virtual ~NCursesMenuItem ();
89 // Release the items memory
91 inline const char* name () const {
92 return ::item_name (item
);
96 inline const char* description () const {
97 return ::item_description (item
);
99 // Description of the item
101 inline int (index
) (void) const {
102 return ::item_index (item
);
104 // Index of the item in an item array (or -1)
106 inline void options_on (Item_Options opts
) {
107 OnError (::item_opts_on (item
, opts
));
109 // Switch on the items options
111 inline void options_off (Item_Options opts
) {
112 OnError (::item_opts_off (item
, opts
));
114 // Switch off the item's option
116 inline Item_Options
options () const {
117 return ::item_opts (item
);
119 // Retrieve the items options
121 inline void set_options (Item_Options opts
) {
122 OnError (::set_item_opts (item
, opts
));
124 // Set the items options
126 inline void set_value (bool f
) {
127 OnError (::set_item_value (item
,f
));
129 // Set/Reset the items selection state
131 inline bool value () const {
132 return ::item_value (item
);
134 // Retrieve the items selection state
136 inline bool visible () const {
137 return ::item_visible (item
);
139 // Retrieve visibility of the item
141 virtual bool action();
142 // Perform an action associated with this item; you may use this in an
143 // user supplied driver for a menu; you may derive from this class and
144 // overload action() to supply items with different actions.
145 // If an action returns true, the menu will be exited. The default action
149 // Prototype for an items callback function.
150 typedef bool ITEMCALLBACK(NCursesMenuItem
&);
152 // If you don't like to create a child class for individual items to
153 // overload action(), you may use this class and provide a callback
154 // function pointer for items.
155 class NCURSES_IMPEXP NCursesMenuCallbackItem
: public NCursesMenuItem
161 NCursesMenuCallbackItem(ITEMCALLBACK
* fct
= NULL
,
162 const char* p_name
= NULL
,
163 const char* p_descript
= NULL
)
164 : NCursesMenuItem (p_name
, p_descript
),
168 NCursesMenuCallbackItem
& operator=(const NCursesMenuCallbackItem
& rhs
)
176 NCursesMenuCallbackItem(const NCursesMenuCallbackItem
& rhs
)
177 : NCursesMenuItem(rhs
),
182 virtual ~NCursesMenuCallbackItem();
187 // This are the built-in hook functions in this C++ binding. In C++ we use
188 // virtual member functions (see below On_..._Init and On_..._Termination)
189 // to provide this functionality in an object oriented manner.
191 void _nc_xx_mnu_init(MENU
*);
192 void _nc_xx_mnu_term(MENU
*);
193 void _nc_xx_itm_init(MENU
*);
194 void _nc_xx_itm_term(MENU
*);
198 // -------------------------------------------------------------------------
199 // This wraps the MENU type of <menu.h>
200 // -------------------------------------------------------------------------
202 class NCURSES_IMPEXP NCursesMenu
: public NCursesPanel
208 NCursesWindow
* sub
; // the subwindow object
209 bool b_sub_owner
; // is this our own subwindow?
210 bool b_framed
; // has the menu a border?
211 bool b_autoDelete
; // Delete items when deleting menu?
213 NCursesMenuItem
** my_items
; // The array of items for this menu
215 // This structure is used for the menu's user data field to link the
216 // MENU* to the C++ object and to provide extra space for a user pointer.
218 void* m_user
; // the pointer for the user's data
219 const NCursesMenu
* m_back
; // backward pointer to C++ object
223 // Get the backward pointer to the C++ object from a MENU
224 static inline NCursesMenu
* getHook(const MENU
*m
) {
225 UserHook
* hook
= STATIC_CAST(UserHook
*)(::menu_userptr(m
));
226 assert(hook
!= 0 && hook
->m_owner
==m
);
227 return const_cast<NCursesMenu
*>(hook
->m_back
);
230 friend void _nc_xx_mnu_init(MENU
*);
231 friend void _nc_xx_mnu_term(MENU
*);
232 friend void _nc_xx_itm_init(MENU
*);
233 friend void _nc_xx_itm_term(MENU
*);
235 // Calculate ITEM* array for the menu
236 ITEM
** mapItems(NCursesMenuItem
* nitems
[]);
240 inline void set_user(void *user
) {
241 UserHook
* uptr
= STATIC_CAST(UserHook
*)(::menu_userptr (menu
));
242 assert (uptr
!= 0 && uptr
->m_back
==this && uptr
->m_owner
==menu
);
246 inline void *get_user() {
247 UserHook
* uptr
= STATIC_CAST(UserHook
*)(::menu_userptr (menu
));
248 assert (uptr
!= 0 && uptr
->m_back
==this && uptr
->m_owner
==menu
);
252 void InitMenu (NCursesMenuItem
* menu
[],
254 bool autoDeleteItems
);
256 inline void OnError (int err
) const THROW2(NCursesException
const, NCursesMenuException
) {
258 THROW(new NCursesMenuException (this, err
));
261 // this wraps the menu_driver call.
262 virtual int driver (int c
) ;
264 // 'Internal' constructor to create a menu without association to
265 // an array of items.
266 NCursesMenu( int nlines
,
270 : NCursesPanel(nlines
,ncols
,begin_y
,begin_x
),
271 menu (STATIC_CAST(MENU
*)(0)),
281 // Make a full window size menu
282 NCursesMenu (NCursesMenuItem
* Items
[],
283 bool with_frame
=FALSE
, // Reserve space for a frame?
284 bool autoDelete_Items
=FALSE
) // Autocleanup of Items?
293 InitMenu(Items
, with_frame
, autoDelete_Items
);
296 // Make a menu with a window of this size.
297 NCursesMenu (NCursesMenuItem
* Items
[],
302 bool with_frame
=FALSE
, // Reserve space for a frame?
303 bool autoDelete_Items
=FALSE
) // Autocleanup of Items?
304 : NCursesPanel(nlines
, ncols
, begin_y
, begin_x
),
312 InitMenu(Items
, with_frame
, autoDelete_Items
);
315 NCursesMenu
& operator=(const NCursesMenu
& rhs
)
319 NCursesPanel::operator=(rhs
);
324 NCursesMenu(const NCursesMenu
& rhs
)
328 b_sub_owner(rhs
.b_sub_owner
),
329 b_framed(rhs
.b_framed
),
330 b_autoDelete(rhs
.b_autoDelete
),
331 my_items(rhs
.my_items
)
335 virtual ~NCursesMenu ();
337 // Retrieve the menus subwindow
338 inline NCursesWindow
& subWindow() const {
343 // Set the menus subwindow
344 void setSubWindow(NCursesWindow
& sub
);
346 // Set these items for the menu
347 inline void setItems(NCursesMenuItem
* Items
[]) {
348 OnError(::set_menu_items(menu
,mapItems(Items
)));
351 // Remove the menu from the screen
352 inline void unpost (void) {
353 OnError (::unpost_menu (menu
));
356 // Post the menu to the screen if flag is true, unpost it otherwise
357 inline void post(bool flag
= TRUE
) {
358 flag
? OnError (::post_menu(menu
)) : OnError (::unpost_menu (menu
));
361 // Get the numer of rows and columns for this menu
362 inline void scale (int& mrows
, int& mcols
) const {
363 OnError (::scale_menu (menu
, &mrows
, &mcols
));
366 // Set the format of this menu
367 inline void set_format(int mrows
, int mcols
) {
368 OnError (::set_menu_format(menu
, mrows
, mcols
));
371 // Get the format of this menu
372 inline void menu_format(int& rows
,int& ncols
) {
373 ::menu_format(menu
,&rows
,&ncols
);
377 inline NCursesMenuItem
* items() const {
381 // Get the number of items in this menu
382 inline int count() const {
383 return ::item_count(menu
);
386 // Get the current item (i.e. the one the cursor is located)
387 inline NCursesMenuItem
* current_item() const {
388 return my_items
[::item_index(::current_item(menu
))];
391 // Get the marker string
392 inline const char* mark() const {
393 return ::menu_mark(menu
);
396 // Set the marker string
397 inline void set_mark(const char *marker
) {
398 OnError (::set_menu_mark (menu
, marker
));
401 // Get the name of the request code c
402 inline static const char* request_name(int c
) {
403 return ::menu_request_name(c
);
406 // Get the current pattern
407 inline char* pattern() const {
408 return ::menu_pattern(menu
);
411 // true if there is a pattern match, false otherwise.
412 bool set_pattern (const char *pat
);
414 // set the default attributes for the menu
415 // i.e. set fore, back and grey attribute
416 virtual void setDefaultAttributes();
418 // Get the menus background attributes
419 inline chtype
back() const {
420 return ::menu_back(menu
);
423 // Get the menus foreground attributes
424 inline chtype
fore() const {
425 return ::menu_fore(menu
);
428 // Get the menus grey attributes (used for unselectable items)
429 inline chtype
grey() const {
430 return ::menu_grey(menu
);
433 // Set the menus background attributes
434 inline chtype
set_background(chtype a
) {
435 return ::set_menu_back(menu
,a
);
438 // Set the menus foreground attributes
439 inline chtype
set_foreground(chtype a
) {
440 return ::set_menu_fore(menu
,a
);
443 // Set the menus grey attributes (used for unselectable items)
444 inline chtype
set_grey(chtype a
) {
445 return ::set_menu_grey(menu
,a
);
448 inline void options_on (Menu_Options opts
) {
449 OnError (::menu_opts_on (menu
,opts
));
452 inline void options_off(Menu_Options opts
) {
453 OnError (::menu_opts_off(menu
,opts
));
456 inline Menu_Options
options() const {
457 return ::menu_opts(menu
);
460 inline void set_options (Menu_Options opts
) {
461 OnError (::set_menu_opts (menu
,opts
));
464 inline int pad() const {
465 return ::menu_pad(menu
);
468 inline void set_pad (int padch
) {
469 OnError (::set_menu_pad (menu
, padch
));
472 // Position the cursor to the current item
473 inline void position_cursor () const {
474 OnError (::pos_menu_cursor (menu
));
477 // Set the current item
478 inline void set_current(NCursesMenuItem
& I
) {
479 OnError (::set_current_item(menu
, I
.item
));
482 // Get the current top row of the menu
483 inline int top_row (void) const {
484 return ::top_row (menu
);
487 // Set the current top row of the menu
488 inline void set_top_row (int row
) {
489 OnError (::set_top_row (menu
, row
));
493 // Set the spacing for the menu
494 inline void setSpacing(int spc_description
,
497 OnError(::set_menu_spacing(menu
,
503 // Get the spacing info for the menu
504 inline void Spacing(int& spc_description
,
506 int& spc_columns
) const {
507 OnError(::menu_spacing(menu
,
514 inline void frame(const char *title
=NULL
, const char* btitle
=NULL
) {
516 NCursesPanel::frame(title
,btitle
);
518 OnError(E_SYSTEM_ERROR
);
521 inline void boldframe(const char *title
=NULL
, const char* btitle
=NULL
) {
523 NCursesPanel::boldframe(title
,btitle
);
525 OnError(E_SYSTEM_ERROR
);
528 inline void label(const char *topLabel
, const char *bottomLabel
) {
530 NCursesPanel::label(topLabel
,bottomLabel
);
532 OnError(E_SYSTEM_ERROR
);
539 // Called after the menu gets repositioned in its window.
540 // This is especially true if the menu is posted.
541 virtual void On_Menu_Init();
543 // Called before the menu gets repositioned in its window.
544 // This is especially true if the menu is unposted.
545 virtual void On_Menu_Termination();
547 // Called after the item became the current item
548 virtual void On_Item_Init(NCursesMenuItem
& item
);
550 // Called before this item is left as current item.
551 virtual void On_Item_Termination(NCursesMenuItem
& item
);
553 // Provide a default key virtualization. Translate the keyboard
554 // code c into a menu request code.
555 // The default implementation provides a hopefully straightforward
556 // mapping for the most common keystrokes and menu requests.
557 virtual int virtualize(int c
);
561 inline NCursesMenuItem
* operator[](int i
) const {
562 if ( (i
< 0) || (i
>= ::item_count (menu
)) )
563 OnError (E_BAD_ARGUMENT
);
564 return (my_items
[i
]);
567 // Perform the menu's operation
568 // Return the item where you left the selection mark for a single
569 // selection menu, or NULL for a multivalued menu.
570 virtual NCursesMenuItem
* operator()(void);
572 // --------------------
573 // Exception handlers
574 // Called by operator()
575 // --------------------
577 // Called if the request is denied
578 virtual void On_Request_Denied(int c
) const;
580 // Called if the item is not selectable
581 virtual void On_Not_Selectable(int c
) const;
583 // Called if pattern doesn't match
584 virtual void On_No_Match(int c
) const;
586 // Called if the command is unknown
587 virtual void On_Unknown_Command(int c
) const;
591 // -------------------------------------------------------------------------
592 // This is the typical C++ typesafe way to allow to attach
593 // user data to an item of a menu. Its assumed that the user
594 // data belongs to some class T. Use T as template argument
595 // to create a UserItem.
596 // -------------------------------------------------------------------------
598 template<class T
> class NCURSES_IMPEXP NCursesUserItem
: public NCursesMenuItem
601 NCursesUserItem (const char* p_name
,
602 const char* p_descript
= NULL
,
603 const T
* p_UserData
= STATIC_CAST(T
*)(0))
604 : NCursesMenuItem (p_name
, p_descript
) {
606 OnError (::set_item_userptr (item
, const_cast<void *>(reinterpret_cast<const void*>(p_UserData
))));
609 virtual ~NCursesUserItem() {}
611 inline const T
* UserData (void) const {
612 return reinterpret_cast<const T
*>(::item_userptr (item
));
615 inline virtual void setUserData(const T
* p_UserData
) {
617 OnError (::set_item_userptr (item
, const_cast<void *>(reinterpret_cast<const void *>(p_UserData
))));
621 // -------------------------------------------------------------------------
622 // The same mechanism is used to attach user data to a menu
623 // -------------------------------------------------------------------------
625 template<class T
> class NCURSES_IMPEXP NCursesUserMenu
: public NCursesMenu
628 NCursesUserMenu( int nlines
,
632 const T
* p_UserData
= STATIC_CAST(T
*)(0))
633 : NCursesMenu(nlines
,ncols
,begin_y
,begin_x
) {
635 set_user (const_cast<void *>(reinterpret_cast<const void*>(p_UserData
)));
639 NCursesUserMenu (NCursesMenuItem
* Items
[],
640 const T
* p_UserData
= STATIC_CAST(T
*)(0),
641 bool with_frame
=FALSE
,
642 bool autoDelete_Items
=FALSE
)
643 : NCursesMenu (Items
, with_frame
, autoDelete_Items
) {
645 set_user (const_cast<void *>(reinterpret_cast<const void*>(p_UserData
)));
648 NCursesUserMenu (NCursesMenuItem
* Items
[],
653 const T
* p_UserData
= STATIC_CAST(T
*)(0),
654 bool with_frame
=FALSE
)
655 : NCursesMenu (Items
, nlines
, ncols
, begin_y
, begin_x
, with_frame
) {
657 set_user (const_cast<void *>(reinterpret_cast<const void*>(p_UserData
)));
660 virtual ~NCursesUserMenu() {
663 inline T
* UserData (void) {
664 return reinterpret_cast<T
*>(get_user ());
667 inline virtual void setUserData (const T
* p_UserData
) {
669 set_user (const_cast<void *>(reinterpret_cast<const void*>(p_UserData
)));
673 #endif /* NCURSES_CURSESM_H_incl */