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