X-Git-Url: https://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=c%2B%2B%2Fcursesw.cc;h=47e5cf64dcf0ded1e7ca1d88f1ed69cc2ae8fbfb;hp=106202a5379d6c24d855c9bd6abf5f51c71c04d2;hb=3996fe0bf797f113d6abc4329cc869951735a4d8;hpb=55ccd2b959766810cf7db8d1c4462f338ce0afc8 diff --git a/c++/cursesw.cc b/c++/cursesw.cc index 106202a5..47e5cf64 100644 --- a/c++/cursesw.cc +++ b/c++/cursesw.cc @@ -1,77 +1,83 @@ // * this is for making emacs happy: -*-Mode: C++;-*- +/**************************************************************************** + * Copyright (c) 2007-2008,2009 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 - and Thomas Dickey (noting that more than 70% of this file has been changed) -*/ + * 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 "internal.h" #include "cursesw.h" -MODULE_ID("$Id: cursesw.cc,v 1.32 2005/08/13 18:12:17 tom Exp $") +MODULE_ID("$Id: cursesw.cc,v 1.51 2009/03/28 21:31:37 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; -/* - * The ncurses library has a fallback for vsscanf(), which may work... - */ -#if !(USE_STRSTREAM_VSCAN || USE_STRSTREAM_VSCAN_CAST) -# undef USE_STDIO_VSCAN -# define USE_STDIO_VSCAN 1 -#endif +int +NCursesWindow::scanw(const char* fmt, ...) +{ + int result = ERR; + + va_list args; + va_start(args, fmt); + result = ::vw_scanw (w, const_cast(fmt), args); + va_end(args); + + return result; +} -#if defined(__GNUG__) -# ifndef _IO_va_list -# define _IO_va_list char * -# endif -#endif int -NCursesWindow::scanw(const char* fmt, ...) +NCursesWindow::scanw(int y, int x, const char* fmt, ...) { int result = ERR; - char buf[BUFSIZ]; - if (::wgetnstr(w, buf, sizeof(buf)) != ERR) { + if (::wmove(w, y, x) != ERR) { va_list args; va_start(args, fmt); -#if USE_STDIO_VSCAN - if (::vsscanf(buf, fmt, args) != -1) - result = OK; -#elif USE_STRSTREAM_VSCAN /* powerpc, os390 */ - strstreambuf ss(buf, sizeof(buf)); - if (ss.vscan(fmt, args) != -1) - result = OK; -#elif USE_STRSTREAM_VSCAN_CAST /* pre-gcc 3.0 */ - strstreambuf ss(buf, sizeof(buf)); - if (ss.vscan(fmt, (_IO_va_list)args) != -1) - result = OK; -#endif + result = ::vw_scanw (w, const_cast(fmt), args); va_end(args); } return result; @@ -79,29 +85,23 @@ NCursesWindow::scanw(const char* fmt, ...) int -NCursesWindow::scanw(int y, int x, const char* fmt, ...) +NCursesWindow::scanw(const char* fmt, va_list args) +{ + int result = ERR; + + result = ::vw_scanw (w, const_cast(fmt), args); + + return result; +} + + +int +NCursesWindow::scanw(int y, int x, const char* fmt, va_list args) { int result = ERR; - char buf[BUFSIZ]; if (::wmove(w, y, x) != ERR) { - if (::wgetnstr(w, buf, sizeof(buf)) != ERR) { - va_list args; - va_start(args, fmt); -#if USE_STDIO_VSCAN - if (::vsscanf(buf, fmt, args) != -1) - result = OK; -#elif USE_STRSTREAM_VSCAN /* powerpc, os390 */ - strstreambuf ss(buf, sizeof(buf)); - if (ss.vscan(fmt, args) != -1) - result = OK; -#elif USE_STRSTREAM_VSCAN_CAST /* pre-gcc 3.0 */ - strstreambuf ss(buf, sizeof(buf)); - if (ss.vscan(fmt, (_IO_va_list)args) != -1) - result = OK; -#endif - va_end(args); - } + result = ::vw_scanw (w, const_cast(fmt), args); } return result; } @@ -112,10 +112,9 @@ NCursesWindow::printw(const char * fmt, ...) { 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; } @@ -126,21 +125,37 @@ NCursesWindow::printw(int y, int x, const char * fmt, ...) va_start(args, fmt); 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; } +int +NCursesWindow::printw(const char * fmt, va_list args) +{ + int result = ::vw_printw(w, fmt, args); + return result; +} + + +int +NCursesWindow::printw(int y, int x, const char * fmt, va_list args) +{ + int result = ::wmove(w, y, x); + if (result == OK) { + result = ::vw_printw(w, fmt, args); + } + return result; +} + + void -NCursesWindow::init(void) +NCursesWindow::set_keyboard(void) { - leaveok(0); - keypad(1); - meta(1); + keypad(TRUE); + meta(TRUE); } void @@ -152,73 +167,73 @@ NCursesWindow::err_handler(const char *msg) const THROWS(NCursesException) void NCursesWindow::initialize() { - if (!b_initialized) { - ::initscr(); - b_initialized = TRUE; - if (colorInitialized==COLORS_NEED_INITIALIZATION) { - colorInitialized=COLORS_NOT_INITIALIZED; - useColors(); + if (!b_initialized) { + ::initscr(); + b_initialized = TRUE; + if (colorInitialized == COLORS_NEED_INITIALIZATION) { + colorInitialized = COLORS_NOT_INITIALIZED; + useColors(); + } + ::noecho(); + ::cbreak(); } - ::noecho(); - ::cbreak(); - } +} + +void +NCursesWindow::constructing() +{ + initialize(); + ++count; } NCursesWindow::NCursesWindow() - : w(0), alloced(0), par(0), subwins(0), sib(0) + : w(0), alloced(FALSE), par(0), subwins(0), sib(0) { - initialize(); + constructing(); - w = static_cast(0); - init(); - alloced = FALSE; - subwins = par = sib = 0; - count++; + w = static_cast(0); + set_keyboard(); } NCursesWindow::NCursesWindow(int nlines, int ncols, int begin_y, int begin_x) - : w(0), alloced(0), par(0), subwins(0), sib(0) + : w(0), alloced(TRUE), par(0), subwins(0), sib(0) { - initialize(); + constructing(); 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) - : w(0), alloced(0), par(0), subwins(0), sib(0) +NCursesWindow::NCursesWindow(WINDOW* window) + : w(0), alloced(FALSE), par(0), subwins(0), sib(0) { - 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(0), par(0), subwins(0), sib(0) + : w(0), alloced(TRUE), par(0), subwins(0), sib(0) { - initialize(); - 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"); } @@ -226,45 +241,40 @@ NCursesWindow::NCursesWindow(NCursesWindow& win, int l, int c, 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(0), par(0), subwins(0), sib(0) + : w(0), alloced(TRUE), par(0), subwins(0), sib(0) { - initialize(); - 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"); - } + 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; - alloced = TRUE; - count++; + par = &win; + sib = win.subwins; + win.subwins = this; + subwins = 0; - if (do_box) { - win.box(); - win.touchwin(); - } + 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; + 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&); @@ -273,62 +283,62 @@ static int r_init_idx = 0; static RIPOFFINIT* prip = R_INIT; NCursesWindow::NCursesWindow(WINDOW *win, int ncols) - : w(0), alloced(0), par(0), subwins(0), sib(0) + : w(0), alloced(FALSE), par(0), subwins(0), sib(0) { - initialize(); - w = win; - assert((w->_maxx+1)==ncols); - alloced = FALSE; - subwins = par = sib = 0; + initialize(); + w = win; } int _nc_xx_ripoff_init(WINDOW *w, int ncols) { - int res = ERR; + int res = ERR; - RIPOFFINIT init = *prip++; - if (init) { - NCursesWindow* W = new NCursesWindow(w,ncols); - res = init(*W); - } - return res; + RIPOFFINIT init = *prip++; + if (init) { + res = init(*(new NCursesWindow(w,ncols))); + } + return res; } int NCursesWindow::ripoffline(int ripoff_lines, 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; + 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; + 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; } } @@ -337,22 +347,21 @@ 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; + 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 { - trail = win; - win = win->sib; } + prev = next; + next = next->sib; } } @@ -360,13 +369,12 @@ NCursesWindow::~NCursesWindow() ::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"); + } } } @@ -379,89 +387,82 @@ void 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(PAIR_NUMBER(getattrs(w))); +} + short NCursesWindow::getcolor(int getback) const { short fore, back; - if (colorInitialized==COLORS_ARE_REALLY_THERE) { - if (::pair_content(static_cast(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, static_cast(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"); + if (HaveColors()) { + if ((pair < 1) || (pair > COLOR_PAIRS)) + err_handler("Can't set color pair"); - attroff(A_COLOR); - attrset(COLOR_PAIR(pair)); - } - return OK; + attroff(A_COLOR); + attrset(COLOR_PAIR(pair)); + } + return OK; } #if HAVE_HAS_KEY bool NCursesWindow::has_mouse() const { - return ((::has_key(KEY_MOUSE) || ::_nc_has_mouse()) - ? TRUE : FALSE); + return ((::has_key(KEY_MOUSE) || ::has_mouse()) + ? TRUE : FALSE); } #endif