cursesm.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. // * This makes emacs happy -*-Mode: C++;-*-
  2. /****************************************************************************
  3. * Copyright (c) 1998-2012,2014 Free Software Foundation, Inc. *
  4. * *
  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: *
  12. * *
  13. * The above copyright notice and this permission notice shall be included *
  14. * in all copies or substantial portions of the Software. *
  15. * *
  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. *
  23. * *
  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 *
  27. * authorization. *
  28. ****************************************************************************/
  29. /****************************************************************************
  30. * Author: Juergen Pfeifer, 1997 *
  31. ****************************************************************************/
  32. // $Id: cursesm.h,v 1.30 2014/08/09 22:06:18 Adam.Jiang Exp $
  33. #ifndef NCURSES_CURSESM_H_incl
  34. #define NCURSES_CURSESM_H_incl 1
  35. #include <cursesp.h>
  36. extern "C" {
  37. # include <menu.h>
  38. }
  39. //
  40. // -------------------------------------------------------------------------
  41. // This wraps the ITEM type of <menu.h>
  42. // -------------------------------------------------------------------------
  43. //
  44. class NCURSES_IMPEXP NCursesMenuItem
  45. {
  46. friend class NCursesMenu;
  47. protected:
  48. ITEM *item;
  49. inline void OnError (int err) const THROW2(NCursesException const, NCursesMenuException) {
  50. if (err != E_OK)
  51. THROW(new NCursesMenuException (err));
  52. }
  53. public:
  54. NCursesMenuItem (const char* p_name = NULL,
  55. const char* p_descript = NULL)
  56. : item(0)
  57. {
  58. item = p_name ? ::new_item (p_name, p_descript) : STATIC_CAST(ITEM*)(0);
  59. if (p_name && !item)
  60. OnError (E_SYSTEM_ERROR);
  61. }
  62. // Create an item. If you pass both parameters as NULL, a delimiting
  63. // item is constructed which can be used to terminate a list of
  64. // NCursesMenu objects.
  65. NCursesMenuItem& operator=(const NCursesMenuItem& rhs)
  66. {
  67. if (this != &rhs) {
  68. *this = rhs;
  69. }
  70. return *this;
  71. }
  72. NCursesMenuItem(const NCursesMenuItem& rhs)
  73. : item(0)
  74. {
  75. (void) rhs;
  76. }
  77. virtual ~NCursesMenuItem ();
  78. // Release the items memory
  79. inline const char* name () const {
  80. return ::item_name (item);
  81. }
  82. // Name of the item
  83. inline const char* description () const {
  84. return ::item_description (item);
  85. }
  86. // Description of the item
  87. inline int (index) (void) const {
  88. return ::item_index (item);
  89. }
  90. // Index of the item in an item array (or -1)
  91. inline void options_on (Item_Options opts) {
  92. OnError (::item_opts_on (item, opts));
  93. }
  94. // Switch on the items options
  95. inline void options_off (Item_Options opts) {
  96. OnError (::item_opts_off (item, opts));
  97. }
  98. // Switch off the item's option
  99. inline Item_Options options () const {
  100. return ::item_opts (item);
  101. }
  102. // Retrieve the items options
  103. inline void set_options (Item_Options opts) {
  104. OnError (::set_item_opts (item, opts));
  105. }
  106. // Set the items options
  107. inline void set_value (bool f) {
  108. OnError (::set_item_value (item,f));
  109. }
  110. // Set/Reset the items selection state
  111. inline bool value () const {
  112. return ::item_value (item);
  113. }
  114. // Retrieve the items selection state
  115. inline bool visible () const {
  116. return ::item_visible (item);
  117. }
  118. // Retrieve visibility of the item
  119. virtual bool action();
  120. // Perform an action associated with this item; you may use this in an
  121. // user supplied driver for a menu; you may derive from this class and
  122. // overload action() to supply items with different actions.
  123. // If an action returns true, the menu will be exited. The default action
  124. // is to do nothing.
  125. };
  126. // Prototype for an items callback function.
  127. typedef bool ITEMCALLBACK(NCursesMenuItem&);
  128. // If you don't like to create a child class for individual items to
  129. // overload action(), you may use this class and provide a callback
  130. // function pointer for items.
  131. class NCURSES_IMPEXP NCursesMenuCallbackItem : public NCursesMenuItem
  132. {
  133. private:
  134. ITEMCALLBACK* p_fct;
  135. public:
  136. NCursesMenuCallbackItem(ITEMCALLBACK* fct = NULL,
  137. const char* p_name = NULL,
  138. const char* p_descript = NULL )
  139. : NCursesMenuItem (p_name, p_descript),
  140. p_fct (fct) {
  141. }
  142. NCursesMenuCallbackItem& operator=(const NCursesMenuCallbackItem& rhs)
  143. {
  144. if (this != &rhs) {
  145. *this = rhs;
  146. }
  147. return *this;
  148. }
  149. NCursesMenuCallbackItem(const NCursesMenuCallbackItem& rhs)
  150. : NCursesMenuItem(rhs),
  151. p_fct(0)
  152. {
  153. }
  154. virtual ~NCursesMenuCallbackItem();
  155. bool action();
  156. };
  157. // This are the built-in hook functions in this C++ binding. In C++ we use
  158. // virtual member functions (see below On_..._Init and On_..._Termination)
  159. // to provide this functionality in an object oriented manner.
  160. extern "C" {
  161. void _nc_xx_mnu_init(MENU *);
  162. void _nc_xx_mnu_term(MENU *);
  163. void _nc_xx_itm_init(MENU *);
  164. void _nc_xx_itm_term(MENU *);
  165. }
  166. //
  167. // -------------------------------------------------------------------------
  168. // This wraps the MENU type of <menu.h>
  169. // -------------------------------------------------------------------------
  170. //
  171. class NCURSES_IMPEXP NCursesMenu : public NCursesPanel
  172. {
  173. protected:
  174. MENU *menu;
  175. private:
  176. NCursesWindow* sub; // the subwindow object
  177. bool b_sub_owner; // is this our own subwindow?
  178. bool b_framed; // has the menu a border?
  179. bool b_autoDelete; // Delete items when deleting menu?
  180. NCursesMenuItem** my_items; // The array of items for this menu
  181. // This structure is used for the menu's user data field to link the
  182. // MENU* to the C++ object and to provide extra space for a user pointer.
  183. typedef struct {
  184. void* m_user; // the pointer for the user's data
  185. const NCursesMenu* m_back; // backward pointer to C++ object
  186. const MENU* m_owner;
  187. } UserHook;
  188. // Get the backward pointer to the C++ object from a MENU
  189. static inline NCursesMenu* getHook(const MENU *m) {
  190. UserHook* hook = STATIC_CAST(UserHook*)(::menu_userptr(m));
  191. assert(hook != 0 && hook->m_owner==m);
  192. return const_cast<NCursesMenu*>(hook->m_back);
  193. }
  194. friend void _nc_xx_mnu_init(MENU *);
  195. friend void _nc_xx_mnu_term(MENU *);
  196. friend void _nc_xx_itm_init(MENU *);
  197. friend void _nc_xx_itm_term(MENU *);
  198. // Calculate ITEM* array for the menu
  199. ITEM** mapItems(NCursesMenuItem* nitems[]);
  200. protected:
  201. // internal routines
  202. inline void set_user(void *user) {
  203. UserHook* uptr = STATIC_CAST(UserHook*)(::menu_userptr (menu));
  204. assert (uptr != 0 && uptr->m_back==this && uptr->m_owner==menu);
  205. uptr->m_user = user;
  206. }
  207. inline void *get_user() {
  208. UserHook* uptr = STATIC_CAST(UserHook*)(::menu_userptr (menu));
  209. assert (uptr != 0 && uptr->m_back==this && uptr->m_owner==menu);
  210. return uptr->m_user;
  211. }
  212. void InitMenu (NCursesMenuItem* menu[],
  213. bool with_frame,
  214. bool autoDeleteItems);
  215. inline void OnError (int err) const THROW2(NCursesException const, NCursesMenuException) {
  216. if (err != E_OK)
  217. THROW(new NCursesMenuException (this, err));
  218. }
  219. // this wraps the menu_driver call.
  220. virtual int driver (int c) ;
  221. // 'Internal' constructor to create a menu without association to
  222. // an array of items.
  223. NCursesMenu( int nlines,
  224. int ncols,
  225. int begin_y = 0,
  226. int begin_x = 0)
  227. : NCursesPanel(nlines,ncols,begin_y,begin_x),
  228. menu (STATIC_CAST(MENU*)(0)),
  229. sub(0),
  230. b_sub_owner(0),
  231. b_framed(0),
  232. b_autoDelete(0),
  233. my_items(0)
  234. {
  235. }
  236. public:
  237. // Make a full window size menu
  238. NCursesMenu (NCursesMenuItem* Items[],
  239. bool with_frame=FALSE, // Reserve space for a frame?
  240. bool autoDelete_Items=FALSE) // Autocleanup of Items?
  241. : NCursesPanel(),
  242. menu(0),
  243. sub(0),
  244. b_sub_owner(0),
  245. b_framed(0),
  246. b_autoDelete(0),
  247. my_items(0)
  248. {
  249. InitMenu(Items, with_frame, autoDelete_Items);
  250. }
  251. // Make a menu with a window of this size.
  252. NCursesMenu (NCursesMenuItem* Items[],
  253. int nlines,
  254. int ncols,
  255. int begin_y = 0,
  256. int begin_x = 0,
  257. bool with_frame=FALSE, // Reserve space for a frame?
  258. bool autoDelete_Items=FALSE) // Autocleanup of Items?
  259. : NCursesPanel(nlines, ncols, begin_y, begin_x),
  260. menu(0),
  261. sub(0),
  262. b_sub_owner(0),
  263. b_framed(0),
  264. b_autoDelete(0),
  265. my_items(0)
  266. {
  267. InitMenu(Items, with_frame, autoDelete_Items);
  268. }
  269. NCursesMenu& operator=(const NCursesMenu& rhs)
  270. {
  271. if (this != &rhs) {
  272. *this = rhs;
  273. NCursesPanel::operator=(rhs);
  274. }
  275. return *this;
  276. }
  277. NCursesMenu(const NCursesMenu& rhs)
  278. : NCursesPanel(rhs),
  279. menu(rhs.menu),
  280. sub(rhs.sub),
  281. b_sub_owner(rhs.b_sub_owner),
  282. b_framed(rhs.b_framed),
  283. b_autoDelete(rhs.b_autoDelete),
  284. my_items(rhs.my_items)
  285. {
  286. }
  287. virtual ~NCursesMenu ();
  288. // Retrieve the menus subwindow
  289. inline NCursesWindow& subWindow() const {
  290. assert(sub!=NULL);
  291. return *sub;
  292. }
  293. // Set the menus subwindow
  294. void setSubWindow(NCursesWindow& sub);
  295. // Set these items for the menu
  296. inline void setItems(NCursesMenuItem* Items[]) {
  297. OnError(::set_menu_items(menu,mapItems(Items)));
  298. }
  299. // Remove the menu from the screen
  300. inline void unpost (void) {
  301. OnError (::unpost_menu (menu));
  302. }
  303. // Post the menu to the screen if flag is true, unpost it otherwise
  304. inline void post(bool flag = TRUE) {
  305. flag ? OnError (::post_menu(menu)) : OnError (::unpost_menu (menu));
  306. }
  307. // Get the numer of rows and columns for this menu
  308. inline void scale (int& mrows, int& mcols) const {
  309. OnError (::scale_menu (menu, &mrows, &mcols));
  310. }
  311. // Set the format of this menu
  312. inline void set_format(int mrows, int mcols) {
  313. OnError (::set_menu_format(menu, mrows, mcols));
  314. }
  315. // Get the format of this menu
  316. inline void menu_format(int& rows,int& ncols) {
  317. ::menu_format(menu,&rows,&ncols);
  318. }
  319. // Items of the menu
  320. inline NCursesMenuItem* items() const {
  321. return *my_items;
  322. }
  323. // Get the number of items in this menu
  324. inline int count() const {
  325. return ::item_count(menu);
  326. }
  327. // Get the current item (i.e. the one the cursor is located)
  328. inline NCursesMenuItem* current_item() const {
  329. return my_items[::item_index(::current_item(menu))];
  330. }
  331. // Get the marker string
  332. inline const char* mark() const {
  333. return ::menu_mark(menu);
  334. }
  335. // Set the marker string
  336. inline void set_mark(const char *marker) {
  337. OnError (::set_menu_mark (menu, marker));
  338. }
  339. // Get the name of the request code c
  340. inline static const char* request_name(int c) {
  341. return ::menu_request_name(c);
  342. }
  343. // Get the current pattern
  344. inline char* pattern() const {
  345. return ::menu_pattern(menu);
  346. }
  347. // true if there is a pattern match, false otherwise.
  348. bool set_pattern (const char *pat);
  349. // set the default attributes for the menu
  350. // i.e. set fore, back and grey attribute
  351. virtual void setDefaultAttributes();
  352. // Get the menus background attributes
  353. inline chtype back() const {
  354. return ::menu_back(menu);
  355. }
  356. // Get the menus foreground attributes
  357. inline chtype fore() const {
  358. return ::menu_fore(menu);
  359. }
  360. // Get the menus grey attributes (used for unselectable items)
  361. inline chtype grey() const {
  362. return ::menu_grey(menu);
  363. }
  364. // Set the menus background attributes
  365. inline chtype set_background(chtype a) {
  366. return ::set_menu_back(menu,a);
  367. }
  368. // Set the menus foreground attributes
  369. inline chtype set_foreground(chtype a) {
  370. return ::set_menu_fore(menu,a);
  371. }
  372. // Set the menus grey attributes (used for unselectable items)
  373. inline chtype set_grey(chtype a) {
  374. return ::set_menu_grey(menu,a);
  375. }
  376. inline void options_on (Menu_Options opts) {
  377. OnError (::menu_opts_on (menu,opts));
  378. }
  379. inline void options_off(Menu_Options opts) {
  380. OnError (::menu_opts_off(menu,opts));
  381. }
  382. inline Menu_Options options() const {
  383. return ::menu_opts(menu);
  384. }
  385. inline void set_options (Menu_Options opts) {
  386. OnError (::set_menu_opts (menu,opts));
  387. }
  388. inline int pad() const {
  389. return ::menu_pad(menu);
  390. }
  391. inline void set_pad (int padch) {
  392. OnError (::set_menu_pad (menu, padch));
  393. }
  394. // Position the cursor to the current item
  395. inline void position_cursor () const {
  396. OnError (::pos_menu_cursor (menu));
  397. }
  398. // Set the current item
  399. inline void set_current(NCursesMenuItem& I) {
  400. OnError (::set_current_item(menu, I.item));
  401. }
  402. // Get the current top row of the menu
  403. inline int top_row (void) const {
  404. return ::top_row (menu);
  405. }
  406. // Set the current top row of the menu
  407. inline void set_top_row (int row) {
  408. OnError (::set_top_row (menu, row));
  409. }
  410. // spacing control
  411. // Set the spacing for the menu
  412. inline void setSpacing(int spc_description,
  413. int spc_rows,
  414. int spc_columns) {
  415. OnError(::set_menu_spacing(menu,
  416. spc_description,
  417. spc_rows,
  418. spc_columns));
  419. }
  420. // Get the spacing info for the menu
  421. inline void Spacing(int& spc_description,
  422. int& spc_rows,
  423. int& spc_columns) const {
  424. OnError(::menu_spacing(menu,
  425. &spc_description,
  426. &spc_rows,
  427. &spc_columns));
  428. }
  429. // Decorations
  430. inline void frame(const char *title=NULL, const char* btitle=NULL) {
  431. if (b_framed)
  432. NCursesPanel::frame(title,btitle);
  433. else
  434. OnError(E_SYSTEM_ERROR);
  435. }
  436. inline void boldframe(const char *title=NULL, const char* btitle=NULL) {
  437. if (b_framed)
  438. NCursesPanel::boldframe(title,btitle);
  439. else
  440. OnError(E_SYSTEM_ERROR);
  441. }
  442. inline void label(const char *topLabel, const char *bottomLabel) {
  443. if (b_framed)
  444. NCursesPanel::label(topLabel,bottomLabel);
  445. else
  446. OnError(E_SYSTEM_ERROR);
  447. }
  448. // -----
  449. // Hooks
  450. // -----
  451. // Called after the menu gets repositioned in its window.
  452. // This is especially true if the menu is posted.
  453. virtual void On_Menu_Init();
  454. // Called before the menu gets repositioned in its window.
  455. // This is especially true if the menu is unposted.
  456. virtual void On_Menu_Termination();
  457. // Called after the item became the current item
  458. virtual void On_Item_Init(NCursesMenuItem& item);
  459. // Called before this item is left as current item.
  460. virtual void On_Item_Termination(NCursesMenuItem& item);
  461. // Provide a default key virtualization. Translate the keyboard
  462. // code c into a menu request code.
  463. // The default implementation provides a hopefully straightforward
  464. // mapping for the most common keystrokes and menu requests.
  465. virtual int virtualize(int c);
  466. // Operators
  467. inline NCursesMenuItem* operator[](int i) const {
  468. if ( (i < 0) || (i >= ::item_count (menu)) )
  469. OnError (E_BAD_ARGUMENT);
  470. return (my_items[i]);
  471. }
  472. // Perform the menu's operation
  473. // Return the item where you left the selection mark for a single
  474. // selection menu, or NULL for a multivalued menu.
  475. virtual NCursesMenuItem* operator()(void);
  476. // --------------------
  477. // Exception handlers
  478. // Called by operator()
  479. // --------------------
  480. // Called if the request is denied
  481. virtual void On_Request_Denied(int c) const;
  482. // Called if the item is not selectable
  483. virtual void On_Not_Selectable(int c) const;
  484. // Called if pattern doesn't match
  485. virtual void On_No_Match(int c) const;
  486. // Called if the command is unknown
  487. virtual void On_Unknown_Command(int c) const;
  488. };
  489. //
  490. // -------------------------------------------------------------------------
  491. // This is the typical C++ typesafe way to allow to attach
  492. // user data to an item of a menu. Its assumed that the user
  493. // data belongs to some class T. Use T as template argument
  494. // to create a UserItem.
  495. // -------------------------------------------------------------------------
  496. //
  497. template<class T> class NCURSES_IMPEXP NCursesUserItem : public NCursesMenuItem
  498. {
  499. public:
  500. NCursesUserItem (const char* p_name,
  501. const char* p_descript = NULL,
  502. const T* p_UserData = STATIC_CAST(T*)(0))
  503. : NCursesMenuItem (p_name, p_descript) {
  504. if (item)
  505. OnError (::set_item_userptr (item, const_cast<void *>(reinterpret_cast<const void*>(p_UserData))));
  506. }
  507. virtual ~NCursesUserItem() {}
  508. inline const T* UserData (void) const {
  509. return reinterpret_cast<const T*>(::item_userptr (item));
  510. };
  511. inline virtual void setUserData(const T* p_UserData) {
  512. if (item)
  513. OnError (::set_item_userptr (item, const_cast<void *>(reinterpret_cast<const void *>(p_UserData))));
  514. }
  515. };
  516. //
  517. // -------------------------------------------------------------------------
  518. // The same mechanism is used to attach user data to a menu
  519. // -------------------------------------------------------------------------
  520. //
  521. template<class T> class NCURSES_IMPEXP NCursesUserMenu : public NCursesMenu
  522. {
  523. protected:
  524. NCursesUserMenu( int nlines,
  525. int ncols,
  526. int begin_y = 0,
  527. int begin_x = 0,
  528. const T* p_UserData = STATIC_CAST(T*)(0))
  529. : NCursesMenu(nlines,ncols,begin_y,begin_x) {
  530. if (menu)
  531. set_user (const_cast<void *>(reinterpret_cast<const void*>(p_UserData)));
  532. }
  533. public:
  534. NCursesUserMenu (NCursesMenuItem* Items[],
  535. const T* p_UserData = STATIC_CAST(T*)(0),
  536. bool with_frame=FALSE,
  537. bool autoDelete_Items=FALSE)
  538. : NCursesMenu (Items, with_frame, autoDelete_Items) {
  539. if (menu)
  540. set_user (const_cast<void *>(reinterpret_cast<const void*>(p_UserData)));
  541. };
  542. NCursesUserMenu (NCursesMenuItem* Items[],
  543. int nlines,
  544. int ncols,
  545. int begin_y = 0,
  546. int begin_x = 0,
  547. const T* p_UserData = STATIC_CAST(T*)(0),
  548. bool with_frame=FALSE)
  549. : NCursesMenu (Items, nlines, ncols, begin_y, begin_x, with_frame) {
  550. if (menu)
  551. set_user (const_cast<void *>(reinterpret_cast<const void*>(p_UserData)));
  552. };
  553. virtual ~NCursesUserMenu() {
  554. };
  555. inline T* UserData (void) {
  556. return reinterpret_cast<T*>(get_user ());
  557. };
  558. inline virtual void setUserData (const T* p_UserData) {
  559. if (menu)
  560. set_user (const_cast<void *>(reinterpret_cast<const void*>(p_UserData)));
  561. }
  562. };
  563. #endif /* NCURSES_CURSESM_H_incl */