Cauterized out the low-level environment operations and put them in
[sw-tools] / src / pres_curses.c
CommitLineData
3315e8b3 1/* -*-c-*-
2 *
37aa0f71 3 * $Id: pres_curses.c,v 1.5 1999/07/27 12:49:16 mdw Exp $
3315e8b3 4 *
5 * Curses-based output presentation
6 *
7 * (c) 1999 EBI
8 */
9
10/*----- Licensing notice --------------------------------------------------*
11 *
12 * This file is part of sw-tools.
13 *
14 * sw-tools is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * sw-tools is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with sw-tools; if not, write to the Free Software Foundation,
26 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 */
28
29/*----- Revision history --------------------------------------------------*
30 *
31 * $Log: pres_curses.c,v $
37aa0f71 32 * Revision 1.5 1999/07/27 12:49:16 mdw
33 * Slight tidying of resizing terminal handling.
34 *
35 * Revision 1.4 1999/07/16 16:52:28 mdw
4840d4f1 36 * `wbkdset' doesn't work so well. Use `wbkgd' instead.
37 *
5636c0ce 38 * Revision 1.3 1999/07/16 12:49:58 mdw
39 * Improve exit status display. New interface from `doto' project.
40 *
63124806 41 * Revision 1.2 1999/06/24 15:51:16 mdw
42 * Fix signal handlers so they don't corrupt `errno'.
43 *
44 * Revision 1.1.1.1 1999/06/02 16:53:35 mdw
45 * Initial import.
3315e8b3 46 *
47 */
48
49/*----- Header files ------------------------------------------------------*/
50
51#include "config.h"
52#ifdef HAVE_CURSES
53
54#include <errno.h>
55#include <signal.h>
56#include <stdio.h>
57#include <stdlib.h>
58#include <string.h>
59
60#include <sys/types.h>
61#include <unistd.h>
62
63#if defined(HAVE_NCURSES_H)
64# include <ncurses.h>
65#elif defined(HAVE_NCURSES_NCURSES_H)
66# include <ncurses/ncurses.h>
67#elif defined(HAVE_CURSES_H)
68# include <curses.h>
69#else
70# error "Where's your <curses.h> header?"
71#endif
72#include <term.h>
73
74#include <mLib/alloc.h>
75#include <mLib/report.h>
76
77#include "sw.h"
78#include "sw_arch.h"
79#include "pres_curses.h"
80
81#ifndef SIGWINCH
82# undef HAVE_WRESIZE
83#endif
84
85/*----- Data structures ---------------------------------------------------*/
86
87typedef struct cwin {
88 struct cwin *next;
89 WINDOW *w;
90 int top;
91 int height;
92 WINDOW *s;
93 archent *e;
94} cwin;
95
96/*----- Static variables --------------------------------------------------*/
97
98static cwin *cwins = 0;
99static int nwins = 0;
100
101/*----- Main code ---------------------------------------------------------*/
102
103/* --- @sizes@ --- *
104 *
105 * Arguments: ---
106 *
107 * Returns: ---
108 *
109 * Use: Calculates window sizes for all the windows. The heights are
110 * determined in a way which doesn't allow rounding errors to be
111 * an issue (although there will be up to a line's height
112 * difference between two windows). No actual changing of
113 * curses structures is done.
114 */
115
116static void sizes(void)
117{
118 cwin *c;
119 int t = 0, h = LINES, w = nwins;
120
121 for (c = cwins; c; c = c->next) {
122 int a = h / w;
123 c->top = t;
124 c->height = a - 1;
125 t += a;
126 h -= a;
127 w--;
128 }
129}
130
131/* --- @sig_tstp@ --- */
132
133#ifdef SIGTSTP
134static void sig_tstp(int s)
135{
63124806 136 int e = errno;
3315e8b3 137 endwin();
63124806 138 errno = e;
3315e8b3 139 raise(SIGSTOP);
140}
141#endif
142
143/* --- @sig_cont@ --- */
144
145#ifdef SIGTSTP
146static void sig_cont(int s)
147{
63124806 148 int e = errno;
3315e8b3 149 wrefresh(curscr);
63124806 150 errno = e;
3315e8b3 151}
152#endif
153
154/* --- @sig_winch@ --- */
155
37aa0f71 156#ifdef SIGWINCH
3315e8b3 157
158static void sig_winch(int s)
159{
63124806 160 int e = errno;
161
37aa0f71 162#ifdef HAVE_WRESIZE
163 cwin *c;
164
3315e8b3 165 endwin();
37aa0f71 166 wrefresh(curscr);
3315e8b3 167 sizes();
168 for (c = cwins; c; c = c->next) {
169 mvwin(c->w, c->top, 0);
170 wresize(c->w, c->height, COLS);
171 mvwin(c->s, c->top + c->height, 0);
172 wnoutrefresh(c->w);
173 wnoutrefresh(c->s);
174 }
175 doupdate();
37aa0f71 176#else
177 endwin();
178 wrefresh(curscr);
179#endif
63124806 180 errno = e;
3315e8b3 181}
182
183#endif
184
185/* --- @curses_ok@ --- */
186
187int curses_ok(void)
188{
189 if (!isatty(STDOUT_FILENO)) {
190 moan("can't use curses: stdout isn't a terminal");
191 return (0);
192 }
193 if (setupterm(0, STDOUT_FILENO, 0) == ERR) {
194 moan("can't use curses: couldn't read terminfo");
195 return (0);
196 }
197 if (!tigetstr("cup")) {
198 moan("can't use curses: terminal insufficiently winning");
199 return (0);
200 }
201 return (1);
202}
203
204/* --- @curses_init@ --- */
205
206int curses_init(archcons *a)
207{
208 cwin **cc = &cwins, *c;
209
210 /* --- Allocate my window structures --- */
211
212 nwins = 0;
213 for (; a; a = a->cdr) {
214 archent *e = a->car;
215 if (!e->r)
216 continue;
217 c = xmalloc(sizeof(cwin));
218 e->pres = c;
219 c->w = 0;
220 c->e = e;
221 nwins++;
222 *cc = c;
223 cc = &c->next;
224 }
225 *cc = 0;
226
227 /* --- Haul curses up by its naughty bits --- */
228
229 initscr();
230 keypad(stdscr, TRUE);
231 cbreak();
232 noecho();
233 nonl();
234 def_prog_mode();
235
236 /* --- Grind through everything setting up windows --- */
237
238 sizes();
239 for (c = cwins; c; c = c->next) {
240 if ((c->w = newwin(c->height, COLS, c->top, 0)) == 0 ||
241 (c->s = newwin(1, COLS, c->top + c->height, 0)) == 0)
242 goto fail_0;
243 scrollok(c->w, TRUE);
244 leaveok(c->w, TRUE);
245 leaveok(c->s, TRUE);
4840d4f1 246 wbkgd(c->s, A_STANDOUT);
5636c0ce 247 mvwprintw(c->s, 0, 0, " %s [running]\n", c->e->arch);
3315e8b3 248 wnoutrefresh(c->w);
249 wnoutrefresh(c->s);
250 }
251 doupdate();
252
253#ifdef HAVE_WRESIZE
254 signal(SIGWINCH, sig_winch);
255#endif
256#ifdef SIGTSTP
257 signal(SIGTSTP, sig_tstp);
258 signal(SIGCONT, sig_cont);
259#endif
260 return (0);
261
262fail_0:
263 c = cwins;
264 while (c) {
265 cwin *cc = c->next;
266 if (c->w)
267 delwin(c->w);
268 if (c->s)
269 delwin(c->s);
270 free(c);
271 c = cc;
272 }
273 endwin();
274 return (-1);
275}
276
277/* --- @curses_output@ --- */
278
279void curses_output(archent *e, const char *p, size_t sz)
280{
281 cwin *c = e->pres;
282 while (sz) {
283 waddch(c->w, *p);
284 p++;
285 sz--;
286 }
287 wrefresh(c->w);
288}
289
290/* --- @curses_close@ --- */
291
5636c0ce 292void curses_close(archent *e, int ok, const char *summ)
3315e8b3 293{
294 cwin *c = e->pres;
5636c0ce 295 mvwprintw(c->s, 0, 0, " %s [%s]\n", e->arch, summ);
3315e8b3 296 wrefresh(c->s);
297}
298
299/* --- @curses_done@ --- */
300
301void curses_done(archcons *a)
302{
303 if (opt_flags & optFlag_beep) {
304 beep();
305 doupdate();
306 }
307 wgetch(cwins->w);
308 cwins = 0;
309 for (; a; a = a->cdr) {
310 archent *e = a->car;
311 cwin *c = e->pres;
312 delwin(c->w);
313 delwin(c->s);
314 free(c);
315 }
316 curses_abort(0);
317}
318
319/* --- @curses_abort@ --- */
320
321void curses_abort(archcons *a)
322{
323#ifdef HAVE_WRESIZE
324 signal(SIGWINCH, SIG_DFL);
325#endif
326#ifdef SIGTSTP
327 signal(SIGTSTP, SIG_DFL);
328 signal(SIGCONT, SIG_DFL);
329#endif
330 endwin();
331}
332
333/*----- That's all, folks -------------------------------------------------*/
334
335#else
336 int pres_curses__built = 1;
337#endif