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