diff options
-rw-r--r-- | include/Makefile | 10 | ||||
-rw-r--r-- | lib/Makefile | 5 | ||||
-rw-r--r-- | lib/libcurses++/Makefile | 20 | ||||
-rw-r--r-- | lib/libcurses++/README-first | 58 | ||||
-rw-r--r-- | lib/libcurses++/cursesapp.cc | 146 | ||||
-rw-r--r-- | lib/libcurses++/cursesapp.h | 163 | ||||
-rw-r--r-- | lib/libcurses++/cursesf.cc | 423 | ||||
-rw-r--r-- | lib/libcurses++/cursesf.h | 823 | ||||
-rw-r--r-- | lib/libcurses++/cursesm.cc | 379 | ||||
-rw-r--r-- | lib/libcurses++/cursesm.h | 592 | ||||
-rw-r--r-- | lib/libcurses++/cursesmain.cc | 51 | ||||
-rw-r--r-- | lib/libcurses++/cursesp.cc | 123 | ||||
-rw-r--r-- | lib/libcurses++/cursesp.h | 186 | ||||
-rw-r--r-- | lib/libcurses++/cursesw.cc | 420 | ||||
-rw-r--r-- | lib/libcurses++/cursesw.h | 1262 | ||||
-rw-r--r-- | lib/libcurses++/cursslk.cc | 121 | ||||
-rw-r--r-- | lib/libcurses++/cursslk.h | 205 | ||||
-rw-r--r-- | lib/libcurses++/demo.cc | 405 | ||||
-rw-r--r-- | lib/libcurses++/etip.h | 248 | ||||
-rw-r--r-- | lib/libcurses++/internal.h | 47 |
20 files changed, 5680 insertions, 7 deletions
diff --git a/include/Makefile b/include/Makefile index c2068df02c7..95b8f851b97 100644 --- a/include/Makefile +++ b/include/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.63 1999/03/29 03:07:39 rahnds Exp $ +# $OpenBSD: Makefile,v 1.64 1999/05/09 00:21:13 millert Exp $ # $NetBSD: Makefile,v 1.59 1996/05/15 21:36:43 jtc Exp $ # @(#)Makefile 5.45.1.1 (Berkeley) 5/6/91 @@ -36,10 +36,10 @@ LDIRS= dev net netinet netinet6 netccitt netiso netns netipx nfs sys ufs vm ddb # Directories with an includes target RDIRS= ../lib/libc_r ../lib/libcom_err ../lib/libcompat ../lib/libcurses \ - ../lib/libform ../lib/libmenu ../lib/libocurses ../lib/libossaudio \ - ../lib/libpanel ../lib/librpcsvc ../lib/libskey ../lib/libedit \ - ../lib/libpcap ../lib/libutil ../lib/libwrap ../lib/libz \ - ../sys/arch/${MACHINE} + ../lib/libcurses++ ../lib/libform ../lib/libmenu ../lib/libocurses \ + ../lib/libossaudio ../lib/libpanel ../lib/librpcsvc ../lib/libskey \ + ../lib/libedit ../lib/libpcap ../lib/libutil ../lib/libwrap \ + ../lib/libz ../sys/arch/${MACHINE} # Places using Makefile that needs a prerequisite target met before includes PRDIRS= diff --git a/lib/Makefile b/lib/Makefile index 45c0a0b320a..dc197b22148 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,9 +1,10 @@ -# $OpenBSD: Makefile,v 1.33 1999/04/23 05:20:40 downsj Exp $ +# $OpenBSD: Makefile,v 1.34 1999/05/09 00:21:14 millert Exp $ # $NetBSD: Makefile,v 1.20.4.1 1996/06/14 17:22:38 cgd Exp $ SUBDIR= csu libarch libc libc_r libcom_err libcompat libcurses libdes libedit \ libform libl libm libmenu libocurses libossaudio libpanel libpcap \ - libresolv librpcsvc libskey libssl libtelnet libutil libwrap liby libz + libresolv librpcsvc libskey libssl libtelnet libutil libwrap liby libz \ + libcurses++ # XXX Temporarily until i386 and pmax are able to use libkvm .if make(obj) diff --git a/lib/libcurses++/Makefile b/lib/libcurses++/Makefile new file mode 100644 index 00000000000..9ca9b1f5a43 --- /dev/null +++ b/lib/libcurses++/Makefile @@ -0,0 +1,20 @@ +# $OpenBSD: Makefile,v 1.1 1999/05/09 00:21:14 millert Exp $ + +# Uncomment this to enable tracing in libcurses +#CURSESTRACE=-DTRACE + +LIB= curses++ +SRCS= cursesapp.cc cursesf.cc cursesm.cc cursesmain.cc cursesp.cc \ + cursesw.cc cursslk.cc +HEADERS=cursesapp.h cursesf.h cursesm.h cursesp.h cursesw.h etip.h cursslk.h + +CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../libcurses ${CURSESTRACE} + +includes: + @for i in ${HEADERS}; do \ + cmp -s ${DESTDIR}/usr/include/g++/$$i ${.CURDIR}/$$i || \ + ${INSTALL} ${INSTALL_COPY} -m 444 -o $(BINOWN) -g $(BINGRP) \ + ${.CURDIR}/$$i ${DESTDIR}/usr/include/g++/$$i; \ + done + +.include <bsd.lib.mk> diff --git a/lib/libcurses++/README-first b/lib/libcurses++/README-first new file mode 100644 index 00000000000..b3b0b9d8f71 --- /dev/null +++ b/lib/libcurses++/README-first @@ -0,0 +1,58 @@ + C++ interface to ncurses routines +----------------------------------------------------------------------- + +This directory contains the source code for several C++ classes which +ease the use of writing ncurses-based programs. The code is derived +from the libg++ CursesWindow class but enhanced for ncurses. + +The classes simplify the use of window specific functions by +encapsulating them in the window object. Function overloading is +used in order to narrow the interface. E.g. you don't have the +distinction between `printw' and `mvprintw' anymore. + +A second benefit is the removal of all #defines which are included in +the curses.h file. This is a steady cause of trouble because many +common identifiers are used. Instead now all #defines are inline +functions which also allows strict type checking of arguments. + +The next enhancement is color support. It was originally provided by a +derived class. This caused some trouble if you think about Panels or +Menus and Forms with colors. We decided to put color support into the +base class so that any derived class may use color support also. +The implementation chosen here is directed to unrestricted use +of mixes of color and monochrome windows. The original NCursesColorWindow +class is maintained for compatibility reasons. + +The last point to mention is the support of other packages that are +distributed with the ncurses package: the panels library, the menu library +and the form library. This support is provided by the NCursesPanel class, +which is also derived from the NCursesWindow class and the NCursesMenu +and NCursesForm classes which are derived from NCursesPanel. This allows +building interfaces with windows. + +Please see the example program for a quick introduction. + +Note that at this point, there is no documentation for these classes. +Hopefully some will be written in the not too distant future. For now, +to find out how to use the classes, read the code and the example program. + +Suggestions for enhancements and contributions of code (and docs) are +welcome. Please let us know which functionality you miss. + + ATTENTION LINUX USERS: There is currently some discussion of + replacing the BSD curses in the Linux libc with ncurses. If + this is done we could perhaps include these classes in the Linux + libg++ replacing the original CursesWindow class (and renaming it + to CursesWindow). This could be done because NCursesWindow can + be made easily to a superset of the CursesWindow class. + + +Original author: + Eric Newton <newton@rocky.oswego.edu> for FSF's libg++ + +Authors of first ncurses based release (NCursesWindow, NCursesPanel): + Ulrich Drepper <drepper@ira.uka.de> + and Anatoly Ivasyuk <anatoly@nick.csh.rit.edu> + +Author of this release: + Juergen Pfeifer <Juergen.Pfeifer@T-Online.de> diff --git a/lib/libcurses++/cursesapp.cc b/lib/libcurses++/cursesapp.cc new file mode 100644 index 00000000000..503de0936cf --- /dev/null +++ b/lib/libcurses++/cursesapp.cc @@ -0,0 +1,146 @@ +// * 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 "cursesapp.h" +#include "internal.h" + +MODULE_ID("$Id: cursesapp.cc,v 1.1 1999/05/09 00:21:14 millert Exp $") + +void +NCursesApplication::init(bool bColors) { + if (bColors) + NCursesWindow::useColors(); + + if (Root_Window->colors() > 1) { + b_Colors = TRUE; + Root_Window->setcolor(1); + Root_Window->setpalette(COLOR_YELLOW,COLOR_BLUE); + Root_Window->setcolor(2); + Root_Window->setpalette(COLOR_CYAN,COLOR_BLUE); + Root_Window->setcolor(3); + Root_Window->setpalette(COLOR_BLACK,COLOR_BLUE); + Root_Window->setcolor(4); + Root_Window->setpalette(COLOR_BLACK,COLOR_CYAN); + Root_Window->setcolor(5); + Root_Window->setpalette(COLOR_BLUE,COLOR_YELLOW); + Root_Window->setcolor(6); + Root_Window->setpalette(COLOR_BLACK,COLOR_GREEN); + } + else + b_Colors = FALSE; + + Root_Window->bkgd(' '|window_backgrounds()); +} + +NCursesApplication* NCursesApplication::theApp = 0; +NCursesWindow* NCursesApplication::titleWindow = 0; +NCursesApplication::SLK_Link* NCursesApplication::slk_stack = 0; + +NCursesApplication::~NCursesApplication() { + Soft_Label_Key_Set* S; + + delete titleWindow; + while( (S=top()) ) { + pop(); + delete S; + } + delete Root_Window; + ::endwin(); +} + +int NCursesApplication::rinit(NCursesWindow& w) { + titleWindow = &w; + return OK; +} + +void NCursesApplication::push(Soft_Label_Key_Set& S) { + SLK_Link* L = new SLK_Link; + assert(L); + L->prev = slk_stack; + L->SLKs = &S; + slk_stack = L; + if (Root_Window) + S.show(); +} + +bool NCursesApplication::pop() { + if (slk_stack) { + SLK_Link* L = slk_stack; + slk_stack = slk_stack->prev; + delete L; + if (Root_Window && top()) + top()->show(); + } + return (slk_stack ? FALSE : TRUE); +} + +Soft_Label_Key_Set* NCursesApplication::top() const { + if (slk_stack) + return slk_stack->SLKs; + else + return (Soft_Label_Key_Set*)0; +} + +int NCursesApplication::operator()(void) { + bool bColors = b_Colors; + Soft_Label_Key_Set* S; + + int ts = titlesize(); + if (ts>0) + NCursesWindow::ripoffline(ts,rinit); + Soft_Label_Key_Set::Label_Layout fmt = useSLKs(); + if (fmt!=Soft_Label_Key_Set::None) { + S = new Soft_Label_Key_Set(fmt); + assert(S); + init_labels(*S); + } + + Root_Window = new NCursesWindow(::stdscr); + init(bColors); + + if (ts>0) + title(); + if (fmt!=Soft_Label_Key_Set::None) { + push(*S); + } + + return run(); +} + +NCursesApplication::NCursesApplication(bool bColors) { + b_Colors = bColors; + if (theApp) + THROW(new NCursesException("Application object already created.")); + else + theApp = this; +} diff --git a/lib/libcurses++/cursesapp.h b/lib/libcurses++/cursesapp.h new file mode 100644 index 00000000000..a1b6aee62b1 --- /dev/null +++ b/lib/libcurses++/cursesapp.h @@ -0,0 +1,163 @@ +// * This makes 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 * + ****************************************************************************/ + +// $Id: cursesapp.h,v 1.1 1999/05/09 00:21:14 millert Exp $ + +#ifndef _CURSESAPP_H +#define _CURSESAPP_H + +#include <cursslk.h> + +class NCursesApplication { +public: + typedef struct _slk_link { // This structure is used to maintain + struct _slk_link* prev; // a stack of SLKs + Soft_Label_Key_Set* SLKs; + } SLK_Link; +private: + static int rinit(NCursesWindow& w); // Internal Init function for title + static NCursesApplication* theApp; // Global ref. to the application + + static SLK_Link* slk_stack; + +protected: + static NCursesWindow* titleWindow; // The Title Window (if any) + + bool b_Colors; // Is this a color application? + NCursesWindow* Root_Window; // This is the stdscr equiv. + + // Initialization of attributes; + // Rewrite this in your derived class if you prefer other settings + virtual void init(bool bColors); + + // The number of lines for the title window. Default is no title window + // You may rewrite this in your derived class + virtual int titlesize() const { + return 0; + } + + // This method is called to put something into the title window initially + // You may rewrite this in your derived class + virtual void title() { + } + + // The layout used for the Soft Label Keys. Default is to have no SLKs. + // You may rewrite this in your derived class + virtual Soft_Label_Key_Set::Label_Layout useSLKs() const { + return Soft_Label_Key_Set::None; + } + + // This method is called to initialize the SLKs. Default is nothing. + // You may rewrite this in your derived class + virtual void init_labels(Soft_Label_Key_Set& S) const { + } + + // Your derived class must implement this method. The return value must + // be the exit value of your application. + virtual int run() = 0; + + + // The constructor is protected, so you may use it in your derived + // class constructor. The argument tells whether or not you want colors. + NCursesApplication(bool wantColors = FALSE); + +public: + virtual ~NCursesApplication(); + + // Get a pointer to the current application object + static NCursesApplication* getApplication() { + return theApp; + } + + // This method runs the application and returns its exit value + int operator()(void); + + // Process the commandline arguments. The default implementation simply + // ignores them. Your derived class may rewrite this. + virtual void handleArgs(int argc, char* argv[]) { + } + + // Does this application use colors? + inline bool useColors() const { + return b_Colors; + } + + // Push the Key Set S onto the SLK Stack. S then becomes the current set + // of Soft Labelled Keys. + void push(Soft_Label_Key_Set& S); + + // Throw away the current set of SLKs and make the previous one the + // new current set. + bool pop(); + + // Retrieve the current set of Soft Labelled Keys. + Soft_Label_Key_Set* top() const; + + // Attributes to use for menu and forms foregrounds + virtual chtype foregrounds() const { + return b_Colors ? COLOR_PAIR(1) : A_BOLD; + } + + // Attributes to use for menu and forms backgrounds + virtual chtype backgrounds() const { + return b_Colors ? COLOR_PAIR(2) : A_NORMAL; + } + + // Attributes to use for inactive (menu) elements + virtual chtype inactives() const { + return b_Colors ? (COLOR_PAIR(3)|A_DIM) : A_DIM; + } + + // Attributes to use for (form) labels and SLKs + virtual chtype labels() const { + return b_Colors ? COLOR_PAIR(4) : A_NORMAL; + } + + // Attributes to use for form backgrounds + virtual chtype dialog_backgrounds() const { + return b_Colors ? COLOR_PAIR(4) : A_NORMAL; + } + + // Attributes to use as default for (form) window backgrounds + virtual chtype window_backgrounds() const { + return b_Colors ? COLOR_PAIR(5) : A_NORMAL; + } + + // Attributes to use for the title window + virtual chtype screen_titles() const { + return b_Colors ? COLOR_PAIR(6) : A_BOLD; + } + +}; + +#endif // _CURSESAPP_H diff --git a/lib/libcurses++/cursesf.cc b/lib/libcurses++/cursesf.cc new file mode 100644 index 00000000000..aa34bd724e4 --- /dev/null +++ b/lib/libcurses++/cursesf.cc @@ -0,0 +1,423 @@ +// * 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 "cursesf.h" +#include "cursesapp.h" +#include "internal.h" + +MODULE_ID("$Id: cursesf.cc,v 1.1 1999/05/09 00:21:14 millert Exp $") + +NCursesFormField::~NCursesFormField () { + if (field) + OnError(::free_field (field)); +} + +/* Construct a FIELD* array from an array of NCursesFormField + * objects. + */ +FIELD** +NCursesForm::mapFields(NCursesFormField* nfields[]) { + int fieldCount = 0,lcv; + + assert(nfields); + + for (lcv=0; nfields[lcv]->field; ++lcv) + ++fieldCount; + + FIELD** fields = new FIELD*[fieldCount + 1]; + + for (lcv=0;nfields[lcv]->field;++lcv) { + fields[lcv] = nfields[lcv]->field; + } + fields[lcv] = NULL; + + my_fields = nfields; + + if (form) + delete[] ::form_fields(form); + return fields; +} + +void NCursesForm::setDefaultAttributes() { + NCursesApplication* S = NCursesApplication::getApplication(); + + int n = count(); + if (n > 0) { + for(int i=0; i<n; i++) { + NCursesFormField* f = (*this)[i]; + if ((f->options() & (O_EDIT|O_ACTIVE))==(O_EDIT|O_ACTIVE)) { + if (S) { + f->set_foreground(S->foregrounds()); + f->set_background(S->backgrounds()); + } + f->set_pad_character('_'); + } + else { + if (S) + f->set_background(S->labels()); + } + } + } + + if (S) { + bkgd(' '|S->dialog_backgrounds()); + if (sub) + sub->bkgd(' '|S->dialog_backgrounds()); + } +} + +void +NCursesForm::InitForm(NCursesFormField* nfields[], + bool with_frame, + bool autoDelete_Fields) { + int mrows, mcols; + + keypad(TRUE); + meta(TRUE); + + b_framed = with_frame; + b_autoDelete = autoDelete_Fields; + + form = (FORM*)0; + form = ::new_form(mapFields(nfields)); + if (!form) + OnError (E_SYSTEM_ERROR); + + UserHook* hook = new UserHook; + hook->m_user = NULL; + hook->m_back = this; + hook->m_owner = form; + ::set_form_userptr(form,(void*)hook); + + ::set_form_init (form, NCursesForm::frm_init); + ::set_form_term (form, NCursesForm::frm_term); + ::set_field_init (form, NCursesForm::fld_init); + ::set_field_term (form, NCursesForm::fld_term); + + scale(mrows, mcols); + ::set_form_win(form, 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_form_sub(form, sub->w); + b_sub_owner = TRUE; + } + else { + sub = (NCursesWindow*)0; + b_sub_owner = FALSE; + } + options_on(O_NL_OVERLOAD); + setDefaultAttributes(); +} + +NCursesForm::~NCursesForm() { + UserHook* hook = (UserHook*)::form_userptr(form); + delete hook; + if (b_sub_owner) { + delete sub; + ::set_form_sub(form,(WINDOW *)0); + } + if (form) { + FIELD** fields = ::form_fields(form); + int cnt = count(); + + OnError(::set_form_fields(form,(FIELD**)0)); + + if (b_autoDelete) { + if (cnt>0) { + for (int i=0; i <= cnt; i++) + delete my_fields[i]; + } + delete[] my_fields; + } + + ::free_form(form); + // It's essential to do this after free_form() + delete[] fields; + } +} + +void +NCursesForm::setSubWindow(NCursesWindow& nsub) { + if (!isDescendant(nsub)) + OnError(E_SYSTEM_ERROR); + else { + if (b_sub_owner) + delete sub; + sub = ⊄ + ::set_form_sub(form,sub->w); + } +} + +/* Internal hook functions. They will route the hook + * calls to virtual methods of the NCursesForm class, + * so in C++ providing a hook is done simply by + * implementing a virtual method in a derived class + */ +void +NCursesForm::frm_init(FORM *f) { + getHook(f)->On_Form_Init(); +} + +void +NCursesForm::frm_term(FORM *f) { + getHook(f)->On_Form_Termination(); +} + +void +NCursesForm::fld_init(FORM *f) { + NCursesForm* F = getHook(f); + F->On_Field_Init (*(F->current_field ())); +} + +void +NCursesForm::fld_term(FORM *f) { + NCursesForm* F = getHook(f); + F->On_Field_Termination (*(F->current_field ())); +} + +void +NCursesForm::On_Form_Init() { +} + +void +NCursesForm::On_Form_Termination() { +} + +void +NCursesForm::On_Field_Init(NCursesFormField& field) { +} + +void +NCursesForm::On_Field_Termination(NCursesFormField& field) { +} + +// call the form driver and do basic error checking. +int +NCursesForm::driver (int c) { + int res = ::form_driver (form, c); + switch (res) { + case E_OK: + case E_REQUEST_DENIED: + case E_INVALID_FIELD: + case E_UNKNOWN_COMMAND: + break; + default: + OnError (res); + } + return (res); +} + +void NCursesForm::On_Request_Denied(int c) const { + beep(); +} + +void NCursesForm::On_Invalid_Field(int c) const { + beep(); +} + +void NCursesForm::On_Unknown_Command(int c) const { + beep(); +} + +static const int CMD_QUIT = MAX_COMMAND + 1; + +NCursesFormField* +NCursesForm::operator()(void) { + int drvCmnd; + int err; + int c; + + post(); + show(); + refresh(); + + while (((drvCmnd = virtualize((c=getch()))) != CMD_QUIT)) { + switch((err=driver(drvCmnd))) { + case E_REQUEST_DENIED: + On_Request_Denied(c); + break; + case E_INVALID_FIELD: + On_Invalid_Field(c); + break; + case E_UNKNOWN_COMMAND: + On_Unknown_Command(c); + break; + case E_OK: + break; + default: + OnError(err); + } + } + + unpost(); + hide(); + refresh(); + return my_fields[::field_index (::current_field (form))]; +} + +// Provide a default key virtualization. Translate the keyboard +// code c into a form request code. +// The default implementation provides a hopefully straightforward +// mapping for the most common keystrokes and form requests. +int +NCursesForm::virtualize(int c) { + switch(c) { + + case KEY_HOME : return(REQ_FIRST_FIELD); + case KEY_END : return(REQ_LAST_FIELD); + + case KEY_DOWN : return(REQ_DOWN_CHAR); + case KEY_UP : return(REQ_UP_CHAR); + case KEY_LEFT : return(REQ_PREV_CHAR); + case KEY_RIGHT : return(REQ_NEXT_CHAR); + + case KEY_NPAGE : return(REQ_NEXT_PAGE); + case KEY_PPAGE : return(REQ_PREV_PAGE); + + case KEY_BACKSPACE : return(REQ_DEL_PREV); + case KEY_ENTER : return(REQ_NEW_LINE); + case KEY_CLEAR : return(REQ_CLR_FIELD); + + case CTRL('X') : return(CMD_QUIT); // eXit + + case CTRL('F') : return(REQ_NEXT_FIELD); // Forward + case CTRL('B') : return(REQ_PREV_FIELD); // Backward + case CTRL('L') : return(REQ_LEFT_FIELD); // Left + case CTRL('R') : return(REQ_RIGHT_FIELD); // Right + case CTRL('U') : return(REQ_UP_FIELD); // Up + case CTRL('D') : return(REQ_DOWN_FIELD); // Down + + case CTRL('W') : return(REQ_NEXT_WORD); + case CTRL('T') : return(REQ_PREV_WORD); + + case CTRL('A') : return(REQ_BEG_FIELD); + case CTRL('E') : return(REQ_END_FIELD); + + case CTRL('I') : return(REQ_INS_CHAR); + case CTRL('M') : + case CTRL('J') : return(REQ_NEW_LINE); + case CTRL('O') : return(REQ_INS_LINE); + case CTRL('V') : return(REQ_DEL_CHAR); + case CTRL('H') : return(REQ_DEL_PREV); + case CTRL('Y') : return(REQ_DEL_LINE); + case CTRL('G') : return(REQ_DEL_WORD); + case CTRL('K') : return(REQ_CLR_EOF); + + case CTRL('N') : return(REQ_NEXT_CHOICE); + case CTRL('P') : return(REQ_PREV_CHOICE); + + default: + return(c); + } +} +// +// ------------------------------------------------------------------------- +// User Defined Fieldtypes +// ------------------------------------------------------------------------- +// +bool UserDefinedFieldType::fcheck(FIELD *f, const void *u) { + NCursesFormField* F = (NCursesFormField*)u; + assert(F); + UserDefinedFieldType* udf = (UserDefinedFieldType*)(F->fieldtype()); + assert(udf); + return udf->field_check(*F); +} + +bool UserDefinedFieldType::ccheck(int c, const void *u) { + NCursesFormField* F = (NCursesFormField*)u; + assert(F); + UserDefinedFieldType* udf = + (UserDefinedFieldType*)(F->fieldtype()); + assert(udf); + return udf->char_check(c); +} + +void* UserDefinedFieldType::makearg(va_list* va) { + return va_arg(*va,NCursesFormField*); +} + +FIELDTYPE* UserDefinedFieldType::generic_fieldtype = + ::new_fieldtype(UserDefinedFieldType::fcheck, + UserDefinedFieldType::ccheck); + +FIELDTYPE* UserDefinedFieldType_With_Choice::generic_fieldtype_with_choice = + ::new_fieldtype(UserDefinedFieldType::fcheck, + UserDefinedFieldType::ccheck); + +bool UserDefinedFieldType_With_Choice::next_choice(FIELD *f, const void *u) { + NCursesFormField* F = (NCursesFormField*)u; + assert(F); + UserDefinedFieldType_With_Choice* udf = + (UserDefinedFieldType_With_Choice*)(F->fieldtype()); + assert(udf); + return udf->next(*F); +} + +bool UserDefinedFieldType_With_Choice::prev_choice(FIELD *f, const void *u) { + NCursesFormField* F = (NCursesFormField*)u; + assert(F); + UserDefinedFieldType_With_Choice* udf = + (UserDefinedFieldType_With_Choice*)(F->fieldtype()); + assert(udf); + return udf->previous(*F); +} + +class UDF_Init { +private: + int code; + static UDF_Init* I; +public: + UDF_Init() { + code = ::set_fieldtype_arg(UserDefinedFieldType::generic_fieldtype, + UserDefinedFieldType::makearg, + NULL, + NULL); + if (code==E_OK) + code = ::set_fieldtype_arg + (UserDefinedFieldType_With_Choice::generic_fieldtype_with_choice, + UserDefinedFieldType::makearg, + NULL, + NULL); + if (code==E_OK) + code = ::set_fieldtype_choice + (UserDefinedFieldType_With_Choice::generic_fieldtype_with_choice, + UserDefinedFieldType_With_Choice::next_choice, + UserDefinedFieldType_With_Choice::prev_choice); + } +}; + +UDF_Init* UDF_Init::I = new UDF_Init(); + diff --git a/lib/libcurses++/cursesf.h b/lib/libcurses++/cursesf.h new file mode 100644 index 00000000000..3ff38999683 --- /dev/null +++ b/lib/libcurses++/cursesf.h @@ -0,0 +1,823 @@ +// * This makes 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 * + ****************************************************************************/ + +// $Id: cursesf.h,v 1.1 1999/05/09 00:21:14 millert Exp $ + +#ifndef _CURSESF_H +#define _CURSESF_H + +#include <cursesp.h> + +extern "C" { +# include <form.h> +} +// +// ------------------------------------------------------------------------- +// The abstract base class for buitin and user defined Fieldtypes. +// ------------------------------------------------------------------------- +// +class NCursesFormField; // forward declaration + +// Class to represent builtin field types as well as C++ written new +// fieldtypes (see classes UserDefineFieldType... +class NCursesFieldType { + friend class NCursesFormField; + +protected: + FIELDTYPE* fieldtype; + + inline void OnError(int err) const THROWS(NCursesFormException) { + if (err!=E_OK) + THROW(new NCursesFormException (err)); + } + + NCursesFieldType(FIELDTYPE *f) : fieldtype(f) { + } + + virtual ~NCursesFieldType() {} + + // Set the fields f fieldtype to this one. + virtual void set(NCursesFormField& f) = 0; + +public: + NCursesFieldType() : fieldtype((FIELDTYPE*)0) { + } +}; + +// +// ------------------------------------------------------------------------- +// The class representing a forms field, wrapping the lowlevel FIELD struct +// ------------------------------------------------------------------------- +// +class NCursesFormField { + friend class NCursesForm; + +protected: + FIELD *field; // lowlevel structure + NCursesFieldType* ftype; // Associated field type + + // Error handler + inline void OnError (int err) const THROWS(NCursesFormException) { + if (err != E_OK) + THROW(new NCursesFormException (err)); + } + +public: + // Create a 'Null' field. Can be used to delimit a field list + NCursesFormField() + : field((FIELD*)0), ftype((NCursesFieldType*)0) { + } + + // Create a new field + NCursesFormField (int rows, + int cols, + int first_row = 0, + int first_col = 0, + int offscreen_rows = 0, + int additional_buffers = 0) + : ftype((NCursesFieldType*)0) { + field = ::new_field(rows,cols,first_row,first_col, + offscreen_rows, additional_buffers); + if (!field) + OnError(errno); + } + + virtual ~NCursesFormField (); + + // Duplicate the field at a new position + inline NCursesFormField* dup(int first_row, int first_col) { + NCursesFormField* f = new NCursesFormField(); + if (!f) + OnError(E_SYSTEM_ERROR); + else { + f->ftype = ftype; + f->field = ::dup_field(field,first_row,first_col); + if (!f->field) + OnError(errno); + } + return f; + } + + // Link the field to a new location + inline NCursesFormField* link(int first_row, int first_col) { + NCursesFormField* f = new NCursesFormField(); + if (!f) + OnError(E_SYSTEM_ERROR); + else { + f->ftype = ftype; + f->field = ::link_field(field,first_row,first_col); + if (!f->field) + OnError(errno); + } + return f; + } + + // Get the lowlevel field representation + inline FIELD* get_field() const { + return field; + } + + // Retrieve info about the field + inline void info(int& rows, int& cols, + int& first_row, int& first_col, + int& offscreen_rows, int& additional_buffers) const { + OnError(::field_info(field, &rows, &cols, + &first_row, &first_col, + &offscreen_rows, &additional_buffers)); + } + + // Retrieve info about the fields dynamic properties. + inline void dynamic_info(int& dynamic_rows, int& dynamic_cols, + int& max_growth) const { + OnError(::dynamic_field_info(field, &dynamic_rows, &dynamic_cols, + &max_growth)); + } + + // For a dynamic field you may set the maximum growth limit. + // A zero means unlimited growth. + inline void set_maximum_growth(int growth = 0) { + OnError(::set_max_field(field,growth)); + } + + // Move the field to a new position + inline void move(int row, int col) { + OnError(::move_field(field,row,col)); + } + + // Mark the field to start a new page + inline void new_page(bool pageFlag = FALSE) { + OnError(::set_new_page(field,pageFlag)); + } + + // Retrieve whether or not the field starts a new page. + inline bool is_new_page() const { + return ::new_page(field); + } + + // Set the justification for the field + inline void set_justification(int just) { + OnError(::set_field_just(field,just)); + } + + // Retrieve the fields justification + inline int justification() const { + return ::field_just(field); + } + // Set the foreground attribute for the field + inline void set_foreground(chtype fore) { + OnError(::set_field_fore(field,fore)); + } + + // Retrieve the fields foreground attribute + inline chtype fore() const { + return ::field_fore(field); + } + + // Set the background attribute for the field + inline void set_background(chtype back) { + OnError(::set_field_back(field,back)); + } + + // Retrieve the fields background attribute + inline chtype back() const { + return ::field_back(field); + } + + // Set the padding character for the field + inline void set_pad_character(int pad) { + OnError(::set_field_pad(field,pad)); + } + + // Retrieve the fields padding character + inline int pad() const { + return ::field_pad(field); + } + + // Switch on the fields options + inline void options_on (Field_Options options) { + OnError (::field_opts_on (field, options)); + } + + // Switch off the fields options + inline void options_off (Field_Options options) { + OnError (::field_opts_off (field, options)); + } + + // Retrieve the fields options + inline Field_Options options () const { + return ::field_opts (field); + } + + // Set the fields options + inline void set_options (Field_Options options) { + OnError (::set_field_opts (field, options)); + } + + // Mark the field as changed + inline void set_changed(bool changeFlag = TRUE) { + OnError(::set_field_status(field,changeFlag)); + } + + // Test whether or not the field is marked as changed + inline bool changed() const { + return ::field_status(field); + } + + // Return the index of the field in the field array of a form + // or -1 if the field is not associated to a form + inline int (index)() const { + return ::field_index(field); + } + + // Store a value in a fields buffer. The default buffer is nr. 0 + inline void set_value(const char *val, int buffer = 0) { + OnError(::set_field_buffer(field,buffer,val)); + } + + // Retrieve the value of a fields buffer. The defaukt buffer is nr. 0 + inline char* value(int buffer = 0) const { + return ::field_buffer(field,buffer); + } + + // Set the validation type of the field. + inline void set_fieldtype(NCursesFieldType& f) { + ftype = &f; + f.set(*this); // A good friend may do that... + } + + // Retrieve the validation type of the field. + inline NCursesFieldType* fieldtype() const { + return ftype; + } + +}; + +// +// ------------------------------------------------------------------------- +// The class representing a form, wrapping the lowlevel FORM struct +// ------------------------------------------------------------------------- +// +class NCursesForm : public NCursesPanel { +protected: + FORM* form; // the lowlevel structure + +private: + NCursesWindow* sub; // the subwindow object + bool b_sub_owner; // is this our own subwindow? + bool b_framed; // has the form a border? + bool b_autoDelete; // Delete fields when deleting form? + + NCursesFormField** my_fields; // The array of fields for this form + + // This structure is used for the form's user data field to link the + // FORM* to the C++ object and to provide extra space for a user pointer. + typedef struct { + void* m_user; // the pointer for the user's data + const NCursesForm* m_back; // backward pointer to C++ object + const FORM* m_owner; + } UserHook; + + // Get the backward pointer to the C++ object from a FORM + static inline NCursesForm* getHook(const FORM *f) { + UserHook* hook = (UserHook*)::form_userptr(f); + assert(hook && hook->m_owner==f); + return (NCursesForm*)(hook->m_back); + } + + // This are the built-in hook functions in this C++ binding. In C++ we use + // virtual member functions (see below On_..._Init and On_..._Termination) + // to provide this functionality in an object oriented manner. + static void frm_init(FORM *); + static void frm_term(FORM *); + static void fld_init(FORM *); + static void fld_term(FORM *); + + // Calculate FIELD* array for the menu + FIELD** mapFields(NCursesFormField* nfields[]); + +protected: + // internal routines + inline void set_user(void *user) { + UserHook* uptr = (UserHook*)::form_userptr (form); + assert (uptr && uptr->m_back==this && uptr->m_owner==form); + uptr->m_user = user; + } + + inline void *get_user() { + UserHook* uptr = (UserHook*)::form_userptr (form); + assert (uptr && uptr->m_back==this && uptr->m_owner==form); + return uptr->m_user; + } + + void InitForm (NCursesFormField* Fields[], + bool with_frame, + bool autoDeleteFields); + + inline void OnError (int err) const THROWS(NCursesFormException) { + if (err != E_OK) + THROW(new NCursesFormException (err)); + } + + // this wraps the form_driver call. + virtual int driver (int c) ; + + // 'Internal' constructor, builds an object without association to a + // field array. + NCursesForm( int lines, + int cols, + int begin_y = 0, + int begin_x = 0) + : NCursesPanel(lines,cols,begin_y,begin_x), + form ((FORM*)0) { + } + +public: + // Create form for the default panel. + NCursesForm (NCursesFormField* Fields[], + bool with_frame=FALSE, // reserve space for a frame? + bool autoDelete_Fields=FALSE) // do automatic cleanup? + : NCursesPanel() { + InitForm(Fields, with_frame, autoDelete_Fields); + } + + // Create a form in a panel with the given position and size. + NCursesForm (NCursesFormField* Fields[], + int lines, + int cols, + int begin_y, + int begin_x, + bool with_frame=FALSE, // reserve space for a frame? + bool autoDelete_Fields=FALSE) // do automatic cleanup? + : NCursesPanel(lines, cols, begin_y, begin_x) { + InitForm(Fields, with_frame, autoDelete_Fields); + } + + virtual ~NCursesForm(); + + // Set the default attributes for the form + virtual void setDefaultAttributes(); + + // Retrieve current field of the form. + inline NCursesFormField* current_field() const { + return my_fields[::field_index(::current_field(form))]; + } + + // Set the forms subwindow + void setSubWindow(NCursesWindow& sub); + + // Set these fields for the form + inline void setFields(NCursesFormField* Fields[]) { + OnError(::set_form_fields(form,mapFields(Fields))); + } + + // Remove the form from the screen + inline void unpost (void) { + OnError (::unpost_form (form)); + } + + // Post the form to the screen if flag is true, unpost it otherwise + inline void post(bool flag = TRUE) { + OnError (flag ? ::post_form(form) : ::unpost_form (form)); + } + + // Decorations + inline void frame(const char *title=NULL, const char* btitle=NULL) { + if (b_framed) + NCursesPanel::frame(title,btitle); + else + OnError(E_SYSTEM_ERROR); + } + + inline void boldframe(const char *title=NULL, const char* btitle=NULL) { + if (b_framed) + NCursesPanel::boldframe(title,btitle); + else + OnError(E_SYSTEM_ERROR); + } + + inline void label(const char *topLabel, const char *bottomLabel) { + if (b_framed) + NCursesPanel::label(topLabel,bottomLabel); + else + OnError(E_SYSTEM_ERROR); + } + + // ----- + // Hooks + // ----- + + // Called after the form gets repositioned in its window. + // This is especially true if the form is posted. + virtual void On_Form_Init(); + + // Called before the form gets repositioned in its window. + // This is especially true if the form is unposted. + virtual void On_Form_Termination(); + + // Called after the field became the current field + virtual void On_Field_Init(NCursesFormField& field); + + // Called before this field is left as current field. + virtual void On_Field_Termination(NCursesFormField& field); + + // Calculate required window size for the form. + void scale(int& rows, int& cols) const { + OnError(::scale_form(form,&rows,&cols)); + } + + // Retrieve number of fields in the form. + int count() const { + return ::field_count(form); + } + + // Make the page the current page of the form. + void set_page(int page) { + OnError(::set_form_page(form,page)); + } + + // Retrieve current page number + int page() const { + return ::form_page(form); + } + + // Switch on the forms options + inline void options_on (Form_Options options) { + OnError (::form_opts_on (form, options)); + } + + // Switch off the forms options + inline void options_off (Form_Options options) { + OnError (::form_opts_off (form, options)); + } + + // Retrieve the forms options + inline Form_Options options () const { + return ::form_opts (form); + } + + // Set the forms options + inline void set_options (Form_Options options) { + OnError (::set_form_opts (form, options)); + } + + // Are there more data in the current field after the data shown + inline bool data_ahead() const { + return ::data_ahead(form); + } + + // Are there more data in the current field before the data shown + inline bool data_behind() const { + return ::data_behind(form); + } + + // Position the cursor to the current field + inline void position_cursor () { + OnError (::pos_form_cursor (form)); + } + // Set the current field + inline void set_current(NCursesFormField& F) { + OnError (::set_current_field(form, F.field)); + } + + // Provide a default key virtualization. Translate the keyboard + // code c into a form request code. + // The default implementation provides a hopefully straightforward + // mapping for the most common keystrokes and form requests. + virtual int virtualize(int c); + + // Operators + inline NCursesFormField* operator[](int i) const { + if ( (i < 0) || (i >= ::field_count (form)) ) + OnError (E_BAD_ARGUMENT); + return my_fields[i]; + } + + // Perform the menu's operation + // Return the field where you left the form. + virtual NCursesFormField* operator()(void); + + // Exception handlers. The default is a Beep. + virtual void On_Request_Denied(int c) const; + virtual void On_Invalid_Field(int c) const; + virtual void On_Unknown_Command(int c) const; + +}; + +// +// ------------------------------------------------------------------------- +// This is the typical C++ typesafe way to allow to attach +// user data to a field of a form. Its assumed that the user +// data belongs to some class T. Use T as template argument +// to create a UserField. +// ------------------------------------------------------------------------- +template<class T> class NCursesUserField : public NCursesFormField +{ +public: + NCursesUserField (int rows, + int cols, + int first_row = 0, + int first_col = 0, + const T* p_UserData = (T*)0, + int offscreen_rows = 0, + int additional_buffers = 0) + : NCursesFormField (rows, cols, + first_row, first_col, + offscreen_rows, additional_buffers) { + if (field) + OnError(::set_field_userptr(field,(void *)p_UserData)); + } + + virtual ~NCursesUserField() {}; + + inline const T* UserData (void) const { + return (const T*)::field_userptr (field); + } + + inline virtual void setUserData(const T* p_UserData) { + if (field) + OnError (::set_field_userptr (field, (void *)p_UserData)); + } +}; +// +// ------------------------------------------------------------------------- +// The same mechanism is used to attach user data to a form +// ------------------------------------------------------------------------- +// +template<class T> class NCursesUserForm : public NCursesForm +{ +protected: + // 'Internal' constructor, builds an object without association to a + // field array. + NCursesUserForm( int lines, + int cols, + int begin_y = 0, + int begin_x = 0, + const T* p_UserData = (T*)0) + : NCursesForm(lines,cols,begin_y,begin_x) { + if (form) + set_user ((void *)p_UserData); + } + +public: + NCursesUserForm (NCursesFormField Fields[], + bool with_frame=FALSE, + bool autoDelete_Fields=FALSE) + : NCursesForm (Fields, with_frame, autoDelete_Fields) { + }; + + NCursesUserForm (NCursesFormField Fields[], + const T* p_UserData = (T*)0, + bool with_frame=FALSE, + bool autoDelete_Fields=FALSE) + : NCursesForm (Fields, with_frame, autoDelete_Fields) { + if (form) + set_user ((void *)p_UserData); + }; + + NCursesUserForm (NCursesFormField Fields[], + int lines, + int cols, + int begin_y = 0, + int begin_x = 0, + const T* p_UserData = (T*)0, + bool with_frame=FALSE, + bool autoDelete_Fields=FALSE) + : NCursesForm (Fields, lines, cols, begin_y, begin_x, + with_frame, autoDelete_Fields) { + if (form) + set_user ((void *)p_UserData); + }; + + virtual ~NCursesUserForm() { + }; + + inline T* UserData (void) const { + return (T*)get_user (); + }; + + inline virtual void setUserData (const T* p_UserData) { + if (form) + set_user ((void *)p_UserData); + } + +}; +// +// ------------------------------------------------------------------------- +// Builtin Fieldtypes +// ------------------------------------------------------------------------- +// +class Alpha_Field : public NCursesFieldType { +private: + int min_field_width; + + void set(NCursesFormField& f) { + OnError(::set_field_type(f.get_field(),fieldtype,min_field_width)); + } + +public: + Alpha_Field(int width) + : NCursesFieldType(TYPE_ALPHA), + min_field_width(width) { + } +}; + +class Alphanumeric_Field : public NCursesFieldType { +private: + int min_field_width; + + void set(NCursesFormField& f) { + OnError(::set_field_type(f.get_field(),fieldtype,min_field_width)); + } + +public: + Alphanumeric_Field(int width) + : NCursesFieldType(TYPE_ALNUM), + min_field_width(width) { + } +}; + +class Integer_Field : public NCursesFieldType { +private: + int precision; + long lower_limit, upper_limit; + + void set(NCursesFormField& f) { + OnError(::set_field_type(f.get_field(),fieldtype, + precision,lower_limit,upper_limit)); + } + +public: + Integer_Field(int prec, long low=0L, long high=0L) + : NCursesFieldType(TYPE_INTEGER), + precision(prec), lower_limit(low), upper_limit(high) { + } +}; + +class Numeric_Field : public NCursesFieldType { +private: + int precision; + double lower_limit, upper_limit; + + void set(NCursesFormField& f) { + OnError(::set_field_type(f.get_field(),fieldtype, + precision,lower_limit,upper_limit)); + } + +public: + Numeric_Field(int prec, double low=0.0, double high=0.0) + : NCursesFieldType(TYPE_NUMERIC), + precision(prec), lower_limit(low), upper_limit(high) { + } +}; + +class Regular_Expression_Field : public NCursesFieldType { +private: + char* regex; + + void set(NCursesFormField& f) { + OnError(::set_field_type(f.get_field(),fieldtype,regex)); + } + +public: + Regular_Expression_Field(const char *expr) + : NCursesFieldType(TYPE_REGEXP) { + regex = new char[1+::strlen(expr)]; + (strcpy)(regex,expr); + } + + ~Regular_Expression_Field() { + delete[] regex; + } +}; + +class Enumeration_Field : public NCursesFieldType { +private: + char** list; + int case_sensitive; + int non_unique_matches; + + void set(NCursesFormField& f) { + OnError(::set_field_type(f.get_field(),fieldtype, + list,case_sensitive,non_unique_matches)); + } +public: + Enumeration_Field(char* enums[], + bool case_sens=FALSE, + bool non_unique=FALSE) + : NCursesFieldType(TYPE_ENUM), + list(enums), + case_sensitive(case_sens?-1:0), + non_unique_matches(non_unique?-1:0) { + } +}; + +class IPV4_Address_Field : public NCursesFieldType { +private: + void set(NCursesFormField& f) { + OnError(::set_field_type(f.get_field(),fieldtype)); + } + +public: + IPV4_Address_Field() : NCursesFieldType(TYPE_IPV4) { + } +}; +// +// ------------------------------------------------------------------------- +// Abstract base class for User-Defined Fieldtypes +// ------------------------------------------------------------------------- +// +class UserDefinedFieldType : public NCursesFieldType { + friend class UDF_Init; // Internal helper to set up statics +private: + // For all C++ defined fieldtypes we need only one generic lowlevel + // FIELDTYPE* element. + static FIELDTYPE* generic_fieldtype; + +protected: + // This are the functions required by the low level libforms functions + // to construct a fieldtype. + static bool fcheck(FIELD *, const void*); + static bool ccheck(int c, const void *); + static void* makearg(va_list*); + + void set(NCursesFormField& f) { + OnError(::set_field_type(f.get_field(),fieldtype,&f)); + } + +protected: + // Redefine this function to do a field validation. The argument + // is a reference to the field you should validate. + virtual bool field_check(NCursesFormField& f) = 0; + + // Redefine this function to do a character validation. The argument + // is the character to be validated. + virtual bool char_check (int c) = 0; + +public: + UserDefinedFieldType() : NCursesFieldType(generic_fieldtype) { + } +}; +// +// ------------------------------------------------------------------------- +// Abstract base class for User-Defined Fieldtypes with Choice functions +// ------------------------------------------------------------------------- +// +class UserDefinedFieldType_With_Choice : public UserDefinedFieldType { + friend class UDF_Init; // Internal helper to set up statics +private: + // For all C++ defined fieldtypes with choice functions we need only one + // generic lowlevel FIELDTYPE* element. + static FIELDTYPE* generic_fieldtype_with_choice; + + // This are the functions required by the low level libforms functions + // to construct a fieldtype with choice functions. + static bool next_choice(FIELD*, const void *); + static bool prev_choice(FIELD*, const void *); + +protected: + // Redefine this function to do the retrieval of the next choice value. + // The argument is a reference to the field tobe examined. + virtual bool next (NCursesFormField& f) = 0; + + // Redefine this function to do the retrieval of the previous choice value. + // The argument is a reference to the field tobe examined. + virtual bool previous(NCursesFormField& f) = 0; + +public: + UserDefinedFieldType_With_Choice() { + fieldtype = generic_fieldtype_with_choice; + } +}; + +#endif // _CURSESF_H + 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(); +} + diff --git a/lib/libcurses++/cursesm.h b/lib/libcurses++/cursesm.h new file mode 100644 index 00000000000..1aa15628466 --- /dev/null +++ b/lib/libcurses++/cursesm.h @@ -0,0 +1,592 @@ +// * This makes 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 * + ****************************************************************************/ + +// $Id: cursesm.h,v 1.1 1999/05/09 00:21:14 millert Exp $ + +#ifndef _CURSESM_H +#define _CURSESM_H + +#include <cursesp.h> + +extern "C" { +# include <menu.h> +} +// +// ------------------------------------------------------------------------- +// This wraps the ITEM type of <menu.h> +// ------------------------------------------------------------------------- +// +class NCursesMenuItem { + friend class NCursesMenu; + +protected: + ITEM *item; + + inline void OnError (int err) const THROWS(NCursesMenuException) { + if (err != E_OK) + THROW(new NCursesMenuException (err)); + } + +public: + NCursesMenuItem (const char* p_name = NULL, + const char* p_descript = NULL ) { + item = p_name ? ::new_item (p_name, p_descript) : (ITEM*)0; + if (p_name && !item) + OnError (E_SYSTEM_ERROR); + } + // Create an item. If you pass both parameters as NULL, a delimiting + // item is constructed which can be used to terminate a list of + // NCursesMenu objects. + + virtual ~NCursesMenuItem (); + // Release the items memory + + inline const char* name () const { + return ::item_name (item); + } + // Name of the item + + inline const char* description () const { + return ::item_description (item); + } + // Description of the item + + inline int (index) (void) const { + return ::item_index (item); + } + // Index of the item in an item array (or -1) + + inline void options_on (Item_Options options) { + OnError (::item_opts_on (item, options)); + } + // Switch on the items options + + inline void options_off (Item_Options options) { + OnError (::item_opts_off (item, options)); + } + // Switch off the item's option + + inline Item_Options options () const { + return ::item_opts (item); + } + // Retrieve the items options + + inline void set_options (Item_Options options) { + OnError (::set_item_opts (item, options)); + } + // Set the items options + + inline void set_value (bool f) { + OnError (::set_item_value (item,f)); + } + // Set/Reset the items selection state + + inline bool value () const { + return ::item_value (item); + } + // Retrieve the items selection state + + inline bool visible () const { + return ::item_visible (item); + } + // Retrieve visibility of the item + + virtual bool action(); + // Perform an action associated with this item; you may use this in an + // user supplied driver for a menu; you may derive from this class and + // overload action() to supply items with different actions. + // If an action returns true, the menu will be exited. The default action + // is to do nothing. +}; + +// Prototype for an items callback function. +typedef bool ITEMCALLBACK(NCursesMenuItem&); + +// If you don't like to create a child class for individual items to +// overload action(), you may use this class and provide a callback +// function pointer for items. +class NCursesMenuCallbackItem : public NCursesMenuItem { +private: + const ITEMCALLBACK* p_fct; + +public: + NCursesMenuCallbackItem(const ITEMCALLBACK* fct = NULL, + const char* p_name = NULL, + const char* p_descript = NULL ) + : NCursesMenuItem (p_name, p_descript), + p_fct (fct) { + } + + virtual ~NCursesMenuCallbackItem(); + + bool action(); +}; +// +// ------------------------------------------------------------------------- +// This wraps the MENU type of <menu.h> +// ------------------------------------------------------------------------- +// +class NCursesMenu : public NCursesPanel { +protected: + MENU *menu; + +private: + NCursesWindow* sub; // the subwindow object + bool b_sub_owner; // is this our own subwindow? + bool b_framed; // has the menu a border? + bool b_autoDelete; // Delete items when deleting menu? + + NCursesMenuItem** my_items; // The array of items for this menu + + // This structure is used for the menu's user data field to link the + // MENU* to the C++ object and to provide extra space for a user pointer. + typedef struct { + void* m_user; // the pointer for the user's data + const NCursesMenu* m_back; // backward pointer to C++ object + const MENU* m_owner; + } UserHook; + + // Get the backward pointer to the C++ object from a MENU + static inline NCursesMenu* getHook(const MENU *m) { + UserHook* hook = (UserHook*)::menu_userptr(m); + assert(hook && hook->m_owner==m); + return (NCursesMenu*)(hook->m_back); + } + + // This are the built-in hook functions in this C++ binding. In C++ we use + // virtual member functions (see below On_..._Init and On_..._Termination) + // to provide this functionality in an object oriented manner. + static void mnu_init(MENU *); + static void mnu_term(MENU *); + static void itm_init(MENU *); + static void itm_term(MENU *); + + // Calculate ITEM* array for the menu + ITEM** mapItems(NCursesMenuItem* nitems[]); + +protected: + // internal routines + inline void set_user(void *user) { + UserHook* uptr = (UserHook*)::menu_userptr (menu); + assert (uptr && uptr->m_back==this && uptr->m_owner==menu); + uptr->m_user = user; + } + + inline void *get_user() { + UserHook* uptr = (UserHook*)::menu_userptr (menu); + assert (uptr && uptr->m_back==this && uptr->m_owner==menu); + return uptr->m_user; + } + + void InitMenu (NCursesMenuItem* menu[], + bool with_frame, + bool autoDeleteItems); + + inline void OnError (int err) const THROWS(NCursesMenuException) { + if (err != E_OK) + THROW(new NCursesMenuException (this, err)); + } + + // this wraps the menu_driver call. + virtual int driver (int c) ; + + // 'Internal' constructor to create a menu without association to + // an array of items. + NCursesMenu( int lines, + int cols, + int begin_y = 0, + int begin_x = 0) + : NCursesPanel(lines,cols,begin_y,begin_x), + menu ((MENU*)0) { + } + +public: + // Make a full window size menu + NCursesMenu (NCursesMenuItem* Items[], + bool with_frame=FALSE, // Reserve space for a frame? + bool autoDelete_Items=FALSE) // Autocleanup of Items? + : NCursesPanel() { + InitMenu(Items, with_frame, autoDelete_Items); + } + + // Make a menu with a window of this size. + NCursesMenu (NCursesMenuItem* Items[], + int lines, + int cols, + int begin_y = 0, + int begin_x = 0, + bool with_frame=FALSE, // Reserve space for a frame? + bool autoDelete_Items=FALSE) // Autocleanup of Items? + : NCursesPanel(lines, cols, begin_y, begin_x) { + InitMenu(Items, with_frame, autoDelete_Items); + } + + virtual ~NCursesMenu (); + + // Retrieve the menus subwindow + inline NCursesWindow& subWindow() const { + assert(sub!=NULL); + return *sub; + } + + // Set the menus subwindow + void setSubWindow(NCursesWindow& sub); + + // Set these items for the menu + inline void setItems(NCursesMenuItem* Items[]) { + OnError(::set_menu_items(menu,mapItems(Items))); + } + + // Remove the menu from the screen + inline void unpost (void) { + OnError (::unpost_menu (menu)); + } + + // Post the menu to the screen if flag is true, unpost it otherwise + inline void post(bool flag = TRUE) { + flag ? OnError (::post_menu(menu)) : OnError (::unpost_menu (menu)); + } + + // Get the numer of rows and columns for this menu + inline void scale (int& mrows, int& mcols) const { + OnError (::scale_menu (menu, &mrows, &mcols)); + } + + // Set the format of this menu + inline void set_format(int mrows, int mcols) { + OnError (::set_menu_format(menu, mrows, mcols)); + } + + // Get the format of this menu + inline void menu_format(int& rows,int& cols) { + ::menu_format(menu,&rows,&cols); + } + + // Items of the menu + inline NCursesMenuItem* items() const { + return *my_items; + } + + // Get the number of items in this menu + inline int count() const { + return ::item_count(menu); + } + + // Get the current item (i.e. the one the cursor is located) + inline NCursesMenuItem* current_item() const { + return my_items[::item_index(::current_item(menu))]; + } + + // Get the marker string + inline const char* mark() const { + return ::menu_mark(menu); + } + + // Set the marker string + inline void set_mark(const char *mark) { + OnError (::set_menu_mark (menu, mark)); + } + + // Get the name of the request code c + inline static const char* request_name(int c) { + return ::menu_request_name(c); + } + + // Get the current pattern + inline char* pattern() const { + return ::menu_pattern(menu); + } + + // true if there is a pattern match, false otherwise. + bool set_pattern (const char *pat); + + // set the default attributes for the menu + // i.e. set fore, back and grey attribute + virtual void setDefaultAttributes(); + + // Get the menus background attributes + inline chtype back() const { + return ::menu_back(menu); + } + + // Get the menus foreground attributes + inline chtype fore() const { + return ::menu_fore(menu); + } + + // Get the menus grey attributes (used for unselectable items) + inline chtype grey() const { + return ::menu_grey(menu); + } + + // Set the menus background attributes + inline chtype set_background(chtype a) { + return ::set_menu_back(menu,a); + } + + // Set the menus foreground attributes + inline chtype set_foreground(chtype a) { + return ::set_menu_fore(menu,a); + } + + // Set the menus grey attributes (used for unselectable items) + inline chtype set_grey(chtype a) { + return ::set_menu_grey(menu,a); + } + + inline void options_on (Menu_Options opts) { + OnError (::menu_opts_on (menu,opts)); + } + + inline void options_off(Menu_Options opts) { + OnError (::menu_opts_off(menu,opts)); + } + + inline Menu_Options options() const { + return ::menu_opts(menu); + } + + inline void set_options (Menu_Options opts) { + OnError (::set_menu_opts (menu,opts)); + } + + inline int pad() const { + return ::menu_pad(menu); + } + + inline void set_pad (int padch) { + OnError (::set_menu_pad (menu, padch)); + } + + // Position the cursor to the current item + inline void position_cursor () const { + OnError (::pos_menu_cursor (menu)); + } + + // Set the current item + inline void set_current(NCursesMenuItem& I) { + OnError (::set_current_item(menu, I.item)); + } + + // Get the current top row of the menu + inline int top_row (void) const { + return ::top_row (menu); + } + + // Set the current top row of the menu + inline void set_top_row (int row) { + OnError (::set_top_row (menu, row)); + } + + // spacing control + // Set the spacing for the menu + inline void setSpacing(int spc_description, + int spc_rows, + int spc_columns) { + OnError(::set_menu_spacing(menu, + spc_description, + spc_rows, + spc_columns)); + } + + // Get the spacing info for the menu + inline void Spacing(int& spc_description, + int& spc_rows, + int& spc_columns) const { + OnError(::menu_spacing(menu, + &spc_description, + &spc_rows, + &spc_columns)); + } + + // Decorations + inline void frame(const char *title=NULL, const char* btitle=NULL) { + if (b_framed) + NCursesPanel::frame(title,btitle); + else + OnError(E_SYSTEM_ERROR); + } + + inline void boldframe(const char *title=NULL, const char* btitle=NULL) { + if (b_framed) + NCursesPanel::boldframe(title,btitle); + else + OnError(E_SYSTEM_ERROR); + } + + inline void label(const char *topLabel, const char *bottomLabel) { + if (b_framed) + NCursesPanel::label(topLabel,bottomLabel); + else + OnError(E_SYSTEM_ERROR); + } + + // ----- + // Hooks + // ----- + + // Called after the menu gets repositioned in its window. + // This is especially true if the menu is posted. + virtual void On_Menu_Init(); + + // Called before the menu gets repositioned in its window. + // This is especially true if the menu is unposted. + virtual void On_Menu_Termination(); + + // Called after the item became the current item + virtual void On_Item_Init(NCursesMenuItem& item); + + // Called before this item is left as current item. + virtual void On_Item_Termination(NCursesMenuItem& item); + + // 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. + virtual int virtualize(int c); + + + // Operators + inline NCursesMenuItem* operator[](int i) const { + if ( (i < 0) || (i >= ::item_count (menu)) ) + OnError (E_BAD_ARGUMENT); + return (my_items[i]); + } + + // Perform the menu's operation + // Return the item where you left the selection mark for a single + // selection menu, or NULL for a multivalued menu. + virtual NCursesMenuItem* operator()(void); + + // -------------------- + // Exception handlers + // Called by operator() + // -------------------- + + // Called if the request is denied + virtual void On_Request_Denied(int c) const; + + // Called if the item is not selectable + virtual void On_Not_Selectable(int c) const; + + // Called if pattern doesn't match + virtual void On_No_Match(int c) const; + + // Called if the command is unknown + virtual void On_Unknown_Command(int c) const; + +}; +// +// ------------------------------------------------------------------------- +// This is the typical C++ typesafe way to allow to attach +// user data to an item of a menu. Its assumed that the user +// data belongs to some class T. Use T as template argument +// to create a UserItem. +// ------------------------------------------------------------------------- +// +template<class T> class NCursesUserItem : public NCursesMenuItem +{ +public: + NCursesUserItem (const char* p_name, + const char* p_descript = NULL, + const T* p_UserData = (T*)0) + : NCursesMenuItem (p_name, p_descript) { + if (item) + OnError (::set_item_userptr (item, (void *)p_UserData)); + }; + + virtual ~NCursesUserItem() {}; + + inline const T* UserData (void) const { + return (const T*)::item_userptr (item); + }; + + inline virtual void setUserData(const T* p_UserData) { + if (item) + OnError (::set_item_userptr (item, (void *)p_UserData)); + } +}; +// +// ------------------------------------------------------------------------- +// The same mechanism is used to attach user data to a menu +// ------------------------------------------------------------------------- +// +template<class T> class NCursesUserMenu : public NCursesMenu +{ +protected: + NCursesUserMenu( int lines, + int cols, + int begin_y = 0, + int begin_x = 0, + const T* p_UserData = (T*)0) + : NCursesMenu(lines,cols,begin_y,begin_x) { + if (menu) + set_user ((void *)p_UserData); + } + +public: + NCursesUserMenu (NCursesMenuItem Items[], + const T* p_UserData = (T*)0, + bool with_frame=FALSE, + bool autoDelete_Items=FALSE) + : NCursesMenu (Items, with_frame, autoDelete_Items) { + if (menu) + set_user ((void *)p_UserData); + }; + + NCursesUserMenu (NCursesMenuItem Items[], + int lines, + int cols, + int begin_y = 0, + int begin_x = 0, + const T* p_UserData = (T*)0, + bool with_frame=FALSE) + : NCursesMenu (Items, lines, cols, begin_y, begin_x, with_frame) { + if (menu) + set_user ((void *)p_UserData); + }; + + virtual ~NCursesUserMenu() { + }; + + inline T* UserData (void) const { + return (T*)get_user (); + }; + + inline virtual void setUserData (const T* p_UserData) { + if (menu) + set_user ((void *)p_UserData); + } +}; + +#endif // _CURSESM_H diff --git a/lib/libcurses++/cursesmain.cc b/lib/libcurses++/cursesmain.cc new file mode 100644 index 00000000000..d3cb692c8bf --- /dev/null +++ b/lib/libcurses++/cursesmain.cc @@ -0,0 +1,51 @@ +// * 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 "cursesapp.h" +#include "internal.h" + +MODULE_ID("$Id: cursesmain.cc,v 1.1 1999/05/09 00:21:14 millert Exp $") + +/* This is the default implementation of main() for a NCursesApplication. + * You only have to instantiate a static NCursesApplication object in your + * main application source file and link this module with your application. + */ +int main(int argc, char* argv[]) +{ + NCursesApplication* A = NCursesApplication::getApplication(); + if (!A) + return(1); + A->handleArgs(argc,argv); + ::endwin(); + return((*A)()); +} diff --git a/lib/libcurses++/cursesp.cc b/lib/libcurses++/cursesp.cc new file mode 100644 index 00000000000..46314f0df79 --- /dev/null +++ b/lib/libcurses++/cursesp.cc @@ -0,0 +1,123 @@ +// * 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> 1993,1997 * + ****************************************************************************/ + +#include "cursesp.h" +#include "internal.h" + +MODULE_ID("$Id: cursesp.cc,v 1.1 1999/05/09 00:21:14 millert Exp $") + +NCursesPanel* NCursesPanel::dummy = (NCursesPanel*)0; + +void NCursesPanel::init() { + p = ::new_panel(w); + if (!p) + OnError(ERR); + + UserHook* hook = new UserHook; + hook->m_user = NULL; + hook->m_back = this; + hook->m_owner = p; + ::set_panel_userptr(p, (void *)hook); +} + +NCursesPanel::~NCursesPanel() { + UserHook* hook = (UserHook*)::panel_userptr(p); + assert(hook && hook->m_back==this && hook->m_owner==p); + delete hook; + ::del_panel(p); + ::update_panels(); +} + +void +NCursesPanel::redraw() { + PANEL *pan; + + pan = ::panel_above(NULL); + while (pan) { + ::touchwin(panel_window(pan)); + pan = ::panel_above(pan); + } + ::update_panels(); + ::doupdate(); +} + +int +NCursesPanel::refresh() { + ::update_panels(); + return doupdate(); +} + +int +NCursesPanel::noutrefresh() { + ::update_panels(); + return OK; +} + +void +NCursesPanel::boldframe(const char *title, const char* btitle) { + standout(); + frame(title, btitle); + standend(); +} + +void +NCursesPanel::frame(const char *title,const char *btitle) { + int err = OK; + if (!title && !btitle) { + err = box(); + } + else { + err = box(); + if (err==OK) + label(title,btitle); + } + OnError(err); +} + +void +NCursesPanel::label(const char *tLabel, const char *bLabel) { + if (tLabel) + centertext(0,tLabel); + if (bLabel) + centertext(maxy(),bLabel); +} + +void +NCursesPanel::centertext(int row,const char *label) { + if (label) { + int x = (maxx() - strlen(label)) / 2; + if (x<0) + x=0; + OnError(addstr(row, x, label, width())); + } +} diff --git a/lib/libcurses++/cursesp.h b/lib/libcurses++/cursesp.h new file mode 100644 index 00000000000..3ea4bf87a35 --- /dev/null +++ b/lib/libcurses++/cursesp.h @@ -0,0 +1,186 @@ +// * This makes emacs happy -*-Mode: C++;-*- +#ifndef _CURSESP_H +#define _CURSESP_H + +// $Id: cursesp.h,v 1.1 1999/05/09 00:21:15 millert Exp $ + +#include <cursesw.h> + +extern "C" { +# include <panel.h> +} + +class NCursesPanel : public NCursesWindow { +protected: + PANEL *p; + static NCursesPanel *dummy; + +private: + // This structure is used for the panel's user data field to link the + // PANEL* to the C++ object and to provide extra space for a user pointer. + typedef struct { + void* m_user; // the pointer for the user's data + const NCursesPanel* m_back; // backward pointer to C++ object + const PANEL* m_owner; // the panel itself + } UserHook; + + void init(); // Initialize the panel object + +protected: + void set_user(void *user) { + UserHook* uptr = (UserHook*)::panel_userptr (p); + assert (uptr && uptr->m_back==this && uptr->m_owner==p); + uptr->m_user = user; + } + // Set the user pointer of the panel. + + void *get_user() { + UserHook* uptr = (UserHook*)::panel_userptr (p); + assert (uptr && uptr->m_back==this && uptr->m_owner==p); + return uptr->m_user; + } + + void OnError (int err) const THROWS((NCursesPanelException)) { + if (err==ERR) + THROW(new NCursesPanelException (this, err)); + } + // If err is equal to the curses error indicator ERR, an error handler + // is called. + +public: + NCursesPanel(int lines, + int cols, + int begin_y = 0, + int begin_x = 0) + : NCursesWindow(lines,cols,begin_y,begin_x) { + init(); + } + // Create a panel with this size starting at the requested position. + + NCursesPanel() : NCursesWindow(::stdscr) { init(); } + // This constructor creates the default Panel associated with the + // ::stdscr window + + virtual ~NCursesPanel(); + + // basic manipulation + inline void hide() { + OnError (::hide_panel(p)); + } + // Hide the panel. It stays in the stack but becomes invisible. + + inline void show() { + OnError (::show_panel(p)); + } + // Show the panel, i.e. make it visible. + + inline void top() { + OnError (::top_panel(p)); + } + // Make this panel the top panel in the stack. + + inline void bottom() { + OnError (::bottom_panel(p)); + } + // Make this panel the bottom panel in the stack. + // N.B.: The panel associated with ::stdscr is always on the bottom. So + // actually bottom() makes the panel the first above ::stdscr. + + inline int mvwin(int y, int x) { + OnError(::move_panel(p, y, x)); + return OK; + } + + inline bool hidden() const { + return (::panel_hidden (p) ? TRUE : FALSE); + } + // Return TRUE if the panel is hidden, FALSE otherwise. + +/* The functions panel_above() and panel_below() are not reflected in + the NCursesPanel class. The reason for this is, that we cannot + assume that a panel retrieved by those operations is one wrapped + by a C++ class. Although this situation might be handled, we also + need a reverse mapping from PANEL to NCursesPanel which needs some + redesign of the low level stuff. At the moment, we define them in the + interface but they will always produce an error. */ + inline NCursesPanel& above() const { + OnError(ERR); + return *dummy; + } + + inline NCursesPanel& below() const { + OnError(ERR); + return *dummy; + } + + // Those two are rewrites of the corresponding virtual members of + // NCursesWindow + int refresh(); + // Propagate all panel changes to the virtual screen and update the + // physical screen. + + int noutrefresh(); + // Propagate all panel changes to the virtual screen. + + static void redraw(); + // Redraw all panels. + + // decorations + virtual void frame(const char* title=NULL, + const char* btitle=NULL); + // Put a frame around the panel and put the title centered in the top line + // and btitle in the bottom line. + + virtual void boldframe(const char* title=NULL, + const char* btitle=NULL); + // Same as frame(), but use highlighted attributes. + + virtual void label(const char* topLabel, + const char* bottomLabel); + // Put the title centered in the top line and btitle in the bottom line. + + virtual void centertext(int row,const char* label); + // Put the label text centered in the specified row. +}; + +/* We use templates to provide a typesafe mechanism to associate + * user data with a panel. A NCursesUserPanel<T> is a panel + * associated with some user data of type T. + */ +template<class T> class NCursesUserPanel : public NCursesPanel +{ +public: + NCursesUserPanel (int lines, + int cols, + int begin_y = 0, + int begin_x = 0, + const T* p_UserData = (T*)0) + : NCursesPanel (lines, cols, begin_y, begin_x) { + if (p) + set_user ((void *)p_UserData); + }; + // This creates an user panel of the requested size with associated + // user data pointed to by p_UserData. + + NCursesUserPanel(const T* p_UserData = (T*)0) : NCursesPanel() { + if (p) + set_user((void *)p_UserData); + }; + // This creates an user panel associated with the ::stdscr and user data + // pointed to by p_UserData. + + virtual ~NCursesUserPanel() {}; + + T* UserData (void) const { + return (T*)get_user (); + }; + // Retrieve the user data associated with the panel. + + virtual void setUserData (const T* p_UserData) { + if (p) + set_user ((void *)p_UserData); + } + // Associate the user panel with the user data pointed to by p_UserData. +}; + +#endif // _CURSESP_H diff --git a/lib/libcurses++/cursesw.cc b/lib/libcurses++/cursesw.cc new file mode 100644 index 00000000000..9fc64b64cbd --- /dev/null +++ b/lib/libcurses++/cursesw.cc @@ -0,0 +1,420 @@ +// * this is for making emacs happy: -*-Mode: C++;-*- + +/* + Copyright (C) 1989 Free Software Foundation + written by Eric Newton (newton@rocky.oswego.edu) + + This file is part of the GNU C++ Library. This library is free + software; you can redistribute it and/or modify it under the terms of + the GNU Library General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. This library is distributed in the hope + that it will be useful, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the GNU Library General Public License for more details. + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + modified by Ulrich Drepper (drepper@karlsruhe.gmd.de) + and Anatoly Ivasyuk (anatoly@nick.csh.rit.edu) + + modified by Juergen Pfeifer (Juergen.Pfeifer@T-Online.de) +*/ + +#include "cursesw.h" +#include "internal.h" + +MODULE_ID("$Id: cursesw.cc,v 1.1 1999/05/09 00:21:15 millert Exp $") + +#define COLORS_NEED_INITIALIZATION -1 +#define COLORS_NOT_INITIALIZED 0 +#define COLORS_MONOCHROME 1 +#define COLORS_ARE_REALLY_THERE 2 + +// declare static variables for the class +long NCursesWindow::count = 0L; +bool NCursesWindow::b_initialized = FALSE; + +#if defined(__GNUG__) +# ifndef _IO_va_list +# define _IO_va_list char * +# endif +#endif + +int +NCursesWindow::scanw(const char* fmt, ...) +{ +#if defined(__GNUG__) + va_list args; + va_start(args, fmt); + char buf[BUFSIZ]; + int result = wgetstr(w, buf); + if (result == OK) { + strstreambuf ss(buf, BUFSIZ); + result = ss.vscan(fmt, (_IO_va_list)args); + } + va_end(args); + return result; +#else + return ERR; +#endif +} + + +int +NCursesWindow::scanw(int y, int x, const char* fmt, ...) +{ +#if defined(__GNUG__) + va_list args; + va_start(args, fmt); + char buf[BUFSIZ]; + int result = wmove(w, y, x); + if (result == OK) { + result = wgetstr(w, buf); + if (result == OK) { + strstreambuf ss(buf, BUFSIZ); + result = ss.vscan(fmt, (_IO_va_list)args); + } + } + va_end(args); + return result; +#else + return ERR; +#endif +} + + +int +NCursesWindow::printw(const char * fmt, ...) +{ + va_list args; + va_start(args, fmt); + char buf[BUFSIZ]; + vsprintf(buf, fmt, args); + va_end(args); + return waddstr(w, buf); +} + + +int +NCursesWindow::printw(int y, int x, const char * fmt, ...) +{ + va_list args; + va_start(args, fmt); + int result = wmove(w, y, x); + if (result == OK) { + char buf[BUFSIZ]; + vsprintf(buf, fmt, args); + result = waddstr(w, buf); + } + va_end(args); + return result; +} + + +void +NCursesWindow::init(void) +{ + leaveok(0); + keypad(1); + meta(1); +} + +void +NCursesWindow::err_handler(const char *msg) const THROWS(NCursesException) +{ + THROW(new NCursesException(msg)); +} + +void +NCursesWindow::initialize() { + if (!b_initialized) { + ::initscr(); + b_initialized = TRUE; + if (colorInitialized==COLORS_NEED_INITIALIZATION) { + colorInitialized=COLORS_NOT_INITIALIZED; + useColors(); + } + ::noecho(); + ::cbreak(); + } +} + +NCursesWindow::NCursesWindow() { + if (!b_initialized) + initialize(); + + w = (WINDOW *)0; + init(); + alloced = FALSE; + subwins = par = sib = 0; + count++; +} + +NCursesWindow::NCursesWindow(int lines, int cols, int begin_y, int begin_x) +{ + if (!b_initialized) + initialize(); + + w = ::newwin(lines, cols, begin_y, begin_x); + if (w == 0) { + err_handler("Cannot construct window"); + } + init(); + + alloced = TRUE; + subwins = par = sib = 0; + count++; +} + +NCursesWindow::NCursesWindow(WINDOW* &window) +{ + if (!b_initialized) + initialize(); + + w = window; + init(); + alloced = FALSE; + subwins = par = sib = 0; + count++; +} + +NCursesWindow::NCursesWindow(NCursesWindow& win, int l, int c, + int begin_y, int begin_x, char absrel) +{ + if (absrel == 'a') { // absolute origin + begin_y -= win.begy(); + begin_x -= win.begx(); + } + + // Even though we treat subwindows as a tree, the standard curses + // library needs the `subwin' call to link to the parent in + // order to correctly perform refreshes, etc. + // Friendly enough, this also works for pads. + w = ::derwin(win.w, l, c, begin_y, begin_x); + if (w == 0) { + err_handler("Cannot construct subwindow"); + } + + par = &win; + sib = win.subwins; + win.subwins = this; + subwins = 0; + alloced = TRUE; + count++; +} + +NCursesWindow NCursesWindow::Clone() { + WINDOW *d = ::dupwin(w); + NCursesWindow W(d); + W.subwins = subwins; + W.sib = sib; + W.par = par; + W.alloced = alloced; + return W; +} + +typedef int (*RIPOFFINIT)(NCursesWindow&); +static RIPOFFINIT R_INIT[5]; // There can't be more +static int r_init_idx = 0; +static RIPOFFINIT* prip = R_INIT; + +extern "C" int _nc_ripoffline(int,int (*init)(WINDOW*,int)); + +NCursesWindow::NCursesWindow(WINDOW *win, int cols) { + w = win; + assert((w->_maxx+1)==cols); + alloced = FALSE; + subwins = par = sib = 0; +} + +int NCursesWindow::ripoff_init(WINDOW *w, int cols) +{ + int res = ERR; + + RIPOFFINIT init = *prip++; + if (init) { + NCursesWindow* W = new NCursesWindow(w,cols); + res = init(*W); + } + return res; +} + +int NCursesWindow::ripoffline(int ripoff_lines, + int (*init)(NCursesWindow& win)) { + int code = ::_nc_ripoffline(ripoff_lines,ripoff_init); + if (code==OK && init && ripoff_lines) { + R_INIT[r_init_idx++] = init; + } + return code; +} + +bool +NCursesWindow::isDescendant(NCursesWindow& win) { + for (NCursesWindow* p = subwins; p != NULL; p = p->sib) { + if (p==&win) + return TRUE; + else { + if (p->isDescendant(win)) + return TRUE; + } + } + return FALSE; +} + +void +NCursesWindow::kill_subwindows() +{ + for (NCursesWindow* p = subwins; p != 0; p = p->sib) { + p->kill_subwindows(); + if (p->alloced) { + if (p->w != 0) + ::delwin(p->w); + p->alloced = FALSE; + } + p->w = 0; // cause a run-time error if anyone attempts to use... + } +} + + +NCursesWindow::~NCursesWindow() +{ + kill_subwindows(); + + if (par != 0) { // Snip us from the parent's list of subwindows. + NCursesWindow * win = par->subwins; + NCursesWindow * trail = 0; + for (;;) { + if (win == 0) + break; + else if (win == this) { + if (trail != 0) + trail->sib = win->sib; + else + par->subwins = win->sib; + break; + } else { + trail = win; + win = win->sib; + } + } + } + + if (alloced && w != 0) + delwin(w); + + if (alloced) { + --count; + if (count == 0) { + ::endwin(); + } + else if (count < 0) { // cannot happen! + err_handler("Too many windows destroyed"); + } + } +} + +// --------------------------------------------------------------------- +// Color stuff +// +int NCursesWindow::colorInitialized = COLORS_NOT_INITIALIZED; + +void +NCursesWindow::useColors(void) +{ + if (colorInitialized == COLORS_NOT_INITIALIZED) { + if (b_initialized) { + if (::has_colors()) { + ::start_color(); + colorInitialized = COLORS_ARE_REALLY_THERE; + } + else + colorInitialized = COLORS_MONOCHROME; + } + else + colorInitialized = COLORS_NEED_INITIALIZATION; + } +} + +short +NCursesWindow::getcolor(int getback) const +{ + short fore, back; + + if (colorInitialized==COLORS_ARE_REALLY_THERE) { + if (pair_content(PAIR_NUMBER(w->_attrs), &fore, &back)) + err_handler("Can't get color pair"); + } + else { + // Monochrome means white on black + back = COLOR_BLACK; + fore = COLOR_WHITE; + } + return getback ? back : fore; +} + +int NCursesWindow::NumberOfColors() +{ + if (colorInitialized==COLORS_ARE_REALLY_THERE) + return COLORS; + else + return 1; // monochrome (actually there are two ;-) +} + +short +NCursesWindow::getcolor() const +{ + if (colorInitialized==COLORS_ARE_REALLY_THERE) + return PAIR_NUMBER(w->_attrs); + else + return 0; // we only have pair zero +} + +int +NCursesWindow::setpalette(short fore, short back, short pair) +{ + if (colorInitialized==COLORS_ARE_REALLY_THERE) + return init_pair(pair, fore, back); + else + return OK; +} + +int +NCursesWindow::setpalette(short fore, short back) +{ + if (colorInitialized==COLORS_ARE_REALLY_THERE) + return setpalette(fore, back, PAIR_NUMBER(w->_attrs)); + else + return OK; +} + + +int +NCursesWindow::setcolor(short pair) +{ + if (colorInitialized==COLORS_ARE_REALLY_THERE) { + if ((pair < 1) || (pair > COLOR_PAIRS)) + err_handler("Can't set color pair"); + + attroff(A_COLOR); + attrset(COLOR_PAIR(pair)); + } + return OK; +} + +extern "C" int _nc_has_mouse(void); + +bool NCursesWindow::has_mouse() const { + return ((::has_key(KEY_MOUSE) || ::_nc_has_mouse()) + ? TRUE : FALSE); +} + +NCursesPad::NCursesPad(int lines, int cols) : NCursesWindow() { + w = ::newpad(lines,cols); + if (w==(WINDOW*)0) { + count--; + err_handler("Cannot construct window"); + } + alloced = TRUE; +} diff --git a/lib/libcurses++/cursesw.h b/lib/libcurses++/cursesw.h new file mode 100644 index 00000000000..830416dd373 --- /dev/null +++ b/lib/libcurses++/cursesw.h @@ -0,0 +1,1262 @@ +// * This makes emacs happy -*-Mode: C++;-*- +#ifndef _CURSESW_H +#define _CURSESW_H + +// $Id: cursesw.h,v 1.1 1999/05/09 00:21:15 millert Exp $ + +#include <etip.h> +#include <stdio.h> +#include <stdarg.h> +#ifdef __MWERKS__ +/* This is a bogus check, stringstream is actually ANSI C++ standard, + * but old compilers like GCC don't have it, and new compilers like Metrowerks + * don't have strstream + */ +#include <sstream> +#else +#include <strstream.h> +#endif + +extern "C" { +# include <curses.h> +} + +/* SCO 3.2v4 curses.h includes term.h, which defines lines as a macro. + Undefine it here, because NCursesWindow uses lines as a method. */ +#undef lines + +/* "Convert" macros to inlines. We'll define it as another symbol to avoid + * conflict with library symbols. + */ +#undef UNDEF +#define UNDEF(name) CUR_ ##name + +#ifdef addch +inline int UNDEF(addch)(chtype ch) { return addch(ch); } +#undef addch +#define addch UNDEF(addch) +#endif + +#ifdef echochar +inline int UNDEF(echochar)(chtype ch) { return echochar(ch); } +#undef echochar +#define echochar UNDEF(echochar) +#endif + +#ifdef insdelln +inline int UNDEF(insdelln)(int n) { return insdelln(n); } +#undef insdelln +#define insdelln UNDEF(insdelln) +#endif + +#ifdef addstr +/* The (char*) cast is to hack around missing const's */ +inline int UNDEF(addstr)(const char * str) { return addstr((char*)str); } +#undef addstr +#define addstr UNDEF(addstr) +#endif + +#ifdef attron +inline int UNDEF(attron)(chtype at) { return attron(at); } +#undef attron +#define attron UNDEF(attron) +#endif + +#ifdef attroff +inline int UNDEF(attroff)(chtype at) { return attroff(at); } +#undef attroff +#define attroff UNDEF(attroff) +#endif + +#ifdef attrset +inline chtype UNDEF(attrset)(chtype at) { return attrset(at); } +#undef attrset +#define attrset UNDEF(attrset) +#endif + +#ifdef color_set +inline chtype UNDEF(color_set)(short p,void* opts) { return color_set(p,opts); } +#undef color_set +#define color_set UNDEF(color_set) +#endif + +#ifdef border +inline int UNDEF(border)(chtype ls, chtype rs, chtype ts, chtype bs, chtype tl, chtype tr, chtype bl, chtype br) +{ return border(ls,rs,ts,bs,tl,tr,bl,br); } +#undef border +#define border UNDEF(border) +#endif + +#ifdef box +inline int UNDEF(box)(WINDOW *win, int v, int h) { return box(win, v, h); } +#undef box +#define box UNDEF(box) +#endif + +#ifdef mvwhline +inline int UNDEF(mvwhline)(WINDOW *win,int y,int x,chtype c,int n) { + return mvwhline(win,y,x,c,n); } +#undef mvwhline +#define mvwhline UNDEF(mvwhline) +#endif + +#ifdef mvwvline +inline int UNDEF(mvwvline)(WINDOW *win,int y,int x,chtype c,int n) { + return mvwvline(win,y,x,c,n); } +#undef mvwvline +#define mvwvline UNDEF(mvwvline) +#endif + +#ifdef clear +inline int UNDEF(clear)() { return clear(); } +#undef clear +#define clear UNDEF(clear) +#endif + +#ifdef clearok +inline int UNDEF(clearok)(WINDOW* win, bool bf) { return clearok(win, bf); } +#undef clearok +#define clearok UNDEF(clearok) +#else +extern "C" int clearok(WINDOW*, bool); +#endif + +#ifdef clrtobot +inline int UNDEF(clrtobot)() { return clrtobot(); } +#undef clrtobot +#define clrtobot UNDEF(clrtobot) +#endif + +#ifdef clrtoeol +inline int UNDEF(clrtoeol)() { return clrtoeol(); } +#undef clrtoeol +#define clrtoeol UNDEF(clrtoeol) +#endif + +#ifdef delch +inline int UNDEF(delch)() { return delch(); } +#undef delch +#define delch UNDEF(delch) +#endif + +#ifdef deleteln +inline int UNDEF(deleteln)() { return deleteln(); } +#undef deleteln +#define deleteln UNDEF(deleteln) +#endif + +#ifdef erase +inline int UNDEF(erase)() { return erase(); } +#undef erase +#define erase UNDEF(erase) +#endif + +#ifdef flushok +inline int UNDEF(flushok)(WINDOW* _win, bool _bf) { + return flushok(_win, _bf); } +#undef flushok +#define flushok UNDEF(flushok) +#else +#define _no_flushok +#endif + +#ifdef getch +inline int UNDEF(getch)() { return getch(); } +#undef getch +#define getch UNDEF(getch) +#endif + +#ifdef getstr +inline int UNDEF(getstr)(char *_str) { return getstr(_str); } +#undef getstr +#define getstr UNDEF(getstr) +#endif + +#ifdef instr +inline int UNDEF(instr)(char *_str) { return instr(_str); } +#undef instr +#define instr UNDEF(instr) +#endif + +#ifdef innstr +inline int UNDEF(innstr)(char *_str, int n) { return innstr(_str,n); } +#undef innstr +#define innstr UNDEF(innstr) +#endif + +#ifdef mvwinnstr +inline int UNDEF(mvwinnstr)(WINDOW *win, int y, int x, char *_str, int n) { + return mvwinnstr(win,y,x,_str,n); } +#undef mvwinnstr +#define mvwinnstr UNDEF(mvwinnstr) +#endif + +#ifdef mvinnstr +inline int UNDEF(mvinnstr)(int y, int x, char *_str, int n) { + return mvinnstr(y,x,_str,n); } +#undef mvinnstr +#define mvinnstr UNDEF(mvinnstr) +#endif + +#ifdef winsstr +inline int UNDEF(winsstr)(WINDOW *w, const char *_str) { + return winsstr(w,_str); } +#undef winsstr +#define winsstr UNDEF(winsstr) +#endif + +#ifdef mvwinsstr +inline int UNDEF(mvwinsstr)(WINDOW *w, int y, int x, const char *_str) { + return mvwinsstr(w,y,x,_str); } +#undef mvwinsstr +#define mvwinsstr UNDEF(mvwinsstr) +#endif + +#ifdef insstr +inline int UNDEF(insstr)(const char *_str) { + return insstr(_str); } +#undef insstr +#define insstr UNDEF(insstr) +#endif + +#ifdef mvinsstr +inline int UNDEF(mvinsstr)(int y, int x,const char *_str) { + return mvinsstr(y,x,_str); } +#undef mvinsstr +#define mvinsstr UNDEF(mvinsstr) +#endif + +#ifdef insnstr +inline int UNDEF(insnstr)(const char *_str, int n) { + return insnstr(_str,n); } +#undef insnstr +#define insnstr UNDEF(insnstr) +#endif + +#ifdef mvwinsnstr +inline int UNDEF(mvwinsnstr)(WINDOW *w, int y, int x,const char *_str, int n) { + return mvwinsnstr(w,y,x,_str,n); } +#undef mvwinsnstr +#define mvwinsnstr UNDEF(mvwinsnstr) +#endif + +#ifdef mvinsnstr +inline int UNDEF(mvinsnstr)(int y, int x,const char *_str, int n) { + return mvinsnstr(y,x,_str,n); } +#undef mvinsnstr +#define mvinsnstr UNDEF(mvinsnstr) +#endif + +#ifdef getnstr +inline int UNDEF(getnstr)(char *_str, int n) { return getnstr(_str,n); } +#undef getnstr +#define getnstr UNDEF(getnstr) +#endif + +#ifdef getyx +inline void UNDEF(getyx)(const WINDOW* win, int& y, int& x) { + getyx(win, y, x); } +#undef getyx +#define getyx UNDEF(getyx) +#endif + +#ifdef getbegyx +inline void UNDEF(getbegyx)(WINDOW* win, int& y, int& x) { getbegyx(win, y, x); } +#undef getbegyx +#define getbegyx UNDEF(getbegyx) +#endif + +#ifdef getmaxyx +inline void UNDEF(getmaxyx)(WINDOW* win, int& y, int& x) { getmaxyx(win, y, x); } +#undef getmaxyx +#define getmaxyx UNDEF(getmaxyx) +#endif + +#ifdef hline +inline int UNDEF(hline)(chtype ch, int n) { return hline(ch, n); } +#undef hline +#define hline UNDEF(hline) +#endif + +#ifdef inch +inline chtype UNDEF(inch)() { return inch(); } +#undef inch +#define inch UNDEF(inch) +#endif + +#ifdef insch +inline int UNDEF(insch)(char c) { return insch(c); } +#undef insch +#define insch UNDEF(insch) +#endif + +#ifdef insertln +inline int UNDEF(insertln)() { return insertln(); } +#undef insertln +#define insertln UNDEF(insertln) +#endif + +#ifdef leaveok +inline int UNDEF(leaveok)(WINDOW* win, bool bf) { return leaveok(win, bf); } +#undef leaveok +#define leaveok UNDEF(leaveok) +#else +extern "C" int leaveok(WINDOW* win, bool bf); +#endif + +#ifdef move +inline int UNDEF(move)(int x, int y) { return move(x, y); } +#undef move +#define move UNDEF(move) +#endif + +#ifdef refresh +inline int UNDEF(refresh)() { return refresh(); } +#undef refresh +#define refresh UNDEF(refresh) +#endif + +#ifdef redrawwin +inline int UNDEF(redrawwin)(WINDOW *win) { return redrawwin(win); } +#undef redrawwin +#define redrawwin UNDEF(redrawwin) +#endif + +#ifdef scrl +inline int UNDEF(scrl)(int l) { return scrl(l); } +#undef scrl +#define scrl UNDEF(scrl) +#endif + +#ifdef scroll +inline int UNDEF(scroll)(WINDOW *win) { return scroll(win); } +#undef scroll +#define scroll UNDEF(scroll) +#endif + +#ifdef scrollok +inline int UNDEF(scrollok)(WINDOW* win, bool bf) { return scrollok(win, bf); } +#undef scrollok +#define scrollok UNDEF(scrollok) +#else +#if defined(__NCURSES_H) +extern "C" int scrollok(WINDOW*, bool); +#else +extern "C" int scrollok(WINDOW*, char); +#endif +#endif + +#ifdef setscrreg +inline int UNDEF(setscrreg)(int t, int b) { return setscrreg(t, b); } +#undef setscrreg +#define setscrreg UNDEF(setscrreg) +#endif + +#ifdef standend +inline int UNDEF(standend)() { return standend(); } +#undef standend +#define standend UNDEF(standend) +#endif + +#ifdef standout +inline int UNDEF(standout)() { return standout(); } +#undef standout +#define standout UNDEF(standout) +#endif + +#ifdef subpad +inline WINDOW *UNDEF(subpad)(WINDOW *p, int l, int c, int y, int x) +{ return derwin(p,l,c,y,x); } +#undef subpad +#define subpad UNDEF(subpad) +#endif + +#ifdef timeout +inline void UNDEF(timeout)(int delay) { timeout(delay); } +#undef timeout +#define timeout UNDEF(timeout) +#endif + +#ifdef touchline +inline int UNDEF(touchline)(WINDOW *win, int s, int c) +{ return touchline(win,s,c); } +#undef touchline +#define touchline UNDEF(touchline) +#endif + +#ifdef touchwin +inline int UNDEF(touchwin)(WINDOW *win) { return touchwin(win); } +#undef touchwin +#define touchwin UNDEF(touchwin) +#endif + +#ifdef untouchwin +inline int UNDEF(untouchwin)(WINDOW *win) { return untouchwin(win); } +#undef untouchwin +#define untouchwin UNDEF(untouchwin) +#endif + +#ifdef vline +inline int UNDEF(vline)(chtype ch, int n) { return vline(ch, n); } +#undef vline +#define vline UNDEF(vline) +#endif + +#ifdef waddstr +inline int UNDEF(waddstr)(WINDOW *win, char *str) { return waddstr(win, str); } +#undef waddstr +#define waddstr UNDEF(waddstr) +#endif + +#ifdef waddchstr +inline int UNDEF(waddchstr)(WINDOW *win, chtype *at) { return waddchstr(win, at); } +#undef waddchstr +#define waddchstr UNDEF(waddchstr) +#endif + +#ifdef wstandend +inline int UNDEF(wstandend)(WINDOW *win) { return wstandend(win); } +#undef wstandend +#define wstandend UNDEF(wstandend) +#endif + +#ifdef wstandout +inline int UNDEF(wstandout)(WINDOW *win) { return wstandout(win); } +#undef wstandout +#define wstandout UNDEF(wstandout) +#endif + + +#ifdef wattroff +inline int UNDEF(wattroff)(WINDOW *win, int att) { return wattroff(win, att); } +#undef wattroff +#define wattroff UNDEF(wattroff) +#endif + +#ifdef chgat +inline int UNDEF(chgat)(int n,attr_t attr, short color, const void *opts) { + return chgat(n,attr,color,opts); } +#undef chgat +#define chgat UNDEF(chgat) +#endif + +#ifdef mvchgat +inline int UNDEF(mvchgat)(int y, int x, int n, + attr_t attr, short color, const void *opts) { + return mvchgat(y,x,n,attr,color,opts); } +#undef mvchgat +#define mvchgat UNDEF(mvchgat) +#endif + +#ifdef mvwchgat +inline int UNDEF(mvwchgat)(WINDOW *win, int y, int x, int n, + attr_t attr, short color, const void *opts) { + return mvwchgat(win,y,x,n,attr,color,opts); } +#undef mvwchgat +#define mvwchgat UNDEF(mvwchgat) +#endif + +#ifdef wattrset +inline int UNDEF(wattrset)(WINDOW *win, int att) { return wattrset(win, att); } +#undef wattrset +#define wattrset UNDEF(wattrset) +#endif + +#ifdef winch +inline chtype UNDEF(winch)(const WINDOW* win) { return winch(win); } +#undef winch +#define winch UNDEF(winch) +#endif + +#ifdef mvwaddch +inline int UNDEF(mvwaddch)(WINDOW *win, int y, int x, const chtype ch) +{ return mvwaddch(win, y, x, ch); } +#undef mvwaddch +#define mvwaddch UNDEF(mvwaddch) +#endif + +#ifdef mvwaddchnstr +inline int UNDEF(mvwaddchnstr)(WINDOW *win, int y, int x, chtype *str, int n) +{ return mvwaddchnstr(win, y, x, str, n); } +#undef mvwaddchnstr +#define mvwaddchnstr UNDEF(mvwaddchnstr) +#endif + +#ifdef mvwaddchstr +inline int UNDEF(mvwaddchstr)(WINDOW *win, int y, int x, chtype *str) +{ return mvwaddchstr(win, y, x, str); } +#undef mvwaddchstr +#define mvwaddchstr UNDEF(mvwaddchstr) +#endif + +#ifdef addnstr +inline int UNDEF(addnstr)(const char *str, int n) +{ return addnstr((char*)str, n); } +#undef addnstr +#define addnstr UNDEF(addnstr) +#endif + +#ifdef mvwaddnstr +inline int UNDEF(mvwaddnstr)(WINDOW *win, int y, int x, const char *str, int n) +{ return mvwaddnstr(win, y, x, (char*)str, n); } +#undef mvwaddnstr +#define mvwaddnstr UNDEF(mvwaddnstr) +#endif + +#ifdef mvwaddstr +inline int UNDEF(mvwaddstr)(WINDOW *win, int y, int x, const char * str) +{ return mvwaddstr(win, y, x, (char*)str); } +#undef mvwaddstr +#define mvwaddstr UNDEF(mvwaddstr) +#endif + +#ifdef mvwdelch +inline int UNDEF(mvwdelch)(WINDOW *win, int y, int x) +{ return mvwdelch(win, y, x); } +#undef mvwdelch +#define mvwdelch UNDEF(mvwdelch) +#endif + +#ifdef mvwgetch +inline int UNDEF(mvwgetch)(WINDOW *win, int y, int x) { return mvwgetch(win, y, x);} +#undef mvwgetch +#define mvwgetch UNDEF(mvwgetch) +#endif + +#ifdef mvwgetstr +inline int UNDEF(mvwgetstr)(WINDOW *win, int y, int x, char *str) +{return mvwgetstr(win,y,x, str);} +#undef mvwgetstr +#define mvwgetstr UNDEF(mvwgetstr) +#endif + +#ifdef mvwgetnstr +inline int UNDEF(mvwgetnstr)(WINDOW *win, int y, int x, char *str, int n) +{return mvwgetnstr(win,y,x, str,n);} +#undef mvwgetnstr +#define mvwgetnstr UNDEF(mvwgetnstr) +#endif + +#ifdef mvwinch +inline chtype UNDEF(mvwinch)(WINDOW *win, int y, int x) { + return mvwinch(win, y, x);} +#undef mvwinch +#define mvwinch UNDEF(mvwinch) +#endif + +#ifdef mvwinsch +inline int UNDEF(mvwinsch)(WINDOW *win, int y, int x, char c) +{ return mvwinsch(win, y, x, c); } +#undef mvwinsch +#define mvwinsch UNDEF(mvwinsch) +#endif + +#ifdef mvaddch +inline int UNDEF(mvaddch)(int y, int x, chtype ch) +{ return mvaddch(y, x, ch); } +#undef mvaddch +#define mvaddch UNDEF(mvaddch) +#endif + +#ifdef mvaddnstr +inline int UNDEF(mvaddnstr)(int y, int x, const char *str, int n) +{ return mvaddnstr(y, x, (char*)str, n); } +#undef mvaddnstr +#define mvaddnstr UNDEF(mvaddnstr) +#endif + +#ifdef mvaddstr +inline int UNDEF(mvaddstr)(int y, int x, const char * str) +{ return mvaddstr(y, x, (char*)str); } +#undef mvaddstr +#define mvaddstr UNDEF(mvaddstr) +#endif + +#ifdef mvdelch +inline int UNDEF(mvdelch)(int y, int x) { return mvdelch(y, x);} +#undef mvdelch +#define mvdelch UNDEF(mvdelch) +#endif + +#ifdef mvgetch +inline int UNDEF(mvgetch)(int y, int x) { return mvgetch(y, x);} +#undef mvgetch +#define mvgetch UNDEF(mvgetch) +#endif + +#ifdef mvgetstr +inline int UNDEF(mvgetstr)(int y, int x, char *str) {return mvgetstr(y, x, str);} +#undef mvgetstr +#define mvgetstr UNDEF(mvgetstr) +#endif + +#ifdef mvgetnstr +inline int UNDEF(mvgetnstr)(int y, int x, char *str, int n) { + return mvgetnstr(y, x, str,n);} +#undef mvgetnstr +#define mvgetnstr UNDEF(mvgetnstr) +#endif + +#ifdef mvinch +inline chtype UNDEF(mvinch)(int y, int x) { return mvinch(y, x);} +#undef mvinch +#define mvinch UNDEF(mvinch) +#endif + +#ifdef mvinsch +inline int UNDEF(mvinsch)(int y, int x, char c) +{ return mvinsch(y, x, c); } +#undef mvinsch +#define mvinsch UNDEF(mvinsch) +#endif + +#ifdef napms +inline void UNDEF(napms)(unsigned long x) { napms(x); } +#undef napms +#define napms UNDEF(napms) +#endif + +#ifdef fixterm +inline int UNDEF(fixterm)(void) { return fixterm(); } +#undef fixterm +#define fixterm UNDEF(fixterm) +#endif + +#ifdef resetterm +inline int UNDEF(resetterm)(void) { return resetterm(); } +#undef resetterm +#define resetterm UNDEF(resetterm) +#endif + +#ifdef saveterm +inline int UNDEF(saveterm)(void) { return saveterm(); } +#undef saveterm +#define saveterm UNDEF(saveterm) +#endif + +#ifdef crmode +inline int UNDEF(crmode)(void) { return crmode(); } +#undef crmode +#define crmode UNDEF(crmode) +#endif + +#ifdef nocrmode +inline int UNDEF(nocrmode)(void) { return nocrmode(); } +#undef nocrmode +#define nocrmode UNDEF(nocrmode) +#endif + +#ifdef getbkgd +inline chtype UNDEF(getbkgd)(const WINDOW *win) { return getbkgd(win); } +#undef getbkgd +#define getbkgd UNDEF(getbkgd) +#endif + +#ifdef bkgd +inline int UNDEF(bkgd)(chtype ch) { return bkgd(ch); } +#undef bkgd +#define bkgd UNDEF(bkgd) +#endif + +#ifdef bkgdset +inline void UNDEF(bkgdset)(chtype ch) { bkgdset(ch); } +#undef bkgdset +#define bkgdset UNDEF(bkgdset) +#endif + +/* + * + * C++ class for windows. + * + * + */ + +class NCursesWindow +{ + friend class NCursesMenu; + friend class NCursesForm; + +private: + static bool b_initialized; + static void initialize(); + static int ripoff_init(WINDOW *,int); + + void init(); + + short getcolor(int getback) const; + + static int setpalette(short fore, short back, short pair); + static int colorInitialized; + + // This private constructor is only used during the initialization + // of windows generated by ripoffline() calls. + NCursesWindow(WINDOW* win, int cols); + +protected: + void err_handler(const char *) const THROWS(NCursesException); + // Signal an error with the given message text. + + static long count; // count of all active windows: + // We rely on the c++ promise that + // all otherwise uninitialized + // static class vars are set to 0 + + WINDOW* w; // the curses WINDOW + + bool alloced; // TRUE if we own the WINDOW + + NCursesWindow* par; // parent, if subwindow + NCursesWindow* subwins; // head of subwindows list + NCursesWindow* sib; // next subwindow of parent + + void kill_subwindows(); // disable all subwindows + // Destroy all subwindows. + + /* Only for use by derived classes. They are then in charge to + fill the member variables correctly. */ + NCursesWindow(); + +public: + NCursesWindow(WINDOW* &window); // useful only for stdscr + + NCursesWindow(int lines, // number of lines + int cols, // number of columns + int begin_y, // line origin + int begin_x); // col origin + + NCursesWindow(NCursesWindow& par,// parent window + int lines, // number of lines + int cols, // number of columns + int begin_y, // absolute or relative + int begin_x, // origins: + char absrel = 'a');// if `a', by & bx are + // absolute screen pos, else if `r', they are relative to par origin + + virtual ~NCursesWindow(); + + NCursesWindow Clone(); + // Make an exact copy of the window. + + // Initialization. + static void useColors(void); + // Call this routine very early if you want to have colors. + + static int ripoffline(int ripoff_lines, + int (*init)(NCursesWindow& win)); + // This function is used to generate a window of ripped-of lines. + // If the argument is positive, lines are removed from the top, if it + // is negative lines are removed from the bottom. This enhances the + // lowlevel ripoffline() function because it uses the internal + // implementation that allows to remove more than just a single line. + // This function must be called before any other ncurses function. The + // creation of the window is defered until ncurses gets initialized. + // The initialization function is then called. + + // ------------------------------------------------------------------------- + // terminal status + // ------------------------------------------------------------------------- + int lines() const { return LINES; } + // Number of lines on terminal, *not* window + + int cols() const { return COLS; } + // Number of cols on terminal, *not* window + + int tabsize() const { return TABSIZE; } + // Size of a tab on terminal, *not* window + + static int NumberOfColors(); + // Number of available colors + + int colors() const { return NumberOfColors(); } + // Number of available colors + + // ------------------------------------------------------------------------- + // window status + // ------------------------------------------------------------------------- + int height() const { return maxy() + 1; } + // Number of lines in this window + + int width() const { return maxx() + 1; } + // Number of columns in this window + + int begx() const { return w->_begx; } + // Column of top left corner relative to stdscr + + int begy() const { return w->_begy; } + // Line of top left corner relative to stdscr + + int maxx() const { return w->_maxx; } + // Largest x coord in window + + int maxy() const { return w->_maxy; } + // Largest y coord in window + + short getcolor() const; + // Actual color pair + + short foreground() const { return getcolor(0); } + // Actual foreground color + + short background() const { return getcolor(1); } + // Actual background color + + int setpalette(short fore, short back); + // Set color palette entry + + int setcolor(short pair); + // Set actually used palette entry + + // ------------------------------------------------------------------------- + // window positioning + // ------------------------------------------------------------------------- + virtual int mvwin(int begin_y, int begin_x) { + return ::mvwin(w,begin_y,begin_x); } + // Move window to new position with the new position as top left corner. + // This is virtual because it is redefined in NCursesPanel. + + // ------------------------------------------------------------------------- + // coordinate positioning + // ------------------------------------------------------------------------- + int move(int y, int x) { return ::wmove(w, y, x); } + // Move cursor the this position + + void getyx(int& y, int& x) const { ::getyx(w, y, x); } + // Get current position of the cursor + + int mvcur(int oldrow, int oldcol, int newrow, int newcol) const { + return ::mvcur(oldrow, oldcol, newrow, newcol); } + // Perform lowlevel cursor motion that takes effect immediately. + + // ------------------------------------------------------------------------- + // input + // ------------------------------------------------------------------------- + int getch() { return ::wgetch(w); } + // Get a keystroke from the window. + + int getch(int y, int x) { return ::mvwgetch(w,y,x); } + // Move cursor to position and get a keystroke from the window + + int getstr(char* str, int n=-1) { + return ::wgetnstr(w, str,n); } + // Read a series of characters into str until a newline or carriage return + // is received. Read at most n characters. If n is negative, the limit is + // ignored. + + int getstr(int y, int x, char* str, int n=-1) { + return ::mvwgetnstr(w,y,x,str,n); } + // Move the cursor to the requested position and then perform the getstr() + // as described above. + + int instr(char *s, int n=-1) { return ::winnstr(w,s,n); } + // Get a string of characters from the window into the buffer s. Retrieve + // at most n characters, if n is negative retrieve all characters up to the + // end of the current line. Attributes are stripped from the characters. + + int instr(int y, int x, char *s, int n=-1) { + return ::mvwinnstr(w,y,x,s,n); } + // Move the cursor to the requested position and then perform the instr() + // as described above. + + int scanw(const char* fmt, ...) + // Perform a scanw function from the window. This only works if you're + // using the GNU C++ compiler. +#if __GNUG__ >= 2 + __attribute__ ((format (scanf, 2, 3))); +#else + ; +#endif + + int scanw(int y, int x, const char* fmt, ...) + // Move the cursor to the requested position and then perform a scanw + // from the window. This nly works if you're using the GNU C++ compiler. +#if __GNUG__ >= 2 + __attribute__ ((format (scanf, 4, 5))); +#else + ; +#endif + + // ------------------------------------------------------------------------- + // output + // ------------------------------------------------------------------------- + int addch(const chtype ch) { return ::waddch(w, ch); } + // Put attributed character to the window. + + int addch(int y, int x, const chtype ch) { + return ::mvwaddch(w,y,x,ch); } + // Move cursor to the requested position and then put attributed character + // to the window. + + int echochar(const chtype ch) { return ::wechochar(w,ch); } + // Put attributed character to the window and refresh it immediately. + + int addstr(const char* str, int n=-1) { + return ::waddnstr(w, (char*)str,n); } + // Write the string str to the window, stop writing if the terminating + // NUL or the limit n is reached. If n is negative, it is ignored. + + int addstr(int y, int x, const char * str, int n=-1) { + return ::mvwaddnstr(w,y,x,(char*)str,n); } + // Move the cursor to the requested position and then perform the addstr + // as described above. + + int printw(const char* fmt, ...) + // Do a formatted print to the window. +#if __GNUG__ >= 2 + __attribute__ ((format (printf, 2, 3))); +#else + ; +#endif + + int printw(int y, int x, const char * fmt, ...) + // Move the cursor and then do a formatted print to the window. +#if __GNUG__ >= 2 + __attribute__ ((format (printf, 4, 5))); +#else + ; +#endif + + chtype inch() const { return ::winch(w); } + // Retrieve attributed character under the current cursor position. + + chtype inch(int y, int x) { return ::mvwinch(w,y,x); } + // Move cursor to requested position and then retrieve attributed character + // at this position. + + int insch(chtype ch) { return ::winsch(w, ch); } + // Insert attributed character into the window before current cursor + // position. + + int insch(int y, int x, chtype ch) { + return ::mvwinsch(w,y,x,ch); } + // Move cursor to requested position and then insert the attributed + // character before that position. + + int insertln() { return ::winsdelln(w,1); } + // Insert an empty line above the current line. + + int insdelln(int n=1) { return ::winsdelln(w,n); } + // If n>0 insert that many lines above the current line. If n<0 delete + // that many lines beginning with the current line. + + int insstr(const char *s, int n=-1) { + return ::winsnstr(w,s,n); } + // Insert the string into the window before the current cursor position. + // Insert stops at end of string or when the limit n is reached. If n is + // negative, it is ignored. + + int insstr(int y, int x, const char *s, int n=-1) { + return ::mvwinsnstr(w,y,x,s,n); } + // Move the cursor to the requested position and then perform the insstr() + // as described above. + + int attron (chtype at) { return ::wattron (w, at); } + // Switch on the window attributes; + + int attroff(chtype at) { return ::wattroff(w, at); } + // Switch off the window attributes; + + int attrset(chtype at) { return ::wattrset(w, at); } + // Set the window attributes; + + int color_set(short color_pair_number, void* opts=NULL) { + return ::wcolor_set(w, color_pair_number, opts); } + // Set the window color attribute; + + int chgat(int n,attr_t attr, short color, const void *opts=NULL) { + return ::wchgat(w,n,attr,color,opts); } + // Change the attributes of the next n characters in the current line. If + // n is negative or greater than the number of remaining characters in the + // line, the attributes will be changed up to the end of the line. + + int chgat(int y, int x, + int n,attr_t attr, short color, const void *opts=NULL) { + return ::mvwchgat(w,y,x,n,attr,color,opts); } + // Move the cursor to the requested position and then perform chgat() as + // described above. + + // ------------------------------------------------------------------------- + // background + // ------------------------------------------------------------------------- + chtype getbkgd() const { return ::getbkgd(w); } + // Get current background setting. + + int bkgd(const chtype ch) { return ::wbkgd(w,ch); } + // Set the background property and apply it to the window. + + void bkgdset(chtype ch) { ::wbkgdset(w,ch); } + // Set the background property. + + // ------------------------------------------------------------------------- + // borders + // ------------------------------------------------------------------------- + int box(chtype vert=0, chtype hor=0) { + return ::wborder(w, vert, vert, hor, hor, 0, 0 ,0, 0); } + // Draw a box around the window with the given vertical and horizontal + // drawing characters. If you specifiy a zero as character, curses will try + // to find a "nice" character. + + int border(chtype left=0, chtype right=0, + chtype top =0, chtype bottom=0, + chtype top_left =0, chtype top_right=0, + chtype bottom_left =0, chtype bottom_right=0) { + return ::wborder(w,left,right,top,bottom,top_left,top_right, + bottom_left,bottom_right); } + // Draw a border around the window with the given characters for the + // various parts of the border. If you pass zero for a character, curses + // will try to find "nice" characters. + + // ------------------------------------------------------------------------- + // lines and boxes + // ------------------------------------------------------------------------- + int hline(int len, chtype ch=0) { return ::whline(w, ch, len); } + // Draw a horizontal line of len characters with the given character. If + // you pass zero for the character, curses will try to find a "nice" one. + + int hline(int y, int x, int len, chtype ch=0) { + return ::mvwhline(w,y,x,ch,len); } + // Move the cursor to the requested position and then draw a horizontal line. + + int vline(int len, chtype ch=0) { return ::wvline(w, ch, len); } + // Draw a vertical line of len characters with the given character. If + // you pass zero for the character, curses will try to find a "nice" one. + + int vline(int y, int x, int len, chtype ch=0) { + return ::mvwvline(w,y,x,ch,len); } + // Move the cursor to the requested position and then draw a vertical line. + + // ------------------------------------------------------------------------- + // erasure + // ------------------------------------------------------------------------- + int erase() { return ::werase(w); } + // Erase the window. + + int clear() { return ::wclear(w); } + // Clear the window. + + int clearok(bool bf) { return ::clearok(w, bf); } + // Set/Reset the clear flag. If set, the next refresh() will clear the + // screen. + + int clrtobot() { return ::wclrtobot(w); } + // Clear to the end of the window. + + int clrtoeol() { return ::wclrtoeol(w); } + // Clear to the end of the line. + + int delch() { return ::wdelch(w); } + // Delete character under the cursor. + + int delch(int y, int x) { return ::mvwdelch(w,y,x); } + // Move cursor to requested position and delete the character under the + // cursor. + + int deleteln() { return ::winsdelln(w,-1); } + // Delete the current line. + + // ------------------------------------------------------------------------- + // screen control + // ------------------------------------------------------------------------- + int scroll(int amount=1) { return ::wscrl(w,amount); } + // Scroll amount lines. If amount is positive, scroll up, otherwise + // scroll down. + + int scrollok(bool bf) { return ::scrollok(w, bf); } + // If bf is TRUE, window scrolls if cursor is moved off the bottom + // edge of the window or a scrolling region, otherwise the cursor is left + // at the bottom line. + + int setscrreg(int from, int to) { + return ::wsetscrreg(w,from,to); } + // Define a soft scrolling region. + + int idlok(bool bf) { return ::idlok(w, bf); } + // If bf is TRUE, use insert/delete line hardware support if possible. + // Otherwise do it in software. + + + void idcok(bool bf) { ::idcok(w, bf); } + // If bf is TRUE, use insert/delete character hardware support if possible. + // Otherwise do it in software. + + int touchwin() { return ::wtouchln(w,0,height(),1); } + // Mark the whole window as modified. + + int untouchwin() { return ::wtouchln(w,0,height(),0); } + // Mark the whole window as unmodified. + + int touchln(int s, int cnt, bool changed=TRUE) { + return ::wtouchln(w,s,cnt,(int)(changed?1:0)); } + // Mark cnt lines beginning from line s as changed or unchanged, depending + // on the value of the changed flag. + + bool is_linetouched(int line) const { + return (::is_linetouched(w,line) ? TRUE:FALSE); } + // Return TRUE if line is marked as changed, FALSE otherwise + + bool is_wintouched() const { + return (::is_wintouched(w) ? TRUE:FALSE); } + // Return TRUE if window is marked as changed, FALSE otherwise + + int leaveok(bool bf) { return ::leaveok(w, bf); } + // If bf is TRUE, curses will leave the cursor after an update whereever + // it is after the update. + + int redrawln(int from, int n) { return ::wredrawln(w,from,n); } + // Redraw n lines starting from the requested line + + int redrawwin() { return ::wredrawln(w,0,height()); } + // Redraw the whole window + + int doupdate() { return ::doupdate(); } + // Do all outputs to make the physical screen looking like the virtual one + + void syncdown() { ::wsyncdown(w); } + // Propagate the changes down to all descendant windows + + void syncup() { ::wsyncup(w); } + // Propagate the changes up in the hierarchy + + void cursyncup() { ::wcursyncup(w); } + // Position the cursor in all ancestor windows corresponding to our setting + + int syncok(bool bf) { return ::syncok(w,bf); } + // If called with bf=TRUE, syncup() is called whenever the window is changed + +#ifndef _no_flushok + int flushok(bool bf) { return ::flushok(w, bf); } +#endif + + void immedok(bool bf) { ::immedok(w,bf); } + // If called with bf=TRUE, any change in the window will cause an + // automatic immediate refresh() + + int keypad(bool bf) { return ::keypad(w, bf); } + // If called with bf=TRUE, the application will interpret function keys. + + int meta(bool bf) { return ::meta(w,bf); } + // If called with bf=TRUE, keys may generate 8-Bit characters. Otherwise + // 7-Bit characters are generated. + + int standout() { return ::wstandout(w); } + // Enable "standout" attributes + + int standend() { return ::wstandend(w); } + // Disable "standout" attributes + + // ------------------------------------------------------------------------- + // The next two are virtual, because we redefine them in the + // NCursesPanel class. + // ------------------------------------------------------------------------- + virtual int refresh() { return ::wrefresh(w); } + // Propagate the changes in this window to the virtual screen and call + // doupdate(). This is redefined in NCursesPanel. + + virtual int noutrefresh() { return ::wnoutrefresh(w); } + // Propagate the changes in this window to the virtual screen. This is + // redefined in NCursesPanel. + + // ------------------------------------------------------------------------- + // multiple window control + // ------------------------------------------------------------------------- + int overlay(NCursesWindow& win) { + return ::overlay(w, win.w); } + // Overlay this window over win. + + int overwrite(NCursesWindow& win) { + return ::overwrite(w, win.w); } + // Overwrite win with this window. + + int copywin(NCursesWindow& win, + int sminrow, int smincol, + int dminrow, int dmincol, + int dmaxrow, int dmaxcol, bool overlay=TRUE) { + return ::copywin(w,win.w,sminrow,smincol,dminrow,dmincol, + dmaxrow,dmaxcol,(int)(overlay?1:0)); } + // Overlay or overwrite the rectangle in win given by dminrow,dmincol, + // dmaxrow,dmaxcol with the rectangle in this window beginning at + // sminrow,smincol. + + // ------------------------------------------------------------------------- + // Mouse related + // ------------------------------------------------------------------------- + bool has_mouse() const; + // Return TRUE if terminal supports a mouse, FALSE otherwise + + // ------------------------------------------------------------------------- + // traversal support + // ------------------------------------------------------------------------- + NCursesWindow* child() { return subwins; } + // Get the first child window. + + NCursesWindow* sibling() { return sib; } + // Get the next child of my parent. + + NCursesWindow* parent() { return par; } + // Get my parent. + + bool isDescendant(NCursesWindow& win); + // Return TRUE if win is a descendant of this. +}; + +// ------------------------------------------------------------------------- +// We leave this here for compatibility reasons. +// ------------------------------------------------------------------------- +class NCursesColorWindow : public NCursesWindow { +public: + NCursesColorWindow(WINDOW* &window) // useful only for stdscr + : NCursesWindow(window) { + useColors(); } + + NCursesColorWindow(int lines, // number of lines + int cols, // number of columns + int begin_y, // line origin + int begin_x) // col origin + : NCursesWindow(lines,cols,begin_y,begin_x) { + useColors(); } + + NCursesColorWindow(NCursesWindow& par,// parent window + int lines, // number of lines + int cols, // number of columns + int begin_y, // absolute or relative + int begin_x, // origins: + char absrel = 'a') // if `a', by & bx are + : NCursesWindow(par,lines,cols, // absolute screen pos, + begin_y,begin_x, // else if `r', they are + absrel ) { // relative to par origin + useColors(); } +}; + +class NCursesPad : public NCursesWindow { +public: + NCursesPad(int lines, int cols); + + int echochar(const chtype ch) { return ::pechochar(w,ch); } + // Put the attributed character onto the pad and immediately do a + // prefresh(). + + // For Pad's we reimplement refresh() and noutrefresh() to do nothing. + // You should call the versions with the argument list that are specific + // for Pad's. + int refresh() { return OK; }; + int noutrefresh() { return OK; }; + + int refresh(int pminrow, int pmincol, + int sminrow, int smincol, + int smaxrow, int smaxcol) { + return ::prefresh(w,pminrow,pmincol, + sminrow,smincol,smaxrow,smaxcol); + } + // The coordinates sminrow,smincol,smaxrow,smaxcol describe a rectangle + // on the screen. <b>refresh</b> copies a rectangle of this size beginning + // with top left corner pminrow,pmincol onto the screen and calls doupdate(). + + int noutrefresh(int pminrow, int pmincol, + int sminrow, int smincol, + int smaxrow, int smaxcol) { + return ::pnoutrefresh(w,pminrow,pmincol, + sminrow,smincol,smaxrow,smaxcol); + } + // Does the same like refresh() but without calling doupdate(). +}; + +#endif // _CURSESW_H diff --git a/lib/libcurses++/cursslk.cc b/lib/libcurses++/cursslk.cc new file mode 100644 index 00000000000..384d7e06ce0 --- /dev/null +++ b/lib/libcurses++/cursslk.cc @@ -0,0 +1,121 @@ +// * 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 "cursslk.h" +#include "cursesapp.h" +#include "internal.h" + +MODULE_ID("$Id: cursslk.cc,v 1.1 1999/05/09 00:21:15 millert Exp $") + +void Soft_Label_Key_Set::Soft_Label_Key::operator=(char *text) { + delete[] label; + label = new char[1 + ::strlen(text)]; + (strcpy)(label,text); +} + +long Soft_Label_Key_Set::count = 0L; +int Soft_Label_Key_Set::num_labels = 0; + +Soft_Label_Key_Set::Label_Layout + Soft_Label_Key_Set::format = None; + +void Soft_Label_Key_Set::init() { + slk_array = new Soft_Label_Key[num_labels]; + for(int i=0; i < num_labels; i++) { + slk_array[i].num = i+1; + } + b_attrInit = FALSE; +} + +Soft_Label_Key_Set::Soft_Label_Key_Set() { + if (format==None) + Error("No default SLK layout"); + init(); +} + +Soft_Label_Key_Set::Soft_Label_Key_Set(Soft_Label_Key_Set::Label_Layout fmt) { + if (fmt==None) + Error("Invalid SLK Layout"); + if (count++==0) { + format = fmt; + if (ERR == ::slk_init((int)fmt)) + Error("slk_init"); + num_labels = (fmt>=PC_Style?12:8); + } + else if (fmt!=format) + Error("All SLKs must have same layout"); + init(); +} + +Soft_Label_Key_Set::~Soft_Label_Key_Set() { + if (!::isendwin()) + clear(); + delete[] slk_array; + count--; +} + +Soft_Label_Key_Set::Soft_Label_Key& Soft_Label_Key_Set::operator[](int i) { + if (i<1 || i>num_labels) + Error("Invalid Label index"); + return slk_array[i-1]; +} + +void Soft_Label_Key_Set::activate_label(int i, bool bf) { + if (!b_attrInit) { + NCursesApplication* A = NCursesApplication::getApplication(); + if (A) attrset(A->labels()); + b_attrInit = TRUE; + } + Soft_Label_Key& K = (*this)[i]; + if (ERR==::slk_set(K.num,bf?K.label:"",K.format)) + Error("slk_set"); + noutrefresh(); +} + +void Soft_Label_Key_Set::activate_labels(bool bf) { + if (!b_attrInit) { + NCursesApplication* A = NCursesApplication::getApplication(); + if (A) attrset(A->labels()); + b_attrInit = TRUE; + } + for(int i=1; i <= num_labels; i++) { + Soft_Label_Key& K = (*this)[i]; + if (ERR==::slk_set(K.num,bf?K.label:"",K.format)) + Error("slk_set"); + } + if (bf) + restore(); + else + clear(); + noutrefresh(); +} diff --git a/lib/libcurses++/cursslk.h b/lib/libcurses++/cursslk.h new file mode 100644 index 00000000000..3f789bb39c8 --- /dev/null +++ b/lib/libcurses++/cursslk.h @@ -0,0 +1,205 @@ +// * 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 * + ****************************************************************************/ + +// $Id: cursslk.h,v 1.1 1999/05/09 00:21:15 millert Exp $ + +#ifndef _CURSSLK_H +#define _CURSSLK_H + +#include <cursesw.h> + +class Soft_Label_Key_Set { +public: + // This inner class represents the attributes of a Soft Label Key (SLK) + class Soft_Label_Key { + friend class Soft_Label_Key_Set; + public: + typedef enum { Left=0, Center=1, Right=2 } Justification; + + private: + char *label; // The Text of the Label + Justification format; // The Justification + int num; // The number of the Label + + Soft_Label_Key() : label((char*)0),format(Left),num(-1) { + } + + virtual ~Soft_Label_Key() { + delete[] label; + }; + + public: + // Set the text of the Label + void operator=(char *text); + + // Set the Justification of the Label + inline void operator=(Justification just) { + format = just; + } + + // Retrieve the text of the label + inline char* operator()(void) const { + return label; + } + }; + +public: + typedef enum { + None = -1, + Three_Two_Three = 0, + Four_Four = 1, + PC_Style = 2, + PC_Style_With_Index = 3 + } Label_Layout; + +private: + static long count; // Number of Key Sets + static Label_Layout format; // Layout of the Key Sets + static int num_labels; // Number Of Labels in Key Sets + bool b_attrInit; // Are attributes initialized + + Soft_Label_Key *slk_array; // The array of SLK's + + // Init the Key Set + void init(); + + // Activate or Deactivate Label# i, Label counting starts with 1! + void activate_label(int i, bool bf=TRUE); + + // Activate of Deactivate all Labels + void activate_labels(bool bf); + +protected: + inline void Error (const char* msg) const THROWS(NCursesException) { + THROW(new NCursesException (msg)); + } + + // Remove SLK's from screen + void clear() { + if (ERR==::slk_clear()) + Error("slk_clear"); + } + + // Restore them + void restore() { + if (ERR==::slk_restore()) + Error("slk_restore"); + } + +public: + + // Construct a Key Set, use the most comfortable layout as default. + // You must create a Soft_Label_Key_Set before you create any object of + // the NCursesWindow, NCursesPanel or derived classes. (Actually before + // ::initscr() is called). + Soft_Label_Key_Set(Label_Layout fmt); + + // This constructor assumes, that you already constructed a Key Set + // with a layout by the constructor above. This layout will be reused. + Soft_Label_Key_Set(); + + virtual ~Soft_Label_Key_Set(); + + // Get Label# i. Label counting starts with 1! + Soft_Label_Key& operator[](int i); + + // Retrieve number of Labels + inline int labels() const { return num_labels; } + + // Refresh the SLK portion of the screen + inline void refresh() { + if (ERR==::slk_refresh()) + Error("slk_refresh"); + } + + // Mark the SLK portion of the screen for refresh, defer actual refresh + // until next update call. + inline void noutrefresh() { + if (ERR==::slk_noutrefresh()) + Error("slk_noutrefresh"); + } + + // Mark the whole SLK portion of the screen as modified + inline void touch() { + if (ERR==::slk_touch()) + Error("slk_touch"); + } + + // Activate Label# i + inline void show(int i) { + activate_label(i,FALSE); + activate_label(i,TRUE); + } + + // Hide Label# i + inline void hide(int i) { + activate_label(i,FALSE); + } + + // Show all Labels + inline void show() { + activate_labels(FALSE); + activate_labels(TRUE); + } + + // Hide all Labels + inline void hide() { + activate_labels(FALSE); + } + + inline void attron(attr_t attrs) { + if (ERR==::slk_attron(attrs)) + Error("slk_attron"); + } + + inline void attroff(attr_t attrs) { + if (ERR==::slk_attroff(attrs)) + Error("slk_attroff"); + } + + inline void attrset(attr_t attrs) { + if (ERR==::slk_attrset(attrs)) + Error("slk_attrset"); + } + + inline void color(short color_pair_number) { + if (ERR==::slk_color(color_pair_number)) + Error("slk_color"); + } + + inline attr_t attr() const { + return ::slk_attr(); + } +}; + +#endif // _CURSSLK_H diff --git a/lib/libcurses++/demo.cc b/lib/libcurses++/demo.cc new file mode 100644 index 00000000000..d529eb386d1 --- /dev/null +++ b/lib/libcurses++/demo.cc @@ -0,0 +1,405 @@ +/* + * Silly demo program for the NCursesPanel class. + * + * written by Anatoly Ivasyuk (anatoly@nick.csh.rit.edu) + * + * Demo code for NCursesMenu and NCursesForm written by + * Juergen Pfeifer <Juergen.Pfeifer@T-Online.de> + * + * $Id: demo.cc,v 1.1 1999/05/09 00:21:15 millert Exp $ + */ + +#include "cursesapp.h" +#include "cursesm.h" +#include "cursesf.h" + +#if HAVE_LIBC_H +# include <libc.h> +#endif + +extern "C" unsigned int sleep(unsigned int); + +#undef index // needed for NeXT + +// +// ------------------------------------------------------------------------- +// +class SillyDemo +{ + public: + void run(int sleeptime) { + + NCursesPanel *std = new NCursesPanel(); + + // Make a few small demo panels + + NCursesPanel *u = new NCursesPanel(8,20,12,4); + NCursesPanel *v = new NCursesPanel(8,20,10,6); + NCursesPanel *w = new NCursesPanel(8,20,8,8); + NCursesPanel *x = new NCursesPanel(8,20,6,10); + NCursesPanel *y = new NCursesPanel(8,20,4,12); + NCursesPanel *z = new NCursesPanel(8,30,2,14); + + // Draw something on the main screen, so we can see what happens + // when panels get moved or deleted. + + std->box(); + std->move(std->height()/2,1); + std->hline(std->width()-2); + std->move(1,std->width()/2); + std->vline(std->height()-2); + std->addch(0,std->width()/2,ACS_TTEE); + std->addch(std->height()-1,std->width()/2,ACS_BTEE); + std->addch(std->height()/2,0,ACS_LTEE); + std->addch(std->height()/2,std->width()-1,ACS_RTEE); + std->addch(std->height()/2,std->width()/2,ACS_PLUS); + + // Draw frames with titles around panels so that we can see where + // the panels are located. + u->boldframe("Win U"); + v->frame("Win V"); + w->boldframe("Win W"); + x->frame("Win X"); + y->boldframe("Win Y"); + z->frame("Win Z"); + if (NCursesApplication::getApplication()->useColors()) { + u->bkgd(' '|COLOR_PAIR(1)); + w->bkgd(' '|COLOR_PAIR(1)); + y->bkgd(' '|COLOR_PAIR(1)); + v->bkgd(' '|COLOR_PAIR(2)); + x->bkgd(' '|COLOR_PAIR(2)); + z->bkgd(' '|COLOR_PAIR(2)); + } + + // A refresh to any valid panel updates all panels and refreshes + // the screen. Using std is just convenient - We know it's always + // valid until the end of the program. + + std->refresh(); + sleep(sleeptime); + + // Show what happens when panels are deleted and moved. + + sleep(sleeptime); + delete u; + std->refresh(); + + sleep(sleeptime); + delete z; + std->refresh(); + + sleep(sleeptime); + delete v; + std->refresh(); + + // show how it looks when a panel moves + sleep(sleeptime); + y->mvwin(5,30); + std->refresh(); + + sleep(sleeptime); + delete y; + std->refresh(); + + // show how it looks when you raise a panel + sleep(sleeptime); + w->top(); + std->refresh(); + + sleep(sleeptime); + delete w; + std->refresh(); + + sleep(sleeptime); + delete x; + + std->clear(); + std->refresh(); + + // Don't forget to clean up the main screen. Since this is the + // last thing using NCursesWindow, this has the effect of + // shutting down ncurses and restoring the terminal state. + + sleep(sleeptime); + delete std; + } +}; + +class UserData +{ +private: + int u; +public: + UserData(int x) : u(x) {} + int sleeptime() const { return u; } +}; +// +// ------------------------------------------------------------------------- +// +template<class T> class MyAction : public NCursesUserItem<T> +{ +public: + MyAction (const char* p_name, + const T* p_UserData) + : NCursesUserItem<T>(p_name, (const char*)0, p_UserData) + {}; + + ~MyAction() {} + + bool action() { + SillyDemo a; + a.run(NCursesUserItem<T>::UserData()->sleeptime()); + return FALSE; + } +}; + +class QuitItem : public NCursesMenuItem +{ +public: + QuitItem() : NCursesMenuItem("Quit") { + } + + bool action() { + return TRUE; + } +}; +// +// ------------------------------------------------------------------------- +// +class Label : public NCursesFormField +{ +public: + Label(const char*title, + int row, int col) + : NCursesFormField(1,(int)::strlen(title),row,col) { + set_value(title); + options_off(O_EDIT|O_ACTIVE); + } +}; +// +// ------------------------------------------------------------------------- +// +class MyFieldType : public UserDefinedFieldType { +private: + int chk; +protected: + bool field_check(NCursesFormField& f) { + return TRUE; + } + bool char_check(int c) { + return (c==chk?TRUE:FALSE); + } +public: + MyFieldType(int x) : chk(x) { + } +}; +// +// ------------------------------------------------------------------------- +// +class TestForm : public NCursesForm +{ +private: + NCursesFormField** F; + MyFieldType* mft; + Integer_Field *ift; + Enumeration_Field *eft; + + static char *weekdays[]; + +public: + TestForm() : NCursesForm(13,51,(lines()-15)/2,(cols()-53)/2) { + + F = new NCursesFormField*[10]; + mft = new MyFieldType('X'); + ift = new Integer_Field(0,1,10); + eft = new Enumeration_Field(weekdays); + + F[0] = new Label("Demo Entry Form",0,16); + F[1] = new Label("Weekday Enum",2,1); + F[2] = new Label("Number(1-10)",2,21); + F[3] = new Label("Only 'X'",2,35); + F[4] = new Label("Multiline Field (Dynamic and Scrollable)",5,1); + F[5] = new NCursesFormField(1,18,3,1); + F[6] = new NCursesFormField(1,12,3,21); + F[7] = new NCursesFormField(1,12,3,35); + F[8] = new NCursesFormField(4,46,6,1,2); + F[9] = new NCursesFormField(); + + InitForm(F,TRUE,TRUE); + boldframe(); + + F[5]->set_fieldtype(*eft); + F[6]->set_fieldtype(*ift); + + F[7]->set_fieldtype(*mft); + F[7]->set_maximum_growth(20); // max. 20 characters + F[7]->options_off(O_STATIC); // make field dynamic + + F[8]->set_maximum_growth(10); // max. 10 lines + F[8]->options_off(O_STATIC); // make field dynamic + } + + ~TestForm() { + delete mft; + delete ift; + delete eft; + } +}; + +char* TestForm::weekdays[] = { + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", + "Friday", "Saturday", (char *)0 }; +// +// ------------------------------------------------------------------------- +// +class FormAction : public NCursesMenuItem +{ +public: + FormAction(const char *s) : NCursesMenuItem(s) { + } + + bool action() { + TestForm F; + Soft_Label_Key_Set* S = new Soft_Label_Key_Set; + for(int i=1; i <= S->labels(); i++) { + char buf[5]; + ::sprintf(buf,"Frm%02d",i); + (*S)[i] = buf; // Text + (*S)[i] = Soft_Label_Key_Set::Soft_Label_Key::Left; // Justification + } + NCursesApplication::getApplication()->push(*S); + F(); + NCursesApplication::getApplication()->pop(); + return FALSE; + } +}; +// +// ------------------------------------------------------------------------- +// +class PassiveItem : public NCursesMenuItem { +public: + PassiveItem(const char* text) : NCursesMenuItem(text) { + options_off(O_SELECTABLE); + } +}; +// +// ------------------------------------------------------------------------- +// +class MyMenu : public NCursesMenu +{ +private: + NCursesPanel* P; + NCursesMenuItem** I; + UserData *u; + +public: + MyMenu () + : NCursesMenu (8, 8, (lines()-10)/2, (cols()-10)/2) + { + u = new UserData(1); + I = new NCursesMenuItem*[7]; + I[0] = new PassiveItem("One"); + I[1] = new PassiveItem("Two"); + I[2] = new MyAction<UserData> ("Silly", u); + I[3] = new FormAction("Form"); + I[4] = new PassiveItem("Five"); + I[5] = new QuitItem(); + I[6] = new NCursesMenuItem(); // Terminating empty item + + InitMenu(I,TRUE,TRUE); + + P = new NCursesPanel(1,6,LINES-1,1); + boldframe("Demo","Silly"); + P->show(); + } + + ~MyMenu() + { + P->hide(); + delete P; + delete u; + } + + virtual void On_Menu_Init() + { + NCursesWindow W(::stdscr); + P->move(0,0); + P->clrtoeol(); + for(int i=1; i<=count(); i++) + P->addch('0' + i); + P->bkgd(W.getbkgd()); + refresh(); + } + + virtual void On_Menu_Termination() + { + P->move(0,0); + P->clrtoeol(); + refresh(); + } + + virtual void On_Item_Init(NCursesMenuItem& item) + { + P->move(0,item.index()); + P->attron(A_REVERSE); + P->printw("%1d",1+item.index()); + P->attroff(A_REVERSE); + refresh(); + } + + virtual void On_Item_Termination(NCursesMenuItem& item) + { + P->move(0,item.index()); + P->attroff(A_REVERSE); + P->printw("%1d",1+item.index()); + refresh(); + } +}; +// +// ------------------------------------------------------------------------- +// +class TestApplication : public NCursesApplication { +protected: + int titlesize() const { return 1; } + void title(); + Soft_Label_Key_Set::Label_Layout useSLKs() const { + return Soft_Label_Key_Set::PC_Style_With_Index; + } + void init_labels(Soft_Label_Key_Set& S) const; + +public: + TestApplication() : NCursesApplication(TRUE) { + } + + int run(); +}; + +void TestApplication::init_labels(Soft_Label_Key_Set& S) const { + for(int i=1; i <= S.labels(); i++) { + char buf[5]; + ::sprintf(buf,"Key%02d",i); + S[i] = buf; // Text + S[i] = Soft_Label_Key_Set::Soft_Label_Key::Left; // Justification + } +} + +void TestApplication::title() { + const char * const title = "Simple C++ Binding Demo"; + const int len = ::strlen(title); + + titleWindow->bkgd(screen_titles()); + titleWindow->addstr(0,(titleWindow->cols()-len)/2,title); + titleWindow->noutrefresh(); +} + + +int TestApplication::run() { + MyMenu M; + M(); + return 0; +} + +// +// ------------------------------------------------------------------------- +// +static TestApplication Demo; diff --git a/lib/libcurses++/etip.h b/lib/libcurses++/etip.h new file mode 100644 index 00000000000..0e4b10c0462 --- /dev/null +++ b/lib/libcurses++/etip.h @@ -0,0 +1,248 @@ +// * This makes 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 * + ****************************************************************************/ + +// $Id: etip.h,v 1.1 1999/05/09 00:21:15 millert Exp $ + +#ifndef _ETIP_H +#define _ETIP_H + +// These are substituted at configure/build time +#ifndef HAVE_BUILTIN_H +# define HAVE_BUILTIN_H 1 +#endif + +#ifndef HAVE_TYPEINFO +# define HAVE_TYPEINFO 1 +#endif + +#ifndef HAVE_VALUES_H +# define HAVE_VALUES_H 0 +#endif + +#ifndef ETIP_NEEDS_MATH_H +#define ETIP_NEEDS_MATH_H 0 +#endif + +#ifndef ETIP_NEEDS_MATH_EXCEPTION +#define ETIP_NEEDS_MATH_EXCEPTION 0 +#endif + +#ifdef __GNUG__ +# if ((__GNUG__ <= 2) && (__GNUC_MINOR__ < 8)) +# if HAVE_TYPEINFO +# include <typeinfo> +# endif +# endif +#endif + +#if defined(__GNUG__) +# if HAVE_BUILTIN_H +# if ETIP_NEEDS_MATH_H +# if ETIP_NEEDS_MATH_EXCEPTION +# undef exception +# define exception math_exception +# endif +# include <math.h> +# endif +# undef exception +# define exception builtin_exception +# include <builtin.h> +# undef exception +# endif +#elif defined (__SUNPRO_CC) +# include <generic.h> +# include <string.h> +#else +# include <string.h> +#endif + +extern "C" { +#if HAVE_VALUES_H +# include <values.h> +#endif + +#include <assert.h> +#include <eti.h> +#include <errno.h> +} + +// Forward Declarations +class NCursesPanel; +class NCursesMenu; +class NCursesForm; + +class NCursesException +{ +public: + const char *message; + int errorno; + + NCursesException (const char* msg, int err) + : message(msg), errorno (err) + {}; + + NCursesException (const char* msg) + : message(msg), errorno (E_SYSTEM_ERROR) + {}; + + virtual const char *classname() const { + return "NCursesWindow"; + } +}; + +class NCursesPanelException : public NCursesException +{ +public: + const NCursesPanel* p; + + NCursesPanelException (const char *msg, int err) : + NCursesException (msg, err), + p ((NCursesPanel*)0) + {}; + + NCursesPanelException (const NCursesPanel* panel, + const char *msg, + int err) : + NCursesException (msg, err), + p (panel) + {}; + + NCursesPanelException (int err) : + NCursesException ("panel library error", err), + p ((NCursesPanel*)0) + {}; + + NCursesPanelException (const NCursesPanel* panel, + int err) : + NCursesException ("panel library error", err), + p (panel) + {}; + + virtual const char *classname() const { + return "NCursesPanel"; + } + +}; + +class NCursesMenuException : public NCursesException +{ +public: + const NCursesMenu* m; + + NCursesMenuException (const char *msg, int err) : + NCursesException (msg, err), + m ((NCursesMenu *)0) + {}; + + NCursesMenuException (const NCursesMenu* menu, + const char *msg, + int err) : + NCursesException (msg, err), + m (menu) + {}; + + NCursesMenuException (int err) : + NCursesException ("menu library error", err), + m ((NCursesMenu *)0) + {}; + + NCursesMenuException (const NCursesMenu* menu, + int err) : + NCursesException ("menu library error", err), + m (menu) + {}; + + virtual const char *classname() const { + return "NCursesMenu"; + } + +}; + +class NCursesFormException : public NCursesException +{ +public: + const NCursesForm* f; + + NCursesFormException (const char *msg, int err) : + NCursesException (msg, err), + f ((NCursesForm*)0) + {}; + + NCursesFormException (const NCursesForm* form, + const char *msg, + int err) : + NCursesException (msg, err), + f (form) + {}; + + NCursesFormException (int err) : + NCursesException ("form library error", err), + f ((NCursesForm*)0) + {}; + + NCursesFormException (const NCursesForm* form, + int err) : + NCursesException ("form library error", err), + f (form) + {}; + + virtual const char *classname() const { + return "NCursesForm"; + } + +}; + +#if !(defined(__GNUG__)||defined(__SUNPRO_CC)) +# include <iostream.h> + extern "C" void exit(int); +#endif + +inline void THROW(const NCursesException *e) { +#if defined(__GNUG__) +# if ((__GNUG__ <= 2) && (__GNUC_MINOR__ < 8)) + (*lib_error_handler)(e?e->classname():"",e?e->message:""); +#else + throw *e; +#endif +#elif defined(__SUNPRO_CC) + genericerror(1, ((e != 0) ? (char *)(e->message) : "")); +#else + if (e) + cerr << e->message << endl; + exit(0); +#endif +} + +#define THROWS(s) + +#endif // _ETIP_H diff --git a/lib/libcurses++/internal.h b/lib/libcurses++/internal.h new file mode 100644 index 00000000000..ce5af0167da --- /dev/null +++ b/lib/libcurses++/internal.h @@ -0,0 +1,47 @@ +// * This makes 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 * + ****************************************************************************/ + +// $Id: internal.h,v 1.1 1999/05/09 00:21:15 millert Exp $ + +#ifndef _CPLUS_INTERNAL_H +#define _CPLUS_INTERNAL_H 1 + +#ifdef USE_RCS_IDS +#define MODULE_ID(id) static const char Ident[] = id; +#else +#define MODULE_ID(id) /*nothing*/ +#endif + +#define CTRL(x) ((x) & 0x1f) + +#endif |