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