1238104Sdes/*	$NetBSD: keyboard.c,v 1.23 2006/05/10 21:53:48 mrg Exp $	*/
2238104Sdes
3238104Sdes/*-
4238104Sdes * Copyright (c) 1980, 1992, 1993
5238104Sdes *	The Regents of the University of California.  All rights reserved.
6238104Sdes *
7238104Sdes * Redistribution and use in source and binary forms, with or without
8238104Sdes * modification, are permitted provided that the following conditions
9238104Sdes * are met:
10238104Sdes * 1. Redistributions of source code must retain the above copyright
11238104Sdes *    notice, this list of conditions and the following disclaimer.
12238104Sdes * 2. Redistributions in binary form must reproduce the above copyright
13238104Sdes *    notice, this list of conditions and the following disclaimer in the
14238104Sdes *    documentation and/or other materials provided with the distribution.
15238104Sdes * 3. Neither the name of the University nor the names of its contributors
16238104Sdes *    may be used to endorse or promote products derived from this software
17238104Sdes *    without specific prior written permission.
18238104Sdes *
19238104Sdes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20238104Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21238104Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22238104Sdes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23238104Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24238104Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25238104Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26238104Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27238104Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28238104Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29238104Sdes * SUCH DAMAGE.
30238104Sdes */
31238104Sdes
32238104Sdes#include <sys/cdefs.h>
33238104Sdes#ifndef lint
34238104Sdes#if 0
35238104Sdesstatic char sccsid[] = "@(#)keyboard.c	8.1 (Berkeley) 6/6/93";
36238104Sdes#endif
37238104Sdes__RCSID("$NetBSD: keyboard.c,v 1.23 2006/05/10 21:53:48 mrg Exp $");
38238104Sdes#endif /* not lint */
39238104Sdes
40238104Sdes#include <sys/types.h>
41238104Sdes
42238104Sdes#include <ctype.h>
43238104Sdes#include <signal.h>
44238104Sdes#include <termios.h>
45238104Sdes#include <stdlib.h>
46238104Sdes#include <string.h>
47238104Sdes#include <signal.h>
48238104Sdes
49238104Sdes#include "systat.h"
50238104Sdes#include "extern.h"
51238104Sdes
52238104Sdesextern sig_atomic_t needsredraw;
53238104Sdes
54238104Sdesvoid
55238104Sdeskeyboard(void)
56238104Sdes{
57238104Sdes	int ch, rch, col;
58238104Sdes	char *line;
59238104Sdes	int i, linesz;
60238104Sdes	static char help[] = "help";
61238104Sdes	static char quit[] = "quit";
62238104Sdes
63238104Sdes	ch = 0;	/* XXX gcc */
64238104Sdes	linesz = COLS - 2;		/* XXX does not get updated on SIGWINCH */
65238104Sdes	if ((line = malloc(linesz)) == NULL) {
66238104Sdes		error("malloc failed");
67238104Sdes		die(0);
68238104Sdes	}
69238104Sdes
70238104Sdes	for (;;) {
71238104Sdes		col = 0;
72238104Sdes		move(CMDLINE, 0);
73238104Sdes
74238104Sdes		while (col == 0 || (ch != '\r' && ch != '\n')) {
75238104Sdes			refresh();
76238104Sdes			for (;;) {
77238104Sdes				ch = getch();
78238104Sdes				if (!needsredraw)
79238104Sdes					break;
80238104Sdes				redraw();
81238104Sdes			}
82238104Sdes			if (ch == ERR) {
83238104Sdes				display(SIGALRM);
84238104Sdes				continue;
85238104Sdes			}
86238104Sdes			if (ch == KEY_RESIZE) {
87238104Sdes				redraw();
88238104Sdes				continue;
89238104Sdes			}
90238104Sdes			ch &= 0177;
91238104Sdes			rch = ch;
92238104Sdes			if (col == 0) {
93238104Sdes				switch(ch) {
94238104Sdes				    case '\n':
95238104Sdes				    case '\r':
96238104Sdes				    case ' ':
97238104Sdes					display(0);
98238104Sdes					break;
99238104Sdes				    case CTRL('l'):
100238104Sdes					wrefresh(curscr);
101238104Sdes					break;
102238104Sdes				    case CTRL('g'):
103238104Sdes					status();
104238104Sdes					break;
105238104Sdes				    case '?':
106238104Sdes				    case 'H':
107238104Sdes				    case 'h':
108238104Sdes					command(help);
109238104Sdes					move(CMDLINE, 0);
110238104Sdes					break;
111238104Sdes				    case 'Q':
112238104Sdes				    case 'q':
113238104Sdes					command(quit);
114238104Sdes					break;
115238104Sdes				    case ':':
116238104Sdes					move(CMDLINE, 0);
117238104Sdes					clrtoeol();
118238104Sdes					addch(':');
119238104Sdes					col++;
120238104Sdes					break;
121238104Sdes				}
122238104Sdes				continue;
123238104Sdes			}
124238104Sdes			if (ch == '\b' || ch == '\?' || ch == erasechar()) {
125238104Sdes				if (col > 0)
126238104Sdes					col--;
127238104Sdes				goto doerase;
128238104Sdes			}
129238104Sdes			if (ch == CTRL('w') && col > 0) {
130238104Sdes				while (--col >= 0 &&
131238104Sdes				    isspace((unsigned char)line[col]))
132238104Sdes					continue;
133238104Sdes				col++;
134238104Sdes				while (--col >= 0 &&
135238104Sdes				    !isspace((unsigned char)line[col]))
136238104Sdes					if (col == 0)
137238104Sdes						break;
138238104Sdes				col++;
139238104Sdes				goto doerase;
140238104Sdes			}
141238104Sdes			if (ch == killchar() && col > 0) {
142238104Sdes				col = 1;
143238104Sdes		doerase:
144238104Sdes				move(CMDLINE, col);
145238104Sdes				clrtoeol();
146238104Sdes				continue;
147238104Sdes			}
148238104Sdes			if (isprint(rch) || rch == ' ') {
149238104Sdes				if (col < linesz) {
150238104Sdes					line[col] = rch;
151238104Sdes					mvaddch(CMDLINE, col, rch);
152238104Sdes					col++;
153238104Sdes				}
154238104Sdes			}
155238104Sdes		}
156238104Sdes		line[col] = '\0';
157238104Sdes		/* pass commands as lowercase */
158238104Sdes		for (i = 1; i < col ; i++)
159238104Sdes			line[i] = tolower((unsigned char)line[i]);
160238104Sdes		command(line + 1);
161238104Sdes	}
162238104Sdes	/* NOTREACHED */
163238104Sdes}
164238104Sdes