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