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
scanw(const char * fmt,...)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
mvscanw(int y,int x,const char * fmt,...)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
printw(const char * fmt,...)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
mvprintw(int y,int x,const char * fmt,...)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
CursesWindow(int lines,int cols,int begin_y,int begin_x)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
CursesWindow(WINDOW * & window)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
CursesWindow(CursesWindow & win,int l,int c,int by,int bx,char absrel)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
kill_subwindows()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
~CursesWindow()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