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