1*58188Selan /* 2*58188Selan Copyright (C) 1989, 1992 Free Software Foundation 3*58188Selan written by Eric Newton (newton@rocky.oswego.edu) 4*58188Selan 5*58188Selan This file is part of the GNU C++ Library. This library is free 6*58188Selan software; you can redistribute it and/or modify it under the terms of 7*58188Selan the GNU Library General Public License as published by the Free 8*58188Selan Software Foundation; either version 2 of the License, or (at your 9*58188Selan option) any later version. This library is distributed in the hope 10*58188Selan that it will be useful, but WITHOUT ANY WARRANTY; without even the 11*58188Selan implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 12*58188Selan PURPOSE. See the GNU Library General Public License for more details. 13*58188Selan You should have received a copy of the GNU Library General Public 14*58188Selan License along with this library; if not, write to the Free Software 15*58188Selan Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 16*58188Selan */ 17*58188Selan #ifdef __GNUG__ 18*58188Selan #pragma implementation 19*58188Selan #endif 20*58188Selan #include <stdio.h> 21*58188Selan #include <stdarg.h> 22*58188Selan #include <builtin.h> 23*58188Selan #include <values.h> 24*58188Selan #ifndef _OLD_STREAMS 25*58188Selan #include <strstream.h> 26*58188Selan #include <ioprivate.h> 27*58188Selan #endif 28*58188Selan // Include CurseW.h and/or curses.h *after* iostream includes, 29*58188Selan // because curses.h defines a clear macro that conflicts with iostream. Sigh. 30*58188Selan #include <CursesW.h> 31*58188Selan 32*58188Selan #if _G_HAVE_CURSES 33*58188Selan 34*58188Selan int CursesWindow::count = 0; 35*58188Selan 36*58188Selan /* 37*58188Selan * C++ interface to curses library. 38*58188Selan * 39*58188Selan */ 40*58188Selan 41*58188Selan /* 42*58188Selan * varargs functions are handled conservatively: 43*58188Selan * They interface directly into the underlying 44*58188Selan * _doscan, _doprnt and/or vfprintf routines rather than 45*58188Selan * assume that such things are handled compatibly in the curses library 46*58188Selan */ 47*58188Selan 48*58188Selan int CursesWindow::scanw(const char * fmt, ...) 49*58188Selan { 50*58188Selan va_list args; 51*58188Selan va_start(args, fmt); 52*58188Selan #ifdef VMS 53*58188Selan int result = wscanw(w , fmt , args); 54*58188Selan #else /* NOT VMS */ 55*58188Selan char buf[BUFSIZ]; 56*58188Selan int result = wgetstr(w, buf); 57*58188Selan if (result == OK) { 58*58188Selan #ifndef _OLD_STREAMS 59*58188Selan strstreambuf ss(buf, BUFSIZ); 60*58188Selan result = ss.vscan(fmt, args); 61*58188Selan #else /* _OLD_STREAMS */ 62*58188Selan #ifndef HAVE_VSCANF 63*58188Selan FILE b; 64*58188Selan b._flag = _IOREAD|_IOSTRG; 65*58188Selan b._base = buf; 66*58188Selan b._ptr = buf; 67*58188Selan b._cnt = BUFSIZ; 68*58188Selan result = _doscan(&b, fmt, args); 69*58188Selan #else /* HAVE_VSCANF */ 70*58188Selan result = vsscanf(buf, fmt, args); 71*58188Selan #endif /* HAVE_VSCANF */ 72*58188Selan #endif /* _OLD_STREAMS */ 73*58188Selan } 74*58188Selan #endif /* !VMS */ 75*58188Selan va_end(args); 76*58188Selan return result; 77*58188Selan } 78*58188Selan 79*58188Selan int CursesWindow::mvscanw(int y, int x, const char * fmt, ...) 80*58188Selan { 81*58188Selan va_list args; 82*58188Selan va_start(args, fmt); 83*58188Selan char buf[BUFSIZ]; 84*58188Selan int result = wmove(w, y, x); 85*58188Selan if (result == OK) 86*58188Selan #ifdef VMS 87*58188Selan result=wscanw(w , fmt , args); 88*58188Selan #else /* !VMS */ 89*58188Selan { 90*58188Selan result = wgetstr(w, buf); 91*58188Selan if (result == OK) { 92*58188Selan #ifndef _OLD_STREAMS 93*58188Selan strstreambuf ss(buf, BUFSIZ); 94*58188Selan result = ss.vscan(fmt, args); 95*58188Selan #else /* OLD_STREAMS */ 96*58188Selan #ifndef HAVE_VSCANF 97*58188Selan FILE b; 98*58188Selan b._flag = _IOREAD|_IOSTRG; 99*58188Selan b._base = buf; 100*58188Selan b._ptr = buf; 101*58188Selan b._cnt = BUFSIZ; 102*58188Selan result = _doscan(&b, fmt, args); 103*58188Selan #else 104*58188Selan result = vsscanf(buf, fmt, args); 105*58188Selan #endif 106*58188Selan #endif /* OLD_STREAMS */ 107*58188Selan } 108*58188Selan } 109*58188Selan #endif /* !VMS */ 110*58188Selan va_end(args); 111*58188Selan return result; 112*58188Selan } 113*58188Selan 114*58188Selan int CursesWindow::printw(const char * fmt, ...) 115*58188Selan { 116*58188Selan va_list args; 117*58188Selan va_start(args, fmt); 118*58188Selan char buf[BUFSIZ]; 119*58188Selan #ifndef _OLD_STREAMS 120*58188Selan strstreambuf ss(buf, BUFSIZ); 121*58188Selan ss.vform(fmt, args); 122*58188Selan ss.sputc(0); 123*58188Selan #else /* _OLD_STREAMS */ 124*58188Selan #ifndef HAVE_VPRINTF 125*58188Selan FILE b; 126*58188Selan b._flag = _IOWRT|_IOSTRG; 127*58188Selan b._ptr = buf; 128*58188Selan b._cnt = BUFSIZ; 129*58188Selan _doprnt(fmt, args, &b); 130*58188Selan putc('\0', &b); 131*58188Selan #else 132*58188Selan vsprintf(buf, fmt, args); 133*58188Selan #endif 134*58188Selan #endif /* _OLD_STREAMS */ 135*58188Selan va_end(args); 136*58188Selan return waddstr(w, buf); 137*58188Selan } 138*58188Selan 139*58188Selan 140*58188Selan int CursesWindow::mvprintw(int y, int x, const char * fmt, ...) 141*58188Selan { 142*58188Selan va_list args; 143*58188Selan va_start(args, fmt); 144*58188Selan int result = wmove(w, y, x); 145*58188Selan if (result == OK) 146*58188Selan { 147*58188Selan char buf[BUFSIZ]; 148*58188Selan #ifndef _OLD_STREAMS 149*58188Selan strstreambuf ss(buf, BUFSIZ); 150*58188Selan ss.vform(fmt, args); 151*58188Selan ss.sputc(0); 152*58188Selan #else /* _OLD_STREAMS */ 153*58188Selan #ifndef HAVE_VPRINTF 154*58188Selan FILE b; 155*58188Selan b._flag = _IOWRT|_IOSTRG; 156*58188Selan b._ptr = buf; 157*58188Selan b._cnt = BUFSIZ; 158*58188Selan _doprnt(fmt, args, &b); 159*58188Selan putc('\0', &b); 160*58188Selan #else 161*58188Selan vsprintf(buf, fmt, args); 162*58188Selan #endif 163*58188Selan #endif /* _OLD_STREAMS */ 164*58188Selan result = waddstr(w, buf); 165*58188Selan } 166*58188Selan va_end(args); 167*58188Selan return result; 168*58188Selan } 169*58188Selan 170*58188Selan CursesWindow::CursesWindow(int lines, int cols, int begin_y, int begin_x) 171*58188Selan { 172*58188Selan if (count==0) 173*58188Selan initscr(); 174*58188Selan 175*58188Selan w = newwin(lines, cols, begin_y, begin_x); 176*58188Selan if (w == 0) 177*58188Selan { 178*58188Selan (*lib_error_handler)("CursesWindow", "Cannot construct window"); 179*58188Selan } 180*58188Selan 181*58188Selan alloced = 1; 182*58188Selan subwins = par = sib = 0; 183*58188Selan count++; 184*58188Selan } 185*58188Selan 186*58188Selan CursesWindow::CursesWindow(WINDOW* &window) 187*58188Selan { 188*58188Selan if (count==0) 189*58188Selan initscr(); 190*58188Selan 191*58188Selan w = window; 192*58188Selan alloced = 0; 193*58188Selan subwins = par = sib = 0; 194*58188Selan count++; 195*58188Selan } 196*58188Selan 197*58188Selan CursesWindow::CursesWindow(CursesWindow& win, int l, int c, 198*58188Selan int by, int bx, char absrel) 199*58188Selan { 200*58188Selan 201*58188Selan if (absrel == 'r') // relative origin 202*58188Selan { 203*58188Selan by += win.begy(); 204*58188Selan bx += win.begx(); 205*58188Selan } 206*58188Selan 207*58188Selan // Even though we treat subwindows as a tree, the standard curses 208*58188Selan // library needs the `subwin' call to link to the root in 209*58188Selan // order to correctly perform refreshes, etc. 210*58188Selan 211*58188Selan CursesWindow* root = &win; 212*58188Selan while (root->par != 0) root = root->par; 213*58188Selan 214*58188Selan w = subwin(root->w, l, c, by, bx); 215*58188Selan if (w == 0) 216*58188Selan { 217*58188Selan (*lib_error_handler)("CursesWindow", "Cannot construct subwindow"); 218*58188Selan } 219*58188Selan 220*58188Selan par = &win; 221*58188Selan sib = win.subwins; 222*58188Selan win.subwins = this; 223*58188Selan subwins = 0; 224*58188Selan alloced = 1; 225*58188Selan count++; 226*58188Selan } 227*58188Selan 228*58188Selan 229*58188Selan void CursesWindow::kill_subwindows() 230*58188Selan { 231*58188Selan for (CursesWindow* p = subwins; p != 0; p = p->sib) 232*58188Selan { 233*58188Selan p->kill_subwindows(); 234*58188Selan if (p->alloced) 235*58188Selan { 236*58188Selan if (p->w != 0) 237*58188Selan ::delwin(p->w); 238*58188Selan p->alloced = 0; 239*58188Selan } 240*58188Selan p->w = 0; // cause a run-time error if anyone attempts to use... 241*58188Selan } 242*58188Selan } 243*58188Selan 244*58188Selan CursesWindow::~CursesWindow() 245*58188Selan { 246*58188Selan kill_subwindows(); 247*58188Selan 248*58188Selan if (par != 0) // Snip us from the parent's list of subwindows. 249*58188Selan { 250*58188Selan CursesWindow * win = par->subwins; 251*58188Selan CursesWindow * trail = 0; 252*58188Selan for (;;) 253*58188Selan { 254*58188Selan if (win == 0) 255*58188Selan break; 256*58188Selan else if (win == this) 257*58188Selan { 258*58188Selan if (trail != 0) 259*58188Selan trail->sib = win->sib; 260*58188Selan else 261*58188Selan par->subwins = win->sib; 262*58188Selan break; 263*58188Selan } 264*58188Selan else 265*58188Selan { 266*58188Selan trail = win; 267*58188Selan win = win->sib; 268*58188Selan } 269*58188Selan } 270*58188Selan } 271*58188Selan 272*58188Selan if (alloced && w != 0) 273*58188Selan delwin(w); 274*58188Selan 275*58188Selan --count; 276*58188Selan if (count == 0) 277*58188Selan endwin(); 278*58188Selan else if (count < 0) // cannot happen! 279*58188Selan { 280*58188Selan (*lib_error_handler)("CursesWindow", "Too many windows destroyed"); 281*58188Selan } 282*58188Selan } 283*58188Selan 284*58188Selan #endif /* _G_HAVE_CURSES */ 285