// * this is for making emacs happy: -*-Mode: C++;-*-
+/****************************************************************************
+ * Copyright (c) 2007 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. *
+ ****************************************************************************/
/*
- 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@gmx.net)
-*/
+ * Authors:
+ * Thomas E. Dickey
+ * Juergen Pfeifer
+ *
+ * The NCursesWindow class was originally based on a file written by
+ * Eric Newton, later modified by Ulrich Drepper and Anatoly Ivasyuk.
+ * However, aside from the compatible interface definition, no trace
+ * of the original code remains in this version: it consists only of
+ * changes introduced since 1995.
+ */
-#include "cursesw.h"
#include "internal.h"
+#include "cursesw.h"
-MODULE_ID("$Id: cursesw.cc,v 1.16 1999/11/13 23:42:17 tom Exp $")
+MODULE_ID("$Id: cursesw.cc,v 1.48 2007/03/24 19:00:58 tom Exp $")
#define COLORS_NEED_INITIALIZATION -1
#define COLORS_NOT_INITIALIZED 0
#define COLORS_MONOCHROME 1
#define COLORS_ARE_REALLY_THERE 2
+#define HaveColors() (colorInitialized == COLORS_ARE_REALLY_THERE)
+
// 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__)
+ int result = ERR;
+
va_list args;
va_start(args, fmt);
- char buf[BUFSIZ];
- int result = wgetstr(w, buf);
- if (result == OK) {
- strstreambuf ss(buf, sizeof(buf));
- result = ss.vscan(fmt, (_IO_va_list)args);
- }
+ result = ::vw_scanw (w, const_cast<NCURSES_CONST char *>(fmt), 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, sizeof(buf));
- result = ss.vscan(fmt, (_IO_va_list)args);
- }
+ int result = ERR;
+
+ if (::wmove(w, y, x) != ERR) {
+ va_list args;
+ va_start(args, fmt);
+ result = ::vw_scanw (w, const_cast<NCURSES_CONST char *>(fmt), args);
+ va_end(args);
}
- va_end(args);
return result;
-#else
- return ERR;
-#endif
}
{
va_list args;
va_start(args, fmt);
- char buf[BUFSIZ];
- vsprintf(buf, fmt, args);
+ int result = ::vw_printw(w, fmt, args);
va_end(args);
- return waddstr(w, buf);
+ return result;
}
{
va_list args;
va_start(args, fmt);
- int result = wmove(w, y, x);
+ int result = ::wmove(w, y, x);
if (result == OK) {
- char buf[BUFSIZ];
- vsprintf(buf, fmt, args);
- result = waddstr(w, buf);
+ result = ::vw_printw(w, fmt, args);
}
va_end(args);
return result;
void
-NCursesWindow::init(void)
+NCursesWindow::set_keyboard(void)
{
- leaveok(0);
- keypad(1);
- meta(1);
+ keypad(TRUE);
+ meta(TRUE);
}
void
}
void
-NCursesWindow::initialize() {
- if (!b_initialized) {
- ::initscr();
- b_initialized = TRUE;
- if (colorInitialized==COLORS_NEED_INITIALIZATION) {
- colorInitialized=COLORS_NOT_INITIALIZED;
- useColors();
+NCursesWindow::initialize()
+{
+ if (!b_initialized) {
+ ::initscr();
+ b_initialized = TRUE;
+ if (colorInitialized == COLORS_NEED_INITIALIZATION) {
+ colorInitialized = COLORS_NOT_INITIALIZED;
+ useColors();
+ }
+ ::noecho();
+ ::cbreak();
}
- ::noecho();
- ::cbreak();
- }
}
-NCursesWindow::NCursesWindow() {
- if (!b_initialized)
+void
+NCursesWindow::constructing()
+{
initialize();
+ ++count;
+}
+
+NCursesWindow::NCursesWindow()
+ : w(0), alloced(FALSE), par(0), subwins(0), sib(0)
+{
+ constructing();
- w = (WINDOW *)0;
- init();
- alloced = FALSE;
- subwins = par = sib = 0;
- count++;
+ w = static_cast<WINDOW *>(0);
+ set_keyboard();
}
-NCursesWindow::NCursesWindow(int lines, int cols, int begin_y, int begin_x)
+NCursesWindow::NCursesWindow(int nlines, int ncols, int begin_y, int begin_x)
+ : w(0), alloced(TRUE), par(0), subwins(0), sib(0)
{
- if (!b_initialized)
- initialize();
+ constructing();
- w = ::newwin(lines, cols, begin_y, begin_x);
+ w = ::newwin(nlines, ncols, begin_y, begin_x);
if (w == 0) {
err_handler("Cannot construct window");
}
- init();
-
- alloced = TRUE;
- subwins = par = sib = 0;
- count++;
+ set_keyboard();
}
-NCursesWindow::NCursesWindow(WINDOW* &window)
+NCursesWindow::NCursesWindow(WINDOW* window)
+ : w(0), alloced(FALSE), par(0), subwins(0), sib(0)
{
- if (!b_initialized)
- initialize();
-
- w = window;
- init();
- alloced = FALSE;
- subwins = par = sib = 0;
- count++;
+ constructing();
+
+ // We used to use a reference on the "window" parameter, but we cannot do
+ // that with an opaque pointer (see NCURSES_OPAQUE). If the parameter was
+ // "::stdscr", that is first set via the "constructing() call, and is null
+ // up to that point. So we allow a null pointer here as meaning the "same"
+ // as "::stdscr".
+ w = window ? window : ::stdscr;
+ set_keyboard();
}
-NCursesWindow::NCursesWindow(NCursesWindow& win, int l, int c,
+NCursesWindow::NCursesWindow(NCursesWindow& win, int ny, int nx,
int begin_y, int begin_x, char absrel)
+ : w(0), alloced(TRUE), par(0), subwins(0), sib(0)
{
- if (absrel == 'a') { // absolute origin
+ constructing();
+ 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);
+ // Link this window into its parent's list of subwindows.
+ // We use derwin(), since this also works for pads.
+ w = ::derwin(win.w, ny, nx, 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(NCursesWindow& win,
bool do_box NCURSES_PARAM_INIT(TRUE))
+ : w(0), alloced(TRUE), par(0), subwins(0), sib(0)
{
- w = :: derwin(win.w,win.height()-2,win.width()-2,1,1);
- if (w == 0) {
- err_handler("Cannot construct subwindow");
- }
-
- par = &win;
- sib = win.subwins;
- win.subwins = this;
- subwins = 0;
- alloced = TRUE;
- count++;
-
- if (do_box) {
- win.box();
- win.touchwin();
- }
+ constructing();
+ int myHeight = win.height();
+ int myWidth = win.width();
+ w = :: derwin(win.w, myHeight - 2, myWidth - 2, 1, 1);
+ if (w == 0) {
+ err_handler("Cannot construct subwindow");
+ }
+
+ par = &win;
+ sib = win.subwins;
+ win.subwins = this;
+ subwins = 0;
+
+ if (do_box) {
+ win.box();
+ win.touchwin();
+ }
}
-NCursesWindow NCursesWindow::Clone() {
- WINDOW *d = ::dupwin(w);
- NCursesWindow W(d);
- W.subwins = subwins;
- W.sib = sib;
- W.par = par;
- W.alloced = alloced;
- return W;
+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 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;
+NCursesWindow::NCursesWindow(WINDOW *win, int ncols)
+ : w(0), alloced(FALSE), par(0), subwins(0), sib(0)
+{
+ initialize();
+ w = win;
+ assert((w->_maxx +1 ) == ncols);
}
-int NCursesWindow::ripoff_init(WINDOW *w, int cols)
+int _nc_xx_ripoff_init(WINDOW *w, int ncols)
{
- int res = ERR;
-
- RIPOFFINIT init = *prip++;
- if (init) {
- NCursesWindow* W = new NCursesWindow(w,cols);
- res = init(*W);
- }
- return res;
+ int res = ERR;
+
+ RIPOFFINIT init = *prip++;
+ if (init) {
+ NCursesWindow* W = new NCursesWindow(w,ncols);
+ 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;
+ int (*init)(NCursesWindow& win))
+{
+ int code = ::_nc_ripoffline(ripoff_lines,_nc_xx_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;
+NCursesWindow::isDescendant(NCursesWindow& win)
+{
+ bool result = FALSE;
+
+ for (NCursesWindow* p = subwins; p != NULL; p = p->sib) {
+ if (p == &win || p->isDescendant(win)) {
+ result = TRUE;
+ break;
+ }
}
- }
- return FALSE;
+ return result;
}
void
NCursesWindow::kill_subwindows()
{
- for (NCursesWindow* p = subwins; p != 0; p = p->sib) {
+ NCursesWindow* p = subwins;
+
+ subwins = 0;
+ while (p != 0) {
+ NCursesWindow* q = 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...
+ delete p;
+ p = q;
}
}
{
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)
+ if (par != 0) {
+ // Remove this window from the parent's list of subwindows.
+ NCursesWindow * next = par->subwins;
+ NCursesWindow * prev = 0;
+ while (next != 0) {
+ if (next == this) {
+ if (prev != 0) {
+ prev->sib = next->sib;
+ } else {
+ par->subwins = next->sib;
+ }
break;
- else if (win == this) {
- if (trail != 0)
- trail->sib = win->sib;
- else
- par->subwins = win->sib;
- break;
- } else {
- trail = win;
- win = win->sib;
}
+ prev = next;
+ next = next->sib;
}
}
if (alloced && w != 0)
- delwin(w);
+ ::delwin(w);
if (alloced) {
- --count;
- if (count == 0) {
- ::endwin();
- }
- else if (count < 0) { // cannot happen!
- err_handler("Too many windows destroyed");
- }
+ --count;
+ if (count == 0) {
+ ::endwin();
+ } else if (count < 0) { // cannot happen!
+ err_handler("Too many windows destroyed");
+ }
}
}
NCursesWindow::useColors(void)
{
if (colorInitialized == COLORS_NOT_INITIALIZED) {
- if (b_initialized) {
- if (::has_colors()) {
- ::start_color();
- colorInitialized = COLORS_ARE_REALLY_THERE;
+ if (b_initialized) {
+ if (::has_colors()) {
+ ::start_color();
+ colorInitialized = COLORS_ARE_REALLY_THERE;
+ } else {
+ colorInitialized = COLORS_MONOCHROME;
+ }
+ } else {
+ colorInitialized = COLORS_NEED_INITIALIZATION;
}
- else
- colorInitialized = COLORS_MONOCHROME;
- }
- else
- colorInitialized = COLORS_NEED_INITIALIZATION;
}
}
+short
+NCursesWindow::getPair() const
+{
+ return static_cast<short>(PAIR_NUMBER(getattrs(w)));
+}
+
short
NCursesWindow::getcolor(int getback) const
{
short fore, back;
- if (colorInitialized==COLORS_ARE_REALLY_THERE) {
- if (pair_content((short)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;
+ if (HaveColors()) {
+ if (::pair_content(getPair(), &fore, &back) == ERR)
+ 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 ;-)
+ return (HaveColors()) ? COLORS : 1;
}
short
NCursesWindow::getcolor() const
{
- if (colorInitialized==COLORS_ARE_REALLY_THERE)
- return PAIR_NUMBER(w->_attrs);
- else
- return 0; // we only have pair zero
+ return (HaveColors()) ? getPair() : 0;
}
int
NCursesWindow::setpalette(short fore, short back, short pair)
{
- if (colorInitialized==COLORS_ARE_REALLY_THERE)
- return init_pair(pair, fore, back);
- else
- return OK;
+ return (HaveColors()) ? ::init_pair(pair, fore, back) : OK;
}
int
NCursesWindow::setpalette(short fore, short back)
{
- if (colorInitialized==COLORS_ARE_REALLY_THERE)
- return setpalette(fore, back, (short)PAIR_NUMBER(w->_attrs));
- else
- return OK;
+ return setpalette(fore, back, getPair());
}
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;
-}
+ if (HaveColors()) {
+ if ((pair < 1) || (pair > COLOR_PAIRS))
+ err_handler("Can't set color pair");
-#ifdef HAVE_HAS_KEY
-extern "C" int _nc_has_mouse(void);
+ attroff(A_COLOR);
+ attrset(COLOR_PAIR(pair));
+ }
+ return OK;
+}
-bool NCursesWindow::has_mouse() const {
- return ((::has_key(KEY_MOUSE) || ::_nc_has_mouse())
- ? TRUE : FALSE);
+#if HAVE_HAS_KEY
+bool NCursesWindow::has_mouse() const
+{
+ return ((::has_key(KEY_MOUSE) || ::_nc_has_mouse())
+ ? TRUE : FALSE);
}
#endif