From 43a83e6e96ce1bce7fffa2060278d7acdaafa445 Mon Sep 17 00:00:00 2001 From: Paul LeoNerd Evans Date: Thu, 8 Mar 2012 21:15:25 +0000 Subject: [PATCH] Move the terminal start/stop code into their own functions, exported (undocumented for now) --- termkey-internal.h | 1 + termkey.c | 124 ++++++++++++++++++++++++++++----------------- termkey.h.in | 3 ++ 3 files changed, 81 insertions(+), 47 deletions(-) diff --git a/termkey-internal.h b/termkey-internal.h index e277939..17ff677 100644 --- a/termkey-internal.h +++ b/termkey-internal.h @@ -45,6 +45,7 @@ struct _TermKey { int waittime; // msec char is_closed; + char is_started; int nkeynames; const char **keynames; diff --git a/termkey.c b/termkey.c index 8e443d1..9286149 100644 --- a/termkey.c +++ b/termkey.c @@ -195,6 +195,7 @@ static TermKey *termkey_alloc(void) tk->waittime = 50; /* msec */ tk->is_closed = 0; + tk->is_started = 0; tk->nkeynames = 64; tk->keynames = NULL; @@ -270,51 +271,10 @@ static int termkey_init(TermKey *tk, const char *term) goto abort_free_keynames; } - if(tk->fd != -1 && !(tk->flags & TERMKEY_FLAG_NOTERMIOS)) { - struct termios termios; - if(tcgetattr(tk->fd, &termios) == 0) { - tk->restore_termios = termios; - tk->restore_termios_valid = 1; - - termios.c_iflag &= ~(IXON|INLCR|ICRNL); - termios.c_lflag &= ~(ICANON|ECHO); - termios.c_cc[VMIN] = 1; - termios.c_cc[VTIME] = 0; - - if(tk->flags & TERMKEY_FLAG_CTRLC) - /* want no signal keys at all, so just disable ISIG */ - termios.c_lflag &= ~ISIG; - else { - /* Disable Ctrl-\==VQUIT and Ctrl-D==VSUSP but leave Ctrl-C as SIGINT */ - termios.c_cc[VQUIT] = _POSIX_VDISABLE; - termios.c_cc[VSUSP] = _POSIX_VDISABLE; - /* Some OSes have Ctrl-Y==VDSUSP */ -#ifdef VDSUSP - termios.c_cc[VDSUSP] = _POSIX_VDISABLE; -#endif - } - -#ifdef DEBUG - fprintf(stderr, "Setting termios(3) flags\n"); -#endif - tcsetattr(tk->fd, TCSANOW, &termios); - } - } - - struct TermKeyDriverNode *p; - for(p = tk->drivers; p; p = p->next) - if(p->driver->start_driver) - if(!(*p->driver->start_driver)(tk, p->info)) - goto abort_free_drivers; - -#ifdef DEBUG - fprintf(stderr, "Drivers started; termkey instance %p is ready\n", tk); -#endif - return 1; abort_free_drivers: - for(p = tk->drivers; p; ) { + for(struct TermKeyDriverNode *p = tk->drivers; p; ) { (*p->driver->free_driver)(p->info); struct TermKeyDriverNode *next = p->next; free(p); @@ -361,12 +321,17 @@ TermKey *termkey_new(int fd, int flags) const char *term = getenv("TERM"); - if(!termkey_init(tk, term)) { - free(tk); - return NULL; - } + if(!termkey_init(tk, term)) + goto abort; + + if(!termkey_start(tk)) + goto abort; return tk; + +abort: + free(tk); + return NULL; } TermKey *termkey_new_abstract(const char *term, int flags) @@ -384,6 +349,8 @@ TermKey *termkey_new_abstract(const char *term, int flags) return NULL; } + termkey_start(tk); + return tk; } @@ -405,6 +372,67 @@ void termkey_free(TermKey *tk) void termkey_destroy(TermKey *tk) { + if(tk->is_started) + termkey_stop(tk); + + termkey_free(tk); +} + +int termkey_start(TermKey *tk) +{ + if(tk->is_started) + return 1; + + if(tk->fd != -1 && !(tk->flags & TERMKEY_FLAG_NOTERMIOS)) { + struct termios termios; + if(tcgetattr(tk->fd, &termios) == 0) { + tk->restore_termios = termios; + tk->restore_termios_valid = 1; + + termios.c_iflag &= ~(IXON|INLCR|ICRNL); + termios.c_lflag &= ~(ICANON|ECHO); + termios.c_cc[VMIN] = 1; + termios.c_cc[VTIME] = 0; + + if(tk->flags & TERMKEY_FLAG_CTRLC) + /* want no signal keys at all, so just disable ISIG */ + termios.c_lflag &= ~ISIG; + else { + /* Disable Ctrl-\==VQUIT and Ctrl-D==VSUSP but leave Ctrl-C as SIGINT */ + termios.c_cc[VQUIT] = _POSIX_VDISABLE; + termios.c_cc[VSUSP] = _POSIX_VDISABLE; + /* Some OSes have Ctrl-Y==VDSUSP */ +#ifdef VDSUSP + termios.c_cc[VDSUSP] = _POSIX_VDISABLE; +#endif + } + +#ifdef DEBUG + fprintf(stderr, "Setting termios(3) flags\n"); +#endif + tcsetattr(tk->fd, TCSANOW, &termios); + } + } + + struct TermKeyDriverNode *p; + for(p = tk->drivers; p; p = p->next) + if(p->driver->start_driver) + if(!(*p->driver->start_driver)(tk, p->info)) + return 0; + +#ifdef DEBUG + fprintf(stderr, "Drivers started; termkey instance %p is ready\n", tk); +#endif + + tk->is_started = 1; + return 1; +} + +int termkey_stop(TermKey *tk) +{ + if(!tk->is_started) + return 1; + struct TermKeyDriverNode *p; for(p = tk->drivers; p; p = p->next) if(p->driver->stop_driver) @@ -413,7 +441,9 @@ void termkey_destroy(TermKey *tk) if(tk->restore_termios_valid) tcsetattr(tk->fd, TCSANOW, &tk->restore_termios); - termkey_free(tk); + tk->is_started = 0; + + return 1; } int termkey_get_fd(TermKey *tk) diff --git a/termkey.h.in b/termkey.h.in index d7317b0..5b7a2ce 100644 --- a/termkey.h.in +++ b/termkey.h.in @@ -161,6 +161,9 @@ TermKey *termkey_new_abstract(const char *term, int flags); void termkey_free(TermKey *tk); void termkey_destroy(TermKey *tk); +int termkey_start(TermKey *tk); +int termkey_stop(TermKey *tk); + int termkey_get_fd(TermKey *tk); int termkey_get_flags(TermKey *tk);