Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-05-18 08:29:43

0001 // * This makes emacs happy -*-Mode: C++;-*-
0002 /****************************************************************************
0003  * Copyright 2019-2020,2022 Thomas E. Dickey                                *
0004  * Copyright 1998-2012,2014 Free Software Foundation, Inc.                  *
0005  *                                                                          *
0006  * Permission is hereby granted, free of charge, to any person obtaining a  *
0007  * copy of this software and associated documentation files (the            *
0008  * "Software"), to deal in the Software without restriction, including      *
0009  * without limitation the rights to use, copy, modify, merge, publish,      *
0010  * distribute, distribute with modifications, sublicense, and/or sell       *
0011  * copies of the Software, and to permit persons to whom the Software is    *
0012  * furnished to do so, subject to the following conditions:                 *
0013  *                                                                          *
0014  * The above copyright notice and this permission notice shall be included  *
0015  * in all copies or substantial portions of the Software.                   *
0016  *                                                                          *
0017  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
0018  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
0019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
0020  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
0021  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
0022  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
0023  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
0024  *                                                                          *
0025  * Except as contained in this notice, the name(s) of the above copyright   *
0026  * holders shall not be used in advertising or otherwise to promote the     *
0027  * sale, use or other dealings in this Software without prior written       *
0028  * authorization.                                                           *
0029  ****************************************************************************/
0030 
0031 /****************************************************************************
0032  *   Author: Juergen Pfeifer, 1997                                          *
0033  ****************************************************************************/
0034 
0035 // $Id: cursesm.h,v 1.35 2022/08/20 20:52:15 tom Exp $
0036 
0037 #ifndef NCURSES_CURSESM_H_incl
0038 #define NCURSES_CURSESM_H_incl 1
0039 
0040 #include <ncursesw/cursesp.h>
0041 
0042 extern "C" {
0043 #  include <ncursesw/menu.h>
0044 }
0045 //
0046 // -------------------------------------------------------------------------
0047 // This wraps the ITEM type of <ncursesw/menu.h>
0048 // -------------------------------------------------------------------------
0049 //
0050 class NCURSES_CXX_IMPEXP NCursesMenuItem
0051 {
0052   friend class NCursesMenu;
0053 
0054 protected:
0055   ITEM *item;
0056 
0057   inline void OnError (int err) const THROW2(NCursesException const, NCursesMenuException) {
0058     if (err != E_OK)
0059       THROW(new NCursesMenuException (err));
0060   }
0061 
0062 public:
0063   NCursesMenuItem (const char* p_name     = NULL,
0064            const char* p_descript = NULL)
0065     : item(0)
0066   {
0067     item = p_name ? ::new_item (p_name, p_descript) : STATIC_CAST(ITEM*)(0);
0068     if (p_name && !item)
0069       OnError (E_SYSTEM_ERROR);
0070   }
0071   // Create an item. If you pass both parameters as NULL, a delimiting
0072   // item is constructed which can be used to terminate a list of
0073   // NCursesMenu objects.
0074 
0075   NCursesMenuItem& operator=(const NCursesMenuItem& rhs)
0076   {
0077     if (this != &rhs) {
0078       *this = rhs;
0079     }
0080     return *this;
0081   }
0082 
0083   NCursesMenuItem(const NCursesMenuItem& rhs)
0084     : item(0)
0085   {
0086     (void) rhs;
0087   }
0088 
0089   virtual ~NCursesMenuItem () THROWS(NCursesException);
0090   // Release the items memory
0091 
0092   inline const char* name () const {
0093     return ::item_name (item);
0094   }
0095   // Name of the item
0096 
0097   inline const char* description () const {
0098     return ::item_description (item);
0099   }
0100   // Description of the item
0101 
0102   inline int (index) (void) const {
0103     return ::item_index (item);
0104   }
0105   // Index of the item in an item array (or -1)
0106 
0107   inline void options_on (Item_Options opts) {
0108     OnError (::item_opts_on (item, opts));
0109   }
0110   // Switch on the items options
0111 
0112   inline void options_off (Item_Options opts) {
0113     OnError (::item_opts_off (item, opts));
0114   }
0115   // Switch off the item's option
0116 
0117   inline Item_Options options () const {
0118     return ::item_opts (item);
0119   }
0120   // Retrieve the items options
0121 
0122   inline void set_options (Item_Options opts) {
0123     OnError (::set_item_opts (item, opts));
0124   }
0125   // Set the items options
0126 
0127   inline void set_value (bool f) {
0128     OnError (::set_item_value (item,f));
0129   }
0130   // Set/Reset the items selection state
0131 
0132   inline bool value () const {
0133     return ::item_value (item);
0134   }
0135   // Retrieve the items selection state
0136 
0137   inline bool visible () const {
0138     return ::item_visible (item);
0139   }
0140   // Retrieve visibility of the item
0141 
0142   virtual bool action();
0143   // Perform an action associated with this item; you may use this in an
0144   // user supplied driver for a menu; you may derive from this class and
0145   // overload action() to supply items with different actions.
0146   // If an action returns true, the menu will be exited. The default action
0147   // is to do nothing.
0148 };
0149 
0150 // Prototype for an items callback function.
0151 typedef bool ITEMCALLBACK(NCursesMenuItem&);
0152 
0153 // If you don't like to create a child class for individual items to
0154 // overload action(), you may use this class and provide a callback
0155 // function pointer for items.
0156 class NCURSES_CXX_IMPEXP NCursesMenuCallbackItem : public NCursesMenuItem
0157 {
0158 private:
0159   ITEMCALLBACK* p_fct;
0160 
0161 public:
0162   NCursesMenuCallbackItem(ITEMCALLBACK* fct       = NULL,
0163               const char* p_name      = NULL,
0164               const char* p_descript  = NULL )
0165     : NCursesMenuItem (p_name, p_descript),
0166       p_fct (fct) {
0167   }
0168 
0169   NCursesMenuCallbackItem& operator=(const NCursesMenuCallbackItem& rhs)
0170   {
0171     if (this != &rhs) {
0172       *this = rhs;
0173     }
0174     return *this;
0175   }
0176 
0177   NCursesMenuCallbackItem(const NCursesMenuCallbackItem& rhs)
0178     : NCursesMenuItem(rhs),
0179       p_fct(0)
0180   {
0181   }
0182 
0183   virtual ~NCursesMenuCallbackItem() THROWS(NCursesException);
0184 
0185   bool action() NCURSES_OVERRIDE;
0186 };
0187 
0188   // This are the built-in hook functions in this C++ binding. In C++ we use
0189   // virtual member functions (see below On_..._Init and On_..._Termination)
0190   // to provide this functionality in an object oriented manner.
0191 extern "C" {
0192   void _nc_xx_mnu_init(MENU *);
0193   void _nc_xx_mnu_term(MENU *);
0194   void _nc_xx_itm_init(MENU *);
0195   void _nc_xx_itm_term(MENU *);
0196 }
0197 
0198 //
0199 // -------------------------------------------------------------------------
0200 // This wraps the MENU type of <ncursesw/menu.h>
0201 // -------------------------------------------------------------------------
0202 //
0203 class NCURSES_CXX_IMPEXP NCursesMenu : public NCursesPanel
0204 {
0205 protected:
0206   MENU *menu;
0207 
0208 private:
0209   NCursesWindow* sub;   // the subwindow object
0210   bool b_sub_owner;     // is this our own subwindow?
0211   bool b_framed;        // has the menu a border?
0212   bool b_autoDelete;    // Delete items when deleting menu?
0213 
0214   NCursesMenuItem** my_items; // The array of items for this menu
0215 
0216   // This structure is used for the menu's user data field to link the
0217   // MENU* to the C++ object and to provide extra space for a user pointer.
0218   typedef struct {
0219     void*              m_user;      // the pointer for the user's data
0220     const NCursesMenu* m_back;      // backward pointer to C++ object
0221     const MENU*        m_owner;
0222   } UserHook;
0223 
0224   // Get the backward pointer to the C++ object from a MENU
0225   static inline NCursesMenu* getHook(const MENU *m) {
0226     UserHook* hook = STATIC_CAST(UserHook*)(::menu_userptr(m));
0227     assert(hook != 0 && hook->m_owner==m);
0228     return const_cast<NCursesMenu*>(hook->m_back);
0229   }
0230 
0231   friend void _nc_xx_mnu_init(MENU *);
0232   friend void _nc_xx_mnu_term(MENU *);
0233   friend void _nc_xx_itm_init(MENU *);
0234   friend void _nc_xx_itm_term(MENU *);
0235 
0236   // Calculate ITEM* array for the menu
0237   ITEM** mapItems(NCursesMenuItem* nitems[]);
0238 
0239 protected:
0240   // internal routines
0241   inline void set_user(void *user) {
0242     UserHook* uptr = STATIC_CAST(UserHook*)(::menu_userptr (menu));
0243     assert (uptr != 0 && uptr->m_back==this && uptr->m_owner==menu);
0244     uptr->m_user = user;
0245   }
0246 
0247   inline void *get_user() {
0248     UserHook* uptr = STATIC_CAST(UserHook*)(::menu_userptr (menu));
0249     assert (uptr != 0 && uptr->m_back==this && uptr->m_owner==menu);
0250     return uptr->m_user;
0251   }
0252 
0253   void InitMenu (NCursesMenuItem* menu[],
0254          bool with_frame,
0255          bool autoDeleteItems);
0256 
0257   inline void OnError (int err) const THROW2(NCursesException const, NCursesMenuException) {
0258     if (err != E_OK)
0259       THROW(new NCursesMenuException (this, err));
0260   }
0261 
0262   // this wraps the menu_driver call.
0263   virtual int driver (int c) ;
0264 
0265   // 'Internal' constructor to create a menu without association to
0266   // an array of items.
0267   NCursesMenu( int  nlines,
0268            int  ncols,
0269            int  begin_y = 0,
0270            int  begin_x = 0)
0271     : NCursesPanel(nlines,ncols,begin_y,begin_x),
0272       menu (STATIC_CAST(MENU*)(0)),
0273       sub(0),
0274       b_sub_owner(0),
0275       b_framed(0),
0276       b_autoDelete(0),
0277       my_items(0)
0278   {
0279   }
0280 
0281 public:
0282   // Make a full window size menu
0283   NCursesMenu (NCursesMenuItem* Items[],
0284            bool with_frame=FALSE,        // Reserve space for a frame?
0285            bool autoDelete_Items=FALSE)  // Autocleanup of Items?
0286     : NCursesPanel(),
0287       menu(0),
0288       sub(0),
0289       b_sub_owner(0),
0290       b_framed(0),
0291       b_autoDelete(0),
0292       my_items(0)
0293   {
0294       InitMenu(Items, with_frame, autoDelete_Items);
0295   }
0296 
0297   // Make a menu with a window of this size.
0298   NCursesMenu (NCursesMenuItem* Items[],
0299            int  nlines,
0300            int  ncols,
0301            int  begin_y = 0,
0302            int  begin_x = 0,
0303            bool with_frame=FALSE,        // Reserve space for a frame?
0304            bool autoDelete_Items=FALSE)  // Autocleanup of Items?
0305     : NCursesPanel(nlines, ncols, begin_y, begin_x),
0306       menu(0),
0307       sub(0),
0308       b_sub_owner(0),
0309       b_framed(0),
0310       b_autoDelete(0),
0311       my_items(0)
0312   {
0313       InitMenu(Items, with_frame, autoDelete_Items);
0314   }
0315 
0316   NCursesMenu& operator=(const NCursesMenu& rhs)
0317   {
0318     if (this != &rhs) {
0319       *this = rhs;
0320       NCursesPanel::operator=(rhs);
0321     }
0322     return *this;
0323   }
0324 
0325   NCursesMenu(const NCursesMenu& rhs)
0326     : NCursesPanel(rhs),
0327       menu(rhs.menu),
0328       sub(rhs.sub),
0329       b_sub_owner(rhs.b_sub_owner),
0330       b_framed(rhs.b_framed),
0331       b_autoDelete(rhs.b_autoDelete),
0332       my_items(rhs.my_items)
0333   {
0334   }
0335 
0336   virtual ~NCursesMenu () THROWS(NCursesException);
0337 
0338   // Retrieve the menus subwindow
0339   inline NCursesWindow& subWindow() const {
0340     assert(sub!=NULL);
0341     return *sub;
0342   }
0343 
0344   // Set the menus subwindow
0345   void setSubWindow(NCursesWindow& sub);
0346 
0347   // Set these items for the menu
0348   inline void setItems(NCursesMenuItem* Items[]) {
0349     OnError(::set_menu_items(menu,mapItems(Items)));
0350   }
0351 
0352   // Remove the menu from the screen
0353   inline void unpost (void) {
0354     OnError (::unpost_menu (menu));
0355   }
0356 
0357   // Post the menu to the screen if flag is true, unpost it otherwise
0358   inline void post(bool flag = TRUE) {
0359     flag ? OnError (::post_menu(menu)) : OnError (::unpost_menu (menu));
0360   }
0361 
0362   // Get the number of rows and columns for this menu
0363   inline void scale (int& mrows, int& mcols) const  {
0364     OnError (::scale_menu (menu, &mrows, &mcols));
0365   }
0366 
0367   // Set the format of this menu
0368   inline void set_format(int mrows, int mcols) {
0369     OnError (::set_menu_format(menu, mrows, mcols));
0370   }
0371 
0372   // Get the format of this menu
0373   inline void menu_format(int& rows,int& ncols) {
0374     ::menu_format(menu,&rows,&ncols);
0375   }
0376 
0377   // Items of the menu
0378   inline NCursesMenuItem* items() const {
0379     return *my_items;
0380   }
0381 
0382   // Get the number of items in this menu
0383   inline int count() const {
0384     return ::item_count(menu);
0385   }
0386 
0387   // Get the current item (i.e. the one the cursor is located)
0388   inline NCursesMenuItem* current_item() const {
0389     return my_items[::item_index(::current_item(menu))];
0390   }
0391 
0392   // Get the marker string
0393   inline const char* mark() const {
0394     return ::menu_mark(menu);
0395   }
0396 
0397   // Set the marker string
0398   inline void set_mark(const char *marker) {
0399     OnError (::set_menu_mark (menu, marker));
0400   }
0401 
0402   // Get the name of the request code c
0403   inline static const char* request_name(int c) {
0404     return ::menu_request_name(c);
0405   }
0406 
0407   // Get the current pattern
0408   inline char* pattern() const {
0409     return ::menu_pattern(menu);
0410   }
0411 
0412   // true if there is a pattern match, false otherwise.
0413   bool set_pattern (const char *pat);
0414 
0415   // set the default attributes for the menu
0416   // i.e. set fore, back and grey attribute
0417   virtual void setDefaultAttributes();
0418 
0419   // Get the menus background attributes
0420   inline chtype back() const {
0421     return ::menu_back(menu);
0422   }
0423 
0424   // Get the menus foreground attributes
0425   inline chtype fore() const {
0426     return ::menu_fore(menu);
0427   }
0428 
0429   // Get the menus grey attributes (used for unselectable items)
0430   inline chtype grey() const {
0431     return ::menu_grey(menu);
0432   }
0433 
0434   // Set the menus background attributes
0435   inline chtype set_background(chtype a) {
0436     return ::set_menu_back(menu,a);
0437   }
0438 
0439   // Set the menus foreground attributes
0440   inline chtype set_foreground(chtype a) {
0441     return ::set_menu_fore(menu,a);
0442   }
0443 
0444   // Set the menus grey attributes (used for unselectable items)
0445   inline chtype set_grey(chtype a) {
0446     return ::set_menu_grey(menu,a);
0447   }
0448 
0449   inline void options_on (Menu_Options opts) {
0450     OnError (::menu_opts_on (menu,opts));
0451   }
0452 
0453   inline void options_off(Menu_Options opts) {
0454     OnError (::menu_opts_off(menu,opts));
0455   }
0456 
0457   inline Menu_Options options() const {
0458     return ::menu_opts(menu);
0459   }
0460 
0461   inline void set_options (Menu_Options opts) {
0462     OnError (::set_menu_opts (menu,opts));
0463   }
0464 
0465   inline int pad() const {
0466     return ::menu_pad(menu);
0467   }
0468 
0469   inline void set_pad (int padch) {
0470     OnError (::set_menu_pad (menu, padch));
0471   }
0472 
0473   // Position the cursor to the current item
0474   inline void position_cursor () const {
0475     OnError (::pos_menu_cursor (menu));
0476   }
0477 
0478   // Set the current item
0479   inline void set_current(NCursesMenuItem& I) {
0480     OnError (::set_current_item(menu, I.item));
0481   }
0482 
0483   // Get the current top row of the menu
0484   inline int top_row (void) const {
0485     return ::top_row (menu);
0486   }
0487 
0488   // Set the current top row of the menu
0489   inline void set_top_row (int row) {
0490     OnError (::set_top_row (menu, row));
0491   }
0492 
0493   // spacing control
0494   // Set the spacing for the menu
0495   inline void setSpacing(int spc_description,
0496              int spc_rows,
0497              int spc_columns) {
0498     OnError(::set_menu_spacing(menu,
0499                    spc_description,
0500                    spc_rows,
0501                    spc_columns));
0502   }
0503 
0504   // Get the spacing info for the menu
0505   inline void Spacing(int& spc_description,
0506               int& spc_rows,
0507               int& spc_columns) const {
0508     OnError(::menu_spacing(menu,
0509                &spc_description,
0510                &spc_rows,
0511                &spc_columns));
0512   }
0513 
0514   // Decorations
0515   inline void frame(const char *title=NULL, const char* btitle=NULL) NCURSES_OVERRIDE {
0516     if (b_framed)
0517       NCursesPanel::frame(title,btitle);
0518     else
0519       OnError(E_SYSTEM_ERROR);
0520   }
0521 
0522   inline void boldframe(const char *title=NULL, const char* btitle=NULL) NCURSES_OVERRIDE {
0523     if (b_framed)
0524       NCursesPanel::boldframe(title,btitle);
0525     else
0526       OnError(E_SYSTEM_ERROR);
0527   }
0528 
0529   inline void label(const char *topLabel, const char *bottomLabel) NCURSES_OVERRIDE {
0530     if (b_framed)
0531       NCursesPanel::label(topLabel,bottomLabel);
0532     else
0533       OnError(E_SYSTEM_ERROR);
0534   }
0535 
0536   // -----
0537   // Hooks
0538   // -----
0539 
0540   // Called after the menu gets repositioned in its window.
0541   // This is especially true if the menu is posted.
0542   virtual void On_Menu_Init();
0543 
0544   // Called before the menu gets repositioned in its window.
0545   // This is especially true if the menu is unposted.
0546   virtual void On_Menu_Termination();
0547 
0548   // Called after the item became the current item
0549   virtual void On_Item_Init(NCursesMenuItem& item);
0550 
0551   // Called before this item is left as current item.
0552   virtual void On_Item_Termination(NCursesMenuItem& item);
0553 
0554   // Provide a default key virtualization. Translate the keyboard
0555   // code c into a menu request code.
0556   // The default implementation provides a hopefully straightforward
0557   // mapping for the most common keystrokes and menu requests.
0558   virtual int virtualize(int c);
0559 
0560 
0561   // Operators
0562   inline NCursesMenuItem* operator[](int i) const {
0563     if ( (i < 0) || (i >= ::item_count (menu)) )
0564       OnError (E_BAD_ARGUMENT);
0565     return (my_items[i]);
0566   }
0567 
0568   // Perform the menu's operation
0569   // Return the item where you left the selection mark for a single
0570   // selection menu, or NULL for a multivalued menu.
0571   virtual NCursesMenuItem* operator()(void);
0572 
0573   // --------------------
0574   // Exception handlers
0575   // Called by operator()
0576   // --------------------
0577 
0578   // Called if the request is denied
0579   virtual void On_Request_Denied(int c) const;
0580 
0581   // Called if the item is not selectable
0582   virtual void On_Not_Selectable(int c) const;
0583 
0584   // Called if pattern doesn't match
0585   virtual void On_No_Match(int c) const;
0586 
0587   // Called if the command is unknown
0588   virtual void On_Unknown_Command(int c) const;
0589 
0590 };
0591 //
0592 // -------------------------------------------------------------------------
0593 // This is the typical C++ typesafe way to allow to attach
0594 // user data to an item of a menu. Its assumed that the user
0595 // data belongs to some class T. Use T as template argument
0596 // to create a UserItem.
0597 // -------------------------------------------------------------------------
0598 //
0599 template<class T> class NCURSES_CXX_IMPEXP NCursesUserItem : public NCursesMenuItem
0600 {
0601 public:
0602   NCursesUserItem (const char* p_name,
0603            const char* p_descript = NULL,
0604            const T* p_UserData    = STATIC_CAST(T*)(0))
0605     : NCursesMenuItem (p_name, p_descript) {
0606       if (item)
0607     OnError (::set_item_userptr (item, const_cast<void *>(reinterpret_cast<const void*>(p_UserData))));
0608   }
0609 
0610   virtual ~NCursesUserItem() THROWS(NCursesException) {}
0611 
0612   inline const T* UserData (void) const {
0613     return reinterpret_cast<const T*>(::item_userptr (item));
0614   };
0615 
0616   inline virtual void setUserData(const T* p_UserData) {
0617     if (item)
0618       OnError (::set_item_userptr (item, const_cast<void *>(reinterpret_cast<const void *>(p_UserData))));
0619   }
0620 };
0621 //
0622 // -------------------------------------------------------------------------
0623 // The same mechanism is used to attach user data to a menu
0624 // -------------------------------------------------------------------------
0625 //
0626 template<class T> class NCURSES_CXX_IMPEXP NCursesUserMenu : public NCursesMenu
0627 {
0628 protected:
0629   NCursesUserMenu( int  nlines,
0630            int  ncols,
0631            int  begin_y = 0,
0632            int  begin_x = 0,
0633            const T* p_UserData = STATIC_CAST(T*)(0))
0634     : NCursesMenu(nlines,ncols,begin_y,begin_x) {
0635       if (menu)
0636     set_user (const_cast<void *>(reinterpret_cast<const void*>(p_UserData)));
0637   }
0638 
0639 public:
0640   NCursesUserMenu (NCursesMenuItem* Items[],
0641            const T* p_UserData = STATIC_CAST(T*)(0),
0642            bool with_frame=FALSE,
0643            bool autoDelete_Items=FALSE)
0644     : NCursesMenu (Items, with_frame, autoDelete_Items) {
0645       if (menu)
0646     set_user (const_cast<void *>(reinterpret_cast<const void*>(p_UserData)));
0647   };
0648 
0649   NCursesUserMenu (NCursesMenuItem* Items[],
0650            int nlines,
0651            int ncols,
0652            int begin_y = 0,
0653            int begin_x = 0,
0654            const T* p_UserData = STATIC_CAST(T*)(0),
0655            bool with_frame=FALSE)
0656     : NCursesMenu (Items, nlines, ncols, begin_y, begin_x, with_frame) {
0657       if (menu)
0658     set_user (const_cast<void *>(reinterpret_cast<const void*>(p_UserData)));
0659   };
0660 
0661   virtual ~NCursesUserMenu() THROWS(NCursesException) {
0662   };
0663 
0664   inline T* UserData (void) {
0665     return reinterpret_cast<T*>(get_user ());
0666   };
0667 
0668   inline virtual void setUserData (const T* p_UserData) {
0669     if (menu)
0670       set_user (const_cast<void *>(reinterpret_cast<const void*>(p_UserData)));
0671   }
0672 };
0673 
0674 #endif /* NCURSES_CURSESM_H_incl */