cursesm.h 19 KB

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