diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 1999-05-09 00:21:16 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 1999-05-09 00:21:16 +0000 |
commit | 9891bec8eb3d751912a9139b6552c207025c8aa5 (patch) | |
tree | 76b682f1ecbece1e7fa034747e7f8c77ba1634c6 /lib/libcurses++/cursesm.cc | |
parent | 71e21992ce3a04e37b129906f21d13e1b4e3571a (diff) |
c++ clasess for ncurses
Diffstat (limited to 'lib/libcurses++/cursesm.cc')
-rw-r--r-- | lib/libcurses++/cursesm.cc | 379 |
1 files changed, 379 insertions, 0 deletions
diff --git a/lib/libcurses++/cursesm.cc b/lib/libcurses++/cursesm.cc new file mode 100644 index 00000000000..02ee75c8c56 --- /dev/null +++ b/lib/libcurses++/cursesm.cc @@ -0,0 +1,379 @@ +// * this is for making emacs happy: -*-Mode: C++;-*- +/**************************************************************************** + * Copyright (c) 1998 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Juergen Pfeifer <Juergen.Pfeifer@T-Online.de> 1997 * + ****************************************************************************/ + +#include "cursesm.h" +#include "cursesapp.h" +#include "internal.h" + +MODULE_ID("$Id: cursesm.cc,v 1.1 1999/05/09 00:21:14 millert Exp $") + +NCursesMenuItem::~NCursesMenuItem() { + if (item) + OnError(::free_item(item)); +} + +bool +NCursesMenuItem::action() { + return FALSE; +}; + +NCursesMenuCallbackItem::~NCursesMenuCallbackItem() { +} + +bool +NCursesMenuCallbackItem::action() { + if (p_fct) + return p_fct (*this); + else + return FALSE; +} + +/* Internal hook functions. They will route the hook + * calls to virtual methods of the NCursesMenu class, + * so in C++ providing a hook is done simply by + * implementing a virtual method in a derived class + */ +void +NCursesMenu::mnu_init(MENU *m) { + getHook(m)->On_Menu_Init(); +} + +void +NCursesMenu::mnu_term(MENU *m) { + getHook(m)->On_Menu_Termination(); +} + +void +NCursesMenu::itm_init(MENU *m) { + NCursesMenu* M = getHook(m); + M->On_Item_Init (*(M->current_item ())); +} + +void +NCursesMenu::itm_term(MENU *m) { + NCursesMenu* M = getHook(m); + M->On_Item_Termination (*(M->current_item ())); +} + +/* Construct an ITEM* array from an array of NCursesMenuItem + * objects. + */ +ITEM** +NCursesMenu::mapItems(NCursesMenuItem* nitems[]) { + int itemCount = 0,lcv; + + for (lcv=0; nitems[lcv]->item; ++lcv) + ++itemCount; + + ITEM** items = new ITEM*[itemCount + 1]; + + for (lcv=0;nitems[lcv]->item;++lcv) { + items[lcv] = nitems[lcv]->item; + } + items[lcv] = NULL; + + my_items = nitems; + + if (menu) + delete[] ::menu_items(menu); + return items; +} + +void +NCursesMenu::InitMenu(NCursesMenuItem* nitems[], + bool with_frame, + bool autoDelete_Items) { + int mrows, mcols; + + keypad(TRUE); + meta(TRUE); + + b_framed = with_frame; + b_autoDelete = autoDelete_Items; + + menu = (MENU*)0; + menu = ::new_menu(mapItems(nitems)); + if (!menu) + OnError (E_SYSTEM_ERROR); + + UserHook* hook = new UserHook; + hook->m_user = NULL; + hook->m_back = this; + hook->m_owner = menu; + ::set_menu_userptr(menu,(void*)hook); + + ::set_menu_init (menu, NCursesMenu::mnu_init); + ::set_menu_term (menu, NCursesMenu::mnu_term); + ::set_item_init (menu, NCursesMenu::itm_init); + ::set_item_term (menu, NCursesMenu::itm_term); + + scale(mrows, mcols); + ::set_menu_win(menu, w); + + if (with_frame) { + if ((mrows > height()-2) || (mcols > width()-2)) + OnError(E_NO_ROOM); + sub = new NCursesWindow(*this,mrows,mcols,1,1,'r'); + ::set_menu_sub(menu, sub->w); + b_sub_owner = TRUE; + } + else { + sub = (NCursesWindow*)0; + b_sub_owner = FALSE; + } + setDefaultAttributes(); +} + +void +NCursesMenu::setDefaultAttributes() { + NCursesApplication* S = NCursesApplication::getApplication(); + if (S) { + ::set_menu_fore(menu, S->foregrounds()); + ::set_menu_back(menu, S->backgrounds()); + ::set_menu_grey(menu, S->inactives()); + } +} + +NCursesMenu::~NCursesMenu() { + UserHook* hook = (UserHook*)::menu_userptr(menu); + delete hook; + if (b_sub_owner) { + delete sub; + ::set_menu_sub(menu,(WINDOW *)0); + } + if (menu) { + ITEM** itms = ::menu_items(menu); + int cnt = count(); + + OnError(::set_menu_items(menu,(ITEM**)0)); + + if (b_autoDelete) { + if (cnt>0) { + for (int i=0; i <= cnt; i++) + delete my_items[i]; + } + delete[] my_items; + } + + ::free_menu(menu); + // It's essential to do this after free_menu() + delete[] itms; + } +} + +void +NCursesMenu::setSubWindow(NCursesWindow& nsub) { + if (!isDescendant(nsub)) + OnError(E_SYSTEM_ERROR); + else { + if (b_sub_owner) + delete sub; + sub = ⊄ + ::set_menu_sub(menu,sub->w); + } +} + +bool +NCursesMenu::set_pattern (const char *pat) { + int res = ::set_menu_pattern (menu, pat); + switch(res) { + case E_OK: + break; + case E_NO_MATCH: + return FALSE; + default: + OnError (res); + } + return TRUE; +} + +// call the menu driver and do basic error checking. +int +NCursesMenu::driver (int c) { + int res = ::menu_driver (menu, c); + switch (res) { + case E_OK: + case E_REQUEST_DENIED: + case E_NOT_SELECTABLE: + case E_UNKNOWN_COMMAND: + case E_NO_MATCH: + break; + default: + OnError (res); + } + return (res); +} + +static const int CMD_QUIT = MAX_COMMAND + 1; +static const int CMD_ACTION = MAX_COMMAND + 2; +// +// ------------------------------------------------------------------------- +// Provide a default key virtualization. Translate the keyboard +// code c into a menu request code. +// The default implementation provides a hopefully straightforward +// mapping for the most common keystrokes and menu requests. +// ------------------------------------------------------------------------- +int +NCursesMenu::virtualize(int c) { + switch(c) { + case CTRL('X') : return(CMD_QUIT); // eXit + + case KEY_DOWN : return(REQ_DOWN_ITEM); + case CTRL('N') : return(REQ_NEXT_ITEM); // Next + case KEY_UP : return(REQ_UP_ITEM); + case CTRL('P') : return(REQ_PREV_ITEM); // Previous + + case CTRL('U') : return(REQ_SCR_ULINE); // Up + case CTRL('D') : return(REQ_SCR_DLINE); // Down + case CTRL('F') : return(REQ_SCR_DPAGE); // Forward + case CTRL('B') : return(REQ_SCR_UPAGE); // Backward + + case CTRL('Y') : return(REQ_CLEAR_PATTERN); + case CTRL('H') : return(REQ_BACK_PATTERN); + case CTRL('A') : return(REQ_NEXT_MATCH); + case CTRL('E') : return(REQ_PREV_MATCH); + case CTRL('T') : return(REQ_TOGGLE_ITEM); + + case CTRL('J') : + case CTRL('M') : return(CMD_ACTION); + + case KEY_HOME : return(REQ_FIRST_ITEM); + case KEY_LEFT : return(REQ_LEFT_ITEM); + case KEY_RIGHT : return(REQ_RIGHT_ITEM); + case KEY_END : return(REQ_LAST_ITEM); + case KEY_BACKSPACE : return(REQ_BACK_PATTERN); + case KEY_NPAGE : return(REQ_SCR_DPAGE); + case KEY_PPAGE : return(REQ_SCR_UPAGE); + + default: + return(c); + } +} + +NCursesMenuItem* +NCursesMenu::operator()(void) { + int drvCmnd; + int err; + int c; + bool b_action = FALSE; + + post(); + show(); + refresh(); + + while (!b_action && ((drvCmnd = virtualize((c=getch()))) != CMD_QUIT)) { + + switch((err=driver(drvCmnd))) { + case E_REQUEST_DENIED: + On_Request_Denied(c); + break; + case E_NOT_SELECTABLE: + On_Not_Selectable(c); + break; + case E_UNKNOWN_COMMAND: + if (drvCmnd == CMD_ACTION) { + if (options() & O_ONEVALUE) { + NCursesMenuItem* itm = current_item(); + assert(itm); + if (itm->options() & O_SELECTABLE) + b_action = itm->action(); + else + On_Not_Selectable(c); + } + else { + int n = count(); + for(int i=0; i<n; i++) { + NCursesMenuItem* itm = my_items[i]; + if (itm->value()) { + b_action |= itm->action(); + } + } + } + } else + On_Unknown_Command(c); + break; + case E_NO_MATCH: + On_No_Match(c); + break; + case E_OK: + break; + default: + OnError(err); + } + } + + unpost(); + hide(); + refresh(); + if (options() & O_ONEVALUE) + return my_items[::item_index (::current_item (menu))]; + else + return NULL; +} + +void +NCursesMenu::On_Menu_Init() { +} + +void +NCursesMenu::On_Menu_Termination() { +} + +void +NCursesMenu::On_Item_Init(NCursesMenuItem& item) { +} + +void +NCursesMenu::On_Item_Termination(NCursesMenuItem& item) { +} + +void +NCursesMenu::On_Request_Denied(int c) const { + beep(); +} + +void +NCursesMenu::On_Not_Selectable(int c) const { + beep(); +} + +void +NCursesMenu::On_No_Match(int c) const { + beep(); +} + +void +NCursesMenu::On_Unknown_Command(int c) const { + beep(); +} + |