/* re_goto_bottom(): * used to go to last used screen line */ libedit_private void re_goto_bottom(EditLine *el) { terminal_move_to_line(el, el->el_refresh.r_oldcv); terminal__putc(el, '\n'); re_clear_display(el); terminal__flush(el); }
/* el_push(): * Push a macro */ void el_wpush(EditLine *el, const wchar_t *str) { struct macros *ma = &el->el_read->macros; if (str != NULL && ma->level + 1 < EL_MAXMACRO) { ma->level++; if ((ma->macro[ma->level] = wcsdup(str)) != NULL) return; ma->level--; } terminal_beep(el); terminal__flush(el); }
/* el_wgetc(): * Read a wide character */ int el_wgetc(EditLine *el, wchar_t *cp) { int num_read; c_macro_t *ma = &el->el_chared.c_macro; terminal__flush(el); for (;;) { if (ma->level < 0) break; if (ma->macro[0][ma->offset] == '\0') { read_pop(ma); continue; } *cp = ma->macro[0][ma->offset++]; if (ma->macro[0][ma->offset] == '\0') { /* Needed for QuoteMode On */ read_pop(ma); } return 1; } #ifdef DEBUG_READ (void) fprintf(el->el_errfile, "Turning raw mode on\n"); #endif /* DEBUG_READ */ if (tty_rawmode(el) < 0)/* make sure the tty is set up correctly */ return 0; #ifdef DEBUG_READ (void) fprintf(el->el_errfile, "Reading a character\n"); #endif /* DEBUG_READ */ num_read = (*el->el_read->read_char)(el, cp); if (num_read < 0) el->el_errno = errno; #ifdef DEBUG_READ (void) fprintf(el->el_errfile, "Got it %lc\n", *cp); #endif /* DEBUG_READ */ return num_read; }
/* sig_handler(): * This is the handler called for all signals * XXX: we cannot pass any data so we just store the old editline * state in a private variable */ static void sig_handler(int signo) { int i, save_errno; sigset_t nset, oset; save_errno = errno; (void) sigemptyset(&nset); (void) sigaddset(&nset, signo); (void) sigprocmask(SIG_BLOCK, &nset, &oset); sel->el_signal->sig_no = signo; switch (signo) { case SIGCONT: tty_rawmode(sel); if (ed_redisplay(sel, 0) == CC_REFRESH) re_refresh(sel); terminal__flush(sel); break; case SIGWINCH: el_resize(sel); break; default: tty_cookedmode(sel); break; } for (i = 0; sighdl[i] != -1; i++) if (signo == sighdl[i]) break; (void) sigaction(signo, &sel->el_signal->sig_action[i], NULL); sel->el_signal->sig_action[i].sa_handler = SIG_ERR; sel->el_signal->sig_action[i].sa_flags = 0; sigemptyset(&sel->el_signal->sig_action[i].sa_mask); (void) sigprocmask(SIG_SETMASK, &oset, NULL); (void) kill(0, signo); errno = save_errno; }
libedit_private void read_prepare(EditLine *el) { if (el->el_flags & HANDLE_SIGNALS) sig_set(el); if (el->el_flags & NO_TTY) return; if ((el->el_flags & (UNBUFFERED|EDIT_DISABLED)) == UNBUFFERED) tty_rawmode(el); /* This is relatively cheap, and things go terribly wrong if we have the wrong size. */ el_resize(el); re_clear_display(el); /* reset the display stuff */ ch_reset(el); re_refresh(el); /* print the prompt */ if (el->el_flags & UNBUFFERED) terminal__flush(el); }
/* el_wgetc(): * Read a wide character */ int el_wgetc(EditLine *el, wchar_t *cp) { struct macros *ma = &el->el_read->macros; int num_read; terminal__flush(el); for (;;) { if (ma->level < 0) break; if (ma->macro[0][ma->offset] == '\0') { read_pop(ma); continue; } *cp = ma->macro[0][ma->offset++]; if (ma->macro[0][ma->offset] == '\0') { /* Needed for QuoteMode On */ read_pop(ma); } return 1; } if (tty_rawmode(el) < 0)/* make sure the tty is set up correctly */ return 0; num_read = (*el->el_read->read_char)(el, cp); /* * Remember the original reason of a read failure * such that el_wgets() can restore it after doing * various cleanup operation that might change errno. */ if (num_read < 0) el->el_read->read_errno = errno; return num_read; }
const wchar_t * el_wgets(EditLine *el, int *nread) { int retval; el_action_t cmdnum = 0; int num; /* how many chars we have read at NL */ wchar_t ch; int nrb; if (nread == NULL) nread = &nrb; *nread = 0; el->el_read->read_errno = 0; if (el->el_flags & NO_TTY) { el->el_line.lastchar = el->el_line.buffer; return noedit_wgets(el, nread); } #ifdef FIONREAD if (el->el_tty.t_mode == EX_IO && el->el_read->macros.level < 0) { int chrs = 0; (void) ioctl(el->el_infd, FIONREAD, &chrs); if (chrs == 0) { if (tty_rawmode(el) < 0) { errno = 0; *nread = 0; return NULL; } } } #endif /* FIONREAD */ if ((el->el_flags & UNBUFFERED) == 0) read_prepare(el); if (el->el_flags & EDIT_DISABLED) { if ((el->el_flags & UNBUFFERED) == 0) el->el_line.lastchar = el->el_line.buffer; terminal__flush(el); return noedit_wgets(el, nread); } for (num = -1; num == -1;) { /* while still editing this line */ /* if EOF or error */ if (read_getcmd(el, &cmdnum, &ch) == -1) break; if ((size_t)cmdnum >= el->el_map.nfunc) /* BUG CHECK command */ continue; /* try again */ /* now do the real command */ /* vi redo needs these way down the levels... */ el->el_state.thiscmd = cmdnum; el->el_state.thisch = ch; if (el->el_map.type == MAP_VI && el->el_map.current == el->el_map.key && el->el_chared.c_redo.pos < el->el_chared.c_redo.lim) { if (cmdnum == VI_DELETE_PREV_CHAR && el->el_chared.c_redo.pos != el->el_chared.c_redo.buf && iswprint(el->el_chared.c_redo.pos[-1])) el->el_chared.c_redo.pos--; else *el->el_chared.c_redo.pos++ = ch; } retval = (*el->el_map.func[cmdnum]) (el, ch); /* save the last command here */ el->el_state.lastcmd = cmdnum; /* use any return value */ switch (retval) { case CC_CURSOR: re_refresh_cursor(el); break; case CC_REDISPLAY: re_clear_lines(el); re_clear_display(el); /* FALLTHROUGH */ case CC_REFRESH: re_refresh(el); break; case CC_REFRESH_BEEP: re_refresh(el); terminal_beep(el); break; case CC_NORM: /* normal char */ break; case CC_ARGHACK: /* Suggested by Rich Salz */ /* <*****@*****.**> */ continue; /* keep going... */ case CC_EOF: /* end of file typed */ if ((el->el_flags & UNBUFFERED) == 0) num = 0; else if (num == -1) { *el->el_line.lastchar++ = CONTROL('d'); el->el_line.cursor = el->el_line.lastchar; num = 1; } break; case CC_NEWLINE: /* normal end of line */ num = (int)(el->el_line.lastchar - el->el_line.buffer); break; case CC_FATAL: /* fatal error, reset to known state */ /* put (real) cursor in a known place */ re_clear_display(el); /* reset the display stuff */ ch_reset(el); /* reset the input pointers */ read_clearmacros(&el->el_read->macros); re_refresh(el); /* print the prompt again */ break; case CC_ERROR: default: /* functions we don't know about */ terminal_beep(el); terminal__flush(el); break; } el->el_state.argument = 1; el->el_state.doingarg = 0; el->el_chared.c_vcmd.action = NOP; if (el->el_flags & UNBUFFERED) break; } terminal__flush(el); /* flush any buffered output */ /* make sure the tty is set up correctly */ if ((el->el_flags & UNBUFFERED) == 0) { read_finish(el); *nread = num != -1 ? num : 0; } else *nread = (int)(el->el_line.lastchar - el->el_line.buffer); if (*nread == 0) { if (num == -1) { *nread = -1; if (el->el_read->read_errno) errno = el->el_read->read_errno; } return NULL; } else return el->el_line.buffer; }
const wchar_t * el_wgets(EditLine *el, int *nread) { int retval; el_action_t cmdnum = 0; int num; /* how many chars we have read at NL */ wchar_t wc; wchar_t ch, *cp; int crlf = 0; int nrb; if (nread == NULL) nread = &nrb; *nread = 0; if (el->el_flags & NO_TTY) { size_t idx; cp = el->el_line.buffer; while ((num = (*el->el_read->read_char)(el, &wc)) == 1) { *cp = wc; /* make sure there is space for next character */ if (cp + 1 >= el->el_line.limit) { idx = (size_t)(cp - el->el_line.buffer); if (!ch_enlargebufs(el, (size_t)2)) break; cp = &el->el_line.buffer[idx]; } cp++; if (el->el_flags & UNBUFFERED) break; if (cp[-1] == '\r' || cp[-1] == '\n') break; } if (num == -1) { if (errno == EINTR) cp = el->el_line.buffer; el->el_errno = errno; } goto noedit; } #ifdef FIONREAD if (el->el_tty.t_mode == EX_IO && el->el_chared.c_macro.level < 0) { int chrs = 0; (void) ioctl(el->el_infd, FIONREAD, &chrs); if (chrs == 0) { if (tty_rawmode(el) < 0) { errno = 0; *nread = 0; return NULL; } } } #endif /* FIONREAD */ if ((el->el_flags & UNBUFFERED) == 0) read_prepare(el); if (el->el_flags & EDIT_DISABLED) { size_t idx; if ((el->el_flags & UNBUFFERED) == 0) cp = el->el_line.buffer; else cp = el->el_line.lastchar; terminal__flush(el); while ((num = (*el->el_read->read_char)(el, &wc)) == 1) { *cp = wc; /* make sure there is space next character */ if (cp + 1 >= el->el_line.limit) { idx = (size_t)(cp - el->el_line.buffer); if (!ch_enlargebufs(el, (size_t)2)) break; cp = &el->el_line.buffer[idx]; } cp++; crlf = cp[-1] == '\r' || cp[-1] == '\n'; if (el->el_flags & UNBUFFERED) break; if (crlf) break; } if (num == -1) { if (errno == EINTR) cp = el->el_line.buffer; el->el_errno = errno; } goto noedit; } for (num = -1; num == -1;) { /* while still editing this line */ #ifdef DEBUG_EDIT read_debug(el); #endif /* DEBUG_EDIT */ /* if EOF or error */ if (read_getcmd(el, &cmdnum, &ch) == -1) { #ifdef DEBUG_READ (void) fprintf(el->el_errfile, "Returning from el_gets\n"); #endif /* DEBUG_READ */ break; } if (el->el_errno == EINTR) { el->el_line.buffer[0] = '\0'; el->el_line.lastchar = el->el_line.cursor = el->el_line.buffer; break; } if ((size_t)cmdnum >= el->el_map.nfunc) { /* BUG CHECK command */ #ifdef DEBUG_EDIT (void) fprintf(el->el_errfile, "ERROR: illegal command from key 0%o\r\n", ch); #endif /* DEBUG_EDIT */ continue; /* try again */ } /* now do the real command */ #ifdef DEBUG_READ { el_bindings_t *b; for (b = el->el_map.help; b->name; b++) if (b->func == cmdnum) break; if (b->name) (void) fprintf(el->el_errfile, "Executing %ls\n", b->name); else (void) fprintf(el->el_errfile, "Error command = %d\n", cmdnum); } #endif /* DEBUG_READ */ /* vi redo needs these way down the levels... */ el->el_state.thiscmd = cmdnum; el->el_state.thisch = ch; if (el->el_map.type == MAP_VI && el->el_map.current == el->el_map.key && el->el_chared.c_redo.pos < el->el_chared.c_redo.lim) { if (cmdnum == VI_DELETE_PREV_CHAR && el->el_chared.c_redo.pos != el->el_chared.c_redo.buf && iswprint(el->el_chared.c_redo.pos[-1])) el->el_chared.c_redo.pos--; else *el->el_chared.c_redo.pos++ = ch; } retval = (*el->el_map.func[cmdnum]) (el, ch); #ifdef DEBUG_READ (void) fprintf(el->el_errfile, "Returned state %d\n", retval ); #endif /* DEBUG_READ */ /* save the last command here */ el->el_state.lastcmd = cmdnum; /* use any return value */ switch (retval) { case CC_CURSOR: re_refresh_cursor(el); break; case CC_REDISPLAY: re_clear_lines(el); re_clear_display(el); /* FALLTHROUGH */ case CC_REFRESH: re_refresh(el); break; case CC_REFRESH_BEEP: re_refresh(el); terminal_beep(el); break; case CC_NORM: /* normal char */ break; case CC_ARGHACK: /* Suggested by Rich Salz */ /* <*****@*****.**> */ continue; /* keep going... */ case CC_EOF: /* end of file typed */ if ((el->el_flags & UNBUFFERED) == 0) num = 0; else if (num == -1) { *el->el_line.lastchar++ = CONTROL('d'); el->el_line.cursor = el->el_line.lastchar; num = 1; } break; case CC_NEWLINE: /* normal end of line */ num = (int)(el->el_line.lastchar - el->el_line.buffer); break; case CC_FATAL: /* fatal error, reset to known state */ #ifdef DEBUG_READ (void) fprintf(el->el_errfile, "*** editor fatal ERROR ***\r\n\n"); #endif /* DEBUG_READ */ /* put (real) cursor in a known place */ re_clear_display(el); /* reset the display stuff */ ch_reset(el, 1); /* reset the input pointers */ re_refresh(el); /* print the prompt again */ break; case CC_ERROR: default: /* functions we don't know about */ #ifdef DEBUG_READ (void) fprintf(el->el_errfile, "*** editor ERROR ***\r\n\n"); #endif /* DEBUG_READ */ terminal_beep(el); terminal__flush(el); break; } el->el_state.argument = 1; el->el_state.doingarg = 0; el->el_chared.c_vcmd.action = NOP; if (el->el_flags & UNBUFFERED) break; } terminal__flush(el); /* flush any buffered output */ /* make sure the tty is set up correctly */ if ((el->el_flags & UNBUFFERED) == 0) { read_finish(el); *nread = num != -1 ? num : 0; } else { *nread = (int)(el->el_line.lastchar - el->el_line.buffer); } goto done; noedit: el->el_line.cursor = el->el_line.lastchar = cp; *cp = '\0'; *nread = (int)(el->el_line.cursor - el->el_line.buffer); done: if (*nread == 0) { if (num == -1) { *nread = -1; errno = el->el_errno; } return NULL; } else return el->el_line.buffer; }