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