d1354425666537994e5fb9343a86d983f4361f4b
[ncurses.git] / c++ / cursesw.cc
1 // * this is for making emacs happy: -*-Mode: C++;-*-
2
3 /*
4   Copyright (C) 1989 Free Software Foundation
5   written by Eric Newton (newton@rocky.oswego.edu)
6
7   This file is part of the GNU C++ Library.  This library is free
8   software; you can redistribute it and/or modify it under the terms of
9   the GNU Library General Public License as published by the Free
10   Software Foundation; either version 2 of the License, or (at your
11   option) any later version.  This library is distributed in the hope
12   that it will be useful, but WITHOUT ANY WARRANTY; without even the
13   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14   PURPOSE.  See the GNU Library General Public License for more details.
15   You should have received a copy of the GNU Library General Public
16   License along with this library; if not, write to the Free Software
17   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18
19   modified by Ulrich Drepper  (drepper@karlsruhe.gmd.de)
20           and Anatoly Ivasyuk (anatoly@nick.csh.rit.edu)
21
22   modified by Juergen Pfeifer (Juergen.Pfeifer@T-Online.de)       
23 */
24
25 #include "internal.h"
26
27 MODULE_ID("$Id: cursesw.cc,v 1.5 1997/05/05 20:04:59 tom Exp $")
28
29 #pragma implementation
30
31 #include "cursesw.h"
32
33 #define COLORS_NEED_INITIALIZATION  -1
34 #define COLORS_NOT_INITIALIZED       0
35 #define COLORS_MONOCHROME            1
36 #define COLORS_ARE_REALLY_THERE      2
37
38
39 // declare static variables for the class
40 int NCursesWindow::count = 0;
41
42 int
43 NCursesWindow::scanw(const char* fmt, ...)
44 {
45 #if defined(__GNUG__)
46     va_list args;
47     va_start(args, fmt);
48     char buf[BUFSIZ];
49     int result = wgetstr(w, buf);
50     if (result == OK) {
51         strstreambuf ss(buf, BUFSIZ);
52         result = ss.vscan(fmt, args);
53     }
54     va_end(args);
55     return result;
56 #else
57     return ERR;
58 #endif
59 }
60
61
62 int
63 NCursesWindow::scanw(int y, int x, const char* fmt, ...)
64 {
65 #if defined(__GNUG__)
66     va_list args;
67     va_start(args, fmt);
68     char buf[BUFSIZ];
69     int result = wmove(w, y, x);
70     if (result == OK) {
71         result = wgetstr(w, buf);
72         if (result == OK) {
73             strstreambuf ss(buf, BUFSIZ);
74             result = ss.vscan(fmt, args);
75         }
76     }
77     va_end(args);
78     return result;
79 #else
80     return ERR;
81 #endif
82 }
83
84
85 int
86 NCursesWindow::printw(const char * fmt, ...)
87 {
88     va_list args;
89     va_start(args, fmt);
90     char buf[BUFSIZ];
91     vsprintf(buf, fmt, args);
92     va_end(args);
93     return waddstr(w, buf);
94 }
95
96
97 int
98 NCursesWindow::printw(int y, int x, const char * fmt, ...)
99 {
100     va_list args;
101     va_start(args, fmt);
102     int result = wmove(w, y, x);
103     if (result == OK) {
104         char buf[BUFSIZ];
105         vsprintf(buf, fmt, args);
106         result = waddstr(w, buf);
107     }
108     va_end(args);
109     return result;
110 }
111
112
113 void
114 NCursesWindow::init(void)
115 {
116     noecho();
117     cbreak();
118     leaveok(0);
119     keypad(1);
120 }
121
122 void
123 NCursesWindow::err_handler(const char *msg) const THROWS(NCursesException)
124 {
125   THROW(new NCursesException(msg));
126 }
127
128 void
129 NCursesWindow::initialize() {
130   ::initscr();
131   if (colorInitialized==COLORS_NEED_INITIALIZATION) {
132     colorInitialized=COLORS_NOT_INITIALIZED;
133     count++;
134     useColors();
135     count--;
136   }
137 }
138
139 NCursesWindow::NCursesWindow(int lines, int cols, int begin_y, int begin_x)
140 {
141     if (count==0)
142       initialize();
143
144     w = ::newwin(lines, cols, begin_y, begin_x);
145     if (w == 0) {
146         err_handler("Cannot construct window");
147     }
148     init();
149
150     alloced = 1;
151     subwins = par = sib = 0;
152     count++;
153 }
154
155 NCursesWindow::NCursesWindow(WINDOW* &window)
156 {
157     if (count==0)
158       initialize();
159     
160     w = window;
161     init();
162     alloced = 0;
163     subwins = par = sib = 0;
164     count++;
165 }
166
167
168 NCursesWindow::NCursesWindow(NCursesWindow& win, int l, int c,
169                              int by, int bx, char absrel)
170 {
171     if (absrel == 'r') { // relative origin 
172         by += win.begy();
173         bx += win.begx();
174     }
175
176     // Even though we treat subwindows as a tree, the standard curses
177     // library needs the `subwin' call to link to the root in
178     // order to correctly perform refreshes, etc.
179
180     NCursesWindow* root = &win;
181     while (root->par != 0) root = root->par;
182
183     w = subwin(root->w, l, c, by, bx);
184     if (w == 0) {
185         err_handler("Cannot construct subwindow");
186     }
187
188     par = &win;
189     sib = win.subwins;
190     win.subwins = this;
191     subwins = 0;
192     alloced = 1;
193     count++;
194 }
195
196 bool
197 NCursesWindow::isDescendant(NCursesWindow& win) {
198   for (NCursesWindow* p = subwins; p != NULL; p = p->sib) {
199     if (p==&win)
200       return TRUE;
201     else {
202       if (p->isDescendant(win))
203         return TRUE;
204     }
205   }
206   return FALSE;
207 }
208
209 void
210 NCursesWindow::kill_subwindows()
211 {
212     for (NCursesWindow* p = subwins; p != 0; p = p->sib) {
213         p->kill_subwindows();
214         if (p->alloced) {
215             if (p->w != 0)
216                 ::delwin(p->w);
217             p->alloced = 0;
218         }
219         p->w = 0; // cause a run-time error if anyone attempts to use...
220     }
221 }
222
223
224 NCursesWindow::~NCursesWindow()
225 {
226     kill_subwindows();
227
228     if (par != 0) {  // Snip us from the parent's list of subwindows.
229         NCursesWindow * win = par->subwins;
230         NCursesWindow * trail = 0;
231         for (;;) {
232             if (win == 0)
233                 break;
234             else if (win == this) {
235                 if (trail != 0)
236                     trail->sib = win->sib;
237                 else
238                     par->subwins = win->sib;
239                 break;
240             } else {
241                 trail = win;
242                 win = win->sib;
243             }
244         }
245     }
246
247     if (alloced && w != 0)
248         delwin(w);
249
250     --count;
251     if (count == 0)
252         endwin();
253     else if (count < 0) { // cannot happen!
254         err_handler("Too many windows destroyed");
255     }
256 }
257
258 // ---------------------------------------------------------------------
259 // Color stuff
260 //
261 int NCursesWindow::colorInitialized = COLORS_NOT_INITIALIZED;
262
263 void
264 NCursesWindow::useColors(void)
265 {
266     if (colorInitialized == COLORS_NOT_INITIALIZED) {        
267       if (count>0) {
268         if (has_colors()) {
269           start_color();
270           colorInitialized = COLORS_ARE_REALLY_THERE;
271         }
272         else
273           colorInitialized = COLORS_MONOCHROME;
274       }
275       else
276         colorInitialized = COLORS_NEED_INITIALIZATION;
277     }
278 }
279
280 short
281 NCursesWindow::getcolor(int getback) const 
282 {
283     short fore, back;
284
285     if (colorInitialized==COLORS_ARE_REALLY_THERE) {
286       if (pair_content(PAIR_NUMBER(w->_attrs), &fore, &back))
287         err_handler("Can't get color pair");
288     }
289     else {
290       // Monochrome means white on black
291       back = COLOR_BLACK;
292       fore = COLOR_WHITE;
293     }
294     return getback ? back : fore;
295 }
296
297 int NCursesWindow::NumberOfColors()
298 {
299   if (colorInitialized==COLORS_ARE_REALLY_THERE)
300     return COLORS;
301   else
302     return 1; // monochrome (actually there are two ;-)
303 }
304
305 short
306 NCursesWindow::getcolor() const 
307 {
308   if (colorInitialized==COLORS_ARE_REALLY_THERE)
309     return PAIR_NUMBER(w->_attrs);
310   else
311     return 0; // we only have pair zero
312 }
313
314 int
315 NCursesWindow::setpalette(short fore, short back, short pair)
316 {
317   if (colorInitialized==COLORS_ARE_REALLY_THERE)
318     return init_pair(pair, fore, back);
319   else
320     return OK;
321 }
322
323 int
324 NCursesWindow::setpalette(short fore, short back)
325 {
326   if (colorInitialized==COLORS_ARE_REALLY_THERE)
327     return setpalette(fore, back, PAIR_NUMBER(w->_attrs));
328   else
329     return OK;
330 }
331
332
333 int
334 NCursesWindow::setcolor(short pair)
335 {
336   if (colorInitialized==COLORS_ARE_REALLY_THERE) {
337     if ((pair < 1) || (pair > COLOR_PAIRS))
338       err_handler("Can't set color pair");
339     
340     attroff(A_COLOR);
341     attrset(COLOR_PAIR(pair));
342   }
343   return OK;
344 }