Mercurial > pidgin.yaz
annotate finch/libgnt/gntentry.c @ 18421:e16d097c5739
Allow executing another application (eg. PAGER) that will use the same
console.
author | Sadrul Habib Chowdhury <imadil@gmail.com> |
---|---|
date | Tue, 03 Jul 2007 08:54:34 +0000 |
parents | aa60f5a89286 |
children | 85b155a574a3 |
rev | line source |
---|---|
18049
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16910
diff
changeset
|
1 /** |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16910
diff
changeset
|
2 * GNT - The GLib Ncurses Toolkit |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16910
diff
changeset
|
3 * |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16910
diff
changeset
|
4 * GNT is the legal property of its developers, whose names are too numerous |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16910
diff
changeset
|
5 * to list here. Please refer to the COPYRIGHT file distributed with this |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16910
diff
changeset
|
6 * source distribution. |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16910
diff
changeset
|
7 * |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16910
diff
changeset
|
8 * This library is free software; you can redistribute it and/or modify |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16910
diff
changeset
|
9 * it under the terms of the GNU General Public License as published by |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16910
diff
changeset
|
10 * the Free Software Foundation; either version 2 of the License, or |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16910
diff
changeset
|
11 * (at your option) any later version. |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16910
diff
changeset
|
12 * |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16910
diff
changeset
|
13 * This program is distributed in the hope that it will be useful, |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16910
diff
changeset
|
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16910
diff
changeset
|
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16910
diff
changeset
|
16 * GNU General Public License for more details. |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16910
diff
changeset
|
17 * |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16910
diff
changeset
|
18 * You should have received a copy of the GNU General Public License |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16910
diff
changeset
|
19 * along with this program; if not, write to the Free Software |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16910
diff
changeset
|
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16910
diff
changeset
|
21 */ |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16910
diff
changeset
|
22 |
15818 | 23 #include <ctype.h> |
24 #include <string.h> | |
25 | |
26 #include "gntbox.h" | |
27 #include "gntentry.h" | |
18382
aa60f5a89286
A 'completion' signal to emit whenever user accepts a completion suggest.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18346
diff
changeset
|
28 #include "gntmarshal.h" |
15818 | 29 #include "gntstyle.h" |
30 #include "gnttree.h" | |
31 #include "gntutils.h" | |
32 | |
33 enum | |
34 { | |
35 SIG_TEXT_CHANGED, | |
18382
aa60f5a89286
A 'completion' signal to emit whenever user accepts a completion suggest.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18346
diff
changeset
|
36 SIG_COMPLETION, |
15818 | 37 SIGS, |
38 }; | |
39 static guint signals[SIGS] = { 0 }; | |
40 | |
41 static GntWidgetClass *parent_class = NULL; | |
42 | |
15959
efbced3f38ac
Update the tab completion a little bit. The binding for suggest-show will perform suggest-next if the suggest-dropdown is already showing. If there's just one suggestion, then complete with that suggestion.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
43 static gboolean gnt_entry_key_pressed(GntWidget *widget, const char *text); |
15818 | 44 static void gnt_entry_set_text_internal(GntEntry *entry, const char *text); |
45 | |
46 static void | |
47 destroy_suggest(GntEntry *entry) | |
48 { | |
49 if (entry->ddown) | |
50 { | |
51 gnt_widget_destroy(entry->ddown->parent); | |
52 entry->ddown = NULL; | |
53 } | |
54 } | |
55 | |
56 static char * | |
57 get_beginning_of_word(GntEntry *entry) | |
58 { | |
59 char *s = entry->cursor; | |
60 while (s > entry->start) | |
61 { | |
62 char *t = g_utf8_find_prev_char(entry->start, s); | |
63 if (isspace(*t)) | |
64 break; | |
65 s = t; | |
66 } | |
67 return s; | |
68 } | |
69 | |
70 static gboolean | |
16900
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
71 complete_suggest(GntEntry *entry, const char *text) |
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
72 { |
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
73 gboolean changed = FALSE; |
18382
aa60f5a89286
A 'completion' signal to emit whenever user accepts a completion suggest.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18346
diff
changeset
|
74 int offstart = 0, offend = 0; |
aa60f5a89286
A 'completion' signal to emit whenever user accepts a completion suggest.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18346
diff
changeset
|
75 |
16900
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
76 if (entry->word) { |
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
77 char *s = get_beginning_of_word(entry); |
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
78 const char *iter = text; |
18382
aa60f5a89286
A 'completion' signal to emit whenever user accepts a completion suggest.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18346
diff
changeset
|
79 offstart = g_utf8_pointer_to_offset(entry->start, s); |
16900
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
80 while (*iter && toupper(*s) == toupper(*iter)) { |
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
81 if (*s != *iter) |
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
82 changed = TRUE; |
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
83 *s++ = *iter++; |
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
84 } |
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
85 if (*iter) { |
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
86 gnt_entry_key_pressed(GNT_WIDGET(entry), iter); |
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
87 changed = TRUE; |
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
88 } |
18382
aa60f5a89286
A 'completion' signal to emit whenever user accepts a completion suggest.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18346
diff
changeset
|
89 offend = g_utf8_pointer_to_offset(entry->start, entry->cursor); |
16900
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
90 } else { |
18382
aa60f5a89286
A 'completion' signal to emit whenever user accepts a completion suggest.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18346
diff
changeset
|
91 offstart = 0; |
16900
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
92 gnt_entry_set_text_internal(entry, text); |
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
93 changed = TRUE; |
18382
aa60f5a89286
A 'completion' signal to emit whenever user accepts a completion suggest.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18346
diff
changeset
|
94 offend = g_utf8_strlen(text, -1); |
16900
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
95 } |
18382
aa60f5a89286
A 'completion' signal to emit whenever user accepts a completion suggest.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18346
diff
changeset
|
96 |
aa60f5a89286
A 'completion' signal to emit whenever user accepts a completion suggest.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18346
diff
changeset
|
97 if (changed) |
aa60f5a89286
A 'completion' signal to emit whenever user accepts a completion suggest.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18346
diff
changeset
|
98 g_signal_emit(G_OBJECT(entry), signals[SIG_COMPLETION], 0, |
aa60f5a89286
A 'completion' signal to emit whenever user accepts a completion suggest.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18346
diff
changeset
|
99 entry->start + offstart, entry->start + offend); |
16900
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
100 return changed; |
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
101 } |
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
102 |
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
103 static gboolean |
15818 | 104 show_suggest_dropdown(GntEntry *entry) |
105 { | |
106 char *suggest = NULL; | |
107 int len; | |
108 int offset = 0, x, y; | |
109 int count = 0; | |
110 GList *iter; | |
16900
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
111 const char *text = NULL; |
16910
6502a3846264
Fix tab-completion.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16900
diff
changeset
|
112 const char *sgst = NULL; |
15818 | 113 |
114 if (entry->word) | |
115 { | |
116 char *s = get_beginning_of_word(entry); | |
117 suggest = g_strndup(s, entry->cursor - s); | |
118 if (entry->scroll < s) | |
119 offset = gnt_util_onscreen_width(entry->scroll, s); | |
120 } | |
121 else | |
122 suggest = g_strdup(entry->start); | |
123 len = strlen(suggest); /* Don't need to use the utf8-function here */ | |
124 | |
125 if (entry->ddown == NULL) | |
126 { | |
127 GntWidget *box = gnt_vbox_new(FALSE); | |
128 entry->ddown = gnt_tree_new(); | |
129 gnt_tree_set_compare_func(GNT_TREE(entry->ddown), (GCompareFunc)g_utf8_collate); | |
130 gnt_box_add_widget(GNT_BOX(box), entry->ddown); | |
131 /* XXX: Connect to the "activate" signal for the dropdown tree */ | |
132 | |
133 GNT_WIDGET_SET_FLAGS(box, GNT_WIDGET_TRANSIENT); | |
134 | |
135 gnt_widget_get_position(GNT_WIDGET(entry), &x, &y); | |
136 x += offset; | |
137 y++; | |
138 if (y + 10 >= getmaxy(stdscr)) | |
139 y -= 11; | |
140 gnt_widget_set_position(box, x, y); | |
141 } | |
142 else | |
143 gnt_tree_remove_all(GNT_TREE(entry->ddown)); | |
144 | |
145 for (count = 0, iter = entry->suggests; iter; iter = iter->next) | |
146 { | |
16900
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
147 text = iter->data; |
15818 | 148 if (g_ascii_strncasecmp(suggest, text, len) == 0 && strlen(text) >= len) |
149 { | |
150 gnt_tree_add_row_after(GNT_TREE(entry->ddown), (gpointer)text, | |
151 gnt_tree_create_row(GNT_TREE(entry->ddown), text), | |
152 NULL, NULL); | |
153 count++; | |
16910
6502a3846264
Fix tab-completion.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16900
diff
changeset
|
154 sgst = text; |
15818 | 155 } |
156 } | |
157 g_free(suggest); | |
158 | |
16900
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
159 if (count == 0) { |
15818 | 160 destroy_suggest(entry); |
161 return FALSE; | |
16900
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
162 } else if (count == 1) { |
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
163 destroy_suggest(entry); |
16910
6502a3846264
Fix tab-completion.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16900
diff
changeset
|
164 return complete_suggest(entry, sgst); |
16900
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
165 } else { |
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
166 gnt_widget_draw(entry->ddown->parent); |
15818 | 167 } |
168 | |
169 return TRUE; | |
170 } | |
171 | |
172 static void | |
173 gnt_entry_draw(GntWidget *widget) | |
174 { | |
175 GntEntry *entry = GNT_ENTRY(widget); | |
176 int stop; | |
177 gboolean focus; | |
178 | |
179 if ((focus = gnt_widget_has_focus(widget))) | |
180 wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_TEXT_NORMAL)); | |
181 else | |
182 wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D)); | |
183 | |
184 if (entry->masked) | |
185 { | |
186 mvwhline(widget->window, 0, 0, gnt_ascii_only() ? '*' : ACS_BULLET, | |
187 g_utf8_pointer_to_offset(entry->scroll, entry->end)); | |
188 } | |
189 else | |
190 mvwprintw(widget->window, 0, 0, "%s", entry->scroll); | |
191 | |
192 stop = gnt_util_onscreen_width(entry->scroll, entry->end); | |
193 if (stop < widget->priv.width) | |
18346
72a52cff76f3
Draw the password entries correctly.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18049
diff
changeset
|
194 mvwhline(widget->window, 0, stop, ENTRY_CHAR, widget->priv.width - stop); |
15818 | 195 |
196 if (focus) | |
197 mvwchgat(widget->window, 0, gnt_util_onscreen_width(entry->scroll, entry->cursor), | |
198 1, A_REVERSE, GNT_COLOR_TEXT_NORMAL, NULL); | |
199 | |
200 GNTDEBUG; | |
201 } | |
202 | |
203 static void | |
204 gnt_entry_size_request(GntWidget *widget) | |
205 { | |
206 if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_MAPPED)) | |
207 { | |
208 widget->priv.height = 1; | |
209 widget->priv.width = 20; | |
210 } | |
211 } | |
212 | |
213 static void | |
214 gnt_entry_map(GntWidget *widget) | |
215 { | |
216 if (widget->priv.width == 0 || widget->priv.height == 0) | |
217 gnt_widget_size_request(widget); | |
218 GNTDEBUG; | |
219 } | |
220 | |
221 static void | |
222 entry_redraw(GntWidget *widget) | |
223 { | |
224 gnt_entry_draw(widget); | |
225 gnt_widget_queue_update(widget); | |
226 } | |
227 | |
228 static void | |
229 entry_text_changed(GntEntry *entry) | |
230 { | |
231 g_signal_emit(entry, signals[SIG_TEXT_CHANGED], 0); | |
232 } | |
233 | |
234 static gboolean | |
235 move_back(GntBindable *bind, GList *null) | |
236 { | |
237 GntEntry *entry = GNT_ENTRY(bind); | |
238 if (entry->cursor <= entry->start) | |
239 return FALSE; | |
240 entry->cursor = g_utf8_find_prev_char(entry->start, entry->cursor); | |
241 if (entry->cursor < entry->scroll) | |
242 entry->scroll = entry->cursor; | |
243 entry_redraw(GNT_WIDGET(entry)); | |
244 return TRUE; | |
245 } | |
246 | |
247 static gboolean | |
248 move_forward(GntBindable *bind, GList *list) | |
249 { | |
250 GntEntry *entry = GNT_ENTRY(bind); | |
251 if (entry->cursor >= entry->end) | |
252 return FALSE; | |
253 entry->cursor = g_utf8_find_next_char(entry->cursor, NULL); | |
254 while (gnt_util_onscreen_width(entry->scroll, entry->cursor) >= GNT_WIDGET(entry)->priv.width) | |
255 entry->scroll = g_utf8_find_next_char(entry->scroll, NULL); | |
256 entry_redraw(GNT_WIDGET(entry)); | |
257 return TRUE; | |
258 } | |
259 | |
260 static gboolean | |
261 backspace(GntBindable *bind, GList *null) | |
262 { | |
263 int len; | |
264 GntEntry *entry = GNT_ENTRY(bind); | |
265 | |
266 if (entry->cursor <= entry->start) | |
267 return TRUE; | |
268 | |
269 len = entry->cursor - g_utf8_find_prev_char(entry->start, entry->cursor); | |
270 entry->cursor -= len; | |
271 memmove(entry->cursor, entry->cursor + len, entry->end - entry->cursor); | |
272 entry->end -= len; | |
273 | |
274 if (entry->scroll > entry->start) | |
275 entry->scroll = g_utf8_find_prev_char(entry->start, entry->scroll); | |
276 | |
277 entry_redraw(GNT_WIDGET(entry)); | |
278 if (entry->ddown) | |
279 show_suggest_dropdown(entry); | |
280 entry_text_changed(entry); | |
281 return TRUE; | |
282 } | |
283 | |
284 static gboolean | |
285 delkey(GntBindable *bind, GList *null) | |
286 { | |
287 int len; | |
288 GntEntry *entry = GNT_ENTRY(bind); | |
289 | |
290 if (entry->cursor >= entry->end) | |
291 return FALSE; | |
292 | |
293 len = g_utf8_find_next_char(entry->cursor, NULL) - entry->cursor; | |
294 memmove(entry->cursor, entry->cursor + len, entry->end - entry->cursor - len + 1); | |
295 entry->end -= len; | |
296 entry_redraw(GNT_WIDGET(entry)); | |
297 | |
298 if (entry->ddown) | |
299 show_suggest_dropdown(entry); | |
300 entry_text_changed(entry); | |
301 return TRUE; | |
302 } | |
303 | |
304 static gboolean | |
305 move_start(GntBindable *bind, GList *null) | |
306 { | |
307 GntEntry *entry = GNT_ENTRY(bind); | |
308 entry->scroll = entry->cursor = entry->start; | |
309 entry_redraw(GNT_WIDGET(entry)); | |
310 return TRUE; | |
311 } | |
312 | |
313 static gboolean | |
314 move_end(GntBindable *bind, GList *null) | |
315 { | |
316 GntEntry *entry = GNT_ENTRY(bind); | |
317 entry->cursor = entry->end; | |
318 /* This should be better than this */ | |
319 while (gnt_util_onscreen_width(entry->scroll, entry->cursor) >= GNT_WIDGET(entry)->priv.width) | |
320 entry->scroll = g_utf8_find_next_char(entry->scroll, NULL); | |
321 entry_redraw(GNT_WIDGET(entry)); | |
322 return TRUE; | |
323 } | |
324 | |
325 static gboolean | |
326 history_prev(GntBindable *bind, GList *null) | |
327 { | |
328 GntEntry *entry = GNT_ENTRY(bind); | |
329 if (entry->histlength && entry->history->prev) | |
330 { | |
331 entry->history = entry->history->prev; | |
332 gnt_entry_set_text_internal(entry, entry->history->data); | |
333 destroy_suggest(entry); | |
334 entry_text_changed(entry); | |
335 | |
336 return TRUE; | |
337 } | |
338 return FALSE; | |
339 } | |
340 | |
341 static gboolean | |
342 history_next(GntBindable *bind, GList *null) | |
343 { | |
344 GntEntry *entry = GNT_ENTRY(bind); | |
345 if (entry->histlength && entry->history->next) | |
346 { | |
347 if (entry->history->prev == NULL) | |
348 { | |
349 /* Save the current contents */ | |
350 char *text = g_strdup(gnt_entry_get_text(entry)); | |
351 g_free(entry->history->data); | |
352 entry->history->data = text; | |
353 } | |
354 | |
355 entry->history = entry->history->next; | |
356 gnt_entry_set_text_internal(entry, entry->history->data); | |
357 destroy_suggest(entry); | |
358 entry_text_changed(entry); | |
359 | |
360 return TRUE; | |
361 } | |
362 return FALSE; | |
363 } | |
364 | |
365 static gboolean | |
366 clipboard_paste(GntBindable *bind, GList *n) | |
367 { | |
368 GntEntry *entry = GNT_ENTRY(bind); | |
369 gchar *i, *text, *a, *all; | |
370 text = i = gnt_get_clipboard_string(); | |
371 while (*i != '\0') { | |
372 i = g_utf8_next_char(i); | |
373 if (*i == '\r' || *i == '\n') | |
374 *i = ' '; | |
375 } | |
376 a = g_strndup(entry->start, entry->cursor - entry->start); | |
377 all = g_strconcat(a, text, entry->cursor, NULL); | |
378 gnt_entry_set_text_internal(entry, all); | |
379 g_free(a); | |
380 g_free(text); | |
381 g_free(all); | |
382 return TRUE; | |
383 } | |
384 | |
385 static gboolean | |
386 suggest_show(GntBindable *bind, GList *null) | |
387 { | |
15959
efbced3f38ac
Update the tab completion a little bit. The binding for suggest-show will perform suggest-next if the suggest-dropdown is already showing. If there's just one suggestion, then complete with that suggestion.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
388 GntEntry *entry = GNT_ENTRY(bind); |
efbced3f38ac
Update the tab completion a little bit. The binding for suggest-show will perform suggest-next if the suggest-dropdown is already showing. If there's just one suggestion, then complete with that suggestion.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
389 if (entry->ddown) { |
16900
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
390 gnt_bindable_perform_action_named(GNT_BINDABLE(entry->ddown), "move-down"); |
15959
efbced3f38ac
Update the tab completion a little bit. The binding for suggest-show will perform suggest-next if the suggest-dropdown is already showing. If there's just one suggestion, then complete with that suggestion.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
391 return TRUE; |
efbced3f38ac
Update the tab completion a little bit. The binding for suggest-show will perform suggest-next if the suggest-dropdown is already showing. If there's just one suggestion, then complete with that suggestion.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
392 } |
efbced3f38ac
Update the tab completion a little bit. The binding for suggest-show will perform suggest-next if the suggest-dropdown is already showing. If there's just one suggestion, then complete with that suggestion.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
393 return show_suggest_dropdown(entry); |
15818 | 394 } |
395 | |
396 static gboolean | |
397 suggest_next(GntBindable *bind, GList *null) | |
398 { | |
399 GntEntry *entry = GNT_ENTRY(bind); | |
400 if (entry->ddown) { | |
401 gnt_bindable_perform_action_named(GNT_BINDABLE(entry->ddown), "move-down", NULL); | |
402 return TRUE; | |
403 } | |
404 return FALSE; | |
405 } | |
406 | |
407 static gboolean | |
408 suggest_prev(GntBindable *bind, GList *null) | |
409 { | |
410 GntEntry *entry = GNT_ENTRY(bind); | |
411 if (entry->ddown) { | |
412 gnt_bindable_perform_action_named(GNT_BINDABLE(entry->ddown), "move-up", NULL); | |
413 return TRUE; | |
414 } | |
415 return FALSE; | |
416 } | |
417 | |
418 static gboolean | |
419 del_to_home(GntBindable *bind, GList *null) | |
420 { | |
421 GntEntry *entry = GNT_ENTRY(bind); | |
422 if (entry->cursor <= entry->start) | |
423 return TRUE; | |
424 memmove(entry->start, entry->cursor, entry->end - entry->cursor); | |
425 entry->end -= (entry->cursor - entry->start); | |
426 entry->cursor = entry->scroll = entry->start; | |
427 memset(entry->end, '\0', entry->buffer - (entry->end - entry->start)); | |
428 entry_redraw(GNT_WIDGET(bind)); | |
429 entry_text_changed(entry); | |
430 return TRUE; | |
431 } | |
432 | |
433 static gboolean | |
434 del_to_end(GntBindable *bind, GList *null) | |
435 { | |
436 GntEntry *entry = GNT_ENTRY(bind); | |
437 if (entry->end <= entry->cursor) | |
438 return TRUE; | |
439 entry->end = entry->cursor; | |
440 memset(entry->end, '\0', entry->buffer - (entry->end - entry->start)); | |
441 entry_redraw(GNT_WIDGET(bind)); | |
442 entry_text_changed(entry); | |
443 return TRUE; | |
444 } | |
445 | |
446 #define SAME(a,b) ((g_unichar_isalpha(a) && g_unichar_isalpha(b)) || \ | |
447 (g_unichar_isdigit(a) && g_unichar_isdigit(b)) || \ | |
448 (g_unichar_isspace(a) && g_unichar_isspace(b)) || \ | |
449 (g_unichar_iswide(a) && g_unichar_iswide(b))) | |
450 | |
451 static const char * | |
452 begin_word(const char *text, const char *begin) | |
453 { | |
454 gunichar ch = 0; | |
455 while (text > begin && (!*text || g_unichar_isspace(g_utf8_get_char(text)))) | |
456 text = g_utf8_find_prev_char(begin, text); | |
457 ch = g_utf8_get_char(text); | |
458 while ((text = g_utf8_find_prev_char(begin, text)) >= begin) { | |
459 gunichar cur = g_utf8_get_char(text); | |
460 if (!SAME(ch, cur)) | |
461 break; | |
462 } | |
463 | |
464 return (text ? g_utf8_find_next_char(text, NULL) : begin); | |
465 } | |
466 | |
467 static const char * | |
468 next_begin_word(const char *text, const char *end) | |
469 { | |
470 gunichar ch = 0; | |
471 ch = g_utf8_get_char(text); | |
472 while ((text = g_utf8_find_next_char(text, end)) != NULL && text <= end) { | |
473 gunichar cur = g_utf8_get_char(text); | |
474 if (!SAME(ch, cur)) | |
475 break; | |
476 } | |
477 | |
478 while (text && text < end && g_unichar_isspace(g_utf8_get_char(text))) | |
479 text = g_utf8_find_next_char(text, end); | |
480 return (text ? text : end); | |
481 } | |
482 | |
483 #undef SAME | |
484 static gboolean | |
485 move_back_word(GntBindable *bind, GList *null) | |
486 { | |
487 GntEntry *entry = GNT_ENTRY(bind); | |
488 const char *iter = g_utf8_find_prev_char(entry->start, entry->cursor); | |
489 | |
490 if (iter < entry->start) | |
491 return TRUE; | |
492 iter = begin_word(iter, entry->start); | |
493 entry->cursor = (char*)iter; | |
494 if (entry->cursor < entry->scroll) | |
495 entry->scroll = entry->cursor; | |
496 entry_redraw(GNT_WIDGET(bind)); | |
497 return TRUE; | |
498 } | |
499 | |
500 static gboolean | |
501 del_prev_word(GntBindable *bind, GList *null) | |
502 { | |
503 GntWidget *widget = GNT_WIDGET(bind); | |
504 GntEntry *entry = GNT_ENTRY(bind); | |
505 char *iter = g_utf8_find_prev_char(entry->start, entry->cursor); | |
506 int count; | |
507 | |
508 if (iter < entry->start) | |
509 return TRUE; | |
510 iter = (char*)begin_word(iter, entry->start); | |
511 count = entry->cursor - iter; | |
512 memmove(iter, entry->cursor, entry->end - entry->cursor); | |
513 entry->end -= count; | |
514 entry->cursor = iter; | |
515 if (entry->cursor <= entry->scroll) { | |
516 entry->scroll = entry->cursor - widget->priv.width + 2; | |
517 if (entry->scroll < entry->start) | |
518 entry->scroll = entry->start; | |
519 } | |
520 memset(entry->end, '\0', entry->buffer - (entry->end - entry->start)); | |
521 entry_redraw(widget); | |
522 entry_text_changed(entry); | |
523 | |
524 return TRUE; | |
525 } | |
526 | |
527 static gboolean | |
528 move_forward_word(GntBindable *bind, GList *list) | |
529 { | |
530 GntEntry *entry = GNT_ENTRY(bind); | |
531 GntWidget *widget = GNT_WIDGET(bind); | |
532 entry->cursor = (char *)next_begin_word(entry->cursor, entry->end); | |
533 while (gnt_util_onscreen_width(entry->scroll, entry->cursor) >= widget->priv.width) { | |
534 entry->scroll = g_utf8_find_next_char(entry->scroll, NULL); | |
535 } | |
536 entry_redraw(widget); | |
537 return TRUE; | |
538 } | |
539 | |
540 static gboolean | |
541 delete_forward_word(GntBindable *bind, GList *list) | |
542 { | |
543 GntEntry *entry = GNT_ENTRY(bind); | |
544 GntWidget *widget = GNT_WIDGET(bind); | |
545 char *iter = (char *)next_begin_word(entry->cursor, entry->end); | |
546 int len = entry->end - iter + 1; | |
547 if (len <= 0) | |
548 return TRUE; | |
549 memmove(entry->cursor, iter, len); | |
550 len = iter - entry->cursor; | |
551 entry->end -= len; | |
552 memset(entry->end, '\0', len); | |
553 entry_redraw(widget); | |
554 entry_text_changed(entry); | |
555 return TRUE; | |
556 } | |
557 | |
558 static gboolean | |
559 gnt_entry_key_pressed(GntWidget *widget, const char *text) | |
560 { | |
561 GntEntry *entry = GNT_ENTRY(widget); | |
562 | |
563 if (text[0] == 27) | |
564 { | |
565 if (text[1] == 0) | |
566 { | |
567 destroy_suggest(entry); | |
568 return TRUE; | |
569 } | |
570 | |
571 return FALSE; | |
572 } | |
573 else | |
574 { | |
16900
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
575 if ((text[0] == '\r' || text[0] == ' ') && entry->ddown) |
15818 | 576 { |
577 char *text = g_strdup(gnt_tree_get_selection_data(GNT_TREE(entry->ddown))); | |
578 destroy_suggest(entry); | |
16900
c31328dba5c2
Fix some ickyness in the tab-completion. Now, if there's only one suggest word, then the first tab will just complete the suggestion. If there's only one suggest word, and it's already completed, then tab will take focus to the next widget. If there is a dropdown, then you can select a suggest word by pressing tabs to move to it, then either space or enter to accept it.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15959
diff
changeset
|
579 complete_suggest(entry, text); |
15818 | 580 g_free(text); |
581 entry_text_changed(entry); | |
582 return TRUE; | |
583 } | |
584 | |
585 if (!iscntrl(text[0])) | |
586 { | |
587 const char *str, *next; | |
588 | |
589 for (str = text; *str; str = next) | |
590 { | |
591 int len; | |
592 next = g_utf8_find_next_char(str, NULL); | |
593 len = next - str; | |
594 | |
595 /* Valid input? */ | |
596 /* XXX: Is it necessary to use _unichar_ variants here? */ | |
597 if (ispunct(*str) && (entry->flag & GNT_ENTRY_FLAG_NO_PUNCT)) | |
598 continue; | |
599 if (isspace(*str) && (entry->flag & GNT_ENTRY_FLAG_NO_SPACE)) | |
600 continue; | |
601 if (isalpha(*str) && !(entry->flag & GNT_ENTRY_FLAG_ALPHA)) | |
602 continue; | |
603 if (isdigit(*str) && !(entry->flag & GNT_ENTRY_FLAG_INT)) | |
604 continue; | |
605 | |
606 /* Reached the max? */ | |
607 if (entry->max && g_utf8_pointer_to_offset(entry->start, entry->end) >= entry->max) | |
608 continue; | |
609 | |
610 if (entry->end + len - entry->start >= entry->buffer) | |
611 { | |
612 /* This will cause the buffer to grow */ | |
613 char *tmp = g_strdup(entry->start); | |
614 gnt_entry_set_text_internal(entry, tmp); | |
615 g_free(tmp); | |
616 } | |
617 | |
618 memmove(entry->cursor + len, entry->cursor, entry->end - entry->cursor + 1); | |
619 entry->end += len; | |
620 | |
621 while (str < next) | |
622 { | |
623 if (*str == '\r' || *str == '\n') | |
624 *entry->cursor = ' '; | |
625 else | |
626 *entry->cursor = *str; | |
627 entry->cursor++; | |
628 str++; | |
629 } | |
630 | |
631 while (gnt_util_onscreen_width(entry->scroll, entry->cursor) >= widget->priv.width) | |
632 entry->scroll = g_utf8_find_next_char(entry->scroll, NULL); | |
633 | |
634 if (entry->ddown) | |
635 show_suggest_dropdown(entry); | |
636 } | |
637 entry_redraw(widget); | |
638 entry_text_changed(entry); | |
639 return TRUE; | |
640 } | |
641 } | |
642 | |
643 return FALSE; | |
644 } | |
645 | |
646 static void | |
647 gnt_entry_destroy(GntWidget *widget) | |
648 { | |
649 GntEntry *entry = GNT_ENTRY(widget); | |
650 g_free(entry->start); | |
651 | |
652 if (entry->history) | |
653 { | |
654 entry->history = g_list_first(entry->history); | |
655 g_list_foreach(entry->history, (GFunc)g_free, NULL); | |
656 g_list_free(entry->history); | |
657 } | |
658 | |
659 if (entry->suggests) | |
660 { | |
661 g_list_foreach(entry->suggests, (GFunc)g_free, NULL); | |
662 g_list_free(entry->suggests); | |
663 } | |
664 | |
665 if (entry->ddown) | |
666 { | |
667 gnt_widget_destroy(entry->ddown->parent); | |
668 } | |
669 } | |
670 | |
671 static void | |
672 gnt_entry_lost_focus(GntWidget *widget) | |
673 { | |
674 GntEntry *entry = GNT_ENTRY(widget); | |
675 destroy_suggest(entry); | |
676 entry_redraw(widget); | |
677 } | |
678 | |
679 static void | |
680 gnt_entry_class_init(GntEntryClass *klass) | |
681 { | |
682 GntBindableClass *bindable = GNT_BINDABLE_CLASS(klass); | |
683 char s[2] = {erasechar(), 0}; | |
684 | |
685 parent_class = GNT_WIDGET_CLASS(klass); | |
686 parent_class->destroy = gnt_entry_destroy; | |
687 parent_class->draw = gnt_entry_draw; | |
688 parent_class->map = gnt_entry_map; | |
689 parent_class->size_request = gnt_entry_size_request; | |
690 parent_class->key_pressed = gnt_entry_key_pressed; | |
691 parent_class->lost_focus = gnt_entry_lost_focus; | |
692 | |
693 signals[SIG_TEXT_CHANGED] = | |
694 g_signal_new("text_changed", | |
695 G_TYPE_FROM_CLASS(klass), | |
696 G_SIGNAL_RUN_LAST, | |
697 G_STRUCT_OFFSET(GntEntryClass, text_changed), | |
698 NULL, NULL, | |
699 g_cclosure_marshal_VOID__VOID, | |
700 G_TYPE_NONE, 0); | |
701 | |
18382
aa60f5a89286
A 'completion' signal to emit whenever user accepts a completion suggest.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18346
diff
changeset
|
702 signals[SIG_COMPLETION] = |
aa60f5a89286
A 'completion' signal to emit whenever user accepts a completion suggest.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18346
diff
changeset
|
703 g_signal_new("completion", |
aa60f5a89286
A 'completion' signal to emit whenever user accepts a completion suggest.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18346
diff
changeset
|
704 G_TYPE_FROM_CLASS(klass), |
aa60f5a89286
A 'completion' signal to emit whenever user accepts a completion suggest.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18346
diff
changeset
|
705 G_SIGNAL_RUN_LAST, |
aa60f5a89286
A 'completion' signal to emit whenever user accepts a completion suggest.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18346
diff
changeset
|
706 0, NULL, NULL, |
aa60f5a89286
A 'completion' signal to emit whenever user accepts a completion suggest.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18346
diff
changeset
|
707 gnt_closure_marshal_VOID__POINTER_POINTER, |
aa60f5a89286
A 'completion' signal to emit whenever user accepts a completion suggest.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18346
diff
changeset
|
708 G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER); |
aa60f5a89286
A 'completion' signal to emit whenever user accepts a completion suggest.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18346
diff
changeset
|
709 |
15818 | 710 gnt_bindable_class_register_action(bindable, "cursor-home", move_start, |
711 GNT_KEY_CTRL_A, NULL); | |
712 gnt_bindable_register_binding(bindable, "cursor-home", GNT_KEY_HOME, NULL); | |
713 gnt_bindable_class_register_action(bindable, "cursor-end", move_end, | |
714 GNT_KEY_CTRL_E, NULL); | |
715 gnt_bindable_register_binding(bindable, "cursor-end", GNT_KEY_END, NULL); | |
716 gnt_bindable_class_register_action(bindable, "delete-prev", backspace, | |
717 GNT_KEY_BACKSPACE, NULL); | |
718 gnt_bindable_register_binding(bindable, "delete-prev", s, NULL); | |
719 gnt_bindable_register_binding(bindable, "delete-prev", GNT_KEY_CTRL_H, NULL); | |
720 gnt_bindable_class_register_action(bindable, "delete-next", delkey, | |
721 GNT_KEY_DEL, NULL); | |
722 gnt_bindable_register_binding(bindable, "delete-next", GNT_KEY_CTRL_D, NULL); | |
723 gnt_bindable_class_register_action(bindable, "delete-start", del_to_home, | |
724 GNT_KEY_CTRL_U, NULL); | |
725 gnt_bindable_class_register_action(bindable, "delete-end", del_to_end, | |
726 GNT_KEY_CTRL_K, NULL); | |
727 gnt_bindable_class_register_action(bindable, "delete-prev-word", del_prev_word, | |
728 GNT_KEY_CTRL_W, NULL); | |
729 gnt_bindable_class_register_action(bindable, "cursor-prev-word", move_back_word, | |
730 "\033" "b", NULL); | |
731 gnt_bindable_class_register_action(bindable, "cursor-prev", move_back, | |
732 GNT_KEY_LEFT, NULL); | |
733 gnt_bindable_register_binding(bindable, "cursor-prev", GNT_KEY_CTRL_B, NULL); | |
734 gnt_bindable_class_register_action(bindable, "cursor-next", move_forward, | |
735 GNT_KEY_RIGHT, NULL); | |
736 gnt_bindable_register_binding(bindable, "cursor-next", GNT_KEY_CTRL_F, NULL); | |
737 gnt_bindable_class_register_action(bindable, "cursor-next-word", move_forward_word, | |
738 "\033" "f", NULL); | |
739 gnt_bindable_class_register_action(bindable, "delete-next-word", delete_forward_word, | |
740 "\033" "d", NULL); | |
741 gnt_bindable_class_register_action(bindable, "suggest-show", suggest_show, | |
742 "\t", NULL); | |
743 gnt_bindable_class_register_action(bindable, "suggest-next", suggest_next, | |
744 GNT_KEY_DOWN, NULL); | |
745 gnt_bindable_class_register_action(bindable, "suggest-prev", suggest_prev, | |
746 GNT_KEY_UP, NULL); | |
747 gnt_bindable_class_register_action(bindable, "history-prev", history_prev, | |
748 GNT_KEY_CTRL_DOWN, NULL); | |
749 gnt_bindable_class_register_action(bindable, "history-next", history_next, | |
750 GNT_KEY_CTRL_UP, NULL); | |
751 gnt_bindable_class_register_action(bindable, "clipboard-paste", clipboard_paste, | |
752 GNT_KEY_CTRL_V, NULL); | |
753 | |
754 gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass)); | |
755 GNTDEBUG; | |
756 } | |
757 | |
758 static void | |
759 gnt_entry_init(GTypeInstance *instance, gpointer class) | |
760 { | |
761 GntWidget *widget = GNT_WIDGET(instance); | |
762 GntEntry *entry = GNT_ENTRY(instance); | |
763 | |
764 entry->flag = GNT_ENTRY_FLAG_ALL; | |
765 entry->max = 0; | |
766 | |
767 entry->histlength = 0; | |
768 entry->history = NULL; | |
769 | |
770 entry->word = TRUE; | |
771 entry->always = FALSE; | |
772 entry->suggests = NULL; | |
773 | |
774 GNT_WIDGET_SET_FLAGS(GNT_WIDGET(entry), | |
775 GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW | GNT_WIDGET_CAN_TAKE_FOCUS); | |
776 GNT_WIDGET_SET_FLAGS(GNT_WIDGET(entry), GNT_WIDGET_GROW_X); | |
777 | |
778 widget->priv.minw = 3; | |
779 widget->priv.minh = 1; | |
780 | |
781 GNTDEBUG; | |
782 } | |
783 | |
784 /****************************************************************************** | |
785 * GntEntry API | |
786 *****************************************************************************/ | |
787 GType | |
788 gnt_entry_get_gtype(void) | |
789 { | |
790 static GType type = 0; | |
791 | |
792 if(type == 0) | |
793 { | |
794 static const GTypeInfo info = { | |
795 sizeof(GntEntryClass), | |
796 NULL, /* base_init */ | |
797 NULL, /* base_finalize */ | |
798 (GClassInitFunc)gnt_entry_class_init, | |
799 NULL, /* class_finalize */ | |
800 NULL, /* class_data */ | |
801 sizeof(GntEntry), | |
802 0, /* n_preallocs */ | |
803 gnt_entry_init, /* instance_init */ | |
804 NULL /* value_table */ | |
805 }; | |
806 | |
807 type = g_type_register_static(GNT_TYPE_WIDGET, | |
808 "GntEntry", | |
809 &info, 0); | |
810 } | |
811 | |
812 return type; | |
813 } | |
814 | |
815 GntWidget *gnt_entry_new(const char *text) | |
816 { | |
817 GntWidget *widget = g_object_new(GNT_TYPE_ENTRY, NULL); | |
818 GntEntry *entry = GNT_ENTRY(widget); | |
819 | |
820 gnt_entry_set_text_internal(entry, text); | |
821 | |
822 return widget; | |
823 } | |
824 | |
825 static void | |
826 gnt_entry_set_text_internal(GntEntry *entry, const char *text) | |
827 { | |
828 int len; | |
829 int scroll, cursor; | |
830 | |
831 g_free(entry->start); | |
832 | |
833 if (text && text[0]) | |
834 { | |
835 len = strlen(text); | |
836 } | |
837 else | |
838 { | |
839 len = 0; | |
840 } | |
841 | |
842 entry->buffer = len + 128; | |
843 | |
844 scroll = entry->scroll - entry->start; | |
845 cursor = entry->end - entry->cursor; | |
846 | |
847 entry->start = g_new0(char, entry->buffer); | |
848 if (text) | |
849 snprintf(entry->start, len + 1, "%s", text); | |
850 entry->end = entry->start + len; | |
851 | |
852 entry->scroll = entry->start + scroll; | |
853 entry->cursor = entry->end - cursor; | |
854 | |
855 if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(entry), GNT_WIDGET_MAPPED)) | |
856 entry_redraw(GNT_WIDGET(entry)); | |
857 } | |
858 | |
859 void gnt_entry_set_text(GntEntry *entry, const char *text) | |
860 { | |
861 gboolean changed = TRUE; | |
862 if (text == NULL && entry->start == NULL) | |
863 changed = FALSE; | |
864 if (text && entry->start && g_utf8_collate(text, entry->start) == 0) | |
865 changed = FALSE; | |
866 gnt_entry_set_text_internal(entry, text); | |
867 if (changed) | |
868 entry_text_changed(entry); | |
869 } | |
870 | |
871 void gnt_entry_set_max(GntEntry *entry, int max) | |
872 { | |
873 entry->max = max; | |
874 } | |
875 | |
876 void gnt_entry_set_flag(GntEntry *entry, GntEntryFlag flag) | |
877 { | |
878 entry->flag = flag; | |
879 /* XXX: Check the existing string to make sure the flags are respected? */ | |
880 } | |
881 | |
882 const char *gnt_entry_get_text(GntEntry *entry) | |
883 { | |
884 return entry->start; | |
885 } | |
886 | |
887 void gnt_entry_clear(GntEntry *entry) | |
888 { | |
889 gnt_entry_set_text_internal(entry, NULL); | |
890 entry->scroll = entry->cursor = entry->end = entry->start; | |
891 entry_redraw(GNT_WIDGET(entry)); | |
892 destroy_suggest(entry); | |
893 entry_text_changed(entry); | |
894 } | |
895 | |
896 void gnt_entry_set_masked(GntEntry *entry, gboolean set) | |
897 { | |
898 entry->masked = set; | |
899 } | |
900 | |
901 void gnt_entry_add_to_history(GntEntry *entry, const char *text) | |
902 { | |
903 g_return_if_fail(entry->history != NULL); /* Need to set_history_length first */ | |
904 | |
905 if (g_list_length(entry->history) >= entry->histlength) | |
906 return; | |
907 | |
908 entry->history = g_list_first(entry->history); | |
909 g_free(entry->history->data); | |
910 entry->history->data = g_strdup(text); | |
911 entry->history = g_list_prepend(entry->history, NULL); | |
912 } | |
913 | |
914 void gnt_entry_set_history_length(GntEntry *entry, int num) | |
915 { | |
916 if (num == 0) | |
917 { | |
918 entry->histlength = num; | |
919 if (entry->history) | |
920 { | |
921 entry->history = g_list_first(entry->history); | |
922 g_list_foreach(entry->history, (GFunc)g_free, NULL); | |
923 g_list_free(entry->history); | |
924 entry->history = NULL; | |
925 } | |
926 return; | |
927 } | |
928 | |
929 if (entry->histlength == 0) | |
930 { | |
931 entry->histlength = num; | |
932 entry->history = g_list_append(NULL, NULL); | |
933 return; | |
934 } | |
935 | |
936 if (num > 0 && num < entry->histlength) | |
937 { | |
938 GList *first, *iter; | |
939 int index = 0; | |
940 for (first = entry->history, index = 0; first->prev; first = first->prev, index++); | |
941 while ((iter = g_list_nth(first, num)) != NULL) | |
942 { | |
943 g_free(iter->data); | |
944 first = g_list_delete_link(first, iter); | |
945 } | |
946 entry->histlength = num; | |
947 if (index >= num) | |
948 entry->history = g_list_last(first); | |
949 return; | |
950 } | |
951 | |
952 entry->histlength = num; | |
953 } | |
954 | |
955 void gnt_entry_set_word_suggest(GntEntry *entry, gboolean word) | |
956 { | |
957 entry->word = word; | |
958 } | |
959 | |
960 void gnt_entry_set_always_suggest(GntEntry *entry, gboolean always) | |
961 { | |
962 entry->always = always; | |
963 } | |
964 | |
965 void gnt_entry_add_suggest(GntEntry *entry, const char *text) | |
966 { | |
967 GList *find; | |
968 | |
969 if (!text || !*text) | |
970 return; | |
971 | |
972 find = g_list_find_custom(entry->suggests, text, (GCompareFunc)g_utf8_collate); | |
973 if (find) | |
974 return; | |
975 entry->suggests = g_list_append(entry->suggests, g_strdup(text)); | |
976 } | |
977 | |
978 void gnt_entry_remove_suggest(GntEntry *entry, const char *text) | |
979 { | |
980 GList *find = g_list_find_custom(entry->suggests, text, (GCompareFunc)g_utf8_collate); | |
981 if (find) | |
982 { | |
983 g_free(find->data); | |
984 entry->suggests = g_list_delete_link(entry->suggests, find); | |
985 } | |
986 } | |
987 |