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