]> git.deb.at Git - pkg/abook.git/blob - abook_rl.c
wide character support
[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 #define KEYPAD_HACK 1 /* enable keypad hack */
16 #define CBREAK_HACK 1 /* enable cbreak hack */
17
18 #ifdef HAVE_CONFIG_H
19 #       include "config.h"
20 #endif
21
22 #if defined(HAVE_READLINE_READLINE_H)
23 #       include <readline/readline.h>
24 #elif defined(HAVE_READLINE_H)
25 #       include <readline.h>
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 #endif
33
34 #ifdef HANDLE_MULTIBYTE
35 #       include <wchar.h>
36 #endif
37
38 #define RL_READLINE_NAME        "Abook"
39
40 static int rl_x, rl_y;
41 static WINDOW *rl_win;
42
43 static bool rl_cancelled;
44
45 static void
46 rl_refresh()
47 {
48         /*refresh();*/
49         wrefresh(rl_win);
50 }
51
52 #ifdef HANDLE_MULTIBYTE
53 static int
54 rline_calc_point()
55 {
56         char *p;
57         int ret = 0;
58         
59         mbtowc(NULL, NULL, 0);
60         for(p = rl_line_buffer;(p - rl_line_buffer) < rl_point;) {
61                 int a, l;
62                 wchar_t wc;
63                 
64                 if((a = mbtowc(&wc, p, MB_CUR_MAX)) == 0)
65                         break;
66                 else if (a == -1)
67                         return rl_point; /* fall back */
68                 else
69                         p += a;
70
71                 l = wcwidth(wc);
72                 if(l > 0)
73                         ret += l;
74         }
75
76         return ret;
77 }
78 #endif
79
80 static void
81 rline_update()
82 {       
83 #ifdef HANDLE_MULTIBYTE
84         int real_point = rline_calc_point() + rl_x;
85 #else
86         int real_point = rl_point + rl_x;
87 #endif
88         
89         if(real_point > (COLS - 1))
90                 mvwaddnstr(rl_win, rl_y, rl_x,
91                         rl_line_buffer + (1 + real_point - COLS),
92                         COLS - rl_x - 1);
93         else
94                 mvwaddnstr(rl_win, rl_y, rl_x, rl_line_buffer, rl_end);
95
96         wclrtoeol(rl_win);
97         wmove(rl_win, rl_y, min(real_point, COLS - 1));
98
99         rl_refresh();
100 }
101
102 static void
103 rline_compdisp(char **matches, int n, int max_len)
104 {
105         /* dummy */
106 }
107
108 static int
109 rl_cancel(int dummy1, int dummy2)
110 {
111         rl_cancelled = TRUE;
112
113         rl_done = 1;
114
115         return 0;
116 }
117
118 static void
119 abook_rl_init(bool use_completion)
120 {
121         rl_readline_name = RL_READLINE_NAME;
122         
123         rl_already_prompted = 1;
124         rl_catch_sigwinch = 0;
125         
126         rl_redisplay_function = rline_update;
127         rl_completion_display_matches_hook = rline_compdisp;
128
129         rl_unbind_function_in_map(rl_clear_screen, rl_get_keymap());
130         rl_unbind_function_in_map(rl_reverse_search_history, rl_get_keymap());
131         rl_unbind_function_in_map(rl_re_read_init_file, rl_get_keymap());
132         
133         if(use_completion) {
134                 rl_bind_key('\t', rl_menu_complete);
135         } else {
136                 rl_unbind_function_in_map(rl_complete, rl_get_keymap());
137                 rl_unbind_function_in_map(rl_menu_complete, rl_get_keymap());
138         }
139
140         rl_bind_key('g' & 31, rl_cancel); /* C-g */
141
142         clear_history();
143
144         rl_cancelled = FALSE;
145 }       
146
147 char *
148 abook_readline(WINDOW *w, int y, int x, char *s, int limit, bool use_completion)
149 {
150         char *ret;
151
152         abook_rl_init(use_completion);
153
154         wmove(rl_win = w, rl_y = y, rl_x = x);
155         rl_refresh();
156
157         if(s && *s)
158                 add_history(s);
159         
160 #ifdef KEYPAD_HACK
161         keypad(w, FALSE);
162 #endif
163 #ifdef CBREAK_HACK
164         nocbreak();
165 #endif
166         ret = readline(NULL);
167 #ifdef CBREAK_HACK
168         cbreak();
169 #endif
170 #ifdef KEYPAD_HACK
171         keypad(w, TRUE);
172 #endif
173
174         if(rl_cancelled && ret) {
175                 free(ret);
176                 ret = NULL;
177         }
178
179         return ret;
180 }
181