comparison libaudacious/xentry.c @ 0:cb178e5ad177 trunk

[svn] Import audacious source.
author nenolod
date Mon, 24 Oct 2005 03:06:47 -0700
parents
children 0a73d1faeb4e
comparison
equal deleted inserted replaced
-1:000000000000 0:cb178e5ad177
1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
19
20 /*
21 * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
25 */
26
27 /*
28 * Small modification of the entry widget where keyboard navigation
29 * works even when the entry is not editable.
30 * Copyright 2003 Haavard Kvaalen <havardk@xmms.org>
31 */
32
33 #include <glib.h>
34 #include <gtk/gtk.h>
35 #include <gdk/gdkkeysyms.h>
36 #include <ctype.h>
37 #include <string.h>
38
39 #include "xentry.h"
40
41 static gint gtk_entry_key_press(GtkWidget * widget, GdkEventKey * event);
42 static void gtk_entry_move_cursor(GtkOldEditable * editable, int x);
43
44 static void gtk_move_forward_character(GtkEntry * entry);
45 static void gtk_move_backward_character(GtkEntry * entry);
46 static void gtk_move_forward_word(GtkEntry * entry);
47 static void gtk_move_backward_word(GtkEntry * entry);
48 static void gtk_move_beginning_of_line(GtkEntry * entry);
49 static void gtk_move_end_of_line(GtkEntry * entry);
50
51
52 static const GtkTextFunction control_keys[26] = {
53 (GtkTextFunction) gtk_move_beginning_of_line, /* a */
54 (GtkTextFunction) gtk_move_backward_character, /* b */
55 (GtkTextFunction) gtk_editable_copy_clipboard, /* c */
56 NULL, /* d */
57 (GtkTextFunction) gtk_move_end_of_line, /* e */
58 (GtkTextFunction) gtk_move_forward_character, /* f */
59 };
60
61 static const GtkTextFunction alt_keys[26] = {
62 NULL, /* a */
63 (GtkTextFunction) gtk_move_backward_word, /* b */
64 NULL, /* c */
65 NULL, /* d */
66 NULL, /* e */
67 (GtkTextFunction) gtk_move_forward_word, /* f */
68 };
69
70
71 static void
72 xmms_entry_class_init(GtkEntryClass * class)
73 {
74 GtkWidgetClass *widget_class = (GtkWidgetClass *) class;
75
76 widget_class->key_press_event = gtk_entry_key_press;
77 }
78
79 GtkType
80 xmms_entry_get_type(void)
81 {
82 static GtkType entry_type = 0;
83
84 if (!entry_type) {
85 static const GtkTypeInfo entry_info = {
86 "XmmsEntry",
87 sizeof(XmmsEntry),
88 sizeof(XmmsEntryClass),
89 (GtkClassInitFunc) xmms_entry_class_init,
90 NULL,
91 /* reserved_1 */ NULL,
92 /* reserved_2 */ NULL,
93 (GtkClassInitFunc) NULL,
94 };
95
96 entry_type = gtk_type_unique(GTK_TYPE_ENTRY, &entry_info);
97 }
98
99 return entry_type;
100 }
101
102 GtkWidget *
103 xmms_entry_new(void)
104 {
105 return GTK_WIDGET(gtk_type_new(XMMS_TYPE_ENTRY));
106 }
107
108 static int
109 gtk_entry_key_press(GtkWidget * widget, GdkEventKey * event)
110 {
111 GtkEntry *entry;
112 GtkOldEditable *editable;
113
114 int return_val;
115 guint initial_pos, sel_start_pos, sel_end_pos;
116 int extend_selection;
117 gboolean extend_start = FALSE;
118
119 g_return_val_if_fail(widget != NULL, FALSE);
120 g_return_val_if_fail(XMMS_IS_ENTRY(widget), FALSE);
121 g_return_val_if_fail(event != NULL, FALSE);
122
123 entry = GTK_ENTRY(widget);
124 editable = GTK_OLD_EDITABLE(widget);
125 return_val = FALSE;
126
127 if (editable->editable)
128 /* Let the regular entry handler do it */
129 return FALSE;
130
131 initial_pos = gtk_editable_get_position(GTK_EDITABLE(editable));
132
133 extend_selection = event->state & GDK_SHIFT_MASK;
134
135 sel_start_pos = editable->selection_start_pos;
136 sel_end_pos = editable->selection_end_pos;
137
138 if (extend_selection) {
139 if (sel_start_pos == sel_end_pos) {
140 sel_start_pos = editable->current_pos;
141 sel_end_pos = editable->current_pos;
142 }
143
144 extend_start = (editable->current_pos == sel_start_pos);
145 }
146
147 switch (event->keyval) {
148 case GDK_Insert:
149 return_val = TRUE;
150 if (event->state & GDK_CONTROL_MASK)
151 gtk_editable_copy_clipboard(GTK_EDITABLE(editable));
152 break;
153 case GDK_Home:
154 return_val = TRUE;
155 gtk_move_beginning_of_line(entry);
156 break;
157 case GDK_End:
158 return_val = TRUE;
159 gtk_move_end_of_line(entry);
160 break;
161 case GDK_Left:
162 return_val = TRUE;
163 if (!extend_selection && sel_start_pos != sel_end_pos) {
164 gtk_editable_set_position(GTK_EDITABLE(editable),
165 MIN(sel_start_pos, sel_end_pos));
166 /* Force redraw below */
167 initial_pos = -1;
168 }
169 else
170 gtk_move_backward_character(entry);
171 break;
172 case GDK_Right:
173 return_val = TRUE;
174 if (!extend_selection && sel_start_pos != sel_end_pos) {
175 gtk_editable_set_position(GTK_EDITABLE(editable),
176 MAX(sel_start_pos, sel_end_pos));
177 /* Force redraw below */
178 initial_pos = -1;
179 }
180 else
181 gtk_move_forward_character(entry);
182 break;
183 case GDK_Return:
184 return_val = TRUE;
185 gtk_widget_activate(widget);
186 break;
187 default:
188 if ((event->keyval >= 0x20) && (event->keyval <= 0xFF)) {
189 int key = event->keyval;
190
191 if (key >= 'A' && key <= 'Z')
192 key -= 'A' - 'a';
193
194 if (key >= 'a' && key <= 'z')
195 key -= 'a';
196 else
197 break;
198
199 if (event->state & GDK_CONTROL_MASK) {
200 if (control_keys[key]) {
201 (*control_keys[key]) (editable, event->time);
202 return_val = TRUE;
203 }
204 break;
205 }
206 else if (event->state & GDK_MOD1_MASK) {
207 if (alt_keys[key]) {
208 (*alt_keys[key]) (editable, event->time);
209 return_val = TRUE;
210 }
211 break;
212 }
213 }
214 }
215
216 if (return_val && (editable->current_pos != initial_pos)) {
217 if (extend_selection) {
218 int cpos = gtk_editable_get_position(GTK_EDITABLE(editable));
219 if (cpos < sel_start_pos)
220 sel_start_pos = cpos;
221 else if (cpos > sel_end_pos)
222 sel_end_pos = cpos;
223 else {
224 if (extend_start)
225 sel_start_pos = cpos;
226 else
227 sel_end_pos = cpos;
228 }
229 }
230 else {
231 sel_start_pos = 0;
232 sel_end_pos = 0;
233 }
234
235 gtk_editable_select_region(GTK_EDITABLE(editable), sel_start_pos,
236 sel_end_pos);
237 }
238
239 return return_val;
240 }
241
242 static void
243 gtk_entry_move_cursor(GtkOldEditable * editable, int x)
244 {
245 int set, pos = gtk_editable_get_position(GTK_EDITABLE(editable));
246 if (pos + x < 0)
247 set = 0;
248 else
249 set = pos + x;
250 gtk_editable_set_position(GTK_EDITABLE(editable), set);
251 }
252
253 static void
254 gtk_move_forward_character(GtkEntry * entry)
255 {
256 gtk_entry_move_cursor(GTK_OLD_EDITABLE(entry), 1);
257 }
258
259 static void
260 gtk_move_backward_character(GtkEntry * entry)
261 {
262 gtk_entry_move_cursor(GTK_OLD_EDITABLE(entry), -1);
263 }
264
265 static void
266 gtk_move_forward_word(GtkEntry * entry)
267 {
268 GtkOldEditable *editable;
269 GdkWChar *text;
270 int i;
271
272 editable = GTK_OLD_EDITABLE(entry);
273
274 /* Prevent any leak of information */
275 if (!editable->visible) {
276 gtk_editable_set_position(GTK_EDITABLE(entry), -1);
277 return;
278 }
279
280 if (entry->text && (editable->current_pos < entry->text_length)) {
281 text = (GdkWChar *) entry->text;
282 i = editable->current_pos;
283
284 /* if ((entry->use_wchar && !gdk_iswalnum(text[i])) ||
285 !isalnum(text[i]))
286 for (; i < entry->text_length; i++)
287 {
288 if (entry->use_wchar)
289 {
290 if (gdk_iswalnum(text[i]))
291 break;
292 else if (isalnum(text[i]))
293 break;
294 }
295 }
296
297 for (; i < entry->text_length; i++)
298 {
299 if (entry->use_wchar)
300 {
301 if (gdk_iswalnum(text[i]))
302 break;
303 else if (isalnum(text[i]))
304 break;
305 }
306 }
307
308 */
309
310 gtk_editable_set_position(GTK_EDITABLE(entry), i);
311 }
312 }
313
314 static void
315 gtk_move_backward_word(GtkEntry * entry)
316 {
317 GtkOldEditable *editable;
318 GdkWChar *text;
319 int i;
320
321 editable = GTK_OLD_EDITABLE(entry);
322
323 /* Prevent any leak of information */
324 if (!editable->visible) {
325 gtk_editable_set_position(GTK_EDITABLE(entry), 0);
326 return;
327 }
328
329 if (entry->text && editable->current_pos > 0) {
330 text = (GdkWChar *) entry->text;
331 i = editable->current_pos;
332
333 /* if ((entry->use_wchar && !gdk_iswalnum(text[i])) ||
334 !isalnum(text[i]))
335 for (; i >= 0; i--)
336 {
337 if (entry->use_wchar)
338 {
339 if (gdk_iswalnum(text[i]))
340 break;
341 else if (isalnum(text[i]))
342 break;
343 }
344 }
345 for (; i >= 0; i--)
346 {
347 if ((entry->use_wchar && !gdk_iswalnum(text[i])) ||
348 !isalnum(text[i]))
349 {
350 i++;
351 break;
352 }
353 }
354 */
355 if (i < 0)
356 i = 0;
357
358 gtk_editable_set_position(GTK_EDITABLE(entry), i);
359 }
360 }
361
362 static void
363 gtk_move_beginning_of_line(GtkEntry * entry)
364 {
365 gtk_editable_set_position(GTK_EDITABLE(entry), 0);
366 }
367
368 static void
369 gtk_move_end_of_line(GtkEntry * entry)
370 {
371 gtk_editable_set_position(GTK_EDITABLE(entry), -1);
372 }