Lines Matching refs:gl

292 static int gl_call_fd_handler(GetLine *gl, GlFdHandler *gfh, int fd,
295 static int gl_call_timeout_handler(GetLine *gl);
417 int ntotal; /* The number of characters in gl->line[] */
418 int buff_curpos; /* The cursor position within gl->line[] */
427 /* the current contents of gl->line[] */
649 static int gl_check_caught_signal(GetLine *gl);
655 static void gl_suspend_process(int signo, GetLine *gl, int ngl);
678 static void gl_query_size(GetLine *gl, int *ncolumn, int *nline);
684 static int gl_override_signal_handlers(GetLine *gl);
690 static int gl_restore_signal_handlers(GetLine *gl);
696 static int gl_mask_signals(GetLine *gl, sigset_t *oldset);
702 static int gl_unmask_signals(GetLine *gl, sigset_t *oldset);
707 static int gl_catch_signals(GetLine *gl);
716 * terminal attributes in gl->oldattr.
718 static int gl_raw_terminal_mode(GetLine *gl);
721 * Restore the terminal attributes from gl->oldattr.
723 static int gl_restore_terminal_attributes(GetLine *gl);
728 static int gl_nonblocking_io(GetLine *gl, int fd);
733 static int gl_blocking_io(GetLine *gl, int fd);
738 static int gl_get_input_line(GetLine *gl, const char *prompt,
744 static int gl_get_query_char(GetLine *gl, const char *prompt, int defchar);
749 static int gl_read_stream_line(GetLine *gl);
754 static int gl_read_stream_char(GetLine *gl);
759 static int gl_present_line(GetLine *gl, const char *prompt,
765 static void gl_reset_input_line(GetLine *gl);
771 static int gl_interpret_char(GetLine *gl, char c);
776 static int gl_bind_control_char(GetLine *gl, KtBinder binder,
782 static int gl_bind_terminal_keys(GetLine *gl);
787 static int gl_control_strings(GetLine *gl, const char *term);
794 static const char *gl_tigetstr(GetLine *gl, const char *name);
796 static const char *gl_tgetstr(GetLine *gl, const char *name, char **bufptr);
802 static int gl_print_raw_string(GetLine *gl, int buffered,
810 static int gl_print_info(GetLine *gl, ...);
816 static int gl_start_newline(GetLine *gl, int buffered);
821 static int gl_print_control_sequence(GetLine *gl, int nline,
829 static int gl_print_char(GetLine *gl, char c, char pad);
830 static int gl_print_string(GetLine *gl, const char *string, char pad);
836 static int gl_delete_chars(GetLine *gl, int nc, int cut);
842 static int gl_add_char_to_line(GetLine *gl, char c);
848 static int gl_add_string_to_line(GetLine *gl, const char *s);
853 static int gl_buffer_char(GetLine *gl, char c, int bufpos);
858 static int gl_buffer_string(GetLine *gl, const char *s, int n, int bufpos);
863 static int gl_make_gap_in_buffer(GetLine *gl, int start, int n);
869 static void gl_remove_from_buffer(GetLine *gl, int start, int n);
874 static int gl_truncate_buffer(GetLine *gl, int n);
880 static int gl_truncate_display(GetLine *gl);
886 static void gl_update_buffer(GetLine *gl);
891 static int gl_read_terminal(GetLine *gl, int keep, char *c);
896 static void gl_discard_chars(GetLine *gl, int nused);
901 static int gl_terminal_move_cursor(GetLine *gl, int n);
906 static int gl_set_term_curpos(GetLine *gl, int term_curpos);
912 static int gl_place_cursor(GetLine *gl, int buff_curpos);
923 static int gl_displayed_tab_width(GetLine *gl, int term_curpos);
929 static int gl_displayed_char_width(GetLine *gl, char c, int term_curpos);
935 static int gl_displayed_string_width(GetLine *gl, const char *string, int nc,
946 static int _gl_read_config_file(GetLine *gl, const char *filename, KtBinder who);
951 static int _gl_read_config_string(GetLine *gl, const char *buffer, KtBinder who);
966 static int _gl_parse_config_line(GetLine *gl, void *stream, GlcGetcFn *getc_fn,
968 static int gl_report_config_error(GetLine *gl, const char *origin, int lineno,
975 static int _gl_bind_arrow_keys(GetLine *gl);
981 static int _gl_rebind_arrow_key(GetLine *gl, const char *name,
992 static void gl_revert_input(GetLine *gl);
997 static int gl_flush_output(GetLine *gl);
1022 static GlReadStatus gl_read_input(GetLine *gl, char *c);
1026 static int gl_event_handler(GetLine *gl, int fd);
1027 static int gl_read_unmasked(GetLine *gl, int fd, char *c);
1038 static int gl_change_editor(GetLine *gl, GlEditor editor);
1045 static int gl_find_char(GetLine *gl, int count, int forward, int onto, char c);
1050 static int gl_nth_word_end_forward(GetLine *gl, int n);
1055 static int gl_nth_word_start_forward(GetLine *gl, int n);
1060 static int gl_nth_word_start_backward(GetLine *gl, int n);
1067 static void gl_save_for_undo(GetLine *gl);
1072 static void gl_vi_command_mode(GetLine *gl);
1079 static int gl_delete_find(GetLine *gl, int count, char c, int forward,
1086 static int gl_copy_find(GetLine *gl, int count, char c, int forward, int onto);
1093 static int gl_index_of_matching_paren(GetLine *gl);
1117 static int gl_display_prompt(GetLine *gl);
1122 static int gl_displayed_prompt_width(GetLine *gl);
1127 static int gl_line_ended(GetLine *gl, int newline_char);
1133 static void gl_queue_redisplay(GetLine *gl);
1139 static int gl_erase_line(GetLine *gl);
1144 static void gl_line_erased(GetLine *gl);
1149 void _gl_abandon_line(GetLine *gl);
1159 static char *_gl_get_line(GetLine *gl, const char *prompt,
1161 static int _gl_query_char(GetLine *gl, const char *prompt, char defchar);
1162 static int _gl_read_char(GetLine *gl);
1163 static int _gl_update_size(GetLine *gl);
1166 * size. Also install the new size in gl.
1168 static int gl_handle_tty_resize(GetLine *gl, int ncolumn, int nline);
1170 static int _gl_change_terminal(GetLine *gl, FILE *input_fp, FILE *output_fp,
1172 static int _gl_configure_getline(GetLine *gl, const char *app_string,
1174 static int _gl_save_history(GetLine *gl, const char *filename,
1176 static int _gl_load_history(GetLine *gl, const char *filename,
1178 static int _gl_watch_fd(GetLine *gl, int fd, GlFdEvent event,
1180 static void _gl_terminal_size(GetLine *gl, int def_ncolumn, int def_nline,
1182 static void _gl_replace_prompt(GetLine *gl, const char *prompt);
1183 static int _gl_trap_signal(GetLine *gl, int signo, unsigned flags,
1185 static int _gl_raw_io(GetLine *gl, int redisplay);
1186 static int _gl_normal_io(GetLine *gl);
1187 static int _gl_completion_action(GetLine *gl, void *data, CplMatchFn *match_fn,
1190 static int _gl_register_action(GetLine *gl, void *data, GlActionFn *fn,
1192 static int _gl_io_mode(GetLine *gl, GlIOMode mode);
1193 static int _gl_set_term_size(GetLine *gl, int ncolumn, int nline);
1194 static int _gl_append_history(GetLine *gl, const char *line);
1198 * gl->rtn_status and gl->rtn_errno.
1200 static void gl_clear_status(GetLine *gl);
1206 static void gl_record_status(GetLine *gl, GlReturnStatus rtn_status,
1726 GetLine *gl; /* The object to be returned */
1738 gl = (GetLine *) malloc(sizeof(GetLine));
1739 if(!gl) {
1748 gl->err = NULL;
1749 gl->glh = NULL;
1750 gl->cpl = NULL;
1752 gl->cplfn.fn = cpl_file_completions;
1754 gl->cplfn.fn = gl_no_completions;
1756 gl->cplfn.data = NULL;
1758 gl->ef = NULL;
1760 gl->capmem = NULL;
1761 gl->cq = NULL;
1762 gl->input_fd = -1;
1763 gl->output_fd = -1;
1764 gl->input_fp = NULL;
1765 gl->output_fp = NULL;
1766 gl->file_fp = NULL;
1767 gl->term = NULL;
1768 gl->is_term = 0;
1769 gl->flush_fn = gl_flush_terminal;
1770 gl->io_mode = GL_NORMAL_MODE;
1771 gl->raw_mode = 0;
1772 gl->pending_io = GLP_WRITE; /* We will start by writing the prompt */
1773 gl_clear_status(gl);
1774 gl->linelen = linelen;
1775 gl->line = NULL;
1776 gl->cutbuf = NULL;
1777 gl->prompt = NULL;
1778 gl->prompt_len = 0;
1779 gl->prompt_changed = 0;
1780 gl->prompt_style = GL_LITERAL_PROMPT;
1781 gl->cpl_mem = NULL;
1782 gl->ext_act_mem = NULL;
1783 gl->sig_mem = NULL;
1784 gl->sigs = NULL;
1785 gl->signals_masked = 0;
1786 gl->signals_overriden = 0;
1787 sigemptyset(&gl->all_signal_set);
1788 sigemptyset(&gl->old_signal_set);
1789 sigemptyset(&gl->use_signal_set);
1790 gl->bindings = NULL;
1791 gl->ntotal = 0;
1792 gl->buff_curpos = 0;
1793 gl->term_curpos = 0;
1794 gl->term_len = 0;
1795 gl->buff_mark = 0;
1796 gl->insert_curpos = 0;
1797 gl->insert = 1;
1798 gl->number = -1;
1799 gl->endline = 1;
1800 gl->displayed = 0;
1801 gl->redisplay = 0;
1802 gl->postpone = 0;
1803 gl->keybuf[0]='\0';
1804 gl->nbuf = 0;
1805 gl->nread = 0;
1806 gl->current_action.fn = 0;
1807 gl->current_action.data = NULL;
1808 gl->current_count = 0;
1809 gl->preload_id = 0;
1810 gl->preload_history = 0;
1811 gl->keyseq_count = 0;
1812 gl->last_search = -1;
1813 gl->editor = GL_EMACS_MODE;
1814 gl->silence_bell = 0;
1815 gl->automatic_history = 1;
1816 gl->vi.undo.line = NULL;
1817 gl->vi.undo.buff_curpos = 0;
1818 gl->vi.undo.ntotal = 0;
1819 gl->vi.undo.saved = 0;
1820 gl->vi.repeat.action.fn = 0;
1821 gl->vi.repeat.action.data = 0;
1822 gl->vi.repeat.count = 0;
1823 gl->vi.repeat.input_curpos = 0;
1824 gl->vi.repeat.command_curpos = 0;
1825 gl->vi.repeat.input_char = '\0';
1826 gl->vi.repeat.saved = 0;
1827 gl->vi.repeat.active = 0;
1828 gl->vi.command = 0;
1829 gl->vi.find_forward = 0;
1830 gl->vi.find_onto = 0;
1831 gl->vi.find_char = '\0';
1832 gl->left = NULL;
1833 gl->right = NULL;
1834 gl->up = NULL;
1835 gl->down = NULL;
1836 gl->home = NULL;
1837 gl->bol = 0;
1838 gl->clear_eol = NULL;
1839 gl->clear_eod = NULL;
1840 gl->u_arrow = NULL;
1841 gl->d_arrow = NULL;
1842 gl->l_arrow = NULL;
1843 gl->r_arrow = NULL;
1844 gl->sound_bell = NULL;
1845 gl->bold = NULL;
1846 gl->underline = NULL;
1847 gl->standout = NULL;
1848 gl->dim = NULL;
1849 gl->reverse = NULL;
1850 gl->blink = NULL;
1851 gl->text_attr_off = NULL;
1852 gl->nline = 0;
1853 gl->ncolumn = 0;
1855 gl->left_n = NULL;
1856 gl->right_n = NULL;
1858 gl->tgetent_buf = NULL;
1859 gl->tgetstr_buf = NULL;
1861 gl->app_file = NULL;
1862 gl->user_file = NULL;
1863 gl->configured = 0;
1864 gl->echo = 1;
1865 gl->last_signal = -1;
1867 gl->fd_node_mem = NULL;
1868 gl->fd_nodes = NULL;
1869 FD_ZERO(&gl->rfds);
1870 FD_ZERO(&gl->wfds);
1871 FD_ZERO(&gl->ufds);
1872 gl->max_fd = 0;
1873 gl->timer.dt.tv_sec = 0;
1874 gl->timer.dt.tv_usec = 0;
1875 gl->timer.fn = 0;
1876 gl->timer.data = NULL;
1881 gl->err = _new_ErrMsg();
1882 if(!gl->err)
1883 return del_GetLine(gl);
1887 gl->glh = _new_GlHistory(histlen);
1888 if(!gl->glh)
1889 return del_GetLine(gl);
1893 gl->cpl = new_WordCompletion();
1894 if(!gl->cpl)
1895 return del_GetLine(gl);
1900 gl->ef = new_ExpandFile();
1901 if(!gl->ef)
1902 return del_GetLine(gl);
1908 gl->capmem = _new_StringGroup(CAPMEM_SEGMENT_SIZE);
1909 if(!gl->capmem)
1910 return del_GetLine(gl);
1914 gl->cq = _new_GlCharQueue();
1915 if(!gl->cq)
1916 return del_GetLine(gl);
1921 gl->line = (char *) malloc(linelen + 2);
1922 if(!gl->line) {
1924 return del_GetLine(gl);
1929 gl_truncate_buffer(gl, 0);
1933 gl->cutbuf = (char *) malloc(linelen + 2);
1934 if(!gl->cutbuf) {
1936 return del_GetLine(gl);
1938 gl->cutbuf[0] = '\0';
1942 _gl_replace_prompt(gl, NULL);
1943 if(!gl->prompt) {
1945 return del_GetLine(gl);
1950 gl->vi.undo.line = (char *) malloc(linelen + 2);
1951 if(!gl->vi.undo.line) {
1953 return del_GetLine(gl);
1955 gl->vi.undo.line[0] = '\0';
1960 gl->cpl_mem = _new_FreeList(sizeof(GlCplCallback), GL_CPL_FREELIST_BLOCKING);
1961 if(!gl->cpl_mem)
1962 return del_GetLine(gl);
1967 gl->ext_act_mem = _new_FreeList(sizeof(GlExternalAction),
1969 if(!gl->ext_act_mem)
1970 return del_GetLine(gl);
1975 gl->sig_mem = _new_FreeList(sizeof(GlSignalNode), GLS_FREELIST_BLOCKING);
1976 if(!gl->sig_mem)
1977 return del_GetLine(gl);
1984 if(_gl_trap_signal(gl, sig->signo, sig->flags, sig->after,
1986 return del_GetLine(gl);
1991 gl->bindings = _new_KeyTab();
1992 if(!gl->bindings)
1993 return del_GetLine(gl);
1998 if(_kt_set_action(gl->bindings, gl_actions[i].name, gl_actions[i].fn, NULL))
1999 return del_GetLine(gl);
2004 if(gl_change_editor(gl, gl->editor))
2005 return del_GetLine(gl);
2010 gl->tgetent_buf = (char *) malloc(TERMCAP_BUF_SIZE);
2011 gl->tgetstr_buf = (char *) malloc(TERMCAP_BUF_SIZE);
2012 if(!gl->tgetent_buf || !gl->tgetstr_buf) {
2014 return del_GetLine(gl);
2020 if(_gl_change_terminal(gl, stdin, stdout, getenv("TERM")))
2021 return del_GetLine(gl);
2026 gl->fd_node_mem = _new_FreeList(sizeof(GlFdNode), GLFD_FREELIST_BLOCKING);
2027 if(!gl->fd_node_mem)
2028 return del_GetLine(gl);
2033 return gl;
2040 * gl GetLine * The object to be deleted.
2044 GetLine *del_GetLine(GetLine *gl)
2046 if(gl) {
2050 _gl_normal_io(gl);
2052 * Deallocate all objects contained by gl.
2054 gl->err = _del_ErrMsg(gl->err);
2055 gl->glh = _del_GlHistory(gl->glh);
2056 gl->cpl = del_WordCompletion(gl->cpl);
2058 gl->ef = del_ExpandFile(gl->ef);
2060 gl->capmem = _del_StringGroup(gl->capmem);
2061 gl->cq = _del_GlCharQueue(gl->cq);
2062 if(gl->file_fp)
2063 fclose(gl->file_fp);
2064 if(gl->term)
2065 free(gl->term);
2066 if(gl->line)
2067 free(gl->line);
2068 if(gl->cutbuf)
2069 free(gl->cutbuf);
2070 if(gl->prompt)
2071 free(gl->prompt);
2072 gl->cpl_mem = _del_FreeList(gl->cpl_mem, 1);
2073 gl->ext_act_mem = _del_FreeList(gl->ext_act_mem, 1);
2074 gl->sig_mem = _del_FreeList(gl->sig_mem, 1);
2075 gl->sigs = NULL; /* Already freed by freeing sig_mem */
2076 gl->bindings = _del_KeyTab(gl->bindings);
2077 if(gl->vi.undo.line)
2078 free(gl->vi.undo.line);
2080 if(gl->tgetent_buf)
2081 free(gl->tgetent_buf);
2082 if(gl->tgetstr_buf)
2083 free(gl->tgetstr_buf);
2085 if(gl->app_file)
2086 free(gl->app_file);
2087 if(gl->user_file)
2088 free(gl->user_file);
2090 gl->fd_node_mem = _del_FreeList(gl->fd_node_mem, 1);
2091 gl->fd_nodes = NULL; /* Already freed by freeing gl->fd_node_mem */
2096 free(gl);
2105 * gl GetLine * The resource object of this program.
2114 static int gl_bind_control_char(GetLine *gl, KtBinder binder, char c,
2137 if(_kt_set_keybinding(gl->bindings, binder, keyseq, action)) {
2138 _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
2148 * gl GetLine * A resource object returned by new_GetLine().
2166 char *gl_get_line(GetLine *gl, const char *prompt,
2173 if(!gl) {
2180 if(gl_mask_signals(gl, &gl->old_signal_set))
2185 retval = _gl_get_line(gl, prompt, start_line, start_pos);
2190 gl_unmask_signals(gl, &gl->old_signal_set);
2198 static char *_gl_get_line(GetLine *gl, const char *prompt,
2206 gl_clear_status(gl);
2211 if(!gl->configured) {
2212 (void) _gl_configure_getline(gl, NULL, NULL, TECLA_CONFIG_FILE);
2213 gl->configured = 1;
2225 waserr = gl_override_signal_handlers(gl);
2230 waserr = waserr || _gl_raw_io(gl, 1);
2240 if(gl->file_fp || !gl->is_term) {
2241 if(gl_read_stream_line(gl)==0) {
2243 } else if(gl->file_fp) {
2244 gl_revert_input(gl);
2245 gl_record_status(gl, GLR_NEWLINE, 0);
2253 * changed gl->file_fp, so it is necessary to retest it here, rather
2256 if(!gl->file_fp && gl->is_term) {
2257 if(gl_get_input_line(gl, prompt, start_line, start_pos))
2264 * If an error occurred, but gl->rtn_status is still set to
2268 * non-generic errors have to remember to update gl->rtn_status
2271 if(waserr && gl->rtn_status == GLR_NEWLINE)
2272 gl_record_status(gl, GLR_ERROR, errno);
2276 if(gl->io_mode != GL_SERVER_MODE)
2277 _gl_normal_io(gl);
2281 gl_restore_signal_handlers(gl);
2285 * gl->rtn_errno. Since errno may have been overwritten by cleanup
2290 errno = gl->rtn_errno;
2294 switch(gl->rtn_status) {
2296 return gl->line;
2301 if(gl->io_mode != GL_SERVER_MODE)
2302 _gl_abandon_line(gl);
2307 _gl_abandon_line(gl);
2316 * gl GetLine * A resource object returned by new_GetLine().
2327 int gl_query_char(GetLine *gl, const char *prompt, char defchar)
2333 if(!gl) {
2340 if(gl_mask_signals(gl, &gl->old_signal_set))
2345 retval = _gl_query_char(gl, prompt, defchar);
2350 gl_unmask_signals(gl, &gl->old_signal_set);
2357 static int _gl_query_char(GetLine *gl, const char *prompt, char defchar)
2365 gl_clear_status(gl);
2370 if(!gl->configured) {
2371 (void) _gl_configure_getline(gl, NULL, NULL, TECLA_CONFIG_FILE);
2372 gl->configured = 1;
2384 waserr = gl_override_signal_handlers(gl);
2390 waserr = waserr || _gl_raw_io(gl, 0);
2400 if(gl->file_fp || !gl->is_term) {
2401 c = gl_read_stream_char(gl);
2405 } else if(gl->file_fp) { /* End of temporary input file? */
2406 gl_revert_input(gl);
2407 gl_record_status(gl, GLR_NEWLINE, 0);
2415 * changed gl->file_fp, so it is necessary to retest it here, rather
2418 if(!gl->file_fp && gl->is_term) {
2419 c = gl_get_query_char(gl, prompt, defchar);
2427 * If an error occurred, but gl->rtn_status is still set to
2431 * non-generic errors have to remember to update gl->rtn_status
2434 if(waserr && gl->rtn_status == GLR_NEWLINE)
2435 gl_record_status(gl, GLR_ERROR, errno);
2439 if(gl->io_mode != GL_SERVER_MODE)
2440 _gl_normal_io(gl);
2444 gl_restore_signal_handlers(gl);
2448 * gl->rtn_errno. Since errno may have been overwritten by cleanup
2453 errno = gl->rtn_errno;
2458 if(gl->rtn_status != GLR_NEWLINE)
2465 _gl_abandon_line(gl);
2477 * gl GetLine * The resource object of this library.
2482 static int gl_override_signal_handlers(GetLine *gl)
2490 memcpy(&act.sa_mask, &gl->all_signal_set, sizeof(sigset_t));
2496 sigemptyset(&gl->use_signal_set);
2497 for(sig=gl->sigs; sig; sig=sig->next) {
2503 !sigismember(&gl->old_signal_set, sig->signo)) {
2504 if(sigaddset(&gl->use_signal_set, sig->signo) == -1) {
2505 _err_record_msg(gl->err, "sigaddset error", END_ERR_MSG);
2513 for(sig=gl->sigs; sig; sig=sig->next) {
2514 if(sigismember(&gl->use_signal_set, sig->signo)) {
2517 _err_record_msg(gl->err, "sigaction error", END_ERR_MSG);
2527 gl->signals_overriden = 1;
2533 if(_gl_update_size(gl))
2542 * gl GetLine * The resource object of this library.
2547 static int gl_restore_signal_handlers(GetLine *gl)
2554 for(sig=gl->sigs; sig; sig=sig->next) {
2555 if(sigismember(&gl->use_signal_set, sig->signo) &&
2557 _err_record_msg(gl->err, "sigaction error", END_ERR_MSG);
2565 gl->signals_overriden = 0;
2581 * settings in gl->attributes.
2584 * gl GetLine * The resource object of this program.
2589 static int gl_raw_terminal_mode(GetLine *gl)
2595 if(gl->raw_mode)
2600 if(tcgetattr(gl->input_fd, &gl->oldattr)) {
2601 _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG);
2608 if(gl->editor == GL_NO_EDITOR)
2613 newattr = gl->oldattr;
2635 newattr.c_cc[VMIN] = gl->io_mode==GL_SERVER_MODE ? 0:1;
2640 while(tcsetattr(gl->input_fd, TCSADRAIN, &newattr)) {
2642 _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
2649 gl->raw_mode = 1;
2654 * Restore the terminal attributes recorded in gl->oldattr.
2657 * gl GetLine * The resource object of this library.
2662 static int gl_restore_terminal_attributes(GetLine *gl)
2668 if(!gl->raw_mode)
2674 if(gl_flush_output(gl))
2680 while(tcsetattr(gl->input_fd, TCSADRAIN, &gl->oldattr)) {
2682 _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
2690 gl->raw_mode = 0;
2698 * gl GetLine * The resource object of gl_get_line().
2701 static int gl_nonblocking_io(GetLine *gl, int fd)
2723 _err_record_msg(gl->err, "fcntl error", END_ERR_MSG);
2734 * gl GetLine * The resource object of gl_get_line().
2737 static int gl_blocking_io(GetLine *gl, int fd)
2753 _err_record_msg(gl->err, "fcntl error", END_ERR_MSG);
2764 * gl GetLine * The resource object of this library.
2779 static int gl_get_input_line(GetLine *gl, const char *prompt,
2786 if(_glq_char_count(gl->cq) > 0 && gl_flush_output(gl))
2791 if(gl->endline) {
2795 if(gl_erase_line(gl))
2800 if(gl_present_line(gl, prompt, start_line, start_pos))
2806 while(gl_read_terminal(gl, 1, &c) == 0) {
2810 gl->keyseq_count++;
2816 if(gl_interpret_char(gl, c))
2822 if(gl->file_fp)
2827 if(gl->endline)
2828 return gl_line_ended(gl, c);
2835 if(gl->endline)
2836 return gl_line_ended(gl, '\n');
2843 if(gl->rtn_status == GLR_BLOCKED && gl->pending_io == GLP_READ)
2844 gl->nread = 0;
2854 * gl GetLine * The resource object of this library.
2863 static int gl_get_query_char(GetLine *gl, const char *prompt, int defchar)
2870 if(_glq_char_count(gl->cq) > 0 && gl_flush_output(gl))
2875 if(gl_erase_line(gl))
2880 if(gl_present_line(gl, prompt, NULL, 0))
2885 if(gl_read_terminal(gl, 1, &c) == 0) {
2889 gl->keyseq_count++;
2893 gl_discard_chars(gl, gl->nread);
2908 if(gl_end_of_line(gl, 1, NULL)==0)
2909 gl_print_char(gl, c, ' ');
2915 gl_record_status(gl, GLR_NEWLINE, 0);
2920 } else if(gl->endline) {
2922 gl_record_status(gl, GLR_NEWLINE, 0);
2929 if(gl_start_newline(gl, 1))
2934 (void) gl_flush_output(gl);
2946 * gl GetLine * The resource object of this library.
2952 static int gl_add_char_to_line(GetLine *gl, char c)
2957 int buff_curpos = gl->buff_curpos;
2958 int term_curpos = gl->term_curpos;
2962 int width = gl_displayed_char_width(gl, c, term_curpos);
2969 if((gl->insert || buff_curpos >= gl->ntotal) && gl->ntotal >= gl->linelen)
2974 if(gl->insert || buff_curpos >= gl->ntotal) {
2978 if(buff_curpos < gl->ntotal)
2979 gl_make_gap_in_buffer(gl, buff_curpos, 1);
2983 gl_buffer_char(gl, c, buff_curpos);
2984 gl->buff_curpos++;
2989 if(gl_print_string(gl, gl->line + buff_curpos, '\0') ||
2990 gl_set_term_curpos(gl, term_curpos + width))
2999 int old_width = gl_displayed_char_width(gl, gl->line[buff_curpos],
3004 gl_buffer_char(gl, c, buff_curpos);
3012 if(gl_print_string(gl, gl->line + buff_curpos, '\0'))
3017 if(gl_truncate_display(gl))
3022 if(gl_set_term_curpos(gl, term_curpos + width))
3024 gl->buff_curpos++;
3034 if(gl_print_string(gl, gl->line + buff_curpos, '\0') ||
3035 gl_set_term_curpos(gl, term_curpos + width))
3037 gl->buff_curpos++;
3046 gl_buffer_char(gl, c, buff_curpos);
3047 gl->buff_curpos++;
3051 if(gl_print_char(gl, c, gl->line[gl->buff_curpos]))
3063 * gl GetLine * The resource object of this library.
3069 static int gl_add_string_to_line(GetLine *gl, const char *s)
3073 int buff_curpos; /* The original value of gl->buff_curpos */
3074 int term_curpos; /* The original value of gl->term_curpos */
3078 buff_curpos = gl->buff_curpos;
3079 term_curpos = gl->term_curpos;
3084 term_slen = gl_displayed_string_width(gl, s, buff_slen, term_curpos);
3090 if(gl->ntotal + buff_slen > gl->linelen)
3096 if(gl->ntotal > gl->buff_curpos)
3097 gl_make_gap_in_buffer(gl, gl->buff_curpos, buff_slen);
3101 gl_buffer_string(gl, s, buff_slen, gl->buff_curpos);
3102 gl->buff_curpos += buff_slen;
3107 if(gl_print_string(gl, gl->line + buff_curpos, '\0') ||
3108 gl_set_term_curpos(gl, term_curpos + term_slen))
3117 * gl GetLine * The resource object of this library.
3131 * latter case gl->endline will be non-zero.
3133 static int gl_read_terminal(GetLine *gl, int keep, char *c)
3139 if(gl_flush_output(gl))
3144 gl->pending_io = GLP_READ;
3149 if(gl->nread < gl->nbuf) {
3150 *c = gl->keybuf[gl->nread];
3155 gl->nread++;
3160 memmove(gl->keybuf + gl->nread, gl->keybuf + gl->nread + 1,
3161 gl->nbuf - gl->nread - 1);
3171 if(gl->nbuf + 1 > GL_KEY_MAX) {
3172 gl_print_info(gl, "gl_read_terminal: Buffer overflow avoided.",
3180 switch(gl_read_input(gl, c)) {
3184 gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO);
3195 gl->keybuf[gl->nbuf] = *c;
3196 gl->nread = ++gl->nbuf;
3205 * gl GetLine * The resource object of this module.
3210 static GlReadStatus gl_read_input(GetLine *gl, char *c)
3220 volatile int fd = gl->file_fp ? fileno(gl->file_fp) : gl->input_fd;
3224 if(gl->endline)
3233 switch(gl->io_mode) {
3239 if(gl_event_handler(gl, fd))
3241 return gl_read_unmasked(gl, fd, c); /* Read one character */
3258 gl_blocking_io(gl, fd); /* switch to blocking I/O */
3259 status = gl_read_unmasked(gl, fd, c); /* Try reading */
3261 if(gl_event_handler(gl, fd)) /* Wait for input */
3264 status = gl_read_unmasked(gl, fd, c); /* Try reading again */
3266 gl_nonblocking_io(gl, fd); /* Restore non-blocking I/O */
3281 if(gl->io_mode == GL_SERVER_MODE)
3282 gl_nonblocking_io(gl, fd);
3286 if(gl_check_caught_signal(gl))
3297 * gl GetLine * The resource object of this module.
3303 static int gl_read_unmasked(GetLine *gl, int fd, char *c)
3309 gl_catch_signals(gl);
3321 gl_mask_signals(gl, NULL);
3337 * key-press lookahead buffer, gl->keybuf[], and arrange for the next
3341 * gl GetLine * The resource object of this module.
3345 static void gl_discard_chars(GetLine *gl, int nused)
3347 int nkeep = gl->nbuf - nused;
3349 memmove(gl->keybuf, gl->keybuf + nused, nkeep);
3350 gl->nbuf = nkeep;
3351 gl->nread = 0;
3353 gl->nbuf = gl->nread = 0;
3362 * gl GetLine * The resource object of this library.
3367 static int gl_check_caught_signal(GetLine *gl)
3390 gl->last_signal = signo;
3400 * Note that the caller of this function should set gl->pending_io
3403 if(gl->io_mode==GL_SERVER_MODE) {
3404 gl_record_status(gl, GLR_SIGNAL, EINTR);
3411 for(sig=gl->sigs; sig && sig->signo != signo; sig=sig->next)
3423 if(signo == SIGWINCH && _gl_update_size(gl))
3430 if(gl_start_newline(gl, 0))
3438 gl_restore_terminal_attributes(gl);
3445 gl_restore_signal_handlers(gl);
3446 gl_unmask_signals(gl, &gl->old_signal_set);
3460 gl_mask_signals(gl, NULL);
3461 gl_override_signal_handlers(gl);
3470 gl_raw_terminal_mode(gl);
3475 gl_queue_redisplay(gl);
3481 gl_newline(gl, 1, NULL);
3482 return gl_flush_output(gl);
3485 gl_record_status(gl, GLR_SIGNAL, sig->errno_value);
3489 return gl_flush_output(gl);
3499 * gl GetLine * The resource object of this library.
3505 static int gl_control_strings(GetLine *gl, const char *term)
3511 gl->left = NULL;
3512 gl->right = NULL;
3513 gl->up = NULL;
3514 gl->down = NULL;
3515 gl->home = NULL;
3516 gl->bol = 0;
3517 gl->clear_eol = NULL;
3518 gl->clear_eod = NULL;
3519 gl->u_arrow = NULL;
3520 gl->d_arrow = NULL;
3521 gl->l_arrow = NULL;
3522 gl->r_arrow = NULL;
3523 gl->sound_bell = NULL;
3524 gl->bold = NULL;
3525 gl->underline = NULL;
3526 gl->standout = NULL;
3527 gl->dim = NULL;
3528 gl->reverse = NULL;
3529 gl->blink = NULL;
3530 gl->text_attr_off = NULL;
3531 gl->nline = 0;
3532 gl->ncolumn = 0;
3534 gl->left_n = NULL;
3535 gl->right_n = NULL;
3544 if(!term || setupterm((char *)term, gl->input_fd, &errret) == ERR) {
3547 _clr_StringGroup(gl->capmem);
3548 gl->left = gl_tigetstr(gl, "cub1");
3549 gl->right = gl_tigetstr(gl, "cuf1");
3550 gl->up = gl_tigetstr(gl, "cuu1");
3551 gl->down = gl_tigetstr(gl, "cud1");
3552 gl->home = gl_tigetstr(gl, "home");
3553 gl->clear_eol = gl_tigetstr(gl, "el");
3554 gl->clear_eod = gl_tigetstr(gl, "ed");
3555 gl->u_arrow = gl_tigetstr(gl, "kcuu1");
3556 gl->d_arrow = gl_tigetstr(gl, "kcud1");
3557 gl->l_arrow = gl_tigetstr(gl, "kcub1");
3558 gl->r_arrow = gl_tigetstr(gl, "kcuf1");
3559 gl->left_n = gl_tigetstr(gl, "cub");
3560 gl->right_n = gl_tigetstr(gl, "cuf");
3561 gl->sound_bell = gl_tigetstr(gl, "bel");
3562 gl->bold = gl_tigetstr(gl, "bold");
3563 gl->underline = gl_tigetstr(gl, "smul");
3564 gl->standout = gl_tigetstr(gl, "smso");
3565 gl->dim = gl_tigetstr(gl, "dim");
3566 gl->reverse = gl_tigetstr(gl, "rev");
3567 gl->blink = gl_tigetstr(gl, "blink");
3568 gl->text_attr_off = gl_tigetstr(gl, "sgr0");
3572 if(!term || tgetent(gl->tgetent_buf, (char *)term) < 0) {
3575 char *tgetstr_buf_ptr = gl->tgetstr_buf;
3576 _clr_StringGroup(gl->capmem);
3577 gl->left = gl_tgetstr(gl, "le", &tgetstr_buf_ptr);
3578 gl->right = gl_tgetstr(gl, "nd", &tgetstr_buf_ptr);
3579 gl->up = gl_tgetstr(gl, "up", &tgetstr_buf_ptr);
3580 gl->down = gl_tgetstr(gl, "do", &tgetstr_buf_ptr);
3581 gl->home = gl_tgetstr(gl, "ho", &tgetstr_buf_ptr);
3582 gl->clear_eol = gl_tgetstr(gl, "ce", &tgetstr_buf_ptr);
3583 gl->clear_eod = gl_tgetstr(gl, "cd", &tgetstr_buf_ptr);
3584 gl->u_arrow = gl_tgetstr(gl, "ku", &tgetstr_buf_ptr);
3585 gl->d_arrow = gl_tgetstr(gl, "kd", &tgetstr_buf_ptr);
3586 gl->l_arrow = gl_tgetstr(gl, "kl", &tgetstr_buf_ptr);
3587 gl->r_arrow = gl_tgetstr(gl, "kr", &tgetstr_buf_ptr);
3588 gl->sound_bell = gl_tgetstr(gl, "bl", &tgetstr_buf_ptr);
3589 gl->bold = gl_tgetstr(gl, "md", &tgetstr_buf_ptr);
3590 gl->underline = gl_tgetstr(gl, "us", &tgetstr_buf_ptr);
3591 gl->standout = gl_tgetstr(gl, "so", &tgetstr_buf_ptr);
3592 gl->dim = gl_tgetstr(gl, "mh", &tgetstr_buf_ptr);
3593 gl->reverse = gl_tgetstr(gl, "mr", &tgetstr_buf_ptr);
3594 gl->blink = gl_tgetstr(gl, "mb", &tgetstr_buf_ptr);
3595 gl->text_attr_off = gl_tgetstr(gl, "me", &tgetstr_buf_ptr);
3602 gl_print_info(gl, "Bad terminal type: \"", term ? term : "(null)",
3608 if(!gl->left)
3609 gl->left = "\b"; /* ^H */
3610 if(!gl->right)
3611 gl->right = GL_ESC_STR "[C";
3612 if(!gl->up)
3613 gl->up = GL_ESC_STR "[A";
3614 if(!gl->down)
3615 gl->down = "\n";
3616 if(!gl->home)
3617 gl->home = GL_ESC_STR "[H";
3618 if(!gl->bol)
3619 gl->bol = "\r";
3620 if(!gl->clear_eol)
3621 gl->clear_eol = GL_ESC_STR "[K";
3622 if(!gl->clear_eod)
3623 gl->clear_eod = GL_ESC_STR "[J";
3624 if(!gl->u_arrow)
3625 gl->u_arrow = GL_ESC_STR "[A";
3626 if(!gl->d_arrow)
3627 gl->d_arrow = GL_ESC_STR "[B";
3628 if(!gl->l_arrow)
3629 gl->l_arrow = GL_ESC_STR "[D";
3630 if(!gl->r_arrow)
3631 gl->r_arrow = GL_ESC_STR "[C";
3632 if(!gl->sound_bell)
3633 gl->sound_bell = "\a";
3634 if(!gl->bold)
3635 gl->bold = GL_ESC_STR "[1m";
3636 if(!gl->underline)
3637 gl->underline = GL_ESC_STR "[4m";
3638 if(!gl->standout)
3639 gl->standout = GL_ESC_STR "[1;7m";
3640 if(!gl->dim)
3641 gl->dim = ""; /* Not available */
3642 if(!gl->reverse)
3643 gl->reverse = GL_ESC_STR "[7m";
3644 if(!gl->blink)
3645 gl->blink = GL_ESC_STR "[5m";
3646 if(!gl->text_attr_off)
3647 gl->text_attr_off = GL_ESC_STR "[m";
3651 (void) _gl_terminal_size(gl, GL_DEF_NCOLUMN, GL_DEF_NLINE, NULL);
3662 * gl GetLine * The resource object of gl_get_line().
3668 static const char *gl_tigetstr(GetLine *gl, const char *name)
3673 return _sg_store_string(gl->capmem, value, 0);
3684 * of the string in gl->capmem.
3687 * gl GetLine * The resource object of gl_get_line().
3691 * gl->tgetstr_buf at which to record the
3698 static const char *gl_tgetstr(GetLine *gl, const char *name, char **bufptr)
3703 return _sg_store_string(gl->capmem, value, 0);
3740 tcflow(gl->output_fd, TCOOFF);
3749 tcflow(gl->output_fd, TCOON);
3764 if(gl_read_terminal(gl, 1, &c))
3770 gl_add_char_to_line(gl, c);
3781 * gl GetLine * The resource object of this library.
3786 static int gl_displayed_tab_width(GetLine *gl, int term_curpos)
3788 return TAB_WIDTH - ((term_curpos % gl->ncolumn) % TAB_WIDTH);
3798 * gl GetLine * The resource object of this library.
3807 static int gl_displayed_char_width(GetLine *gl, char c, int term_curpos)
3810 return gl_displayed_tab_width(gl, term_curpos);
3823 * gl GetLine * The resource object of this library.
3834 static int gl_displayed_string_width(GetLine *gl, const char *string, int nc,
3848 slen += gl_displayed_char_width(gl, string[i], term_curpos + slen);
3859 * gl GetLine * The resource object of the gl_get_line().
3873 static int gl_print_raw_string(GetLine *gl, int buffered,
3876 GlWriteFn *write_fn = buffered ? gl_write_fn : gl->flush_fn;
3880 if(gl->echo) {
3886 if(gl_flush_output(gl))
3897 if(write_fn(gl, string + ndone, n-ndone) != n)
3909 * gl GetLine * The resource object of this library.
3917 static int gl_print_control_sequence(GetLine *gl, int nline, const char *string)
3923 if(gl->echo) {
3925 tputs_gl = gl;
3930 waserr = gl_print_raw_string(gl, 1, string, -1);
3956 * gl GetLine * The resource object of this program.
3962 static int gl_terminal_move_cursor(GetLine *gl, int n)
3973 if(!gl->displayed)
3978 if(gl->term_curpos + n < 0)
3979 n = gl->term_curpos;
3983 cur_row = gl->term_curpos / gl->ncolumn;
3984 cur_col = gl->term_curpos % gl->ncolumn;
3985 new_row = (gl->term_curpos + n) / gl->ncolumn;
3986 new_col = (gl->term_curpos + n) % gl->ncolumn;
3991 if(gl_print_control_sequence(gl, 1, gl->down))
3998 if(gl_print_control_sequence(gl, 1, gl->up))
4010 if(gl->right_n != NULL && new_col - cur_col > 1) {
4011 if(gl_print_control_sequence(gl, 1, tparm((char *)gl->right_n,
4018 if(gl_print_control_sequence(gl, 1, gl->right))
4031 if(gl->left_n != NULL && cur_col - new_col > 3) {
4032 if(gl_print_control_sequence(gl, 1, tparm((char *)gl->left_n,
4039 if(gl_print_control_sequence(gl, 1, gl->left))
4047 gl->term_curpos += n;
4056 * gl GetLine * The resource object of this program.
4073 static int gl_print_char(GetLine *gl, char c, char pad)
4086 nchar = gl_displayed_tab_width(gl, gl->term_curpos);
4110 if(gl_print_raw_string(gl, 1, string, -1))
4116 gl->term_curpos += nchar;
4121 if(gl->term_curpos > gl->term_len)
4122 gl->term_len = gl->term_curpos;
4129 if(gl->term_curpos % gl->ncolumn == 0) {
4130 int term_curpos = gl->term_curpos;
4131 if(gl_print_char(gl, pad ? pad : ' ', ' ') ||
4132 gl_set_term_curpos(gl, term_curpos))
4143 * gl GetLine * The resource object of this program.
4160 static int gl_print_string(GetLine *gl, const char *string, char pad)
4165 if(gl_print_char(gl, *cptr, nextc ? nextc : pad))
4175 * gl GetLine * The resource object of this library.
4181 static int gl_set_term_curpos(GetLine *gl, int term_curpos)
4183 return gl_terminal_move_cursor(gl, term_curpos - gl->term_curpos);
4192 return gl_place_cursor(gl, gl->buff_curpos - count);
4201 return gl_place_cursor(gl, gl->buff_curpos + count);
4210 gl->insert = !gl->insert;
4220 return gl_place_cursor(gl, 0);
4229 return gl_place_cursor(gl, gl->ntotal);
4242 gl_save_for_undo(gl);
4246 strlcpy(gl->cutbuf, gl->line, gl->linelen);
4250 gl_truncate_buffer(gl, 0);
4254 if(gl_place_cursor(gl, 0))
4259 if(gl_truncate_display(gl))
4274 gl_save_for_undo(gl);
4278 strlcpy(gl->cutbuf, gl->line + gl->buff_curpos, gl->linelen);
4282 gl_truncate_buffer(gl, gl->buff_curpos);
4286 if(gl_truncate_display(gl))
4292 return gl_place_cursor(gl, gl->buff_curpos);
4304 int nc = gl->buff_curpos - gl->insert_curpos;
4312 return gl_place_cursor(gl, gl->insert_curpos) ||
4313 gl_delete_chars(gl, nc, gl->editor == GL_EMACS_MODE || gl->vi.command);
4321 return gl_place_cursor(gl, gl_nth_word_end_forward(gl, count) +
4322 (gl->editor==GL_EMACS_MODE));
4331 return gl_place_cursor(gl, gl_nth_word_start_forward(gl, count));
4339 return gl_place_cursor(gl, gl_nth_word_start_backward(gl, count));
4346 * gl GetLine * The resource object of this library.
4353 static int gl_delete_chars(GetLine *gl, int nc, int cut)
4359 gl_save_for_undo(gl);
4364 if(gl->buff_curpos + nc > gl->ntotal)
4365 nc = gl->ntotal - gl->buff_curpos;
4370 memcpy(gl->cutbuf, gl->line + gl->buff_curpos, nc);
4371 gl->cutbuf[nc] = '\0';
4382 if(gl->editor == GL_VI_MODE && !gl->vi.command && !gl->insert) {
4387 int nrestore = gl->buff_curpos + nc <= gl->vi.undo.ntotal ?
4388 nc : gl->vi.undo.ntotal - gl->buff_curpos;
4393 gl_buffer_string(gl, gl->vi.undo.line + gl->buff_curpos, nrestore,
4394 gl->buff_curpos);
4404 gl_truncate_buffer(gl, (gl->vi.undo.ntotal > gl->buff_curpos) ?
4405 gl->vi.undo.ntotal : gl->buff_curpos);
4411 gl_remove_from_buffer(gl, gl->buff_curpos, nc);
4416 if(gl_print_string(gl, gl->line + gl->buff_curpos, '\0'))
4421 if(gl_truncate_display(gl))
4426 return gl_place_cursor(gl, gl->buff_curpos);
4438 return gl_delete_chars(gl, count, gl->vi.command);
4451 if(count > gl->buff_curpos - gl->insert_curpos)
4452 count = gl->buff_curpos - gl->insert_curpos;
4457 gl_save_for_undo(gl);
4458 return gl_cursor_left(gl, count, NULL) ||
4459 gl_delete_chars(gl, count, gl->vi.command);
4467 if (--count >= gl->buff_curpos)
4468 return gl_forward_delete_char(gl, count - gl->buff_curpos, NULL);
4470 return gl_backward_delete_char(gl, gl->buff_curpos - count, NULL);
4479 int curpos = gl_index_of_matching_paren(gl);
4481 gl_save_for_undo(gl);
4482 if(curpos >= gl->buff_curpos)
4483 return gl_forward_delete_char(gl, curpos - gl->buff_curpos + 1, NULL);
4485 return gl_backward_delete_char(gl, ++gl->buff_curpos - curpos + 1, NULL);
4500 gl_save_for_undo(gl);
4505 if(gl->editor == GL_EMACS_MODE) {
4506 return gl_delete_chars(gl,
4507 gl_nth_word_end_forward(gl,count) - gl->buff_curpos + 1, 1);
4509 return gl_delete_chars(gl,
4510 gl_nth_word_start_forward(gl,count) - gl->buff_curpos,
4511 gl->vi.command);
4524 int buff_curpos = gl->buff_curpos;
4529 gl_save_for_undo(gl);
4533 if(gl_backward_word(gl, count, NULL))
4538 return gl_delete_chars(gl, buff_curpos - gl->buff_curpos,
4539 gl->editor == GL_EMACS_MODE || gl->vi.command);
4547 * gl GetLine * The getline resource object.
4564 static int gl_delete_find(GetLine *gl, int count, char c, int forward,
4570 int pos = gl_find_char(gl, count, forward, onto, c);
4577 gl_save_for_undo(gl);
4583 gl->vi.command = 0;
4588 if(gl_delete_chars(gl, pos - gl->buff_curpos + 1, 1))
4591 int buff_curpos = gl->buff_curpos;
4592 if(gl_place_cursor(gl, pos) ||
4593 gl_delete_chars(gl, buff_curpos - gl->buff_curpos, 1))
4599 if(change && gl_vi_insert(gl, 0, NULL))
4610 return gl_delete_find(gl, count, '\0', 1, 1, 0);
4619 return gl_delete_find(gl, count, '\0', 0, 1, 0);
4628 return gl_delete_find(gl, count, '\0', 1, 0, 0);
4637 return gl_delete_find(gl, count, '\0', 0, 0, 0);
4646 return gl_delete_find(gl, count, gl->vi.find_char, gl->vi.find_forward,
4647 gl->vi.find_onto, 0);
4656 return gl_delete_find(gl, count, gl->vi.find_char,
4657 !gl->vi.find_forward, gl->vi.find_onto, 0);
4669 int last = gl_nth_word_end_forward(gl, count);
4674 gl_save_for_undo(gl);
4678 while(gl->buff_curpos <= last) {
4679 char *cptr = gl->line + gl->buff_curpos;
4684 gl_buffer_char(gl, toupper((int) *cptr), gl->buff_curpos);
4685 gl->buff_curpos++;
4690 if(gl_print_char(gl, *cptr, cptr[1]))
4693 return gl_place_cursor(gl, gl->buff_curpos); /* bounds check */
4705 int last = gl_nth_word_end_forward(gl, count);
4710 gl_save_for_undo(gl);
4714 while(gl->buff_curpos <= last) {
4715 char *cptr = gl->line + gl->buff_curpos;
4720 gl_buffer_char(gl, tolower((int) *cptr), gl->buff_curpos);
4721 gl->buff_curpos++;
4726 if(gl_print_char(gl, *cptr, cptr[1]))
4729 return gl_place_cursor(gl, gl->buff_curpos); /* bounds check */
4739 char *cptr; /* &gl->line[gl->buff_curpos] */
4745 int insert = gl->insert;
4750 gl_save_for_undo(gl);
4754 gl->insert = 0;
4758 for(i=0; i<count && gl->buff_curpos < gl->ntotal; i++) {
4759 int pos = gl->buff_curpos;
4763 for(cptr = gl->line + pos ; pos<gl->ntotal && !gl_is_word_char((int) *cptr);
4769 if(gl_place_cursor(gl, pos))
4775 for(first=1; gl->buff_curpos<gl->ntotal && gl_is_word_char((int) *cptr);
4776 gl->buff_curpos++, cptr++) {
4782 gl_buffer_char(gl, toupper((int) *cptr), cptr - gl->line);
4785 gl_buffer_char(gl, tolower((int) *cptr), cptr - gl->line);
4792 if(gl_print_char(gl, *cptr, cptr[1]))
4799 gl->insert = insert;
4800 return gl_place_cursor(gl, gl->buff_curpos); /* bounds check */
4811 int buff_curpos = gl->buff_curpos;
4815 if(gl->endline)
4820 if(gl_erase_line(gl))
4825 if(gl_display_prompt(gl))
4830 if(gl_print_string(gl, gl->line, '\0'))
4835 if(gl_place_cursor(gl, buff_curpos))
4840 gl->redisplay = 0;
4844 return gl_flush_output(gl);
4856 if(gl_print_control_sequence(gl, gl->nline, gl->home) ||
4857 gl_print_control_sequence(gl, gl->nline, gl->clear_eod))
4862 gl_line_erased(gl);
4866 gl_queue_redisplay(gl);
4882 if(gl->buff_curpos < 1 || gl->buff_curpos >= gl->ntotal)
4888 gl_save_for_undo(gl);
4892 from[0] = gl->line[gl->buff_curpos - 1];
4893 from[1] = gl->line[gl->buff_curpos];
4895 swap[0] = gl->line[gl->buff_curpos];
4896 swap[1] = gl->line[gl->buff_curpos - 1];
4901 if(gl_place_cursor(gl, gl->buff_curpos-1))
4906 gl_buffer_char(gl, swap[0], gl->buff_curpos);
4907 gl_buffer_char(gl, swap[1], gl->buff_curpos+1);
4913 if(gl_displayed_string_width(gl, from, -1, gl->term_curpos) ==
4914 gl_displayed_string_width(gl, swap, -1, gl->term_curpos)) {
4915 int insert = gl->insert;
4916 gl->insert = 0;
4917 if(gl_print_char(gl, swap[0], swap[1]) ||
4918 gl_print_char(gl, swap[1], gl->line[gl->buff_curpos+2]))
4920 gl->insert = insert;
4926 if(gl_print_string(gl, gl->line + gl->buff_curpos, '\0') ||
4927 gl_truncate_display(gl))
4933 return gl_place_cursor(gl, gl->buff_curpos + 2);
4942 gl->buff_mark = gl->buff_curpos;
4956 int old_mark = gl->buff_mark <= gl->ntotal ? gl->buff_mark : gl->ntotal;
4960 gl->buff_mark = gl->buff_curpos;
4964 return gl_place_cursor(gl, old_mark);
4969 * mark and the cursor, recording them in gl->cutbuf for later pasting.
4977 gl_save_for_undo(gl);
4981 if(gl->buff_mark > gl->ntotal)
4982 gl->buff_mark = gl->ntotal;
4987 if(gl->buff_mark == gl->buff_curpos) {
4988 gl->cutbuf[0] = '\0';
4994 if(gl->buff_mark < gl->buff_curpos && gl_exchange_point_and_mark(gl,1,NULL))
4999 if(gl_delete_chars(gl, gl->buff_mark - gl->buff_curpos, 1))
5004 gl->buff_mark = gl->buff_curpos;
5010 * mark and the cursor, in gl->cutbuf for later pasting.
5019 mark = gl->buff_mark > gl->ntotal ? gl->ntotal : gl->buff_mark;
5024 if(mark == gl->buff_curpos) {
5025 gl->cutbuf[0] = '\0';
5031 if(mark < gl->buff_curpos) {
5033 cb = gl->buff_curpos - 1;
5035 ca = gl->buff_curpos;
5041 memcpy(gl->cutbuf, gl->line + ca, cb + 1 - ca);
5042 gl->cutbuf[cb + 1 - ca] = '\0';
5056 gl->buff_mark = gl->buff_curpos;
5060 if(gl->cutbuf[0] == '\0')
5061 return gl_ring_bell(gl, 1, NULL);
5066 gl_save_for_undo(gl);
5071 if(gl_add_string_to_line(gl, gl->cutbuf))
5078 if(gl->editor == GL_VI_MODE && gl_cursor_left(gl, 1, NULL))
5089 int was_command = gl->vi.command;
5094 if(gl->cutbuf[0] == '\0')
5095 return gl_ring_bell(gl, 1, NULL);
5099 gl->buff_mark = gl->buff_curpos + 1;
5104 gl_save_for_undo(gl);
5108 if(gl_vi_append(gl, 0, NULL))
5114 if(gl_add_string_to_line(gl, gl->cutbuf))
5121 gl_vi_command_mode(gl);
5128 * the current values of gl->ncolumn and gl->nrow are returned.
5131 * gl GetLine * The resource object of gl_get_line().
5136 static void gl_query_size(GetLine *gl, int *ncolumn, int *nline)
5143 if(ioctl(gl->output_fd, TIOCGWINSZ, &size) == 0 &&
5153 *ncolumn = gl->ncolumn;
5154 *nline = gl->nline;
5163 * gl GetLine * The resource object of gl_get_line().
5168 static int _gl_update_size(GetLine *gl)
5174 gl_query_size(gl, &ncolumn, &nline);
5176 * Update gl and the displayed line to fit the new dimensions.
5178 return gl_handle_tty_resize(gl, ncolumn, nline);
5183 * size. Also install the new size in gl.
5186 * gl GetLine * The resource object of gl_get_line().
5193 static int gl_handle_tty_resize(GetLine *gl, int ncolumn, int nline)
5198 if(!gl->is_term) {
5199 gl->nline = nline;
5200 gl->ncolumn = ncolumn;
5204 } else if(ncolumn != gl->ncolumn || nline != gl->nline) {
5208 if(gl_erase_line(gl))
5213 gl->nline = nline;
5214 gl->ncolumn = ncolumn;
5219 gl_queue_redisplay(gl);
5234 gl_vi_command_mode(gl);
5238 gl->preload_id = 0;
5242 gl->last_search = gl->keyseq_count;
5246 if(_glh_search_prefix(gl->glh, gl->line, 0)) {
5247 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
5255 if(_glh_find_backwards(gl->glh, gl->line, gl->linelen+1) == NULL)
5257 while(--count && _glh_find_backwards(gl->glh, gl->line, gl->linelen+1))
5260 * Accomodate the new contents of gl->line[].
5262 gl_update_buffer(gl);
5266 gl->buff_curpos = gl->ntotal;
5270 gl_queue_redisplay(gl);
5284 gl_vi_command_mode(gl);
5288 gl->last_search = gl->keyseq_count;
5293 if(_glh_line_id(gl->glh, 0) == 0 && gl->preload_id) {
5294 _glh_recall_line(gl->glh, gl->preload_id, gl->line, gl->linelen+1);
5295 gl->preload_id = 0;
5300 if(_glh_search_prefix(gl->glh, gl->line, 0)) {
5301 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
5309 if(_glh_find_forwards(gl->glh, gl->line, gl->linelen+1) == NULL)
5311 while(--count && _glh_find_forwards(gl->glh, gl->line, gl->linelen+1))
5315 * Accomodate the new contents of gl->line[].
5317 gl_update_buffer(gl);
5321 gl->buff_curpos = gl->ntotal;
5325 gl_queue_redisplay(gl);
5341 gl_vi_command_mode(gl);
5345 gl->preload_id = 0;
5349 gl->last_search = gl->keyseq_count;
5357 if(count >= 0 && !_glh_search_active(gl->glh) &&
5358 _glh_search_prefix(gl->glh, gl->line, gl->buff_curpos +
5359 (gl->editor==GL_VI_MODE && gl->ntotal>0))) {
5360 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
5367 if(_glh_find_backwards(gl->glh, gl->line, gl->linelen+1) == NULL)
5370 * Accomodate the new contents of gl->line[].
5372 gl_update_buffer(gl);
5376 gl->buff_curpos = gl->ntotal;
5380 gl_queue_redisplay(gl);
5391 return gl_history_search_backward(gl, -1, NULL);
5407 gl_vi_command_mode(gl);
5411 gl->last_search = gl->keyseq_count;
5419 if(count >= 0 && !_glh_search_active(gl->glh) &&
5420 _glh_search_prefix(gl->glh, gl->line, gl->buff_curpos +
5421 (gl->editor==GL_VI_MODE && gl->ntotal>0))) {
5422 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
5428 if(_glh_find_forwards(gl->glh, gl->line, gl->linelen+1) == NULL)
5431 * Accomodate the new contents of gl->line[].
5433 gl_update_buffer(gl);
5437 gl->buff_curpos = gl->ntotal;
5441 gl_queue_redisplay(gl);
5452 return gl_history_search_forward(gl, -1, NULL);
5485 GlCplCallback *cb = data ? (GlCplCallback *) data : &gl->cplfn;
5491 if(gl->vi.command && gl_vi_append(gl, 0, NULL))
5496 buff_pos = gl->buff_curpos;
5500 matches = cpl_complete_word(gl->cpl, gl->line, gl->buff_curpos, cb->data,
5506 waserr = gl_print_info(gl, cpl_last_error(gl->cpl), GL_END_INFO);
5514 if(matches->nmatch > 1 && gl->echo) {
5515 if(_gl_normal_io(gl) ||
5516 _cpl_output_completions(matches, gl_write_fn, gl, gl->ncolumn))
5532 if(gl_newline(gl, 1, NULL))
5546 if(gl->ntotal + nextra < gl->linelen) {
5550 gl_make_gap_in_buffer(gl, gl->buff_curpos, nextra);
5554 gl_buffer_string(gl, matches->suffix, suffix_len, gl->buff_curpos);
5558 gl_buffer_string(gl, matches->cont_suffix, cont_len,
5559 gl->buff_curpos + suffix_len);
5563 gl->buff_curpos += nextra;
5569 if(gl->displayed) {
5570 if(gl_truncate_display(gl) ||
5571 gl_print_string(gl, gl->line + buff_pos, '\0') ||
5572 gl_place_cursor(gl, gl->buff_curpos))
5576 (void) gl_print_info(gl,
5588 if(_gl_raw_io(gl, 1))
5602 /* gl->line[]. */
5614 if(gl->vi.command && gl_vi_append(gl, 0, NULL))
5619 start_path = _pu_start_of_path(gl->line, gl->buff_curpos);
5625 pathlen = gl->buff_curpos - (start_path - gl->line);
5629 result = ef_expand_file(gl->ef, start_path, pathlen);
5634 return gl_print_info(gl, ef_last_error(gl->ef), GL_END_INFO);
5639 return gl_print_info(gl, "No files match.", GL_END_INFO);
5644 gl_save_for_undo(gl);
5671 if(gl->ntotal + nextra >= gl->linelen) {
5672 return gl_print_info(gl, "Insufficient room in line for file expansion.",
5680 gl_make_gap_in_buffer(gl, gl->buff_curpos, nextra);
5682 gl->buff_curpos += nextra;
5683 gl_remove_from_buffer(gl, gl->buff_curpos, -nextra);
5689 for(i=0,j=start_path - gl->line; i<result->nfile; i++) {
5695 gl_buffer_char(gl, '\\', j++);
5697 gl_buffer_char(gl, c, j++);
5699 gl_buffer_char(gl, ' ', j++);
5706 if(gl_place_cursor(gl, start_path - gl->line) ||
5707 gl_truncate_display(gl) ||
5708 gl_print_string(gl, start_path, start_path[length]))
5713 return gl_place_cursor(gl, (start_path - gl->line) + length);
5726 /* gl->line[]. */
5732 start_path = _pu_start_of_path(gl->line, gl->buff_curpos);
5738 pathlen = gl->buff_curpos - (start_path - gl->line);
5742 result = ef_expand_file(gl->ef, start_path, pathlen);
5747 return gl_print_info(gl, ef_last_error(gl->ef), GL_END_INFO);
5752 return gl_print_info(gl, "No files match.", GL_END_INFO);
5756 } else if(gl->echo) {
5757 if(gl_start_newline(gl, 1) ||
5758 _ef_output_expansions(result, gl_write_fn, gl, gl->ncolumn))
5760 gl_queue_redisplay(gl);
5784 * gl GetLine * The resource object of the command-line input
5797 int gl_customize_completion(GetLine *gl, void *data, CplMatchFn *match_fn)
5803 if(!gl || !match_fn) {
5804 if(gl)
5805 _err_record_msg(gl->err, "NULL argument", END_ERR_MSG);
5812 gl_mask_signals(gl, &oldset);
5816 gl->cplfn.fn = match_fn;
5817 gl->cplfn.data = data;
5821 gl_unmask_signals(gl, &oldset);
5829 * gl GetLine * The resource object of the command-line input
5841 int gl_change_terminal(GetLine *gl, FILE *input_fp, FILE *output_fp,
5849 if(!gl) {
5856 if(gl_mask_signals(gl, &oldset))
5861 status = _gl_change_terminal(gl, input_fp, output_fp, term);
5865 gl_unmask_signals(gl, &oldset);
5874 static int _gl_change_terminal(GetLine *gl, FILE *input_fp, FILE *output_fp,
5883 gl_print_info(gl, "Can't change terminal. Bad input/output stream(s).",
5891 if(gl->input_fd >= 0) {
5895 if(_gl_normal_io(gl))
5901 FD_CLR(gl->input_fd, &gl->rfds);
5907 gl->input_fp = input_fp;
5908 gl->input_fd = fileno(input_fp);
5909 gl->output_fp = output_fp;
5910 gl->output_fd = fileno(output_fp);
5916 if(gl->input_fd > gl->max_fd)
5917 gl->max_fd = gl->input_fd;
5923 gl->is_term = 0;
5929 is_term = isatty(gl->input_fd) && isatty(gl->output_fd);
5939 if(term != gl->term) {
5943 if(gl->term) {
5944 free(gl->term);
5945 gl->term = NULL;
5953 gl->term = (char *) malloc(termsz);
5954 if(gl->term)
5955 strlcpy(gl->term, term, termsz);
5962 _kt_clear_bindings(gl->bindings, KTB_TERM);
5970 if(tcgetattr(gl->input_fd, &gl->oldattr)) {
5971 _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG);
5978 gl->is_term = 1;
5982 if(gl_control_strings(gl, term)) {
5983 gl->is_term = 0;
5989 if(gl_bind_terminal_keys(gl))
5995 gl->io_mode = GL_NORMAL_MODE;
5999 if(_gl_io_mode(gl, gl->io_mode))
6008 * gl GetLine * The resource object of the command-line input
6014 static int gl_bind_terminal_keys(GetLine *gl)
6019 if(gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VINTR],
6021 gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VQUIT], "abort") ||
6022 gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VSUSP], "suspend"))
6028 if(gl->editor == GL_VI_MODE) {
6029 if(gl_bind_control_char(gl, KTB_TERM, MAKE_META(gl->oldattr.c_cc[VINTR]),
6031 gl_bind_control_char(gl, KTB_TERM, MAKE_META(gl->oldattr.c_cc[VQUIT]),
6033 gl_bind_control_char(gl, KTB_TERM, MAKE_META(gl->oldattr.c_cc[VSUSP]),
6041 if(gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VLNEXT],
6045 if(_kt_set_keybinding(gl->bindings, KTB_TERM, "^V", "literal-next")) {
6046 _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
6054 if(_gl_bind_arrow_keys(gl))
6071 if(gl->ntotal < 1) {
6072 gl_record_status(gl, GLR_EOF, 0);
6077 } else if(gl->buff_curpos >= gl->ntotal) {
6078 return gl_list_completions(gl, 1, NULL);
6087 gl_save_for_undo(gl);
6091 return gl_forward_delete_char(gl, count, NULL);
6106 if(gl->ntotal < 1) {
6107 gl_record_status(gl, GLR_EOF, 0);
6113 return gl_list_completions(gl, 1, NULL);
6129 GlCplCallback *cb = data ? (GlCplCallback *) data : &gl->cplfn;
6133 CplMatches *matches = cpl_complete_word(gl->cpl, gl->line, gl->buff_curpos,
6139 waserr = gl_print_info(gl, cpl_last_error(gl->cpl), GL_END_INFO);
6143 } else if(matches->nmatch > 0 && gl->echo) {
6144 if(_gl_normal_io(gl) ||
6145 _cpl_output_completions(matches, gl_write_fn, gl, gl->ncolumn))
6153 if(_gl_raw_io(gl, 1))
6164 * gl GetLine * The getline resource object.
6169 static int _gl_bind_arrow_keys(GetLine *gl)
6174 if(_gl_rebind_arrow_key(gl, "up", gl->u_arrow, "^[[A", "^[OA") ||
6175 _gl_rebind_arrow_key(gl, "down", gl->d_arrow, "^[[B", "^[OB") ||
6176 _gl_rebind_arrow_key(gl, "left", gl->l_arrow, "^[[D", "^[OD") ||
6177 _gl_rebind_arrow_key(gl, "right", gl->r_arrow, "^[[C", "^[OC"))
6193 * gl GetLine * The resource object of gl_get_line().
6202 static int _gl_rebind_arrow_key(GetLine *gl, const char *name,
6212 if(_kt_lookup_keybinding(gl->bindings, name, strlen(name), &keysym, &nsym)
6224 _kt_set_keyfn(gl->bindings, KTB_TERM, term_seq, fn, data)) ||
6226 _kt_set_keyfn(gl->bindings, KTB_NORM, def_seq1, fn, data)) ||
6228 _kt_set_keyfn(gl->bindings, KTB_NORM, def_seq2, fn, data))) {
6229 _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
6240 * gl GetLine * The getline resource object.
6251 static int _gl_read_config_file(GetLine *gl, const char *filename, KtBinder who)
6258 _err_record_msg(gl->err,
6271 if(!gl || !filename) {
6272 if(gl)
6273 _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
6280 expansion = ef_expand_file(gl->ef, filename, -1);
6282 gl_print_info(gl, "Unable to expand ", filename, " (",
6283 ef_last_error(gl->ef), ").", GL_END_INFO);
6299 waserr = _gl_parse_config_line(gl, fp, glc_file_getc, filename, who,
6304 if(_gl_bind_arrow_keys(gl))
6319 static int _gl_read_config_string(GetLine *gl, const char *buffer, KtBinder who)
6327 if(!gl || !buffer) {
6328 if(gl)
6329 _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
6341 waserr = _gl_parse_config_line(gl, &bptr, glc_buff_getc, "", who, &lineno);
6345 if(_gl_bind_arrow_keys(gl))
6354 * gl GetLine * The getline resource object.
6370 static int _gl_parse_config_line(GetLine *gl, void *stream, GlcGetcFn *getc_fn,
6429 gl_report_config_error(gl, origin, *lineno, "Too many arguments.");
6471 gl_report_config_error(gl, origin, *lineno, "Line too long.");
6488 if(_kt_set_keybinding(gl->bindings, who, keyseq, action)) {
6489 gl_report_config_error(gl, origin, *lineno,
6490 _kt_last_error(gl->bindings));
6494 gl_report_config_error(gl, origin, *lineno, "Wrong number of arguments.");
6498 gl_change_editor(gl, GL_EMACS_MODE);
6500 gl_change_editor(gl, GL_VI_MODE);
6502 gl_change_editor(gl, GL_NO_EDITOR);
6504 gl_report_config_error(gl, origin, *lineno,
6508 gl->silence_bell = 1;
6510 gl_report_config_error(gl, origin, *lineno, "Unknown command name.");
6527 * gl GetLine * The resource object of gl_get_line().
6536 static int gl_report_config_error(GetLine *gl, const char *origin, int lineno,
6547 return gl_print_info(gl, origin, ":", lnum, ": ", errmsg, GL_END_INFO);
6579 /* gl->line[]. */
6585 start_path = _pu_start_of_path(gl->line, gl->buff_curpos);
6591 pathlen = gl->buff_curpos - (start_path - gl->line);
6595 result = ef_expand_file(gl->ef, start_path, pathlen);
6600 return gl_print_info(gl, ef_last_error(gl->ef), GL_END_INFO);
6605 return gl_print_info(gl, "No files match.", GL_END_INFO);
6610 return gl_print_info(gl, "More than one file matches.", GL_END_INFO);
6618 return gl_print_info(gl, "Not a normal file.", GL_END_INFO);
6623 gl->file_fp = fopen(result->files[0], "r");
6624 if(!gl->file_fp) {
6625 return gl_print_info(gl, "Unable to open: ", result->files[0],
6633 if(fileno(gl->file_fp) > gl->max_fd)
6634 gl->max_fd = fileno(gl->file_fp);
6639 if(gl->raw_mode && gl->io_mode==GL_SERVER_MODE &&
6640 gl_nonblocking_io(gl, fileno(gl->file_fp))) {
6641 gl_revert_input(gl);
6642 return gl_print_info(gl, "Can't read file %s with non-blocking I/O",
6648 if(gl_print_info(gl, "<Taking input from ", result->files[0], ">",
6660 * gl GetLine * The getline resource object.
6662 static void gl_revert_input(GetLine *gl)
6664 if(gl->file_fp)
6665 fclose(gl->file_fp);
6666 gl->file_fp = NULL;
6667 gl->endline = 1;
6680 gl_vi_command_mode(gl);
6684 gl->preload_id = 0;
6688 gl->last_search = gl->keyseq_count;
6692 if(_glh_oldest_line(gl->glh, gl->line, gl->linelen+1) == NULL)
6695 * Accomodate the new contents of gl->line[].
6697 gl_update_buffer(gl);
6701 gl->buff_curpos = gl->ntotal;
6705 gl_queue_redisplay(gl);
6720 gl_vi_command_mode(gl);
6724 gl->preload_id = 0;
6728 gl->last_search = gl->keyseq_count;
6732 if(_glh_current_line(gl->glh, gl->line, gl->linelen+1) == NULL)
6735 * Accomodate the new contents of gl->line[].
6737 gl_update_buffer(gl);
6741 gl->buff_curpos = gl->ntotal;
6745 gl_queue_redisplay(gl);
6764 if(gl->vi.command && gl->number < 0 && count == '0')
6765 return gl_beginning_of_line(gl, count, NULL);
6769 if(gl->number < 0 || !is_digit)
6770 gl->number = 0;
6784 gl->number = gl->number * 10 + n;
6790 * The newline action function sets gl->endline to tell
6799 gl->endline = 1;
6804 id = _glh_line_id(gl->glh, 1);
6806 gl->preload_id = id;
6811 * The 'repeat' action function sets gl->endline to tell
6813 * ID of the next history line in gl->preload_id so that the next call
6818 gl->endline = 1;
6819 gl->preload_id = _glh_line_id(gl->glh, 1);
6820 gl->preload_history = 1;
6828 * gl GetLine * The getline resource object.
6833 * See gl->rtn_status for details.
6835 static int gl_flush_output(GetLine *gl)
6840 gl->pending_io = GLP_WRITE;
6845 switch(_glq_flush_queue(gl->cq, gl->flush_fn, gl)) {
6847 return gl->redisplay && !gl->postpone && gl_redisplay(gl, 1, NULL);
6850 gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO);
6854 gl_record_status(gl, errno==EINTR ? GLR_SIGNAL : GLR_ERROR, errno);
6870 GetLine *gl = (GetLine *) data;
6875 int nnew = write(gl->output_fd, s, n-ndone);
6923 * gl GetLine * The getline resource object.
6929 static int gl_change_editor(GetLine *gl, GlEditor editor)
6936 _kt_clear_bindings(gl->bindings, KTB_NORM);
6937 _kt_clear_bindings(gl->bindings, KTB_TERM);
6938 (void) _kt_add_bindings(gl->bindings, KTB_NORM, gl_emacs_bindings,
6942 _kt_clear_bindings(gl->bindings, KTB_NORM);
6943 _kt_clear_bindings(gl->bindings, KTB_TERM);
6944 (void) _kt_add_bindings(gl->bindings, KTB_NORM, gl_vi_bindings,
6950 _err_record_msg(gl->err, "Unknown editor", END_ERR_MSG);
6957 gl->editor = editor;
6958 gl->vi.command = 0; /* Start in input mode */
6959 gl->insert_curpos = 0;
6963 if(gl->editor != GL_NO_EDITOR && gl->input_fp)
6964 (void) gl_bind_terminal_keys(gl);
6973 return gl_change_editor(gl, GL_EMACS_MODE);
6981 return gl_change_editor(gl, GL_VI_MODE);
6993 gl_save_for_undo(gl);
6997 gl->insert = 1;
6998 gl->vi.command = 0;
6999 gl->insert_curpos = gl->buff_curpos;
7012 gl_save_for_undo(gl);
7016 gl->insert = 0;
7017 gl->vi.command = 0;
7018 gl->insert_curpos = gl->buff_curpos;
7032 int insert = gl->insert;
7037 gl_save_for_undo(gl);
7041 gl->insert = 0;
7045 for(i=0; i<count && gl->buff_curpos < gl->ntotal; i++) {
7046 char *cptr = gl->line + gl->buff_curpos++;
7051 gl_buffer_char(gl, toupper((int) *cptr), cptr - gl->line);
7053 gl_buffer_char(gl, tolower((int) *cptr), cptr - gl->line);
7058 if(gl_print_char(gl, *cptr, cptr[1]))
7064 gl->insert = insert;
7065 return gl_place_cursor(gl, gl->buff_curpos); /* bounds check */
7074 gl_save_for_undo(gl);
7075 return gl_beginning_of_line(gl, 0, NULL) ||
7076 gl_vi_insert(gl, 0, NULL);
7087 gl_save_for_undo(gl);
7088 gl->vi.command = 0; /* Allow cursor at EOL */
7089 return gl_end_of_line(gl, 0, NULL) ||
7090 gl_vi_insert(gl, 0, NULL);
7100 gl_save_for_undo(gl);
7101 gl->vi.command = 0; /* Allow cursor at EOL */
7102 return gl_cursor_right(gl, 1, NULL) ||
7103 gl_vi_insert(gl, 0, NULL);
7112 return gl_place_cursor(gl, count - 1);
7126 int insert = gl->insert;
7130 if(gl->vi.repeat.active) {
7131 c = gl->vi.repeat.input_char;
7133 if(gl_read_terminal(gl, 1, &c))
7135 gl->vi.repeat.input_char = c;
7140 if(gl->ntotal - gl->buff_curpos >= count) {
7145 gl_save_for_undo(gl);
7149 gl->insert = 0;
7155 gl_add_char_to_line(gl, c);
7159 gl->insert = insert;
7161 return gl_place_cursor(gl, gl->buff_curpos); /* bounds check */
7170 gl_save_for_undo(gl);
7171 gl->vi.command = 0; /* Allow cursor at EOL */
7172 return gl_kill_line(gl, count, NULL) || gl_vi_insert(gl, 0, NULL);
7181 return gl_backward_kill_line(gl,count,NULL) || gl_vi_insert(gl,0,NULL);
7190 return gl_delete_line(gl,count,NULL) || gl_vi_insert(gl,0,NULL);
7202 if(gl->buff_curpos + count >= gl->ntotal)
7203 count = gl->ntotal - gl->buff_curpos;
7209 memcpy(gl->cutbuf, gl->line + gl->buff_curpos, count);
7210 gl->cutbuf[count] = '\0';
7224 if(count > gl->buff_curpos)
7225 count = gl->buff_curpos;
7228 gl_place_cursor(gl, gl->buff_curpos - count);
7232 memcpy(gl->cutbuf, gl->line + gl->buff_curpos, count);
7233 gl->cutbuf[count] = '\0';
7243 if (--count >= gl->buff_curpos)
7244 return gl_forward_copy_char(gl, count - gl->buff_curpos, NULL);
7246 return gl_backward_copy_char(gl, gl->buff_curpos - count, NULL);
7255 int curpos = gl_index_of_matching_paren(gl);
7257 gl_save_for_undo(gl);
7258 if(curpos >= gl->buff_curpos)
7259 return gl_forward_copy_char(gl, curpos - gl->buff_curpos + 1, NULL);
7261 return gl_backward_copy_char(gl, ++gl->buff_curpos - curpos + 1, NULL);
7275 memcpy(gl->cutbuf, gl->line + gl->buff_curpos, gl->ntotal - gl->buff_curpos);
7276 gl->cutbuf[gl->ntotal - gl->buff_curpos] = '\0';
7289 memcpy(gl->cutbuf, gl->line, gl->buff_curpos);
7290 gl->cutbuf[gl->buff_curpos] = '\0';
7291 gl_place_cursor(gl, 0);
7303 memcpy(gl->cutbuf, gl->line, gl->ntotal);
7304 gl->cutbuf[gl->ntotal] = '\0';
7313 int pos = gl_find_char(gl, count, 1, 1, '\0');
7314 return pos >= 0 && gl_place_cursor(gl, pos);
7322 int pos = gl_find_char(gl, count, 0, 1, '\0');
7323 return pos >= 0 && gl_place_cursor(gl, pos);
7332 int pos = gl_find_char(gl, count, 1, 0, '\0');
7333 return pos >= 0 && gl_place_cursor(gl, pos);
7342 int pos = gl_find_char(gl, count, 0, 0, '\0');
7343 return pos >= 0 && gl_place_cursor(gl, pos);
7352 * gl GetLine * The getline resource object.
7362 * return int The index of the character in gl->line[], or
7365 static int gl_find_char(GetLine *gl, int count, int forward, int onto, char c)
7377 if(gl->vi.repeat.active) {
7378 c = gl->vi.find_char;
7380 if(gl_read_terminal(gl, 1, &c))
7385 gl->vi.find_forward = forward;
7386 gl->vi.find_onto = onto;
7387 gl->vi.find_char = c;
7398 for(i=0, pos=gl->buff_curpos; i<count && pos < gl->ntotal; i++) {
7407 for( ; pos<gl->ntotal && c!=gl->line[pos]; pos++)
7415 if(!onto && pos<gl->ntotal)
7422 for(i=0, pos=gl->buff_curpos; i<count && pos >= gl->insert_curpos; i++) {
7431 for( ; pos>=gl->insert_curpos && c!=gl->line[pos]; pos--)
7439 if(!onto && pos>=gl->insert_curpos)
7446 if(pos >= gl->insert_curpos && pos < gl->ntotal) {
7449 (void) gl_ring_bell(gl, 1, NULL);
7460 int pos = gl->vi.find_char ?
7461 gl_find_char(gl, count, gl->vi.find_forward, gl->vi.find_onto,
7462 gl->vi.find_char) : -1;
7463 return pos >= 0 && gl_place_cursor(gl, pos);
7472 int pos = gl->vi.find_char ?
7473 gl_find_char(gl, count, !gl->vi.find_forward, gl->vi.find_onto,
7474 gl->vi.find_char) : -1;
7475 return pos >= 0 && gl_place_cursor(gl, pos);
7484 * gl GetLine * The getline resource object.
7489 static int gl_nth_word_end_forward(GetLine *gl, int n)
7498 bufpos = gl->buff_curpos + 1;
7504 if(bufpos >= gl->ntotal)
7505 return gl->ntotal - 1;
7509 for(i=0; i<n && bufpos<gl->ntotal; i++) {
7513 for( ; bufpos<gl->ntotal && !gl_is_word_char((int)gl->line[bufpos]);
7519 for( ; bufpos<gl->ntotal && gl_is_word_char((int)gl->line[bufpos]);
7535 * gl GetLine * The getline resource object.
7540 static int gl_nth_word_start_forward(GetLine *gl, int n)
7547 bufpos = gl->buff_curpos;
7551 for(i=0; i<n && bufpos<gl->ntotal; i++) {
7555 for( ; bufpos<gl->ntotal && gl_is_word_char((int)gl->line[bufpos]);
7561 for( ; bufpos<gl->ntotal && !gl_is_word_char((int)gl->line[bufpos]);
7574 * gl GetLine * The getline resource object.
7579 static int gl_nth_word_start_backward(GetLine *gl, int n)
7586 bufpos = gl->buff_curpos;
7591 for(i=0; i<n && bufpos > gl->insert_curpos; i++) {
7597 while(--bufpos >= gl->insert_curpos &&
7598 !gl_is_word_char((int)gl->line[bufpos]))
7603 while(--bufpos >= gl->insert_curpos &&
7604 gl_is_word_char((int)gl->line[bufpos]))
7611 return bufpos >= gl->insert_curpos ? bufpos : gl->insert_curpos;
7624 int next = gl->editor == GL_EMACS_MODE ?
7625 gl_nth_word_end_forward(gl, count) :
7626 gl_nth_word_start_forward(gl, count);
7630 int n = next - gl->buff_curpos;
7634 memcpy(gl->cutbuf, gl->line + gl->buff_curpos, n);
7635 gl->cutbuf[n] = '\0';
7648 int next = gl_nth_word_start_backward(gl, count);
7652 int n = gl->buff_curpos - next;
7653 gl_place_cursor(gl, next);
7657 memcpy(gl->cutbuf, gl->line + next, n);
7658 gl->cutbuf[n] = '\0';
7667 * gl GetLine * The getline resource object.
7681 static int gl_copy_find(GetLine *gl, int count, char c, int forward, int onto)
7687 int pos = gl_find_char(gl, count, forward, onto, c);
7694 n = pos + 1 - gl->buff_curpos;
7695 memcpy(gl->cutbuf, gl->line + gl->buff_curpos, n);
7697 n = gl->buff_curpos - pos;
7698 memcpy(gl->cutbuf, gl->line + pos, n);
7699 if(gl->editor == GL_VI_MODE)
7700 gl_place_cursor(gl, pos);
7705 gl->cutbuf[n] = '\0';
7715 return gl_copy_find(gl, count, '\0', 1, 1);
7724 return gl_copy_find(gl, count, '\0', 0, 1);
7733 return gl_copy_find(gl, count, '\0', 1, 0);
7742 return gl_copy_find(gl, count, '\0', 0, 0);
7751 return gl_copy_find(gl, count, gl->vi.find_char, gl->vi.find_forward,
7752 gl->vi.find_onto);
7761 return gl_copy_find(gl, count, gl->vi.find_char, !gl->vi.find_forward,
7762 gl->vi.find_onto);
7770 * gl GetLine * The getline resource object.
7776 static int gl_place_cursor(GetLine *gl, int buff_curpos)
7782 if(buff_curpos >= gl->ntotal)
7783 buff_curpos = gl->vi.command ? gl->ntotal-1 : gl->ntotal;
7789 gl->buff_curpos = buff_curpos;
7793 return gl_set_term_curpos(gl, gl->prompt_len +
7794 gl_displayed_string_width(gl, gl->line, buff_curpos, gl->prompt_len));
7801 * functions, gl_interpret_char() sets gl->vi.undo.saved to 0 before
7806 * gl GetLine * The getline resource object.
7808 static void gl_save_for_undo(GetLine *gl)
7810 if(gl->vi.command && !gl->vi.undo.saved) {
7811 strlcpy(gl->vi.undo.line, gl->line, gl->linelen);
7812 gl->vi.undo.buff_curpos = gl->buff_curpos;
7813 gl->vi.undo.ntotal = gl->ntotal;
7814 gl->vi.undo.saved = 1;
7816 if(gl->vi.command && !gl->vi.repeat.saved &&
7817 gl->current_action.fn != gl_vi_repeat_change) {
7818 gl->vi.repeat.action = gl->current_action;
7819 gl->vi.repeat.count = gl->current_count;
7820 gl->vi.repeat.saved = 1;
7835 char *undo_ptr = gl->vi.undo.line;
7836 char *line_ptr = gl->line;
7849 if(gl->ntotal > gl->vi.undo.ntotal) {
7850 strlcpy(undo_ptr, line_ptr, gl->linelen);
7853 strlcpy(line_ptr, undo_ptr, gl->linelen);
7859 gl->vi.undo.ntotal = gl->ntotal;
7861 * Accomodate the new contents of gl->line[].
7863 gl_update_buffer(gl);
7868 if(gl->buff_curpos < gl->vi.undo.buff_curpos)
7869 gl->vi.undo.buff_curpos = gl->buff_curpos;
7871 gl->buff_curpos = gl->vi.undo.buff_curpos;
7876 gl->vi.repeat.action.fn = gl_vi_undo;
7877 gl->vi.repeat.action.data = NULL;
7878 gl->vi.repeat.count = 1;
7882 gl_queue_redisplay(gl);
7891 gl_save_for_undo(gl);
7892 gl->vi.command = 0; /* Allow cursor at EOL */
7893 return gl_forward_delete_word(gl, count, NULL) || gl_vi_insert(gl, 0, NULL);
7901 return gl_backward_delete_word(gl, count, NULL) || gl_vi_insert(gl, 0, NULL);
7909 return gl_delete_find(gl, count, '\0', 1, 1, 1);
7917 return gl_delete_find(gl, count, '\0', 0, 1, 1);
7925 return gl_delete_find(gl, count, '\0', 1, 0, 1);
7933 return gl_delete_find(gl, count, '\0', 0, 0, 1);
7942 return gl_delete_find(gl, count, gl->vi.find_char, gl->vi.find_forward,
7943 gl->vi.find_onto, 1);
7952 return gl_delete_find(gl, count, gl->vi.find_char, !gl->vi.find_forward,
7953 gl->vi.find_onto, 1);
7961 gl_save_for_undo(gl);
7962 gl->vi.command = 0; /* Allow cursor at EOL */
7963 return gl_delete_chars(gl, count, 1) || gl_vi_insert(gl, 0, NULL);
7971 return gl_backward_delete_char(gl, count, NULL) || gl_vi_insert(gl, 0, NULL);
7979 if (--count >= gl->buff_curpos)
7980 return gl_vi_forward_change_char(gl, count - gl->buff_curpos, NULL);
7982 return gl_vi_backward_change_char(gl, gl->buff_curpos - count, NULL);
7991 int curpos = gl_index_of_matching_paren(gl);
7993 gl_save_for_undo(gl);
7994 if(curpos >= gl->buff_curpos)
7995 return gl_vi_forward_change_char(gl, curpos - gl->buff_curpos + 1, NULL);
7997 return gl_vi_backward_change_char(gl, ++gl->buff_curpos - curpos + 1,
8007 * gl GetLine * The getline resource object.
8009 static void gl_vi_command_mode(GetLine *gl)
8011 if(gl->editor == GL_VI_MODE && !gl->vi.command) {
8012 gl->insert = 1;
8013 gl->vi.command = 1;
8014 gl->vi.repeat.input_curpos = gl->insert_curpos;
8015 gl->vi.repeat.command_curpos = gl->buff_curpos;
8016 gl->insert_curpos = 0; /* unrestrict left motion boundary */
8017 gl_cursor_left(gl, 1, NULL); /* Vi moves 1 left on entering command mode */
8026 return gl->silence_bell ? 0 :
8027 gl_print_control_sequence(gl, 1, gl->sound_bell);
8041 if(!gl->vi.repeat.action.fn)
8042 return gl_ring_bell(gl, 1, NULL);
8047 gl->vi.repeat.active = 1;
8051 status = gl->vi.repeat.action.fn(gl, gl->vi.repeat.count,
8052 gl->vi.repeat.action.data);
8056 gl->vi.repeat.active = 0;
8062 if(status==0 && !gl->vi.command) {
8066 gl_save_for_undo(gl);
8070 if(gl->vi.repeat.input_curpos >= 0 &&
8071 gl->vi.repeat.input_curpos <= gl->vi.repeat.command_curpos &&
8072 gl->vi.repeat.command_curpos <= gl->vi.undo.ntotal) {
8079 for(i=gl->vi.repeat.input_curpos; i<gl->vi.repeat.command_curpos; i++) {
8080 if(gl_add_char_to_line(gl, gl->vi.undo.line[i]))
8087 gl_vi_command_mode(gl);
8100 * gl GetLine * The getline resource object.
8105 static int gl_index_of_matching_paren(GetLine *gl)
8117 char c = gl->line[gl->buff_curpos];
8125 for(i=gl->buff_curpos+1; i<gl->ntotal; i++) {
8126 if(gl->line[i] == c)
8128 else if(gl->line[i] == match && --matches_needed==0)
8138 for(i=gl->buff_curpos-1; i>=0; i--) {
8139 if(gl->line[i] == c)
8141 else if(gl->line[i] == match && --matches_needed==0)
8149 for(i=gl->buff_curpos+1; i<gl->ntotal; i++)
8150 if(strchr(c_paren, gl->line[i]) != NULL)
8156 (void) gl_ring_bell(gl, 1, NULL);
8166 int curpos = gl_index_of_matching_paren(gl);
8168 return gl_place_cursor(gl, curpos);
8177 * gl GetLine * The resource object of this library.
8183 static int gl_interpret_char(GetLine *gl, char first_char)
8198 if(gl->editor == GL_NO_EDITOR) {
8199 gl_discard_chars(gl, 1);
8200 if(gl->ntotal >= gl->linelen)
8203 return gl_newline(gl, 1, NULL);
8204 gl_buffer_char(gl, c, gl->ntotal);
8211 if(gl->number >= 0 && isdigit((int)(unsigned char) c)) {
8212 gl_discard_chars(gl, 1);
8213 return gl_digit_argument(gl, c, NULL);
8218 } else if(gl->vi.command && c != GL_ESC_CHAR) {
8230 * Compose a potentially multiple key-sequence in gl->keyseq.
8254 if(keyseq[0] == GL_ESC_CHAR && !gl->vi.command)
8255 gl_vi_command_mode(gl);
8259 switch(_kt_lookup_keybinding(gl->bindings, keyseq, nkey, &keysym, &nsym)) {
8272 count = gl->number >= 0 ? gl->number : 1;
8277 gl->current_action = *action;
8278 gl->current_count = count;
8282 gl->vi.undo.saved = 0;
8283 gl->vi.repeat.saved = 0;
8287 * explicitly by looking at whether gl->number is -1 or not. If
8290 ret = action->fn(gl, count, action->data);
8298 if(gl->rtn_status == GLR_BLOCKED && gl->pending_io==GLP_READ)
8303 gl_discard_chars(gl, gl->nread);
8308 if(gl->last_search != gl->keyseq_count)
8309 _glh_cancel_search(gl->glh);
8314 gl->number = -1;
8318 if(gl_read_terminal(gl, 1, &c))
8328 gl_ring_bell(gl, 1, NULL);
8335 count = gl->number >= 0 ? gl->number : 1;
8337 gl_add_char_to_line(gl, first_char);
8338 gl->number = -1;
8340 gl_discard_chars(gl, 1);
8341 _glh_cancel_search(gl->glh);
8345 gl_ring_bell(gl, 1, NULL);
8346 gl_discard_chars(gl, gl->nread);
8347 _glh_cancel_search(gl->glh);
8359 gl_ring_bell(gl, 1, NULL);
8360 gl_discard_chars(gl, 1);
8373 * gl GetLine * The resource object of this library.
8393 int gl_configure_getline(GetLine *gl, const char *app_string,
8401 if(!gl) {
8408 if(gl_mask_signals(gl, &oldset))
8413 status = _gl_configure_getline(gl, app_string, app_file, user_file);
8417 gl_unmask_signals(gl, &oldset);
8426 static int _gl_configure_getline(GetLine *gl, const char *app_string,
8432 gl->configured = 1;
8437 (void) _gl_read_config_string(gl, app_string, KTB_NORM);
8442 (void) _gl_read_config_file(gl, app_file, KTB_NORM);
8447 (void) _gl_read_config_file(gl, user_file, KTB_USER);
8452 if(gl_record_string(&gl->app_file, app_file) ||
8453 gl_record_string(&gl->user_file, user_file)) {
8455 _err_record_msg(gl->err,
8515 return _gl_configure_getline(gl, NULL, gl->app_file, gl->user_file);
8523 * gl GetLine * The resource object of this library.
8537 int gl_save_history(GetLine *gl, const char *filename, const char *comment,
8545 if(!gl || !filename || !comment) {
8546 if(gl)
8547 _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
8554 if(gl_mask_signals(gl, &oldset))
8559 status = _gl_save_history(gl, filename, comment, max_lines);
8563 gl_unmask_signals(gl, &oldset);
8572 static int _gl_save_history(GetLine *gl, const char *filename,
8580 _err_record_msg(gl->err, "Can't save history without filesystem access",
8589 expansion = ef_expand_file(gl->ef, filename, -1);
8591 gl_print_info(gl, "Unable to expand ", filename, " (",
8592 ef_last_error(gl->ef), ").", GL_END_INFO);
8598 if(_glh_save_history(gl->glh, expansion->files[0], comment, max_lines)) {
8599 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
8610 * gl GetLine * The resource object of this library.
8619 int gl_load_history(GetLine *gl, const char *filename, const char *comment)
8626 if(!gl || !filename || !comment) {
8627 if(gl)
8628 _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
8635 if(gl_mask_signals(gl, &oldset))
8640 status = _gl_load_history(gl, filename, comment);
8644 gl_unmask_signals(gl, &oldset);
8653 static int _gl_load_history(GetLine *gl, const char *filename,
8661 _err_record_msg(gl->err, "Can't load history without filesystem access",
8670 expansion = ef_expand_file(gl->ef, filename, -1);
8672 gl_print_info(gl, "Unable to expand ", filename, " (",
8673 ef_last_error(gl->ef), ").", GL_END_INFO);
8679 if(_glh_load_history(gl->glh, expansion->files[0], comment,
8680 gl->cutbuf, gl->linelen+1)) {
8681 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
8682 gl->cutbuf[0] = '\0';
8685 gl->cutbuf[0] = '\0';
8695 * gl GetLine * The resource object of the command-line input
8706 * 1 - Either gl==NULL, or this facility isn't
8712 int gl_watch_fd(GetLine *gl, int fd, GlFdEvent event,
8720 if(!gl) {
8725 _err_record_msg(gl->err, "Error: fd < 0", END_ERR_MSG);
8732 if(gl_mask_signals(gl, &oldset))
8737 status = _gl_watch_fd(gl, fd, event, callback, data);
8741 gl_unmask_signals(gl, &oldset);
8750 static int _gl_watch_fd(GetLine *gl, int fd, GlFdEvent event,
8756 GlFdNode *prev; /* The node that precedes 'node' in gl->fd_nodes */
8762 for(prev=NULL,node=gl->fd_nodes; node && node->fd != fd;
8777 node = (GlFdNode *) _new_FreeListNode(gl->fd_node_mem);
8780 _err_record_msg(gl->err, "Insufficient memory", END_ERR_MSG);
8786 node->next = gl->fd_nodes;
8787 gl->fd_nodes = node;
8804 FD_SET(fd, &gl->rfds);
8806 FD_CLR(fd, &gl->rfds);
8812 FD_SET(fd, &gl->wfds);
8814 FD_CLR(fd, &gl->wfds);
8820 FD_SET(fd, &gl->ufds);
8822 FD_CLR(fd, &gl->ufds);
8828 if(fd > gl->max_fd)
8829 gl->max_fd = fd;
8839 gl->fd_nodes = node->next;
8840 node = (GlFdNode *) _del_FreeListNode(gl->fd_node_mem, node);
8866 * gl GetLine * The resource object of the command-line input
8879 * 1 - Either gl==NULL, or this facility isn't
8885 int gl_inactivity_timeout(GetLine *gl, GlTimeoutFn *timeout_fn, void *data,
8895 if(!gl) {
8902 if(gl_mask_signals(gl, &oldset))
8908 gl->timer.dt.tv_sec = sec;
8909 gl->timer.dt.tv_usec = nsec / 1000;
8910 gl->timer.fn = timeout_fn;
8911 gl->timer.data = data;
8913 gl->timer.fn = 0;
8914 gl->timer.data = NULL;
8919 gl_unmask_signals(gl, &oldset);
8931 * gl GetLine * The resource object of this module.
8937 static int gl_event_handler(GetLine *gl, int fd)
8954 while(gl->fd_nodes || gl->timer.fn) {
8959 fd_set rfds = gl->rfds;
8960 fd_set wfds = gl->wfds;
8961 fd_set ufds = gl->ufds;
8965 struct timeval dt = gl->timer.fn ? gl->timer.dt : zero;
8975 gl_catch_signals(gl);
8979 nready = select(gl->max_fd+1, &rfds, &wfds, &ufds,
8980 (gl->timer.fn || gl->io_mode==GL_SERVER_MODE) ? &dt : NULL);
8988 gl_mask_signals(gl, NULL);
9000 if(gl_call_timeout_handler(gl)) {
9002 } else if(gl->io_mode == GL_SERVER_MODE) {
9003 gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO);
9011 gl_record_status(gl, GLR_ERROR, errno);
9028 for(node=gl->fd_nodes; node; node=node->next) {
9033 if(gl_call_fd_handler(gl, &node->ur, node->fd, GLFD_URGENT))
9040 if(gl_call_fd_handler(gl, &node->rd, node->fd, GLFD_READ))
9047 if(gl_call_fd_handler(gl, &node->wr, node->fd, GLFD_WRITE))
9057 if(gl_flush_output(gl))
9070 * gl GetLine * The resource object of gl_get_line().
9078 static int gl_call_fd_handler(GetLine *gl, GlFdHandler *gfh, int fd,
9088 if(tcgetattr(gl->input_fd, &attr)) {
9089 _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG);
9093 while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) {
9095 _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
9102 switch(gfh->fn(gl, gfh->data, fd, event)) {
9105 gl_record_status(gl, GLR_FDABORT, 0);
9109 gl_queue_redisplay(gl);
9118 while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) {
9120 _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
9132 * gl GetLine * The resource object of gl_get_line().
9137 static int gl_call_timeout_handler(GetLine *gl)
9144 if(!gl->timer.fn)
9151 if(tcgetattr(gl->input_fd, &attr)) {
9152 _err_record_msg(gl->err, "tcgetattr error", END_ERR_MSG);
9156 while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) {
9158 _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
9165 switch(gl->timer.fn(gl, gl->timer.data)) {
9168 gl_record_status(gl, GLR_TIMEOUT, 0);
9172 gl_queue_redisplay(gl);
9181 while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) {
9183 _err_record_msg(gl->err, "tcsetattr error", END_ERR_MSG);
9201 * gl GetLine * The resource object of gl_get_line().
9207 int gl_group_history(GetLine *gl, unsigned id)
9214 if(!gl) {
9221 if(gl_mask_signals(gl, &oldset))
9226 if(_glh_get_group(gl->glh) == id) {
9231 } else if(_glh_set_group(gl->glh, id)) {
9232 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
9239 gl->preload_history = 0;
9240 gl->last_search = -1;
9246 gl_unmask_signals(gl, &oldset);
9254 * gl GetLine * The resource object of gl_get_line().
9279 int gl_show_history(GetLine *gl, FILE *fp, const char *fmt, int all_groups,
9287 if(!gl || !fp || !fmt) {
9288 if(gl)
9289 _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
9296 if(gl_mask_signals(gl, &oldset))
9301 status = _glh_show_history(gl->glh, _io_write_stdio, fp, fmt, all_groups,
9304 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
9308 gl_unmask_signals(gl, &oldset);
9316 * gl GetLine * The resource object of gl_get_line().
9324 GlTerminalSize gl_terminal_size(GetLine *gl, int def_ncolumn, int def_nline)
9330 * Block all signals while accessing gl.
9332 gl_mask_signals(gl, &oldset);
9336 _gl_terminal_size(gl, def_ncolumn, def_nline, &size);
9340 gl_unmask_signals(gl, &oldset);
9349 static void _gl_terminal_size(GetLine *gl, int def_ncolumn, int def_nline,
9358 gl->nline = 0;
9359 gl->ncolumn = 0;
9363 if(gl->is_term) {
9367 (void) _gl_update_size(gl);
9370 * left gl->nrow and gl->ncolumn unchanged. If these values haven't
9379 if(gl->nline < 1) {
9381 gl->nline = n;
9384 gl->nline = tigetnum((char *)"lines");
9387 gl->nline = tgetnum("li");
9396 if(gl->ncolumn < 1) {
9398 gl->ncolumn = n;
9401 gl->ncolumn = tigetnum((char *)"cols");
9404 gl->ncolumn = tgetnum("co");
9412 if(gl->nline <= 0)
9413 gl->nline = def_nline;
9414 if(gl->ncolumn <= 0)
9415 gl->ncolumn = def_ncolumn;
9420 size->nline = gl->nline;
9421 size->ncolumn = gl->ncolumn;
9430 * gl GetLine * The resource object of gl_get_line().
9439 int gl_resize_history(GetLine *gl, size_t bufsize)
9446 if(!gl)
9449 * Block all signals while modifying the contents of gl.
9451 if(gl_mask_signals(gl, &oldset))
9456 status = _glh_resize_history(gl->glh, bufsize);
9458 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
9462 gl_unmask_signals(gl, &oldset);
9471 * gl GetLine * The resource object of gl_get_line().
9476 void gl_limit_history(GetLine *gl, int max_lines)
9478 if(gl) {
9483 gl_mask_signals(gl, &oldset);
9487 _glh_limit_history(gl->glh, max_lines);
9491 gl_unmask_signals(gl, &oldset);
9500 * gl GetLine * The resource object of gl_get_line().
9505 void gl_clear_history(GetLine *gl, int all_groups)
9507 if(gl) {
9512 gl_mask_signals(gl, &oldset);
9516 _glh_clear_history(gl->glh, all_groups);
9520 gl_unmask_signals(gl, &oldset);
9528 * gl GetLine * The resource object of gl_get_line().
9532 void gl_toggle_history(GetLine *gl, int enable)
9534 if(gl) {
9539 gl_mask_signals(gl, &oldset);
9543 _glh_toggle_history(gl->glh, enable);
9547 gl_unmask_signals(gl, &oldset);
9556 * gl GetLine * The resource object of gl_get_line().
9575 * to any functions that take *gl as an
9578 int gl_lookup_history(GetLine *gl, unsigned long id, GlHistoryLine *line)
9585 if(!gl)
9588 * Block all signals while modifying the contents of gl.
9590 if(gl_mask_signals(gl, &oldset))
9595 status = _glh_lookup_history(gl->glh, (GlhLineID) id, &line->line,
9598 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
9602 gl_unmask_signals(gl, &oldset);
9611 * gl GetLine * The resource object of gl_get_line().
9616 void gl_state_of_history(GetLine *gl, GlHistoryState *state)
9618 if(gl && state) {
9623 gl_mask_signals(gl, &oldset);
9627 _glh_state_of_history(gl->glh, &state->enabled, &state->group,
9632 gl_unmask_signals(gl, &oldset);
9640 * gl GetLine * The resource object of gl_get_line().
9645 void gl_range_of_history(GetLine *gl, GlHistoryRange *range)
9647 if(gl && range) {
9652 gl_mask_signals(gl, &oldset);
9656 _glh_range_of_history(gl->glh, &range->oldest, &range->newest,
9661 gl_unmask_signals(gl, &oldset);
9670 * gl GetLine * The gl_get_line() resource object.
9675 void gl_size_of_history(GetLine *gl, GlHistorySize *size)
9677 if(gl && size) {
9682 gl_mask_signals(gl, &oldset);
9686 _glh_size_of_history(gl->glh, &size->size, &size->used);
9690 gl_unmask_signals(gl, &oldset);
9703 if(gl_start_newline(gl, 1))
9708 _glh_show_history(gl->glh, gl_write_fn, gl, "%N %T %H\r\n", 0,
9713 gl_queue_redisplay(gl);
9723 * gl GetLine * The gl_get_line() resource object.
9733 int gl_echo_mode(GetLine *gl, int enable)
9735 if(gl) {
9741 gl_mask_signals(gl, &oldset);
9745 was_echoing = gl->echo;
9747 gl->echo = enable;
9751 gl_unmask_signals(gl, &oldset);
9764 * gl GetLine * The resource object of gl_get_line().
9769 static int gl_display_prompt(GetLine *gl)
9771 const char *pptr; /* A pointer into gl->prompt[] */
9777 int kept_echo = gl->echo;
9778 gl->echo = 1;
9783 if(gl_print_control_sequence(gl, 1, gl->bol))
9788 gl->displayed = 1;
9792 switch(gl->prompt_style) {
9794 if(gl_print_string(gl, gl->prompt, '\0'))
9798 for(pptr=gl->prompt; *pptr; pptr++) {
9866 if(gl_print_control_sequence(gl, 1, gl->text_attr_off))
9875 gl_print_control_sequence(gl, 1, gl->bold))
9878 gl_print_control_sequence(gl, 1, gl->underline))
9881 gl_print_control_sequence(gl, 1, gl->standout))
9884 gl_print_control_sequence(gl, 1, gl->dim))
9887 gl_print_control_sequence(gl, 1, gl->reverse))
9890 gl_print_control_sequence(gl, 1, gl->blink))
9897 if(gl_print_char(gl, *pptr, pptr[1]))
9904 if(gl_print_control_sequence(gl, 1, gl->text_attr_off))
9911 gl->echo = kept_echo;
9915 gl->prompt_changed = 0;
9925 * gl GetLine * The resource object of gl_get_line().
9928 void gl_replace_prompt(GetLine *gl, const char *prompt)
9930 if(gl) {
9935 gl_mask_signals(gl, &oldset);
9939 _gl_replace_prompt(gl, prompt);
9943 gl_unmask_signals(gl, &oldset);
9952 static void _gl_replace_prompt(GetLine *gl, const char *prompt)
9962 * Gaurd against aliasing between prompt and gl->prompt.
9964 if(gl->prompt != prompt) {
9973 if(!gl->prompt || slen > strlen(gl->prompt)) {
9974 char *new_prompt = gl->prompt ? realloc(gl->prompt, size) : malloc(size);
9977 gl->prompt = new_prompt;
9982 strlcpy(gl->prompt, prompt, size);
9987 gl->prompt_len = gl_displayed_prompt_width(gl);
9988 gl->prompt_changed = 1;
9989 gl_queue_redisplay(gl);
9998 * gl GetLine * The resource object of this library.
10002 static int gl_displayed_prompt_width(GetLine *gl)
10009 switch(gl->prompt_style) {
10011 return gl_displayed_string_width(gl, gl->prompt, -1, 0);
10018 for(pptr=gl->prompt; *pptr; pptr++) {
10038 slen += gl_displayed_char_width(gl, *pptr, slen);
10050 * gl GetLine * The resource object of gl_get_line().
10054 void gl_prompt_style(GetLine *gl, GlPromptStyle style)
10056 if(gl) {
10061 gl_mask_signals(gl, &oldset);
10063 * Install the new style in gl while signals are blocked.
10065 if(style != gl->prompt_style) {
10066 gl->prompt_style = style;
10067 gl->prompt_len = gl_displayed_prompt_width(gl);
10068 gl->prompt_changed = 1;
10069 gl_queue_redisplay(gl);
10074 gl_unmask_signals(gl, &oldset);
10085 * gl GetLine * The resource object of gl_get_line().
10095 int gl_trap_signal(GetLine *gl, int signo, unsigned flags,
10103 if(!gl) {
10108 * Block all signals while modifying the contents of gl.
10110 if(gl_mask_signals(gl, &oldset))
10115 status = _gl_trap_signal(gl, signo, flags, after, errno_value);
10119 gl_unmask_signals(gl, &oldset);
10128 static int _gl_trap_signal(GetLine *gl, int signo, unsigned flags,
10149 for(sig=gl->sigs; sig && sig->signo != signo; sig = sig->next)
10156 sig = (GlSignalNode *) _new_FreeListNode(gl->sig_mem);
10162 sig->next = gl->sigs;
10163 gl->sigs = sig;
10173 _err_record_msg(gl->err, "sigaddset error", END_ERR_MSG);
10174 sig = (GlSignalNode *) _del_FreeListNode(gl->sig_mem, sig);
10180 sigaddset(&gl->all_signal_set, signo);
10195 * gl GetLine * The resource object of gl_get_line().
10201 int gl_ignore_signal(GetLine *gl, int signo)
10203 GlSignalNode *sig; /* The gl->sigs list node of the specified signal */
10210 if(!gl) {
10215 * Block all signals while modifying the contents of gl.
10217 if(gl_mask_signals(gl, &oldset))
10220 * Find the node of the gl->sigs list which records the disposition
10223 for(prev=NULL,sig=gl->sigs; sig && sig->signo != signo;
10233 gl->sigs = sig->next;
10237 sig = (GlSignalNode *) _del_FreeListNode(gl->sig_mem, sig);
10241 sigdelset(&gl->all_signal_set, signo);
10246 gl_unmask_signals(gl, &oldset);
10257 * gl GetLine * The resource object of gl_get_line().
10264 static int gl_line_ended(GetLine *gl, int newline_char)
10271 if(gl_end_of_line(gl, 1, NULL) || gl_add_char_to_line(gl, newline_char))
10278 gl_buffer_char(gl, newline_char, gl->ntotal);
10284 if(gl->echo && gl->automatic_history && newline_char=='\n')
10285 (void) _gl_append_history(gl, gl->line);
10290 if(gl->editor != GL_NO_EDITOR && gl_start_newline(gl, 1))
10295 gl_record_status(gl, GLR_NEWLINE, 0);
10299 (void) gl_flush_output(gl);
10306 gl->pending_io = GLP_WRITE;
10317 * gl GetLine * The resource object of gl_get_line().
10323 int gl_last_signal(GetLine *gl)
10326 if(gl) {
10331 gl_mask_signals(gl, &oldset);
10333 * Access gl now that signals are blocked.
10335 signo = gl->last_signal;
10339 gl_unmask_signals(gl, &oldset);
10348 * gl GetLine * The resource object of this library.
10363 static int gl_present_line(GetLine *gl, const char *prompt,
10369 gl_reset_input_line(gl);
10374 _gl_replace_prompt(gl, prompt);
10378 if(_glh_cancel_search(gl->glh)) {
10379 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
10386 if(gl->preload_history) {
10387 gl->preload_history = 0;
10388 if(gl->preload_id) {
10389 if(_glh_recall_line(gl->glh, gl->preload_id, gl->line, gl->linelen+1)) {
10390 gl_update_buffer(gl); /* Compute gl->ntotal etc.. */
10391 gl->buff_curpos = gl->ntotal;
10393 gl_truncate_buffer(gl, 0);
10395 gl->preload_id = 0;
10401 char *cptr; /* A pointer into gl->line[] */
10410 if(start_len > gl->linelen)
10411 start_len = gl->linelen;
10415 if(start_line != gl->line)
10416 gl_buffer_string(gl, start_line, start_len, 0);
10420 for(cptr=gl->line + gl->ntotal - 1; cptr >= gl->line &&
10421 (*cptr=='\n' || *cptr=='\r'); cptr--,gl->ntotal--)
10423 gl_truncate_buffer(gl, gl->ntotal < 0 ? 0 : gl->ntotal);
10427 if(start_pos < 0 || start_pos > gl->ntotal) {
10428 if(gl_place_cursor(gl, gl->ntotal))
10431 if(gl_place_cursor(gl, start_pos))
10438 gl_truncate_buffer(gl, 0);
10443 gl_queue_redisplay(gl);
10447 return gl_flush_output(gl);
10454 * gl GetLine * The line editor resource object.
10456 static void gl_reset_input_line(GetLine *gl)
10458 gl->ntotal = 0;
10459 gl->line[0] = '\0';
10460 gl->buff_curpos = 0;
10461 gl->term_curpos = 0;
10462 gl->term_len = 0;
10463 gl->insert_curpos = 0;
10464 gl->number = -1;
10465 gl->displayed = 0;
10466 gl->endline = 0;
10467 gl->redisplay = 0;
10468 gl->postpone = 0;
10469 gl->nbuf = 0;
10470 gl->nread = 0;
10471 gl->vi.command = 0;
10472 gl->vi.undo.line[0] = '\0';
10473 gl->vi.undo.ntotal = 0;
10474 gl->vi.undo.buff_curpos = 0;
10475 gl->vi.repeat.action.fn = 0;
10476 gl->vi.repeat.action.data = 0;
10477 gl->last_signal = -1;
10485 * gl GetLine * The line editor resource object.
10492 static int gl_print_info(GetLine *gl, ...)
10500 if(gl->echo) {
10504 if(gl_start_newline(gl, 1))
10509 va_start(ap, gl);
10511 waserr = gl_print_raw_string(gl, 1, s, -1);
10516 waserr = waserr || gl_print_raw_string(gl, 1, "\n\r", -1);
10520 gl_queue_redisplay(gl);
10533 * gl GetLine * The line editor resource object.
10541 static int gl_start_newline(GetLine *gl, int buffered)
10552 if(gl->displayed) { /* Is an input line currently displayed? */
10557 int curs_line = gl->term_curpos / gl->ncolumn;
10558 int last_line = gl->term_len / gl->ncolumn;
10564 waserr = waserr || gl_print_raw_string(gl, buffered, "\n", 1);
10565 waserr = waserr || gl_print_raw_string(gl, buffered, "\r", 1);
10569 gl_line_erased(gl);
10590 GetLine *gl = (GetLine *) data;
10591 int ndone = _glq_append_chars(gl->cq, s, n, gl->flush_fn, gl);
10593 _err_record_msg(gl->err, _glq_last_error(gl->cq), END_ERR_MSG);
10601 * gl GetLine * The line editor resource object.
10606 GlReturnStatus gl_return_status(GetLine *gl)
10609 if(gl) {
10614 gl_mask_signals(gl, &oldset);
10616 * Access gl while signals are blocked.
10618 rtn_status = gl->rtn_status;
10622 gl_unmask_signals(gl, &oldset);
10634 * gl GetLine * The resource object of gl_get_line().
10638 GlPendingIO gl_pending_io(GetLine *gl)
10641 if(gl) {
10646 gl_mask_signals(gl, &oldset);
10648 * Access gl while signals are blocked.
10650 pending_io = gl->pending_io;
10654 gl_unmask_signals(gl, &oldset);
10674 * gl GetLine * The line editor resource object.
10679 int gl_raw_io(GetLine *gl)
10686 if(!gl) {
10693 if(gl_mask_signals(gl, &oldset))
10698 if(gl->io_mode != GL_SERVER_MODE) {
10699 _err_record_msg(gl->err, "Can't switch to raw I/O unless in server mode",
10707 status = _gl_raw_io(gl, 1);
10712 gl_unmask_signals(gl, &oldset);
10723 static int _gl_raw_io(GetLine *gl, int redisplay)
10728 if(gl->raw_mode)
10733 if(gl->is_term && gl_raw_terminal_mode(gl))
10738 if(gl->io_mode==GL_SERVER_MODE &&
10739 (gl_nonblocking_io(gl, gl->input_fd) ||
10740 gl_nonblocking_io(gl, gl->output_fd) ||
10741 (gl->file_fp && gl_nonblocking_io(gl, fileno(gl->file_fp))))) {
10742 if(gl->is_term)
10743 gl_restore_terminal_attributes(gl);
10751 gl->postpone = 0;
10752 gl_queue_redisplay(gl);
10766 * gl GetLine * The line editor resource object.
10771 int gl_normal_io(GetLine *gl)
10778 if(!gl) {
10785 if(gl_mask_signals(gl, &oldset))
10790 status = _gl_normal_io(gl);
10794 gl_unmask_signals(gl, &oldset);
10803 static int _gl_normal_io(GetLine *gl)
10808 if(!gl->raw_mode)
10811 * Postpone subsequent redisplays until after _gl_raw_io(gl, 1)
10814 gl->postpone = 1;
10822 if(gl->io_mode==GL_SERVER_MODE &&
10823 (gl_blocking_io(gl, gl->input_fd) ||
10824 gl_blocking_io(gl, gl->output_fd) ||
10825 (gl->file_fp && gl_blocking_io(gl, fileno(gl->file_fp)))))
10832 if(gl->is_term && gl_start_newline(gl, 0))
10837 if(gl->is_term && gl_restore_terminal_attributes(gl)) {
10842 if(gl->io_mode==GL_SERVER_MODE) {
10843 gl_nonblocking_io(gl, gl->input_fd);
10844 gl_nonblocking_io(gl, gl->output_fd);
10845 if(gl->file_fp)
10846 gl_nonblocking_io(gl, fileno(gl->file_fp));
10861 * gl GetLine * The resource object of the command-line input
10883 int gl_completion_action(GetLine *gl, void *data, CplMatchFn *match_fn,
10891 if(!gl || !name || !match_fn) {
10898 if(gl_mask_signals(gl, &oldset))
10903 status = _gl_completion_action(gl, data, match_fn, list_only, name, keyseq);
10907 gl_unmask_signals(gl, &oldset);
10916 static int _gl_completion_action(GetLine *gl, void *data, CplMatchFn *match_fn,
10929 if(_kt_lookup_action(gl->bindings, name, &current_fn, &current_data) == 0) {
10940 _err_record_msg(gl->err,
10952 GlCplCallback *cb = (GlCplCallback *) _new_FreeListNode(gl->cpl_mem);
10955 _err_record_msg(gl->err, "Insufficient memory to add completion action",
10967 if(_kt_set_action(gl->bindings, name, action_fn, cb)) {
10968 _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
10969 _del_FreeListNode(gl->cpl_mem, (void *) cb);
10976 if(keyseq && _kt_set_keybinding(gl->bindings, KTB_NORM, keyseq, name)) {
10977 _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
10990 * gl GetLine * The resource object of the command-line input
11009 int gl_register_action(GetLine *gl, void *data, GlActionFn *fn,
11017 if(!gl || !name || !fn) {
11024 if(gl_mask_signals(gl, &oldset))
11029 status = _gl_register_action(gl, data, fn, name, keyseq);
11033 gl_unmask_signals(gl, &oldset);
11042 static int _gl_register_action(GetLine *gl, void *data, GlActionFn *fn,
11055 if(_kt_lookup_action(gl->bindings, name, &current_fn, &current_data) == 0) {
11066 _err_record_msg(gl->err,
11079 (GlExternalAction *) _new_FreeListNode(gl->ext_act_mem);
11082 _err_record_msg(gl->err, "Insufficient memory to add completion action",
11094 if(_kt_set_action(gl->bindings, name, action_fn, a)) {
11095 _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
11096 _del_FreeListNode(gl->cpl_mem, (void *) a);
11103 if(keyseq && _kt_set_keybinding(gl->bindings, KTB_NORM, keyseq, name)) {
11104 _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
11124 status = a->fn(gl, a->data, count, gl->buff_curpos, gl->line);
11129 if(_gl_raw_io(gl, 1))
11137 gl_record_status(gl, GLR_ERROR, errno);
11141 return gl_newline(gl, 1, NULL);
11266 * gl GetLine * The resource object of gl_get_line().
11303 int gl_display_text(GetLine *gl, int indentation, const char *prefix,
11312 if(!gl || !string) {
11319 if(gl_mask_signals(gl, &oldset))
11324 status = _io_display_text(_io_write_stdio, gl->output_fp, indentation,
11326 gl->ncolumn > 0 ? gl->ncolumn : def_width,
11331 gl_unmask_signals(gl, &oldset);
11339 * gl GetLine * The resource object of gl_get_line().
11348 static int gl_mask_signals(GetLine *gl, sigset_t *oldset)
11354 if(sigprocmask(SIG_BLOCK, &gl->all_signal_set, oldset) >= 0) {
11355 gl->signals_masked = 1;
11365 gl->signals_masked = 0;
11374 * gl GetLine * The resource object of gl_get_line().
11381 static int gl_unmask_signals(GetLine *gl, sigset_t *oldset)
11383 gl->signals_masked = 0;
11388 * Arrange to temporarily catch the signals marked in gl->use_signal_set.
11391 * gl GetLine * The resource object of gl_get_line().
11396 static int gl_catch_signals(GetLine *gl)
11398 return sigprocmask(SIG_UNBLOCK, &gl->use_signal_set, NULL) < 0;
11405 * gl GetLine * The resource object of gl_get_line().
11411 int gl_io_mode(GetLine *gl, GlIOMode mode)
11418 if(!gl) {
11431 _err_record_msg(gl->err, "Unknown gl_get_line() I/O mode requested.",
11438 if(gl_mask_signals(gl, &oldset))
11443 status = _gl_io_mode(gl, mode);
11447 gl_unmask_signals(gl, &oldset);
11456 static int _gl_io_mode(GetLine *gl, GlIOMode mode)
11461 if(mode == gl->io_mode)
11466 _gl_normal_io(gl);
11470 gl->io_mode = mode;
11475 if(_gl_raw_io(gl, 1))
11487 * gl GetLine * The resource object of gl_get_line().
11505 const char *gl_error_message(GetLine *gl, char *buff, size_t n)
11507 if(!gl) {
11520 gl_mask_signals(gl, &oldset);
11525 strncpy(buff, _err_get_msg(gl->err), n);
11531 gl_unmask_signals(gl, &oldset);
11533 return _err_get_msg(gl->err);
11543 * gl GetLine * The resource object of gl_get_line().
11555 int gl_list_signals(GetLine *gl, sigset_t *set)
11560 if(!gl || !set) {
11561 if(gl)
11562 _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
11569 memcpy(set, &gl->all_signal_set, sizeof(*set));
11588 * gl GetLine * The resource object of gl_get_line().
11590 void gl_catch_blocked(GetLine *gl)
11593 GlSignalNode *sig; /* A signal node in gl->sigs */
11597 if(!gl) {
11602 * Temporarily block all signals while we modify the contents of gl.
11604 gl_mask_signals(gl, &oldset);
11608 for(sig=gl->sigs; sig; sig=sig->next)
11614 gl_unmask_signals(gl, &oldset);
11643 * gl GetLine * The first element of an array of 'ngl' GetLine
11645 * ngl int The number of elements in the gl[] array. Normally
11648 void gl_handle_signal(int signo, GetLine *gl, int ngl)
11657 if(ngl < 1 || !gl)
11669 * Temporarily block all signals while we modify the gl objects.
11677 gl_suspend_process(signo, gl, ngl);
11689 gl[i].pending_io = GLP_WRITE;
11716 * gl GetLine * The first element of an array of 'ngl' GetLine objects
11719 * ngl int The number of elements in the gl[] array.
11721 static void gl_suspend_process(int signo, GetLine *gl, int ngl)
11743 GetLine *obj = gl + i;
11780 GetLine *obj = gl + i;
11830 * gl GetLine * The line editor resource object.
11832 void gl_abandon_line(GetLine *gl)
11838 if(!gl) {
11843 * Temporarily block all signals while we modify the contents of gl.
11845 gl_mask_signals(gl, &oldset);
11849 _gl_abandon_line(gl);
11854 gl_unmask_signals(gl, &oldset);
11863 void _gl_abandon_line(GetLine *gl)
11865 gl->endline = 1;
11866 gl->pending_io = GLP_WRITE;
11891 * gl GetLine * The resource object of gl_get_line().
11898 int gl_set_term_size(GetLine *gl, int ncolumn, int nline)
11904 * Block all signals while accessing gl.
11906 gl_mask_signals(gl, &oldset);
11910 status = _gl_set_term_size(gl, ncolumn, nline);
11914 gl_unmask_signals(gl, &oldset);
11923 static int _gl_set_term_size(GetLine *gl, int ncolumn, int nline)
11928 if(!gl) {
11936 _err_record_msg(gl->err, "Invalid terminal size", END_ERR_MSG);
11945 if(gl->is_term) {
11951 if(ioctl(gl->output_fd, TIOCSWINSZ, &size) == -1) {
11952 _err_record_msg(gl->err, "Can't change terminal size", END_ERR_MSG);
11960 * gl->nline and gl->ncolumn.
11962 return gl_handle_tty_resize(gl, ncolumn, nline);
11969 * gl GetLine * The resource object of gl_get_line().
11977 static int gl_buffer_char(GetLine *gl, char c, int bufpos)
11982 if(bufpos >= gl->linelen)
11987 gl->line[bufpos] = c;
11990 * line, update gl->ntotal to reflect the increased number of characters
11991 * that are in gl->line, and terminate the string.
11993 if(bufpos >= gl->ntotal) {
11994 gl->ntotal = bufpos+1;
11995 gl->line[gl->ntotal] = '\0';
12005 * gl GetLine * The resource object of gl_get_line().
12015 static int gl_buffer_string(GetLine *gl, const char *s, int n, int bufpos)
12022 nnew = bufpos + n <= gl->linelen ? n : (gl->linelen - bufpos);
12027 gl_buffer_char(gl, s[i], bufpos + i);
12040 * gl GetLine * The resource object of gl_get_line().
12047 static int gl_make_gap_in_buffer(GetLine *gl, int start, int n)
12052 if(gl->ntotal + n > gl->linelen)
12058 memmove(gl->line + start + n, gl->line + start, gl->ntotal - start + 1);
12062 gl->ntotal += n;
12072 * gl GetLine * The resource object of gl_get_line().
12076 static void gl_remove_from_buffer(GetLine *gl, int start, int n)
12078 memmove(gl->line + start, gl->line + start + n, gl->ntotal - start - n + 1);
12082 gl->ntotal -= n;
12090 * gl GetLine * The resource object of gl_get_line().
12094 * 1 - n > gl->linelen.
12096 static int gl_truncate_buffer(GetLine *gl, int n)
12098 if(n > gl->linelen)
12100 gl->line[n] = '\0';
12101 gl->ntotal = n;
12106 * When the contents of gl->line[] are changed without calling any of the
12111 * gl GetLine * The resource object of gl_get_line().
12113 static void gl_update_buffer(GetLine *gl)
12119 for(len=0; len <= gl->linelen && gl->line[len]; len++)
12124 gl->line[len] = '\0';
12126 * Record the number of characters that are now in gl->line[].
12128 gl->ntotal = len;
12133 if(gl->buff_curpos > gl->ntotal)
12134 gl->buff_curpos = gl->ntotal;
12138 gl_queue_redisplay(gl);
12150 * gl GetLine * The resource object of gl_get_line().
12155 static int gl_erase_line(GetLine *gl)
12160 if(gl->displayed) {
12165 int cursor_line = gl->term_curpos / gl->ncolumn;
12170 if(gl_print_control_sequence(gl, 1, gl->up))
12173 if(gl_print_control_sequence(gl, 1, gl->bol))
12178 if(gl_print_control_sequence(gl, gl->nline, gl->clear_eod))
12183 gl_line_erased(gl);
12193 * gl GetLine * The resource object of gl_get_line().
12195 static void gl_queue_redisplay(GetLine *gl)
12197 gl->redisplay = 1;
12198 gl->pending_io = GLP_WRITE;
12207 * gl GetLine * The resource object of gl_get_line().
12212 static int gl_truncate_display(GetLine *gl)
12217 int term_curpos = gl->term_curpos;
12221 if(gl_print_control_sequence(gl, 1, gl->clear_eol))
12233 if(gl->term_len / gl->ncolumn > gl->term_curpos / gl->ncolumn) {
12234 if(gl_print_control_sequence(gl, 1, gl->down) ||
12235 gl_print_control_sequence(gl, 1, gl->bol) ||
12236 gl_print_control_sequence(gl, gl->nline, gl->clear_eod))
12241 gl->term_curpos = gl->ncolumn * (term_curpos / gl->ncolumn + 1);
12245 gl_set_term_curpos(gl, term_curpos);
12250 gl->term_len = gl->term_curpos;
12282 * gl GetLine * The resource object of gl_get_line().
12287 static int gl_read_stream_line(GetLine *gl)
12293 gl->pending_io = GLP_READ;
12297 if(gl->endline)
12298 gl_reset_input_line(gl);
12302 while(gl->ntotal < gl->linelen && c != '\n') {
12306 switch(gl_read_input(gl, &c)) {
12316 if(gl->ntotal > 0) {
12319 gl_record_status(gl, GLR_EOF, 0);
12324 gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO);
12334 if(gl_buffer_char(gl, c, gl->ntotal))
12340 gl->endline = (c == '\n');
12348 * gl GetLine * The resource object of gl_get_line().
12352 static int gl_read_stream_char(GetLine *gl)
12359 _gl_abandon_line(gl);
12363 gl->pending_io = GLP_READ;
12367 switch(gl_read_input(gl, &c)) {
12372 gl_record_status(gl, GLR_BLOCKED, BLOCKED_ERRNO);
12376 gl_record_status(gl, GLR_EOF, 0);
12390 * gl GetLine * The resource object of gl_get_line().
12400 int gl_bind_keyseq(GetLine *gl, GlKeyOrigin origin, const char *keyseq,
12407 if(!gl || !keyseq) {
12409 if(gl)
12410 _err_record_msg(gl->err, "NULL argument(s)", END_ERR_MSG);
12427 if(keyseq && _kt_set_keybinding(gl->bindings, binder, keyseq, action)) {
12428 _err_record_msg(gl->err, _kt_last_error(gl->bindings), END_ERR_MSG);
12441 * gl GetLine * The resource object of gl_get_line().
12446 int gl_erase_terminal(GetLine *gl)
12452 * Block all signals while accessing gl.
12454 gl_mask_signals(gl, &oldset);
12458 status = gl_clear_screen(gl, 1, NULL);
12464 (void) gl_flush_output(gl);
12468 gl_unmask_signals(gl, &oldset);
12477 * gl GetLine * The resource object of gl_get_line().
12479 static void gl_line_erased(GetLine *gl)
12481 gl->displayed = 0;
12482 gl->term_curpos = 0;
12483 gl->term_len = 0;
12490 * gl GetLine * The resource object of gl_get_line().
12496 int gl_append_history(GetLine *gl, const char *line)
12504 if(!gl || !line) {
12511 if(gl_mask_signals(gl, &oldset))
12516 status = _gl_append_history(gl, line);
12520 gl_unmask_signals(gl, &oldset);
12529 static int _gl_append_history(GetLine *gl, const char *line)
12531 int status =_glh_add_history(gl->glh, line, 0);
12533 _err_record_msg(gl->err, _glh_last_error(gl->glh), END_ERR_MSG);
12542 * gl GetLine * The resource object of gl_get_line().
12554 int gl_automatic_history(GetLine *gl, int enable)
12561 if(!gl) {
12568 if(gl_mask_signals(gl, &oldset))
12573 gl->automatic_history = enable;
12577 gl_unmask_signals(gl, &oldset);
12586 * gl GetLine * A resource object previously returned by
12593 int gl_read_char(GetLine *gl)
12599 * do it again, and overwrite gl->old_signal_set.
12601 int was_masked = gl->signals_masked;
12605 if(!gl) {
12612 if(!was_masked && gl_mask_signals(gl, &gl->old_signal_set))
12617 retval = _gl_read_char(gl);
12623 gl_unmask_signals(gl, &gl->old_signal_set);
12630 static int _gl_read_char(GetLine *gl)
12642 int was_overriden = gl->signals_overriden;
12643 int was_raw = gl->raw_mode;
12648 GlPendingIO old_pending_io = gl->pending_io;
12653 gl_clear_status(gl);
12658 if(!gl->configured) {
12659 (void) _gl_configure_getline(gl, NULL, NULL, TECLA_CONFIG_FILE);
12660 gl->configured = 1;
12673 waserr = gl_override_signal_handlers(gl);
12680 waserr = waserr || _gl_raw_io(gl, 0);
12690 if(gl->file_fp || !gl->is_term) {
12691 retval = gl_read_stream_char(gl);
12694 } else if(gl->file_fp) { /* End of temporary input file? */
12695 gl_revert_input(gl);
12696 gl_record_status(gl, GLR_NEWLINE, 0);
12704 * changed gl->file_fp, so it is necessary to retest it here, rather
12707 if(!gl->file_fp && gl->is_term) {
12712 if(_glq_char_count(gl->cq) > 0 && gl_flush_output(gl)) {
12718 } else if(gl_read_terminal(gl, 0, &c) == 0) {
12726 gl->keyseq_count++;
12730 gl_discard_chars(gl, 1);
12739 * If an error occurred, but gl->rtn_status is still set to
12743 * non-generic errors have to remember to update gl->rtn_status
12746 if(waserr && gl->rtn_status == GLR_NEWLINE)
12747 gl_record_status(gl, GLR_ERROR, errno);
12751 if(!was_raw && gl->io_mode != GL_SERVER_MODE)
12752 _gl_normal_io(gl);
12757 gl_restore_signal_handlers(gl);
12761 * gl->rtn_errno. Since errno may have been overwritten by cleanup
12766 errno = gl->rtn_errno;
12771 if(gl->rtn_status != GLR_NEWLINE)
12777 gl->pending_io = old_pending_io;
12791 * gl GetLine * The resource object of this module.
12793 static void gl_clear_status(GetLine *gl)
12795 gl_record_status(gl, GLR_NEWLINE, 0);
12805 * gl GetLine * The resource object of this module.
12812 static void gl_record_status(GetLine *gl, GlReturnStatus rtn_status,
12820 if(rtn_status == GLR_NEWLINE || gl->rtn_status == GLR_NEWLINE) {
12821 gl->rtn_status = rtn_status;
12822 gl->rtn_errno = rtn_errno;