]> git.deb.at Git - pkg/abook.git/blob - abook_rl.c
- handle terminal preparation more elegantly
[pkg/abook.git] / abook_rl.c
1 /*
2  * $Id$
3  *
4  * by JH <jheinonen@users.sourceforge.net>
5  *
6  * Copyright (C) Jaakko Heinonen
7  */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <sys/types.h>
12 #include "abook.h"
13 #include "abook_rl.h"
14
15 #ifdef HAVE_CONFIG_H
16 #       include "config.h"
17 #endif
18
19 #if defined(HAVE_READLINE_READLINE_H)
20 #       include <readline/readline.h>
21 #elif defined(HAVE_READLINE_H)
22 #       include <readline.h>
23 #else
24 #       error "You don't seem to have readhline.h"
25 #       error "No HAVE_READLINE_READLINE_H or HAVE_READLINE_H defined"
26 #endif
27
28 #if defined(HAVE_READLINE_HISTORY_H)
29 #       include <readline/history.h>
30 #elif defined(HAVE_HISTORY_H)
31 #       include <history.h>
32 #else
33 #       error "You don't seem to have history.h"
34 #       error "No HAVE_READLINE_HISTORY_H or HAVE_HISTORY_H defined"
35 #endif
36
37 #ifdef HANDLE_MULTIBYTE
38 #       include <mbswidth.h>
39 #endif
40
41 #define RL_READLINE_NAME        "Abook"
42
43 static int rl_x, rl_y;
44 static WINDOW *rl_win;
45
46 static bool rl_cancelled;
47
48 static void
49 rl_refresh()
50 {
51         /* refresh(); */
52         wrefresh(rl_win);
53 }
54
55 #ifdef HANDLE_MULTIBYTE
56 static int
57 rline_calc_point()
58 {
59         return (int)mbsnwidth(rl_line_buffer, rl_point, 0);
60 }
61 #endif
62
63 static void
64 rline_update()
65 {
66 #ifdef HANDLE_MULTIBYTE
67         int real_point = rline_calc_point() + rl_x;
68 #else
69         int real_point = rl_point + rl_x;
70 #endif
71
72         if(real_point > (COLS - 1))
73                 mvwaddnstr(rl_win, rl_y, rl_x,
74                         rl_line_buffer + (1 + real_point - COLS),
75                         COLS - rl_x - 1);
76         else
77                 mvwaddnstr(rl_win, rl_y, rl_x, rl_line_buffer, rl_end);
78
79         wclrtoeol(rl_win);
80         wmove(rl_win, rl_y, min(real_point, COLS - 1));
81
82         rl_refresh();
83 }
84
85 static void
86 rline_compdisp(char **matches, int n, int max_len)
87 {
88         /* dummy */
89 }
90
91 static void
92 rline_prep_terminal(int dummy)
93 {
94 #if (RL_VERSION_MAJOR == 4 && RL_VERSION_MINOR > 2) || (RL_VERSION_MAJOR > 4)
95         /* nothing */
96 #else
97 #       warning "You seem to have rather old readline version or non-GNU \
98 version of the readline. If you have problems please use \
99 GNU readline 4.3 or newer. \
100 GNU readline versions 4.0, 4.1 and 4.2 should be OK despite \
101 of this warning."
102         /*
103          * this kludge avoids older readline libraries to print a newline
104          */
105         extern int readline_echoing_p;
106         readline_echoing_p = 0;
107 #endif
108         raw();
109         keypad(rl_win, FALSE);
110 }
111
112 static void
113 rline_deprep_terminal(void)
114 {
115         cbreak();
116         keypad(rl_win, TRUE);
117 }
118
119 static int
120 rl_cancel(int dummy1, int dummy2)
121 {
122         rl_cancelled = TRUE;
123
124         rl_done = 1;
125
126         return 0;
127 }
128
129 static void
130 abook_rl_init(bool use_completion)
131 {
132         rl_readline_name = RL_READLINE_NAME;
133
134 #if RL_VERSION_MAJOR >= 4
135         rl_already_prompted = 1;
136 #endif
137         rl_catch_sigwinch = 0;
138         rl_erase_empty_line = 0;
139
140         rl_redisplay_function = rline_update;
141         rl_completion_display_matches_hook = rline_compdisp;
142         rl_prep_term_function = rline_prep_terminal;
143         rl_deprep_term_function = rline_deprep_terminal;
144
145         rl_unbind_function_in_map(rl_clear_screen, rl_get_keymap());
146         rl_unbind_function_in_map(rl_reverse_search_history, rl_get_keymap());
147         rl_unbind_function_in_map(rl_re_read_init_file, rl_get_keymap());
148
149         if(use_completion) {
150                 rl_bind_key('\t', rl_menu_complete);
151         } else {
152                 rl_unbind_function_in_map(rl_complete, rl_get_keymap());
153                 rl_unbind_function_in_map(rl_menu_complete, rl_get_keymap());
154         }
155
156         rl_bind_key('g' & 31, rl_cancel); /* C-g */
157
158         clear_history();
159
160         rl_cancelled = FALSE;
161 }
162
163 char *
164 abook_readline(WINDOW *w, int y, int x, char *s, int limit, bool use_completion)
165 {
166         char *ret;
167
168         abook_rl_init(use_completion);
169
170         wmove(rl_win = w, rl_y = y, rl_x = x);
171         rl_refresh();
172
173         if(s && *s)
174                 add_history(s);
175
176         ret = readline(NULL);
177
178         if(rl_cancelled && ret) {
179                 free(ret);
180                 ret = NULL;
181         }
182
183         return ret;
184 }
185