/*
- Generalized consol input/output handler
- Kern Sibbald, December MMIII
+ Generalized console input/output handler
+ A maintanable replacement for readline()
+
+ Kern Sibbald, December MMIII
+
+ This code is in part derived from code that I wrote in
+ 1981, so some of it is a bit old and could use a cleanup.
+
*/
+/*
+ Copyright (C) 1981-2004 Kern Sibbald and John Walker
-#define BACULA
-#ifdef BACULA
-#include "bacula.h"
-#else
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ */
+
+
+#ifdef TEST_PROGRAM
#include <stdio.h>
#include <unistd.h>
+#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <ctype.h>
-#endif
-
-#include <curses.h>
-#include <term.h>
-#include "func.h"
+#else
-/* Global functions imported */
+/* We are in Bacula */
+#include "bacula.h"
+#endif
-extern char *getenv(char *);
+#include <termios.h>
+#include <termcap.h>
+#include "func.h"
-static void add_smap(char *str, int func);
/* From termios library */
extern char *BC;
extern char *UP;
+/* Forward referenced functions */
+static void sigintcatcher(int);
+static void add_smap(char *str, int func);
+
+
/* Global variables */
static char *t_up = "\n"; /* scroll up character */
static char *t_honk = "\007"; /* sound beep */
-static char *t_flag = "+"; /* mark flag sequence */
-static char *t_norm = " "; /* clear mark sequence */
static char *t_il; /* insert line */
static char *t_dl; /* delete line */
static char *t_cs; /* clear screen */
static char *t_cl; /* clear line */
static int t_width = 79; /* terminal width */
static int t_height = 24; /* terminal height */
-static int t_flagl = 1; /* # chars for flag */
static int linsdel_ok = 0; /* set if term has line insert & delete fncs */
-static short dioflag = 1; /* set if ok to use ibm bios calls */
static char *t_cm; /* cursor positioning */
static char *t_ti; /* init sequence */
/* Keypad and Function Keys */
static char *kl; /* left key */
static char *kr; /* right */
-static char *ku;
-static char *kd;
+static char *ku; /* up */
+static char *kd; /* down */
static char *kh; /* home */
static char *kb; /* backspace */
-static char *k0; /* function key 10 */
-static char *k1; /* function key 1 */
-static char *k2; /* function key 2 */
-static char *k3; /* function key 3 */
-static char *k4; /* function key 4 */
-static char *k5; /* function key 5 */
-static char *k6; /* function key 6 */
-static char *k7; /* function key 7 */
-static char *k8; /* function key 8 */
-static char *k9; /* function key 9 */
static char *kD; /* delete key */
static char *kI; /* insert */
static char *kN; /* next page */
static char *kH; /* home */
static char *kE; /* end */
-static int use_termcap;
#ifndef EOS
#define EOS '\0' /* end of string terminator */
#endif
static stab_t **stab = NULL; /* array of stabs by length */
static int num_stab; /* size of stab array */
-/* Local variables */
-
+static bool old_term_params_set = false;
static struct termios old_term_params;
/* Maintain lines in a doubly linked circular pool of lines. Each line is
static int mode_insert = 0;
static int mode_wspace = 1; /* words separated by spaces */
-/* Forward referenced functions */
-static void sigintcatcher(int);
-
-/* Global variables Exported */
static short char_map[600]= {
- 0, F_NXTWRD, /* ^A Next Word */
- F_SPLIT, /* ^B Split line */ F_EOI, /* ^C Quit */
- F_DELCHR, /* ^D Delete character */ F_EOF, /* ^E End of file */
- F_INSCHR, /* ^F Insert character */ F_TABBAK, /* ^G Back tab */
+ 0, F_SOL, /* ^a Line start */
+ F_PRVWRD, /* ^b Previous word */ F_BREAK, /* ^C break */
+ F_DELCHR, /* ^D Delete character */ F_EOL, /* ^e End of line */
+ F_CSRRGT, /* ^f Right */ F_TABBAK, /* ^G Back tab */
F_CSRLFT, /* ^H Left */ F_TAB, /* ^I Tab */
- F_CSRDWN, /* ^J Down */ F_CSRUP, /* ^K Up */
- F_CSRRGT, /* ^L Right */ F_RETURN, /* ^M Carriage return */
- F_EOL, /* ^N End of line */ F_CONCAT, /* ^O Concatenate lines */
- F_MARK, /* ^P Set marker */ F_TINS, /* ^Q Insert character mode */
+ F_CSRDWN, /* ^J Down */ F_DELEOL, /* ^K kill to eol */
+ F_CLRSCRN,/* ^L clear screen */ F_RETURN, /* ^M Carriage return */
+ F_RETURN, /* ^N enter line */ F_CONCAT, /* ^O Concatenate lines */
+ F_CSRUP, /* ^P cursor up */ F_TINS, /* ^Q Insert character mode */
F_PAGUP, /* ^R Page up */ F_CENTER, /* ^S Center text */
- F_PAGDWN, /* ^T Page down */ F_SOL, /* ^U Line start */
+ F_PAGDWN, /* ^T Page down */ F_DELSOL, /* ^U delete to start of line */
F_DELWRD, /* ^V Delete word */ F_PRVWRD, /* ^W Previous word */
F_NXTMCH, /* ^X Next match */ F_DELEOL, /* ^Y Delete to end of line */
- F_DELLIN, /* ^Z Delete line */ 0x1B, /* ^[=ESC escape */
+ F_BACKGND,/* ^Z Background */ 0x1B, /* ^[=ESC escape */
F_TENTRY, /* ^\ Entry mode */ F_PASTECB,/* ^]=paste clipboard */
F_HOME, /* ^^ Home */ F_ERSLIN, /* ^_ Erase line */
+
' ','!','"','#','$','%','&','\047',
'(',')','*','+','\054','-','.','/',
'0','1','2','3','4','5','6','7',
static void t_insert_line(void);
static void t_delete_line(void);
static void t_clrline(int pos, int width);
-static void t_sendl(char *msg, int len);
-static void t_send(char *msg);
-static void t_char(char c);
+void t_sendl(char *msg, int len);
+void t_send(char *msg);
+void t_char(char c);
+static void asclrs();
+static void ascurs(int y, int x);
-static void rawmode(void);
+static void rawmode(FILE *input);
static void normode(void);
static int t_getch();
-static void trapctlc();
static void asclrl(int pos, int width);
static void asinsl();
static void asdell();
int input_line(char *string, int length);
-
-void con_init()
+void con_term();
+void trapctlc();
+
+void con_init(FILE *input)
{
- rawmode();
+ atexit(con_term);
+ rawmode(input);
trapctlc();
}
+/*
+ * Zed control keys
+ */
+void con_set_zed_keys(void)
+{
+ char_map[1] = F_NXTWRD; /* ^A Next Word */
+ char_map[2] = F_SPLIT; /* ^B Split line */
+ char_map[3] = F_EOI; /* ^C Quit */
+ char_map[4] = F_DELCHR; /* ^D Delete character */
+ char_map[5] = F_EOF; /* ^E End of file */
+ char_map[6] = F_INSCHR; /* ^F Insert character */
+ char_map[7] = F_TABBAK; /* ^G Back tab */
+ char_map[8] = F_CSRLFT; /* ^H Left */
+ char_map[9] = F_TAB; /* ^I Tab */
+ char_map[10] = F_CSRDWN; /* ^J Down */
+ char_map[11] = F_CSRUP; /* ^K Up */
+ char_map[12] = F_CSRRGT; /* ^L Right */
+ char_map[13] = F_RETURN; /* ^M Carriage return */
+ char_map[14] = F_EOL; /* ^N End of line */
+ char_map[15] = F_CONCAT; /* ^O Concatenate lines */
+ char_map[16] = F_MARK; /* ^P Set marker */
+ char_map[17] = F_TINS; /* ^Q Insert character mode */
+ char_map[18] = F_PAGUP; /* ^R Page up */
+ char_map[19] = F_CENTER; /* ^S Center text */
+ char_map[20] = F_PAGDWN; /* ^T Page down */
+ char_map[21] = F_SOL; /* ^U Line start */
+ char_map[22] = F_DELWRD; /* ^V Delete word */
+ char_map[23] = F_PRVWRD; /* ^W Previous word */
+ char_map[24] = F_NXTMCH; /* ^X Next match */
+ char_map[25] = F_DELEOL; /* ^Y Delete to end of line */
+ char_map[26] = F_DELLIN; /* ^Z Delete line */
+ /* 27 = ESC */
+ char_map[28] = F_TENTRY; /* ^\ Entry mode */
+ char_map[29] = F_PASTECB;/* ^]=paste clipboard */
+ char_map[30] = F_HOME; /* ^^ Home */
+ char_map[31] = F_ERSLIN; /* ^_ Erase line */
+
+}
+
void con_term()
{
normode();
}
-#ifndef BACULA
+#ifdef TEST_PROGRAM
/*
* Guarantee that the string is properly terminated */
-static char *bstrncpy(char *dest, const char *src, int maxlen)
+char *bstrncpy(char *dest, const char *src, int maxlen)
{
strncpy(dest, src, maxlen-1);
dest[maxlen-1] = 0;
/* Get the next character from the terminal - performs table lookup on
the character to do the desired translation */
static int
-/*FCN*/input_char()
+input_char()
{
int c;
if (c == F_SCRSIZ) {
int y, x;
y = t_gnc() - 0x20; /* y */
- x = t_gnc() - 0x20; /* x */
+ x = t_gnc() - 0x20; /* x */
c = input_char();
}
return c;
/* Get a complete input line */
int
-/*FCN*/input_line(char *string, int length)
+input_line(char *string, int length)
{
char curline[200]; /* edit buffer */
int noline;
case F_RETURN: /* CR */
t_sendl("\r\n", 2); /* yes, print it and */
goto done; /* get out */
+ case F_CLRSCRN: /* clear screen */
+ asclrs();
+ t_sendl(curline, cl);
+ ascurs(0, cp);
+ break;
case F_CSRUP:
-#ifdef xxx
if (noline) { /* no line fetched yet */
getnext(); /* getnext so getprev gets current */
noline = 0; /* we now have line */
}
-#endif
bstrncpy(curline, getprev(), sizeof(curline));
prtcur(curline);
break;
/* Insert a space at the current cursor position */
static void
-/*FCN*/insert_space(char *curline, int curline_len)
+insert_space(char *curline, int curline_len)
{
int i;
/* Move cursor forward keeping characters under it */
static void
-/*FCN*/forward(int i,char *str, int str_len)
+forward(int i,char *str, int str_len)
{
while (i--) {
if (cp > str_len) {
/* Backup cursor keeping characters under it */
static void
-/*FCN*/backup(int i)
+backup(int i)
{
for ( ;i && cp; i--,cp--)
t_char('\010');
/* Delete the character under the cursor */
static void
-/*FCN*/delchr(int cnt, char *curline, int line_len)
+delchr(int cnt, char *curline, int line_len)
{
register int i;
/* Determine if character is part of a word */
static int
-/*FCN*/iswordc(char c)
+iswordc(char c)
{
if (mode_wspace)
return !isspace(c);
/* Return number of characters to get to next word */
static int
-/*FCN*/next_word(char *ldb_buf)
+next_word(char *ldb_buf)
{
int ncp;
/* Return number of characters to get to previous word */
static int
-/*FCN*/prev_word(char *ldb_buf)
+prev_word(char *ldb_buf)
{
int ncp, i;
/* Display new current line */
static void
-/*FCN*/prtcur(char *str)
+prtcur(char *str)
{
backup(cp);
t_clrline(0,t_width);
/* Initialize line pool. Split pool into two pieces. */
static void
-/*FCN*/poolinit()
+poolinit()
{
slptr = lptr = (struct lstr *)pool;
lptr->nextl = lptr;
/* Return pointer to next line in the pool and advance current line pointer */
static char *
-/*FCN*/getnext()
+getnext()
{
do { /* find next used line */
lptr = lptr->nextl;
/* Return pointer to previous line in the pool */
static char *
-/*FCN*/getprev()
+getprev()
{
do { /* find previous used line */
lptr = lptr->prevl;
}
static void
-/*FCN*/putline(char *newl, int newlen)
+putline(char *newl, int newlen)
{
struct lstr *nptr; /* points to next line */
char *p;
#ifdef DEBUGOUT
static void
-/*FCN*/dump(struct lstr *ptr, char *msg)
+dump(struct lstr *ptr, char *msg)
{
printf("%s buf=%x nextl=%x prevl=%x len=%d used=%d\n",
msg,ptr,ptr->nextl,ptr->prevl,ptr->len,ptr->used);
/* Honk horn on terminal */
static void
-/*FCN*/t_honk_horn()
+t_honk_horn()
{
t_send(t_honk);
}
/* Insert line on terminal */
static void
-/*FCN*/t_insert_line()
+t_insert_line()
{
asinsl();
}
/* Delete line from terminal */
static void
-/*FCN*/t_delete_line()
+t_delete_line()
{
asdell();
}
/* clear line from pos to width */
static void
-/*FCN*/t_clrline(int pos, int width)
+t_clrline(int pos, int width)
{
asclrl(pos, width); /* clear to end of line */
}
mode in which all characters can be read as they are entered. CBREAK
mode is not sufficient.
*/
-/*FCN*/static void rawmode(void)
+static void rawmode(FILE *input)
{
struct termios t;
static char term_buf[2048];
static char *term_buffer = term_buf;
char *termtype = (char *)getenv("TERM");
+ /* Make sure we are dealing with a terminal */
+ if (!isatty(fileno(input))) {
+ return;
+ }
if (tcgetattr(0, &old_term_params) != 0) {
- printf("Cannot tcgetattr()\n");
+ printf("conio: Cannot tcgetattr()\n");
exit(1);
}
+ old_term_params_set = true;
t = old_term_params;
t.c_cc[VMIN] = 1; /* satisfy read after 1 char */
t.c_cc[VTIME] = 0;
t.c_iflag &= ~(BRKINT | IGNPAR | PARMRK | INPCK |
ISTRIP | ICRNL | IXON | IXOFF | INLCR | IGNCR);
t.c_iflag |= IGNBRK;
- t.c_oflag &= ~(OPOST); /* no output processing */
+ t.c_oflag |= ONLCR;
t.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL | ICANON |
- ISIG | NOFLSH | TOSTOP);
+ NOFLSH | TOSTOP);
tcflush(0, TCIFLUSH);
if (tcsetattr(0, TCSANOW, &t) == -1) {
printf("Cannot tcsetattr()\n");
}
+ /* Defaults, the main program can override these */
signal(SIGQUIT, SIG_IGN);
signal(SIGHUP, SIG_IGN);
- signal(SIGSTOP, SIG_IGN);
+// signal(SIGSTOP, SIG_IGN);
signal(SIGINT, sigintcatcher);
signal(SIGWINCH, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
signal(SIGCHLD, SIG_IGN);
- signal(SIGTSTP, SIG_IGN);
+// signal(SIGTSTP, SIG_IGN);
if (!termtype) {
printf("Cannot get terminal type.\n");
t_up = (char *)tgetstr("up", &term_buffer);
t_do = (char *)tgetstr("do", &term_buffer);
t_sf = (char *)tgetstr("sf", &term_buffer);
- t_flag = (char *)tgetstr("so", &term_buffer);
- t_norm = (char *)tgetstr("se", &term_buffer);
-
-
-
- dioflag = 1;
- use_termcap = 1;
- t_flagl = tgetnum("sg");
- if (t_flagl < 0) {
- t_flagl = 0;
- }
num_stab = MAX_STAB; /* get default stab size */
stab = (stab_t **)malloc(sizeof(stab_t *) * num_stab);
kd = (char *)tgetstr("kd", &term_buffer);
kh = (char *)tgetstr("kh", &term_buffer);
kb = (char *)tgetstr("kb", &term_buffer);
- k0 = (char *)tgetstr("k0", &term_buffer);
- k1 = (char *)tgetstr("k1", &term_buffer);
- k2 = (char *)tgetstr("k2", &term_buffer);
- k3 = (char *)tgetstr("k3", &term_buffer);
- k4 = (char *)tgetstr("k4", &term_buffer);
- k5 = (char *)tgetstr("k5", &term_buffer);
- k6 = (char *)tgetstr("k6", &term_buffer);
- k7 = (char *)tgetstr("k7", &term_buffer);
- k8 = (char *)tgetstr("k8", &term_buffer);
- k9 = (char *)tgetstr("k9", &term_buffer);
kD = (char *)tgetstr("kD", &term_buffer);
kI = (char *)tgetstr("kI", &term_buffer);
kN = (char *)tgetstr("kN", &term_buffer);
add_esc_smap("[2~", F_TINS);
add_esc_smap("[3~", F_DELCHR);
add_esc_smap("[4~", F_EOF);
+ add_esc_smap("f", F_NXTWRD);
+ add_esc_smap("b", F_PRVWRD);
+
#ifdef needed
for (i=301; i<600; i++) {
/* Restore tty mode */
-/*FCN*/static void normode()
+static void normode()
{
- tcsetattr(0, TCSANOW, &old_term_params);
+ if (old_term_params_set) {
+ tcsetattr(0, TCSANOW, &old_term_params);
+ old_term_params_set = false;
+ }
}
/* Get next character from terminal/script file/unget buffer */
static int
-/*FCN*/t_gnc()
+t_gnc()
{
- int ch;
-
- while ((ch=t_getch()) == 0) ; /* get next input character */
- return(ch);
+ return t_getch();
}
#endif
/* Send message to terminal - primitive routine */
-static void
-/*FCN*/t_sendl(char *msg,int len)
+void
+t_sendl(char *msg,int len)
{
write(1, msg, len);
}
-static void
-/*FCN*/t_send(char *msg)
+void
+t_send(char *msg)
{
if (msg == NULL) {
return;
t_sendl(msg, strlen(msg)); /* faster than one char at time */
}
-/* Send single character to terminal - primitive routine -
- NOTE! don't convert this routine to use the dioflag routines unless
- those routines are made to simulate a backspace. */
-static void
-/*FCN*/t_char(char c)
+/* Send single character to terminal - primitive routine - */
+void
+t_char(char c)
{
write(1, &c, 1);
}
static int brkflg = 0; /* set on user break */
/* Routine to return true if user types break */
-/*FCN*/int usrbrk()
+int usrbrk()
{
return brkflg;
}
/* Interrupt caught here */
static void sigintcatcher(int sig)
{
- brkflg = 1;
+ brkflg++;
signal(SIGINT, sigintcatcher);
}
/* Trap Ctl-C */
-/*FCN*/void trapctlc()
+void trapctlc()
{
signal(SIGINT, sigintcatcher);
}
}
-#ifdef xxx
/* ASCURS -- Set cursor position */
static void ascurs(int y, int x)
t_send(t_cs);
}
-#endif
/* ASINSL -- insert new line after cursor */