1 // * this is for making emacs happy: -*-Mode: C++;-*-
2 /*-----------------------------------------------------------------------------+
3 | The ncurses menu C++ binding is Copyright (C) 1997 |
4 | by Juergen Pfeifer <Juergen.Pfeifer@T-Online.de> |
5 | All Rights Reserved. |
7 | Permission to use, copy, modify, and distribute this software and its |
8 | documentation for any purpose and without fee is hereby granted, provided |
9 | that the above copyright notice appear in all copies and that both that |
10 | copyright notice and this permission notice appear in supporting |
11 | documentation, and that the name of the above listed copyright holder(s) not |
12 | be used in advertising or publicity pertaining to distribution of the |
13 | software without specific, written prior permission. |
15 | THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD TO |
16 | THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT- |
17 | NESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR |
18 | ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RE- |
19 | SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
20 | NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH |
21 | THE USE OR PERFORMANCE OF THIS SOFTWARE. |
22 +-----------------------------------------------------------------------------*/
26 MODULE_ID("$Id: cursesm.cc,v 1.4 1997/05/05 20:27:32 tom Exp $")
28 #pragma implementation
32 const int CMD_ACTION = MAX_COMMAND + 1;
33 const int CMD_QUIT = MAX_COMMAND + 2;
35 unsigned long NCursesMenu::total_count = 0;
37 /* Internal hook functions. They will route the hook
38 * calls to virtual methods of the NCursesMenu class,
39 * so in C++ providing a hook is done simply by
40 * implementing a virtual method in a derived class
43 NCursesMenu::mnu_init(MENU *m)
45 getHook(m)->On_Menu_Init();
49 NCursesMenu::mnu_term(MENU *m)
51 getHook(m)->On_Menu_Termination();
55 NCursesMenu::itm_init(MENU *m)
57 NCursesMenu* M = getHook(m);
58 M->On_Item_Init (M->current_item ());
62 NCursesMenu::itm_term(MENU *m)
64 NCursesMenu* M = getHook(m);
65 M->On_Item_Termination (M->current_item ());
68 /* Construct an ITEM* array from an array of NCursesMenuItem
72 NCursesMenu::mapItems(NCursesMenuItem* nitems[]) {
73 int itemCount = 0,lcv;
75 for (lcv=0; nitems[lcv]->item; ++lcv)
78 ITEM** items = new ITEM*[itemCount + 1];
80 for (lcv=0;nitems[lcv]->item;++lcv) {
81 items[lcv] = nitems[lcv]->item;
88 delete[] ::menu_items(menu);
94 NCursesMenu::setItems(NCursesMenuItem* nitems[])
96 OnError(::set_menu_items(menu,mapItems(nitems)));
100 NCursesMenu::InitMenu(NCursesMenuItem* nitems[],
104 if (total_count++==0) {
109 b_framed = with_frame;
112 menu = ::new_menu(mapItems(nitems));
114 OnError (E_SYSTEM_ERROR);
116 UserHook* hook = new UserHook;
119 hook->m_owner = menu;
120 ::set_menu_userptr(menu,(const void*)hook);
122 ::set_menu_init (menu, NCursesMenu::mnu_init);
123 ::set_menu_term (menu, NCursesMenu::mnu_term);
124 ::set_item_init (menu, NCursesMenu::itm_init);
125 ::set_item_term (menu, NCursesMenu::itm_term);
128 ::set_menu_win(menu, w);
131 if ((mrows > height()-2) || (mcols > width()-2))
133 sub = new NCursesWindow(*this,mrows,mcols,1,1,'r');
134 ::set_menu_sub(menu, sub->w);
138 sub = (NCursesWindow*)0;
141 setDefaultAttributes();
145 NCursesMenu::setDefaultAttributes() {
146 if (NumberOfColors() > 1) {
148 setpalette(COLOR_YELLOW,COLOR_BLUE);
150 setpalette(COLOR_CYAN,COLOR_BLUE);
152 setpalette(COLOR_WHITE,COLOR_CYAN);
153 ::set_menu_fore(menu, COLOR_PAIR(1));
154 ::set_menu_back(menu, COLOR_PAIR(2));
155 ::set_menu_grey(menu, COLOR_PAIR(3));
158 ::set_menu_fore(menu, A_BOLD);
159 ::set_menu_back(menu, A_NORMAL);
160 ::set_menu_grey(menu, A_DIM);
165 NCursesMenu::NCursesMenu(NCursesMenuItem* menu[])
170 NCursesMenu::NCursesMenu(NCursesMenuItem* menu[],
176 : NCursesPanel(lines, cols, begin_y, begin_x) {
177 InitMenu(menu,with_frame);
180 NCursesMenu::~NCursesMenu() {
181 UserHook* hook = (UserHook*)::menu_userptr(menu);
185 ::set_menu_sub(menu,(WINDOW *)0);
189 // It's essential to do this after free_menu()
190 delete[] ::menu_items(menu);
195 NCursesMenu::setSubWindow(NCursesWindow& nsub)
197 if (!isDescendant(nsub))
198 OnError(E_SYSTEM_ERROR);
203 ::set_menu_sub(menu,sub->w);
207 // call the menu driver and do basic error checking.
209 NCursesMenu::driver (int c) {
210 int res = ::menu_driver (menu, c);
213 case E_REQUEST_DENIED:
214 case E_NOT_SELECTABLE:
215 case E_UNKNOWN_COMMAND:
225 NCursesMenu::set_pattern (const char *pat) {
226 int res = ::set_menu_pattern (menu, pat);
238 // Provide a default key virtualization. Translate the keyboard
239 // code c into a menu request code.
240 // The default implementation provides a hopefully straightforward
241 // mapping for the most common keystrokes and menu requests.
243 NCursesMenu::virtualize(int c) {
245 case CTRL('Q') : return(CMD_QUIT);
247 case CTRL('N') : return(REQ_NEXT_ITEM);
249 case CTRL('P') : return(REQ_PREV_ITEM);
250 case CTRL('U') : return(REQ_SCR_ULINE);
251 case CTRL('D') : return(REQ_SCR_DLINE);
252 case CTRL('F') : return(REQ_SCR_DPAGE);
253 case CTRL('B') : return(REQ_SCR_UPAGE);
254 case CTRL('X') : return(REQ_CLEAR_PATTERN);
255 case CTRL('H') : return(REQ_BACK_PATTERN);
256 case CTRL('A') : return(REQ_NEXT_MATCH);
257 case CTRL('Z') : return(REQ_PREV_MATCH);
258 case CTRL('T') : return(REQ_TOGGLE_ITEM);
260 case CTRL('M') : return(CMD_ACTION);
261 case KEY_HOME : return(REQ_FIRST_ITEM);
262 case KEY_LEFT : return(REQ_LEFT_ITEM);
263 case KEY_RIGHT : return(REQ_RIGHT_ITEM);
264 case KEY_END : return(REQ_LAST_ITEM);
265 case KEY_BACKSPACE : return(REQ_BACK_PATTERN);
266 case KEY_NPAGE : return(REQ_SCR_DPAGE);
267 case KEY_PPAGE : return(REQ_SCR_UPAGE);
275 NCursesMenu::operator()(void) {
279 bool b_action = FALSE;
285 while (!b_action && ((drvCmnd = virtualize((c=getch()))) != CMD_QUIT)) {
286 switch((err=driver(drvCmnd))) {
287 case E_REQUEST_DENIED:
288 On_Request_Denied(c);
290 case E_NOT_SELECTABLE:
291 On_Not_Selectable(c);
293 case E_UNKNOWN_COMMAND:
294 if (drvCmnd == CMD_ACTION) {
295 NCursesMenuItem& itm = current_item();
296 b_action = itm.action();
298 On_Unknown_Command(c);
313 return *(my_items[::item_index (::current_item (menu))]);