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