1 // * This makes emacs happy -*-Mode: C++;-*-
2 /****************************************************************************
3 * Copyright 2019,2020 Thomas E. Dickey *
4 * Copyright 1998-2012,2014 Free Software Foundation, Inc. *
6 * Permission is hereby granted, free of charge, to any person obtaining a *
7 * copy of this software and associated documentation files (the *
8 * "Software"), to deal in the Software without restriction, including *
9 * without limitation the rights to use, copy, modify, merge, publish, *
10 * distribute, distribute with modifications, sublicense, and/or sell *
11 * copies of the Software, and to permit persons to whom the Software is *
12 * furnished to do so, subject to the following conditions: *
14 * The above copyright notice and this permission notice shall be included *
15 * in all copies or substantial portions of the Software. *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
20 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
23 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
25 * Except as contained in this notice, the name(s) of the above copyright *
26 * holders shall not be used in advertising or otherwise to promote the *
27 * sale, use or other dealings in this Software without prior written *
29 ****************************************************************************/
31 /****************************************************************************
32 * Author: Juergen Pfeifer, 1997 *
33 ****************************************************************************/
35 // $Id: cursesm.h,v 1.34 2020/05/24 01:40:20 anonymous.maarten Exp $
37 #ifndef NCURSES_CURSESM_H_incl
38 #define NCURSES_CURSESM_H_incl 1
46 // -------------------------------------------------------------------------
47 // This wraps the ITEM type of <menu.h>
48 // -------------------------------------------------------------------------
50 class NCURSES_CXX_IMPEXP NCursesMenuItem
52 friend class NCursesMenu;
57 inline void OnError (int err) const THROW2(NCursesException const, NCursesMenuException) {
59 THROW(new NCursesMenuException (err));
63 NCursesMenuItem (const char* p_name = NULL,
64 const char* p_descript = NULL)
67 item = p_name ? ::new_item (p_name, p_descript) : STATIC_CAST(ITEM*)(0);
69 OnError (E_SYSTEM_ERROR);
71 // Create an item. If you pass both parameters as NULL, a delimiting
72 // item is constructed which can be used to terminate a list of
73 // NCursesMenu objects.
75 NCursesMenuItem& operator=(const NCursesMenuItem& rhs)
83 NCursesMenuItem(const NCursesMenuItem& rhs)
89 virtual ~NCursesMenuItem () THROWS(NCursesException);
90 // Release the items memory
92 inline const char* name () const {
93 return ::item_name (item);
97 inline const char* description () const {
98 return ::item_description (item);
100 // Description of the item
102 inline int (index) (void) const {
103 return ::item_index (item);
105 // Index of the item in an item array (or -1)
107 inline void options_on (Item_Options opts) {
108 OnError (::item_opts_on (item, opts));
110 // Switch on the items options
112 inline void options_off (Item_Options opts) {
113 OnError (::item_opts_off (item, opts));
115 // Switch off the item's option
117 inline Item_Options options () const {
118 return ::item_opts (item);
120 // Retrieve the items options
122 inline void set_options (Item_Options opts) {
123 OnError (::set_item_opts (item, opts));
125 // Set the items options
127 inline void set_value (bool f) {
128 OnError (::set_item_value (item,f));
130 // Set/Reset the items selection state
132 inline bool value () const {
133 return ::item_value (item);
135 // Retrieve the items selection state
137 inline bool visible () const {
138 return ::item_visible (item);
140 // Retrieve visibility of the item
142 virtual bool action();
143 // Perform an action associated with this item; you may use this in an
144 // user supplied driver for a menu; you may derive from this class and
145 // overload action() to supply items with different actions.
146 // If an action returns true, the menu will be exited. The default action
150 // Prototype for an items callback function.
151 typedef bool ITEMCALLBACK(NCursesMenuItem&);
153 // If you don't like to create a child class for individual items to
154 // overload action(), you may use this class and provide a callback
155 // function pointer for items.
156 class NCURSES_CXX_IMPEXP NCursesMenuCallbackItem : public NCursesMenuItem
162 NCursesMenuCallbackItem(ITEMCALLBACK* fct = NULL,
163 const char* p_name = NULL,
164 const char* p_descript = NULL )
165 : NCursesMenuItem (p_name, p_descript),
169 NCursesMenuCallbackItem& operator=(const NCursesMenuCallbackItem& rhs)
177 NCursesMenuCallbackItem(const NCursesMenuCallbackItem& rhs)
178 : NCursesMenuItem(rhs),
183 virtual ~NCursesMenuCallbackItem() THROWS(NCursesException);
188 // This are the built-in hook functions in this C++ binding. In C++ we use
189 // virtual member functions (see below On_..._Init and On_..._Termination)
190 // to provide this functionality in an object oriented manner.
192 void _nc_xx_mnu_init(MENU *);
193 void _nc_xx_mnu_term(MENU *);
194 void _nc_xx_itm_init(MENU *);
195 void _nc_xx_itm_term(MENU *);
199 // -------------------------------------------------------------------------
200 // This wraps the MENU type of <menu.h>
201 // -------------------------------------------------------------------------
203 class NCURSES_CXX_IMPEXP NCursesMenu : public NCursesPanel
209 NCursesWindow* sub; // the subwindow object
210 bool b_sub_owner; // is this our own subwindow?
211 bool b_framed; // has the menu a border?
212 bool b_autoDelete; // Delete items when deleting menu?
214 NCursesMenuItem** my_items; // The array of items for this menu
216 // This structure is used for the menu's user data field to link the
217 // MENU* to the C++ object and to provide extra space for a user pointer.
219 void* m_user; // the pointer for the user's data
220 const NCursesMenu* m_back; // backward pointer to C++ object
224 // Get the backward pointer to the C++ object from a MENU
225 static inline NCursesMenu* getHook(const MENU *m) {
226 UserHook* hook = STATIC_CAST(UserHook*)(::menu_userptr(m));
227 assert(hook != 0 && hook->m_owner==m);
228 return const_cast<NCursesMenu*>(hook->m_back);
231 friend void _nc_xx_mnu_init(MENU *);
232 friend void _nc_xx_mnu_term(MENU *);
233 friend void _nc_xx_itm_init(MENU *);
234 friend void _nc_xx_itm_term(MENU *);
236 // Calculate ITEM* array for the menu
237 ITEM** mapItems(NCursesMenuItem* nitems[]);
241 inline void set_user(void *user) {
242 UserHook* uptr = STATIC_CAST(UserHook*)(::menu_userptr (menu));
243 assert (uptr != 0 && uptr->m_back==this && uptr->m_owner==menu);
247 inline void *get_user() {
248 UserHook* uptr = STATIC_CAST(UserHook*)(::menu_userptr (menu));
249 assert (uptr != 0 && uptr->m_back==this && uptr->m_owner==menu);
253 void InitMenu (NCursesMenuItem* menu[],
255 bool autoDeleteItems);
257 inline void OnError (int err) const THROW2(NCursesException const, NCursesMenuException) {
259 THROW(new NCursesMenuException (this, err));
262 // this wraps the menu_driver call.
263 virtual int driver (int c) ;
265 // 'Internal' constructor to create a menu without association to
266 // an array of items.
267 NCursesMenu( int nlines,
271 : NCursesPanel(nlines,ncols,begin_y,begin_x),
272 menu (STATIC_CAST(MENU*)(0)),
282 // Make a full window size menu
283 NCursesMenu (NCursesMenuItem* Items[],
284 bool with_frame=FALSE, // Reserve space for a frame?
285 bool autoDelete_Items=FALSE) // Autocleanup of Items?
294 InitMenu(Items, with_frame, autoDelete_Items);
297 // Make a menu with a window of this size.
298 NCursesMenu (NCursesMenuItem* Items[],
303 bool with_frame=FALSE, // Reserve space for a frame?
304 bool autoDelete_Items=FALSE) // Autocleanup of Items?
305 : NCursesPanel(nlines, ncols, begin_y, begin_x),
313 InitMenu(Items, with_frame, autoDelete_Items);
316 NCursesMenu& operator=(const NCursesMenu& rhs)
320 NCursesPanel::operator=(rhs);
325 NCursesMenu(const NCursesMenu& rhs)
329 b_sub_owner(rhs.b_sub_owner),
330 b_framed(rhs.b_framed),
331 b_autoDelete(rhs.b_autoDelete),
332 my_items(rhs.my_items)
336 virtual ~NCursesMenu () THROWS(NCursesException);
338 // Retrieve the menus subwindow
339 inline NCursesWindow& subWindow() const {
344 // Set the menus subwindow
345 void setSubWindow(NCursesWindow& sub);
347 // Set these items for the menu
348 inline void setItems(NCursesMenuItem* Items[]) {
349 OnError(::set_menu_items(menu,mapItems(Items)));
352 // Remove the menu from the screen
353 inline void unpost (void) {
354 OnError (::unpost_menu (menu));
357 // Post the menu to the screen if flag is true, unpost it otherwise
358 inline void post(bool flag = TRUE) {
359 flag ? OnError (::post_menu(menu)) : OnError (::unpost_menu (menu));
362 // Get the number of rows and columns for this menu
363 inline void scale (int& mrows, int& mcols) const {
364 OnError (::scale_menu (menu, &mrows, &mcols));
367 // Set the format of this menu
368 inline void set_format(int mrows, int mcols) {
369 OnError (::set_menu_format(menu, mrows, mcols));
372 // Get the format of this menu
373 inline void menu_format(int& rows,int& ncols) {
374 ::menu_format(menu,&rows,&ncols);
378 inline NCursesMenuItem* items() const {
382 // Get the number of items in this menu
383 inline int count() const {
384 return ::item_count(menu);
387 // Get the current item (i.e. the one the cursor is located)
388 inline NCursesMenuItem* current_item() const {
389 return my_items[::item_index(::current_item(menu))];
392 // Get the marker string
393 inline const char* mark() const {
394 return ::menu_mark(menu);
397 // Set the marker string
398 inline void set_mark(const char *marker) {
399 OnError (::set_menu_mark (menu, marker));
402 // Get the name of the request code c
403 inline static const char* request_name(int c) {
404 return ::menu_request_name(c);
407 // Get the current pattern
408 inline char* pattern() const {
409 return ::menu_pattern(menu);
412 // true if there is a pattern match, false otherwise.
413 bool set_pattern (const char *pat);
415 // set the default attributes for the menu
416 // i.e. set fore, back and grey attribute
417 virtual void setDefaultAttributes();
419 // Get the menus background attributes
420 inline chtype back() const {
421 return ::menu_back(menu);
424 // Get the menus foreground attributes
425 inline chtype fore() const {
426 return ::menu_fore(menu);
429 // Get the menus grey attributes (used for unselectable items)
430 inline chtype grey() const {
431 return ::menu_grey(menu);
434 // Set the menus background attributes
435 inline chtype set_background(chtype a) {
436 return ::set_menu_back(menu,a);
439 // Set the menus foreground attributes
440 inline chtype set_foreground(chtype a) {
441 return ::set_menu_fore(menu,a);
444 // Set the menus grey attributes (used for unselectable items)
445 inline chtype set_grey(chtype a) {
446 return ::set_menu_grey(menu,a);
449 inline void options_on (Menu_Options opts) {
450 OnError (::menu_opts_on (menu,opts));
453 inline void options_off(Menu_Options opts) {
454 OnError (::menu_opts_off(menu,opts));
457 inline Menu_Options options() const {
458 return ::menu_opts(menu);
461 inline void set_options (Menu_Options opts) {
462 OnError (::set_menu_opts (menu,opts));
465 inline int pad() const {
466 return ::menu_pad(menu);
469 inline void set_pad (int padch) {
470 OnError (::set_menu_pad (menu, padch));
473 // Position the cursor to the current item
474 inline void position_cursor () const {
475 OnError (::pos_menu_cursor (menu));
478 // Set the current item
479 inline void set_current(NCursesMenuItem& I) {
480 OnError (::set_current_item(menu, I.item));
483 // Get the current top row of the menu
484 inline int top_row (void) const {
485 return ::top_row (menu);
488 // Set the current top row of the menu
489 inline void set_top_row (int row) {
490 OnError (::set_top_row (menu, row));
494 // Set the spacing for the menu
495 inline void setSpacing(int spc_description,
498 OnError(::set_menu_spacing(menu,
504 // Get the spacing info for the menu
505 inline void Spacing(int& spc_description,
507 int& spc_columns) const {
508 OnError(::menu_spacing(menu,
515 inline void frame(const char *title=NULL, const char* btitle=NULL) {
517 NCursesPanel::frame(title,btitle);
519 OnError(E_SYSTEM_ERROR);
522 inline void boldframe(const char *title=NULL, const char* btitle=NULL) {
524 NCursesPanel::boldframe(title,btitle);
526 OnError(E_SYSTEM_ERROR);
529 inline void label(const char *topLabel, const char *bottomLabel) {
531 NCursesPanel::label(topLabel,bottomLabel);
533 OnError(E_SYSTEM_ERROR);
540 // Called after the menu gets repositioned in its window.
541 // This is especially true if the menu is posted.
542 virtual void On_Menu_Init();
544 // Called before the menu gets repositioned in its window.
545 // This is especially true if the menu is unposted.
546 virtual void On_Menu_Termination();
548 // Called after the item became the current item
549 virtual void On_Item_Init(NCursesMenuItem& item);
551 // Called before this item is left as current item.
552 virtual void On_Item_Termination(NCursesMenuItem& item);
554 // Provide a default key virtualization. Translate the keyboard
555 // code c into a menu request code.
556 // The default implementation provides a hopefully straightforward
557 // mapping for the most common keystrokes and menu requests.
558 virtual int virtualize(int c);
562 inline NCursesMenuItem* operator[](int i) const {
563 if ( (i < 0) || (i >= ::item_count (menu)) )
564 OnError (E_BAD_ARGUMENT);
565 return (my_items[i]);
568 // Perform the menu's operation
569 // Return the item where you left the selection mark for a single
570 // selection menu, or NULL for a multivalued menu.
571 virtual NCursesMenuItem* operator()(void);
573 // --------------------
574 // Exception handlers
575 // Called by operator()
576 // --------------------
578 // Called if the request is denied
579 virtual void On_Request_Denied(int c) const;
581 // Called if the item is not selectable
582 virtual void On_Not_Selectable(int c) const;
584 // Called if pattern doesn't match
585 virtual void On_No_Match(int c) const;
587 // Called if the command is unknown
588 virtual void On_Unknown_Command(int c) const;
592 // -------------------------------------------------------------------------
593 // This is the typical C++ typesafe way to allow to attach
594 // user data to an item of a menu. Its assumed that the user
595 // data belongs to some class T. Use T as template argument
596 // to create a UserItem.
597 // -------------------------------------------------------------------------
599 template<class T> class NCURSES_CXX_IMPEXP NCursesUserItem : public NCursesMenuItem
602 NCursesUserItem (const char* p_name,
603 const char* p_descript = NULL,
604 const T* p_UserData = STATIC_CAST(T*)(0))
605 : NCursesMenuItem (p_name, p_descript) {
607 OnError (::set_item_userptr (item, const_cast<void *>(reinterpret_cast<const void*>(p_UserData))));
610 virtual ~NCursesUserItem() THROWS(NCursesException) {}
612 inline const T* UserData (void) const {
613 return reinterpret_cast<const T*>(::item_userptr (item));
616 inline virtual void setUserData(const T* p_UserData) {
618 OnError (::set_item_userptr (item, const_cast<void *>(reinterpret_cast<const void *>(p_UserData))));
622 // -------------------------------------------------------------------------
623 // The same mechanism is used to attach user data to a menu
624 // -------------------------------------------------------------------------
626 template<class T> class NCURSES_CXX_IMPEXP NCursesUserMenu : public NCursesMenu
629 NCursesUserMenu( int nlines,
633 const T* p_UserData = STATIC_CAST(T*)(0))
634 : NCursesMenu(nlines,ncols,begin_y,begin_x) {
636 set_user (const_cast<void *>(reinterpret_cast<const void*>(p_UserData)));
640 NCursesUserMenu (NCursesMenuItem* Items[],
641 const T* p_UserData = STATIC_CAST(T*)(0),
642 bool with_frame=FALSE,
643 bool autoDelete_Items=FALSE)
644 : NCursesMenu (Items, with_frame, autoDelete_Items) {
646 set_user (const_cast<void *>(reinterpret_cast<const void*>(p_UserData)));
649 NCursesUserMenu (NCursesMenuItem* Items[],
654 const T* p_UserData = STATIC_CAST(T*)(0),
655 bool with_frame=FALSE)
656 : NCursesMenu (Items, nlines, ncols, begin_y, begin_x, with_frame) {
658 set_user (const_cast<void *>(reinterpret_cast<const void*>(p_UserData)));
661 virtual ~NCursesUserMenu() THROWS(NCursesException) {
664 inline T* UserData (void) {
665 return reinterpret_cast<T*>(get_user ());
668 inline virtual void setUserData (const T* p_UserData) {
670 set_user (const_cast<void *>(reinterpret_cast<const void*>(p_UserData)));
674 #endif /* NCURSES_CURSESM_H_incl */