New silcconfig library and server parser. Merged silc-newconfig-final.patch.
[silc.git] / apps / irssi / src / fe-text / gui-readline.c
1 /*
2  gui-readline.c : irssi
3
4     Copyright (C) 1999 Timo Sirainen
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #include "module.h"
22 #include "signals.h"
23 #include "misc.h"
24 #include "settings.h"
25 #include "special-vars.h"
26 #include "servers.h"
27
28 #include "completion.h"
29 #include "command-history.h"
30 #include "keyboard.h"
31 #include "translation.h"
32
33 #include "term.h"
34 #include "gui-entry.h"
35 #include "gui-windows.h"
36
37 #include <signal.h>
38
39 typedef void (*ENTRY_REDIRECT_KEY_FUNC) (int key, void *data, SERVER_REC *server, WI_ITEM_REC *item);
40 typedef void (*ENTRY_REDIRECT_ENTRY_FUNC) (const char *line, void *data, SERVER_REC *server, WI_ITEM_REC *item);
41
42 typedef struct {
43         SIGNAL_FUNC func;
44         int flags;
45         void *data;
46 } ENTRY_REDIRECT_REC;
47
48 static KEYBOARD_REC *keyboard;
49 static ENTRY_REDIRECT_REC *redir;
50
51 char *cutbuffer;
52 static int readtag;
53 static time_t idle_time;
54
55 static void sig_input(void);
56
57 void input_listen_init(int handle)
58 {
59         GIOChannel *stdin_channel;
60
61         stdin_channel = g_io_channel_unix_new(handle);
62         readtag = g_input_add_full(stdin_channel,
63                                    G_PRIORITY_HIGH, G_INPUT_READ,
64                                    (GInputFunction) sig_input, NULL);
65         g_io_channel_unref(stdin_channel);
66 }
67
68 void input_listen_deinit(void)
69 {
70         g_source_remove(readtag);
71         readtag = -1;
72 }
73
74 static void handle_key_redirect(int key)
75 {
76         ENTRY_REDIRECT_KEY_FUNC func;
77         void *data;
78
79         func = (ENTRY_REDIRECT_KEY_FUNC) redir->func;
80         data = redir->data;
81         g_free_and_null(redir);
82
83         if (func != NULL)
84                 func(key, data, active_win->active_server, active_win->active);
85
86         gui_entry_set_prompt(active_entry, "");
87 }
88
89 static void handle_entry_redirect(const char *line)
90 {
91         ENTRY_REDIRECT_ENTRY_FUNC func;
92         void *data;
93
94         gui_entry_set_hidden(active_entry, FALSE);
95
96         func = (ENTRY_REDIRECT_ENTRY_FUNC) redir->func;
97         data = redir->data;
98         g_free_and_null(redir);
99
100         if (func != NULL) {
101                 func(line, data, active_win->active_server,
102                      active_win->active);
103         }
104
105         gui_entry_set_prompt(active_entry, "");
106 }
107
108 static int get_scroll_count(void)
109 {
110         const char *str;
111         double count;
112
113         str = settings_get_str("scroll_page_count");
114         count = atof(str + (*str == '/'));
115         if (count <= 0)
116                 count = 1;
117         else if (count < 1)
118                 count = 1.0/count;
119
120         if (*str == '/') {
121                 count = (active_mainwin->height-active_mainwin->statusbar_lines)/count;
122         }
123         return (int)count;
124 }
125
126 static void window_prev_page(void)
127 {
128         gui_window_scroll(active_win, -get_scroll_count());
129 }
130
131 static void window_next_page(void)
132 {
133         gui_window_scroll(active_win, get_scroll_count());
134 }
135
136 void handle_key(int key)
137 {
138         char str[3];
139
140         idle_time = time(NULL);
141
142         if (redir != NULL && redir->flags & ENTRY_REDIRECT_FLAG_HOTKEY) {
143                 handle_key_redirect(key);
144                 return;
145         }
146
147         if (key >= 0 && key < 32) {
148                 /* control key */
149                 str[0] = '^';
150                 str[1] = key+'@';
151                 str[2] = '\0';
152         } else if (key == 127) {
153                 str[0] = '^';
154                 str[1] = '?';
155                 str[2] = '\0';
156         } else {
157                 str[0] = key;
158                 str[1] = '\0';
159         }
160
161         if (!key_pressed(keyboard, str)) {
162                 /* key wasn't used for anything, print it */
163                 gui_entry_insert_char(active_entry, (char) key);
164         }
165 }
166
167 static void key_send_line(void)
168 {
169         HISTORY_REC *history;
170         char *str, *add_history;
171
172         str = gui_entry_get_text(active_entry);
173         if (*str == '\0') return;
174
175         /* we can't use gui_entry_get_text() later, since the entry might
176            have been destroyed after we get back */
177         add_history = g_strdup(str);
178         history = command_history_current(active_win);
179
180         translate_output(str);
181
182         if (redir == NULL) {
183                 signal_emit("send command", 3, str,
184                             active_win->active_server,
185                             active_win->active);
186         } else {
187                 if (redir->flags & ENTRY_REDIRECT_FLAG_HIDDEN)
188                         g_free_and_null(add_history);
189                 handle_entry_redirect(str);
190         }
191
192         if (add_history != NULL) {
193                 history = command_history_find(history);
194                 if (history != NULL)
195                         command_history_add(history, add_history);
196                 g_free(add_history);
197         }
198
199         if (active_entry != NULL)
200                 gui_entry_set_text(active_entry, "");
201         command_history_clear_pos(active_win);
202 }
203
204 static void key_combo(void)
205 {
206 }
207
208 static void key_backward_history(void)
209 {
210         const char *text;
211
212         text = command_history_prev(active_win, gui_entry_get_text(active_entry));
213         gui_entry_set_text(active_entry, text);
214 }
215
216 static void key_forward_history(void)
217 {
218         const char *text;
219
220         text = command_history_next(active_win, gui_entry_get_text(active_entry));
221         gui_entry_set_text(active_entry, text);
222 }
223
224 static void key_beginning_of_line(void)
225 {
226         gui_entry_set_pos(active_entry, 0);
227 }
228
229 static void key_end_of_line(void)
230 {
231         gui_entry_set_pos(active_entry, strlen(gui_entry_get_text(active_entry)));
232 }
233
234 static void key_backward_character(void)
235 {
236         gui_entry_move_pos(active_entry, -1);
237 }
238
239 static void key_forward_character(void)
240 {
241         gui_entry_move_pos(active_entry, 1);
242 }
243
244 static void key_backward_word(void)
245 {
246         gui_entry_move_words(active_entry, -1, FALSE);
247 }
248
249 static void key_forward_word(void)
250 {
251         gui_entry_move_words(active_entry, 1, FALSE);
252 }
253
254 static void key_backward_to_space(void)
255 {
256         gui_entry_move_words(active_entry, -1, TRUE);
257 }
258
259 static void key_forward_to_space(void)
260 {
261         gui_entry_move_words(active_entry, 1, TRUE);
262 }
263
264 static void key_erase_line(void)
265 {
266         g_free_not_null(cutbuffer);
267         cutbuffer = g_strdup(gui_entry_get_text(active_entry));
268
269         gui_entry_set_text(active_entry, "");
270 }
271
272 static void key_erase_to_beg_of_line(void)
273 {
274         int pos;
275
276         pos = gui_entry_get_pos(active_entry);
277         g_free_not_null(cutbuffer);
278         cutbuffer = g_strndup(gui_entry_get_text(active_entry), pos);
279
280         gui_entry_erase(active_entry, pos);
281 }
282
283 static void key_erase_to_end_of_line(void)
284 {
285         int pos;
286
287         pos = gui_entry_get_pos(active_entry);
288         g_free_not_null(cutbuffer);
289         cutbuffer = g_strdup(gui_entry_get_text(active_entry)+pos);
290
291         gui_entry_set_pos(active_entry, strlen(gui_entry_get_text(active_entry)));
292         gui_entry_erase(active_entry, strlen(gui_entry_get_text(active_entry)) - pos);
293 }
294
295 static void key_yank_from_cutbuffer(void)
296 {
297         if (cutbuffer != NULL)
298                 gui_entry_insert_text(active_entry, cutbuffer);
299 }
300
301 static void key_transpose_characters(void)
302 {
303         char *line, c;
304         int pos;
305
306         pos = gui_entry_get_pos(active_entry);
307         line = gui_entry_get_text(active_entry);
308         if (pos == 0 || strlen(line) < 2)
309                 return;
310
311         if (line[pos] != '\0')
312                 gui_entry_move_pos(active_entry, 1);
313         c = line[gui_entry_get_pos(active_entry)-1];
314         gui_entry_erase(active_entry, 1);
315         gui_entry_move_pos(active_entry, -1);
316         gui_entry_insert_char(active_entry, c);
317         gui_entry_set_pos(active_entry, pos);
318         gui_entry_move_pos(active_entry, 1);
319 }
320
321 static void key_delete_character(void)
322 {
323         if (gui_entry_get_pos(active_entry) < (int)strlen(gui_entry_get_text(active_entry))) {
324                 gui_entry_move_pos(active_entry, 1);
325                 gui_entry_erase(active_entry, 1);
326         }
327 }
328
329 static void key_backspace(void)
330 {
331         gui_entry_erase(active_entry, 1);
332 }
333
334 static void key_delete_previous_word(void)
335 {
336         gui_entry_erase_word(active_entry, FALSE);
337 }
338
339 static void key_delete_next_word(void)
340 {
341         gui_entry_erase_next_word(active_entry, FALSE);
342 }
343
344 static void key_delete_to_previous_space(void)
345 {
346         gui_entry_erase_word(active_entry, TRUE);
347 }
348
349 static void key_delete_to_next_space(void)
350 {
351         gui_entry_erase_next_word(active_entry, TRUE);
352 }
353
354 static void sig_input(void)
355 {
356         unsigned char buffer[128];
357         int ret, i;
358
359         if (!active_entry) {
360                 /* no active entry yet - wait until we have it */
361                 return;
362         }
363
364         ret = term_gets(buffer, sizeof(buffer));
365         if (ret == -1) {
366                 /* lost terminal */
367                 if (!term_detached)
368                         signal_emit("command quit", 1, "Lost terminal");
369         } else {
370                 for (i = 0; i < ret; i++)
371                         handle_key(buffer[i]);
372         }
373 }
374
375 time_t get_idle_time(void)
376 {
377         return idle_time;
378 }
379
380 static void key_scroll_backward(void)
381 {
382         window_prev_page();
383 }
384
385 static void key_scroll_forward(void)
386 {
387         window_next_page();
388 }
389
390 static void key_scroll_start(void)
391 {
392         signal_emit("command scrollback home", 3, NULL, active_win->active_server, active_win->active);
393 }
394
395 static void key_scroll_end(void)
396 {
397         signal_emit("command scrollback end", 3, NULL, active_win->active_server, active_win->active);
398 }
399
400 static void key_change_window(const char *data)
401 {
402         signal_emit("command window goto", 3, data, active_win->active_server, active_win->active);
403 }
404
405 static void key_completion(int erase)
406 {
407         char *line;
408         int pos;
409
410         pos = gui_entry_get_pos(active_entry);
411
412         line = word_complete(active_win, gui_entry_get_text(active_entry),
413                              &pos, erase);
414         if (line != NULL) {
415                 gui_entry_set_text(active_entry, line);
416                 gui_entry_set_pos(active_entry, pos);
417                 g_free(line);
418         }
419 }
420
421 static void key_word_completion(void)
422 {
423         key_completion(FALSE);
424 }
425
426 static void key_erase_completion(void)
427 {
428         key_completion(TRUE);
429 }
430
431 static void key_check_replaces(void)
432 {
433         char *line;
434         int pos;
435
436         pos = gui_entry_get_pos(active_entry);
437
438         line = auto_word_complete(gui_entry_get_text(active_entry), &pos);
439         if (line != NULL) {
440                 gui_entry_set_text(active_entry, line);
441                 gui_entry_set_pos(active_entry, pos);
442                 g_free(line);
443         }
444 }
445
446 static void key_previous_window(void)
447 {
448         signal_emit("command window previous", 3, "", active_win->active_server, active_win->active);
449 }
450
451 static void key_next_window(void)
452 {
453         signal_emit("command window next", 3, "", active_win->active_server, active_win->active);
454 }
455
456 static void key_left_window(void)
457 {
458         signal_emit("command window left", 3, "", active_win->active_server, active_win->active);
459 }
460
461 static void key_right_window(void)
462 {
463         signal_emit("command window right", 3, "", active_win->active_server, active_win->active);
464 }
465
466 static void key_upper_window(void)
467 {
468         signal_emit("command window up", 3, "", active_win->active_server, active_win->active);
469 }
470
471 static void key_lower_window(void)
472 {
473         signal_emit("command window down", 3, "", active_win->active_server, active_win->active);
474 }
475
476 static void key_active_window(void)
477 {
478         signal_emit("command window goto", 3, "active", active_win->active_server, active_win->active);
479 }
480
481 static void key_previous_window_item(void)
482 {
483         SERVER_REC *server;
484         GSList *pos;
485
486         if (active_win->items != NULL)
487                 signal_emit("command window item prev", 3, "", active_win->active_server, active_win->active);
488         else if (servers != NULL) {
489                 /* change server */
490                 if (active_win->active_server == NULL)
491                         server = servers->data;
492                 else {
493                         pos = g_slist_find(servers, active_win->active_server);
494                         server = pos->next != NULL ? pos->next->data : servers->data;
495                 }
496                 signal_emit("command window server", 3, server->tag, active_win->active_server, active_win->active);
497         }
498 }
499
500 static void key_next_window_item(void)
501 {
502         SERVER_REC *server;
503         int index;
504
505         if (active_win->items != NULL) {
506                 signal_emit("command window item next", 3, "",
507                             active_win->active_server, active_win->active);
508         }
509         else if (servers != NULL) {
510                 /* change server */
511                 if (active_win->active_server == NULL)
512                         server = servers->data;
513                 else {
514                         index = g_slist_index(servers, active_win->active_server);
515                         server = index > 0 ? g_slist_nth(servers, index-1)->data :
516                                 g_slist_last(servers)->data;
517                 }
518                 signal_emit("command window server", 3, server->tag,
519                             active_win->active_server, active_win->active);
520         }
521 }
522
523 static void key_insert_text(const char *data)
524 {
525         char *str;
526
527         str = parse_special_string(data, active_win->active_server,
528                                    active_win->active, "", NULL, 0);
529         gui_entry_insert_text(active_entry, str);
530         g_free(str);
531 }
532
533 static void key_sig_stop(void)
534 {
535         term_stop();
536 }
537
538 static void sig_window_auto_changed(void)
539 {
540         if (active_entry == NULL)
541                 return;
542
543         command_history_next(active_win, gui_entry_get_text(active_entry));
544         gui_entry_set_text(active_entry, "");
545 }
546
547 static void sig_gui_entry_redirect(SIGNAL_FUNC func, const char *entry,
548                                    void *flags, void *data)
549 {
550         redir = g_new0(ENTRY_REDIRECT_REC, 1);
551         redir->func = func;
552         redir->flags = GPOINTER_TO_INT(flags);
553         redir->data = data;
554
555         if (redir->flags & ENTRY_REDIRECT_FLAG_HIDDEN)
556                 gui_entry_set_hidden(active_entry, TRUE);
557         gui_entry_set_prompt(active_entry, entry);
558 }
559
560 void gui_readline_init(void)
561 {
562         static char changekeys[] = "1234567890qwertyuio";
563         char *key, data[MAX_INT_STRLEN];
564         int n;
565
566         cutbuffer = NULL;
567         redir = NULL;
568         idle_time = time(NULL);
569         input_listen_init(STDIN_FILENO);
570
571         settings_add_str("history", "scroll_page_count", "/2");
572
573         keyboard = keyboard_create(NULL);
574         key_configure_freeze();
575
576         key_bind("key", NULL, " ", "space", (SIGNAL_FUNC) key_combo);
577         key_bind("key", NULL, "^M", "return", (SIGNAL_FUNC) key_combo);
578         key_bind("key", NULL, "^J", "return", (SIGNAL_FUNC) key_combo);
579         key_bind("key", NULL, "^H", "backspace", (SIGNAL_FUNC) key_combo);
580         key_bind("key", NULL, "^?", "backspace", (SIGNAL_FUNC) key_combo);
581
582         /* meta */
583         key_bind("key", NULL, "^[", "meta", (SIGNAL_FUNC) key_combo);
584         key_bind("key", NULL, "meta-[", "meta2", (SIGNAL_FUNC) key_combo);
585         key_bind("key", NULL, "meta-O", "meta2", (SIGNAL_FUNC) key_combo);
586         key_bind("key", NULL, "meta-[O", "meta2", (SIGNAL_FUNC) key_combo);
587
588         /* arrow keys */
589         key_bind("key", NULL, "meta2-A", "up", (SIGNAL_FUNC) key_combo);
590         key_bind("key", NULL, "meta2-B", "down", (SIGNAL_FUNC) key_combo);
591         key_bind("key", NULL, "meta2-C", "right", (SIGNAL_FUNC) key_combo);
592         key_bind("key", NULL, "meta2-D", "left", (SIGNAL_FUNC) key_combo);
593
594         key_bind("key", NULL, "meta2-1~", "home", (SIGNAL_FUNC) key_combo);
595         key_bind("key", NULL, "meta2-7~", "home", (SIGNAL_FUNC) key_combo);
596         key_bind("key", NULL, "meta2-H", "home", (SIGNAL_FUNC) key_combo);
597
598         key_bind("key", NULL, "meta2-4~", "end", (SIGNAL_FUNC) key_combo);
599         key_bind("key", NULL, "meta2-8~", "end", (SIGNAL_FUNC) key_combo);
600         key_bind("key", NULL, "meta2-F", "end", (SIGNAL_FUNC) key_combo);
601
602         key_bind("key", NULL, "meta2-5~", "prior", (SIGNAL_FUNC) key_combo);
603         key_bind("key", NULL, "meta2-I", "prior", (SIGNAL_FUNC) key_combo);
604         key_bind("key", NULL, "meta2-6~", "next", (SIGNAL_FUNC) key_combo);
605         key_bind("key", NULL, "meta2-G", "next", (SIGNAL_FUNC) key_combo);
606
607         key_bind("key", NULL, "meta2-2~", "insert", (SIGNAL_FUNC) key_combo);
608         key_bind("key", NULL, "meta2-3~", "delete", (SIGNAL_FUNC) key_combo);
609
610         key_bind("key", NULL, "meta2-d", "cleft", (SIGNAL_FUNC) key_combo);
611         key_bind("key", NULL, "meta2-c", "cright", (SIGNAL_FUNC) key_combo);
612         key_bind("key", NULL, "meta2-5D", "cleft", (SIGNAL_FUNC) key_combo);
613         key_bind("key", NULL, "meta2-5C", "cright", (SIGNAL_FUNC) key_combo);
614
615         /* cursor movement */
616         key_bind("backward_character", "", "left", NULL, (SIGNAL_FUNC) key_backward_character);
617         key_bind("forward_character", "", "right", NULL, (SIGNAL_FUNC) key_forward_character);
618         key_bind("backward_word", "", "cleft", NULL, (SIGNAL_FUNC) key_backward_word);
619         key_bind("forward_word", "", "cright", NULL, (SIGNAL_FUNC) key_forward_word);
620         key_bind("backward_to_space", "", NULL, NULL, (SIGNAL_FUNC) key_backward_to_space);
621         key_bind("forward_to_space", "", NULL, NULL, (SIGNAL_FUNC) key_forward_to_space);
622         key_bind("beginning_of_line", "", "home", NULL, (SIGNAL_FUNC) key_beginning_of_line);
623         key_bind("beginning_of_line", NULL, "^A", NULL, (SIGNAL_FUNC) key_beginning_of_line);
624         key_bind("end_of_line", "", "end", NULL, (SIGNAL_FUNC) key_end_of_line);
625         key_bind("end_of_line", NULL, "^E", NULL, (SIGNAL_FUNC) key_end_of_line);
626
627         /* history */
628         key_bind("backward_history", "", "up", NULL, (SIGNAL_FUNC) key_backward_history);
629         key_bind("forward_history", "", "down", NULL, (SIGNAL_FUNC) key_forward_history);
630
631         /* line editing */
632         key_bind("backspace", "", "backspace", NULL, (SIGNAL_FUNC) key_backspace);
633         key_bind("delete_character", "", "delete", NULL, (SIGNAL_FUNC) key_delete_character);
634         key_bind("delete_character", NULL, "^D", NULL, (SIGNAL_FUNC) key_delete_character);
635         key_bind("delete_next_word", "", NULL, NULL, (SIGNAL_FUNC) key_delete_next_word);
636         key_bind("delete_previous_word", "meta-backspace", NULL, NULL, (SIGNAL_FUNC) key_delete_previous_word);
637         key_bind("delete_to_previous_space", "", "^W", NULL, (SIGNAL_FUNC) key_delete_to_previous_space);
638         key_bind("delete_to_next_space", "", "", NULL, (SIGNAL_FUNC) key_delete_to_next_space);
639         key_bind("erase_line", "", "^U", NULL, (SIGNAL_FUNC) key_erase_line);
640         key_bind("erase_to_beg_of_line", "", NULL, NULL, (SIGNAL_FUNC) key_erase_to_beg_of_line);
641         key_bind("erase_to_end_of_line", "", "^K", NULL, (SIGNAL_FUNC) key_erase_to_end_of_line);
642         key_bind("yank_from_cutbuffer", "", "^Y", NULL, (SIGNAL_FUNC) key_yank_from_cutbuffer);
643         key_bind("transpose_characters", "Swap current and previous character", "^T", NULL, (SIGNAL_FUNC) key_transpose_characters);
644
645         /* line transmitting */
646         key_bind("send_line", "Execute the input line", "return", NULL, (SIGNAL_FUNC) key_send_line);
647         key_bind("word_completion", "", "^I", NULL, (SIGNAL_FUNC) key_word_completion);
648         key_bind("erase_completion", "", "meta-k", NULL, (SIGNAL_FUNC) key_erase_completion);
649         key_bind("check_replaces", "Check word replaces", NULL, NULL, (SIGNAL_FUNC) key_check_replaces);
650
651         /* window managing */
652         key_bind("previous_window", "Previous window", "^P", NULL, (SIGNAL_FUNC) key_previous_window);
653         key_bind("left_window", "Window in left", "meta-left", NULL, (SIGNAL_FUNC) key_left_window);
654         key_bind("next_window", "Next window", "^N", NULL, (SIGNAL_FUNC) key_next_window);
655         key_bind("right_window", "Window in right", "meta-right", NULL, (SIGNAL_FUNC) key_right_window);
656         key_bind("upper_window", "Upper window", "meta-up", NULL, (SIGNAL_FUNC) key_upper_window);
657         key_bind("lower_window", "Lower window", "meta-down", NULL, (SIGNAL_FUNC) key_lower_window);
658         key_bind("active_window", "Go to next window with the highest activity", "meta-a", NULL, (SIGNAL_FUNC) key_active_window);
659         key_bind("next_window_item", "Next channel/query", "^X", NULL, (SIGNAL_FUNC) key_next_window_item);
660         key_bind("previous_window_item", "Previous channel/query", NULL, NULL, (SIGNAL_FUNC) key_previous_window_item);
661
662         key_bind("refresh_screen", "Redraw screen", "^L", NULL, (SIGNAL_FUNC) irssi_redraw);
663         key_bind("scroll_backward", "Previous page", "prior", NULL, (SIGNAL_FUNC) key_scroll_backward);
664         key_bind("scroll_backward", NULL, "meta-p", NULL, (SIGNAL_FUNC) key_scroll_backward);
665         key_bind("scroll_forward", "Next page", "next", NULL, (SIGNAL_FUNC) key_scroll_forward);
666         key_bind("scroll_forward", NULL, "meta-n", NULL, (SIGNAL_FUNC) key_scroll_forward);
667         key_bind("scroll_start", "Beginning of the window", "", NULL, (SIGNAL_FUNC) key_scroll_start);
668         key_bind("scroll_end", "End of the window", "", NULL, (SIGNAL_FUNC) key_scroll_end);
669
670         /* inserting special input characters to line.. */
671         key_bind("insert_text", "Append text to line", NULL, NULL, (SIGNAL_FUNC) key_insert_text);
672
673         /* autoreplaces */
674         key_bind("multi", NULL, "return", "check_replaces;send_line", NULL);
675         key_bind("multi", NULL, "space", "check_replaces;insert_text  ", NULL);
676
677         /* moving between windows */
678         for (n = 0; changekeys[n] != '\0'; n++) {
679                 key = g_strdup_printf("meta-%c", changekeys[n]);
680                 ltoa(data, n+1);
681                 key_bind("change_window", "Change window", key, data, (SIGNAL_FUNC) key_change_window);
682                 g_free(key);
683         }
684
685         /* misc */
686         key_bind("stop_irc", "Send SIGSTOP to client", "^Z", NULL, (SIGNAL_FUNC) key_sig_stop);
687
688         key_configure_thaw();
689
690         signal_add("window changed automatic", (SIGNAL_FUNC) sig_window_auto_changed);
691         signal_add("gui entry redirect", (SIGNAL_FUNC) sig_gui_entry_redirect);
692 }
693
694 void gui_readline_deinit(void)
695 {
696         g_free_not_null(cutbuffer);
697         input_listen_deinit();
698
699         key_configure_freeze();
700
701         key_unbind("backward_character", (SIGNAL_FUNC) key_backward_character);
702         key_unbind("forward_character", (SIGNAL_FUNC) key_forward_character);
703         key_unbind("backward_word", (SIGNAL_FUNC) key_backward_word);
704         key_unbind("forward_word", (SIGNAL_FUNC) key_forward_word);
705         key_unbind("backward_to_space", (SIGNAL_FUNC) key_backward_to_space);
706         key_unbind("forward_to_space", (SIGNAL_FUNC) key_forward_to_space);
707         key_unbind("beginning_of_line", (SIGNAL_FUNC) key_beginning_of_line);
708         key_unbind("end_of_line", (SIGNAL_FUNC) key_end_of_line);
709
710         key_unbind("backward_history", (SIGNAL_FUNC) key_backward_history);
711         key_unbind("forward_history", (SIGNAL_FUNC) key_forward_history);
712
713         key_unbind("backspace", (SIGNAL_FUNC) key_backspace);
714         key_unbind("delete_character", (SIGNAL_FUNC) key_delete_character);
715         key_unbind("delete_next_word", (SIGNAL_FUNC) key_delete_next_word);
716         key_unbind("delete_previous_word", (SIGNAL_FUNC) key_delete_previous_word);
717         key_unbind("delete_to_next_space", (SIGNAL_FUNC) key_delete_to_next_space);
718         key_unbind("delete_to_previous_space", (SIGNAL_FUNC) key_delete_to_previous_space);
719         key_unbind("erase_line", (SIGNAL_FUNC) key_erase_line);
720         key_unbind("erase_to_beg_of_line", (SIGNAL_FUNC) key_erase_to_beg_of_line);
721         key_unbind("erase_to_end_of_line", (SIGNAL_FUNC) key_erase_to_end_of_line);
722         key_unbind("yank_from_cutbuffer", (SIGNAL_FUNC) key_yank_from_cutbuffer);
723         key_unbind("transpose_characters", (SIGNAL_FUNC) key_transpose_characters);
724
725         key_unbind("word_completion", (SIGNAL_FUNC) key_word_completion);
726         key_unbind("check_replaces", (SIGNAL_FUNC) key_check_replaces);
727
728         key_unbind("previous_window", (SIGNAL_FUNC) key_previous_window);
729         key_unbind("next_window", (SIGNAL_FUNC) key_next_window);
730         key_unbind("upper_window", (SIGNAL_FUNC) key_upper_window);
731         key_unbind("lower_window", (SIGNAL_FUNC) key_lower_window);
732         key_unbind("active_window", (SIGNAL_FUNC) key_active_window);
733         key_unbind("next_window_item", (SIGNAL_FUNC) key_next_window_item);
734         key_unbind("previous_window_item", (SIGNAL_FUNC) key_previous_window_item);
735
736         key_unbind("refresh_screen", (SIGNAL_FUNC) irssi_redraw);
737         key_unbind("scroll_backward", (SIGNAL_FUNC) key_scroll_backward);
738         key_unbind("scroll_forward", (SIGNAL_FUNC) key_scroll_forward);
739         key_unbind("scroll_start", (SIGNAL_FUNC) key_scroll_start);
740         key_unbind("scroll_end", (SIGNAL_FUNC) key_scroll_end);
741
742         key_unbind("insert_text", (SIGNAL_FUNC) key_insert_text);
743         key_unbind("change_window", (SIGNAL_FUNC) key_change_window);
744         key_unbind("stop_irc", (SIGNAL_FUNC) key_sig_stop);
745         keyboard_destroy(keyboard);
746
747         key_configure_thaw();
748
749         signal_remove("window changed automatic", (SIGNAL_FUNC) sig_window_auto_changed);
750         signal_remove("gui entry redirect", (SIGNAL_FUNC) sig_gui_entry_redirect);
751 }