1 /*
2  * Copyright (C) 2009 - 2011 Vivien Malerba <malerba@gnome-db.org>
3  * Copyright (C) 2010 David King <davidk@openismus.com>
4  * Copyright (C) 2011 Murray Cumming <murrayc@murrayc.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA  02110-1301, USA.
20  */
21 
22 #include <glib/gi18n-lib.h>
23 #include <string.h>
24 #include "gdaui-entry-string.h"
25 #include "gdaui-entry.h"
26 #include <libgda/gda-data-handler.h>
27 #include "gdk/gdkkeysyms.h"
28 #include <libgda/gda-debug-macros.h>
29 
30 /*
31  * Main static functions
32  */
33 static void gdaui_entry_string_class_init (GdauiEntryStringClass *klass);
34 static void gdaui_entry_string_init (GdauiEntryString *srv);
35 static void gdaui_entry_string_dispose (GObject *object);
36 static void gdaui_entry_string_finalize (GObject *object);
37 
38 static void gdaui_entry_string_set_property (GObject *object,
39 					     guint param_id,
40 					     const GValue *value,
41 					     GParamSpec *pspec);
42 static void gdaui_entry_string_get_property (GObject *object,
43 					     guint param_id,
44 					     GValue *value,
45 					     GParamSpec *pspec);
46 
47 /* properties */
48 enum
49 {
50 	PROP_0,
51 	PROP_MULTILINE,
52 	PROP_EDITING_CANCELED,
53 	PROP_OPTIONS
54 };
55 
56 /* GtkCellEditable interface */
57 static void gdaui_entry_string_cell_editable_init (GtkCellEditableIface *iface);
58 static void gdaui_entry_string_start_editing (GtkCellEditable *iface, GdkEvent *event);
59 static void sync_entry_options (GdauiEntryString *mgstr);
60 
61 /* virtual functions */
62 static GtkWidget *create_entry (GdauiEntryWrapper *mgwrap);
63 static void       real_set_value (GdauiEntryWrapper *mgwrap, const GValue *value);
64 static GValue    *real_get_value (GdauiEntryWrapper *mgwrap);
65 static void       connect_signals(GdauiEntryWrapper *mgwrap, GCallback modify_cb, GCallback activate_cb);
66 static void       set_editable (GdauiEntryWrapper *mgwrap, gboolean editable);
67 static void       grab_focus (GdauiEntryWrapper *mgwrap);
68 
69 /* options */
70 static void set_entry_options (GdauiEntryString *mgstr, const gchar *options);
71 
72 /* get a pointer to the parents to be able to call their destructor */
73 static GObjectClass  *parent_class = NULL;
74 
75 /* private structure */
76 struct _GdauiEntryStringPrivate
77 {
78 	gboolean       multiline;
79 	gboolean       hidden;
80 	GtkWidget     *vbox;
81 
82 	GtkWidget     *entry;
83 	gboolean       editing_canceled;
84 
85 	GtkTextBuffer *buffer;
86 	GtkWidget     *sw;
87 	GtkWidget     *view;
88 
89 	gint           maxsize;
90 
91 	gulong         entry_change_sig;
92 };
93 
94 static void
gdaui_entry_string_cell_editable_init(GtkCellEditableIface * iface)95 gdaui_entry_string_cell_editable_init (GtkCellEditableIface *iface)
96 {
97 	iface->start_editing = gdaui_entry_string_start_editing;
98 }
99 
100 GType
gdaui_entry_string_get_type(void)101 gdaui_entry_string_get_type (void)
102 {
103 	static GType type = 0;
104 
105 	if (G_UNLIKELY (type == 0)) {
106 		static const GTypeInfo info = {
107 			sizeof (GdauiEntryStringClass),
108 			(GBaseInitFunc) NULL,
109 			(GBaseFinalizeFunc) NULL,
110 			(GClassInitFunc) gdaui_entry_string_class_init,
111 			NULL,
112 			NULL,
113 			sizeof (GdauiEntryString),
114 			0,
115 			(GInstanceInitFunc) gdaui_entry_string_init,
116 			0
117 		};
118 
119 		static const GInterfaceInfo cell_editable_info = {
120 			(GInterfaceInitFunc) gdaui_entry_string_cell_editable_init,    /* interface_init */
121 			NULL,                                                 /* interface_finalize */
122 			NULL                                                  /* interface_data */
123 		};
124 
125 		type = g_type_register_static (GDAUI_TYPE_ENTRY_WRAPPER, "GdauiEntryString", &info, 0);
126 		g_type_add_interface_static (type, GTK_TYPE_CELL_EDITABLE, &cell_editable_info);
127 	}
128 	return type;
129 }
130 
131 static void
gdaui_entry_string_class_init(GdauiEntryStringClass * klass)132 gdaui_entry_string_class_init (GdauiEntryStringClass * klass)
133 {
134 	GObjectClass   *object_class = G_OBJECT_CLASS (klass);
135 
136 	parent_class = g_type_class_peek_parent (klass);
137 
138 	object_class->dispose = gdaui_entry_string_dispose;
139 	object_class->finalize = gdaui_entry_string_finalize;
140 
141 	GDAUI_ENTRY_WRAPPER_CLASS (klass)->create_entry = create_entry;
142 	GDAUI_ENTRY_WRAPPER_CLASS (klass)->real_set_value = real_set_value;
143 	GDAUI_ENTRY_WRAPPER_CLASS (klass)->real_get_value = real_get_value;
144 	GDAUI_ENTRY_WRAPPER_CLASS (klass)->connect_signals = connect_signals;
145 	GDAUI_ENTRY_WRAPPER_CLASS (klass)->set_editable = set_editable;
146 	GDAUI_ENTRY_WRAPPER_CLASS (klass)->grab_focus = grab_focus;
147 
148 	/* Properties */
149 	object_class->set_property = gdaui_entry_string_set_property;
150 	object_class->get_property = gdaui_entry_string_get_property;
151 
152 	g_object_class_install_property (object_class, PROP_MULTILINE,
153 					 g_param_spec_boolean ("multiline", NULL, NULL, FALSE,
154 							       G_PARAM_READABLE | G_PARAM_WRITABLE));
155 	g_object_class_install_property (object_class, PROP_EDITING_CANCELED,
156 					 g_param_spec_boolean ("editing-canceled", NULL, NULL, FALSE,
157 							       G_PARAM_READABLE | G_PARAM_WRITABLE));
158 	g_object_class_install_property (object_class, PROP_OPTIONS,
159 					 g_param_spec_string ("options", NULL, NULL, NULL, G_PARAM_WRITABLE));
160 }
161 
162 static gboolean
key_press_event_cb(GdauiEntryString * mgstr,GdkEventKey * key_event,G_GNUC_UNUSED gpointer data)163 key_press_event_cb (GdauiEntryString *mgstr, GdkEventKey *key_event, G_GNUC_UNUSED gpointer data)
164 {
165 	if (key_event->keyval == GDK_KEY_Escape)
166 		mgstr->priv->editing_canceled = TRUE;
167 	return FALSE;
168 }
169 
170 static void
gdaui_entry_string_init(GdauiEntryString * mgstr)171 gdaui_entry_string_init (GdauiEntryString *mgstr)
172 {
173 	mgstr->priv = g_new0 (GdauiEntryStringPrivate, 1);
174 	mgstr->priv->multiline = FALSE;
175 	mgstr->priv->hidden = FALSE;
176 	mgstr->priv->vbox = NULL;
177 	mgstr->priv->entry = NULL;
178 	mgstr->priv->editing_canceled = FALSE;
179 	mgstr->priv->buffer = NULL;
180 	mgstr->priv->view = NULL;
181 	mgstr->priv->sw = NULL;
182 
183 	mgstr->priv->maxsize = 65535; /* eg. unlimited for GtkEntry */
184 
185 	mgstr->priv->entry_change_sig = 0;
186 
187 	g_signal_connect (mgstr, "key-press-event",
188 			  G_CALLBACK (key_press_event_cb), NULL);
189 }
190 
191 /**
192  * gdaui_entry_string_new:
193  * @dh: the data handler to be used by the new widget
194  * @type: the requested data type (compatible with @dh)
195  *
196  * Creates a new data entry widget
197  *
198  * Returns: (transfer full): the new widget
199  */
200 GtkWidget *
gdaui_entry_string_new(GdaDataHandler * dh,GType type,const gchar * options)201 gdaui_entry_string_new (GdaDataHandler *dh, GType type, const gchar *options)
202 {
203 	GObject *obj;
204 	GdauiEntryString *mgstr;
205 
206 	g_return_val_if_fail (GDA_IS_DATA_HANDLER (dh), NULL);
207 	g_return_val_if_fail (gda_data_handler_accepts_g_type (dh, type), NULL);
208 	g_return_val_if_fail (type == G_TYPE_STRING, NULL);
209 
210 	obj = g_object_new (GDAUI_TYPE_ENTRY_STRING, "handler", dh, NULL);
211 	mgstr = GDAUI_ENTRY_STRING (obj);
212 	gdaui_data_entry_set_value_type (GDAUI_DATA_ENTRY (mgstr), type);
213 
214 	g_object_set (obj, "options", options, NULL);
215 
216 	return GTK_WIDGET (obj);
217 }
218 
219 static void
gdaui_entry_string_dispose(GObject * object)220 gdaui_entry_string_dispose (GObject   * object)
221 {
222 	GdauiEntryString *mgstr;
223 
224 	g_return_if_fail (object != NULL);
225 	g_return_if_fail (GDAUI_IS_ENTRY_STRING (object));
226 
227 	mgstr = GDAUI_ENTRY_STRING (object);
228 	if (mgstr->priv) {
229 		if (mgstr->priv->entry)
230 			mgstr->priv->entry = NULL;
231 
232 		if (mgstr->priv->view)
233 			mgstr->priv->view = NULL;
234 	}
235 
236 	/* parent class */
237 	parent_class->dispose (object);
238 }
239 
240 static void
gdaui_entry_string_finalize(GObject * object)241 gdaui_entry_string_finalize (GObject   * object)
242 {
243 	GdauiEntryString *mgstr;
244 
245 	g_return_if_fail (object != NULL);
246 	g_return_if_fail (GDAUI_IS_ENTRY_STRING (object));
247 
248 	mgstr = GDAUI_ENTRY_STRING (object);
249 	if (mgstr->priv) {
250 		g_free (mgstr->priv);
251 		mgstr->priv = NULL;
252 	}
253 
254 	/* parent class */
255 	parent_class->finalize (object);
256 }
257 
258 static void
gdaui_entry_string_set_property(GObject * object,guint param_id,const GValue * value,GParamSpec * pspec)259 gdaui_entry_string_set_property (GObject *object,
260 				 guint param_id,
261 				 const GValue *value,
262 				 GParamSpec *pspec)
263 {
264 	GdauiEntryString *mgstr;
265 
266 	mgstr = GDAUI_ENTRY_STRING (object);
267 	if (mgstr->priv) {
268 		switch (param_id) {
269 		case PROP_MULTILINE:
270 			if (g_value_get_boolean (value) != mgstr->priv->multiline) {
271 				mgstr->priv->multiline = g_value_get_boolean (value);
272 				if (mgstr->priv->multiline) {
273 					gtk_widget_hide (mgstr->priv->entry);
274 					gtk_widget_show (mgstr->priv->sw);
275 					gtk_widget_set_vexpand (GTK_WIDGET (mgstr), TRUE);
276 				}
277 				else {
278 					gtk_widget_show (mgstr->priv->entry);
279 					gtk_widget_hide (mgstr->priv->sw);
280 					gtk_widget_set_vexpand (GTK_WIDGET (mgstr), FALSE);
281 				}
282 				g_signal_emit_by_name (object, "expand-changed");
283 			}
284 			break;
285 		case PROP_OPTIONS:
286 			set_entry_options (mgstr, g_value_get_string (value));
287 			break;
288 		case PROP_EDITING_CANCELED:
289 			TO_IMPLEMENT;
290 			break;
291 		default:
292 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
293 			break;
294 		}
295 	}
296 }
297 
298 static void
gdaui_entry_string_get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)299 gdaui_entry_string_get_property (GObject *object,
300 				 guint param_id,
301 				 GValue *value,
302 				 GParamSpec *pspec)
303 {
304 	GdauiEntryString *mgstr;
305 
306 	mgstr = GDAUI_ENTRY_STRING (object);
307 	if (mgstr->priv) {
308 		switch (param_id) {
309 		case PROP_MULTILINE:
310 			g_value_set_boolean (value, mgstr->priv->multiline);
311 			break;
312 		case PROP_EDITING_CANCELED:
313 			g_value_set_boolean (value, mgstr->priv->editing_canceled);
314 			break;
315 		default:
316 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
317 			break;
318 		}
319 	}
320 }
321 
322 static void widget_shown_cb (GtkWidget *wid, GdauiEntryString *mgstr);
323 
324 static GtkWidget *
create_entry(GdauiEntryWrapper * mgwrap)325 create_entry (GdauiEntryWrapper *mgwrap)
326 {
327 	GtkWidget *vbox;
328 	GdauiEntryString *mgstr;
329 
330 	g_return_val_if_fail (GDAUI_IS_ENTRY_STRING (mgwrap), NULL);
331 	mgstr = GDAUI_ENTRY_STRING (mgwrap);
332 	g_return_val_if_fail (mgstr->priv, NULL);
333 
334 	vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
335 	mgstr->priv->vbox = vbox;
336 
337 	/* one line entry */
338 	mgstr->priv->entry = gdaui_entry_new (NULL, NULL);
339 	sync_entry_options (mgstr);
340 	gtk_box_pack_start (GTK_BOX (vbox), mgstr->priv->entry, FALSE, TRUE, 0);
341 	g_signal_connect_after (G_OBJECT (mgstr->priv->entry), "show",
342 				G_CALLBACK (widget_shown_cb), mgstr);
343 
344 	/* multiline entry */
345 	mgstr->priv->view = gtk_text_view_new ();
346 	mgstr->priv->buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (mgstr->priv->view));
347 	mgstr->priv->sw = gtk_scrolled_window_new (NULL, NULL);
348 	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (mgstr->priv->sw), GTK_SHADOW_IN);
349 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (mgstr->priv->sw),
350 					GTK_POLICY_AUTOMATIC,
351 					GTK_POLICY_AUTOMATIC);
352 	gtk_container_add (GTK_CONTAINER (mgstr->priv->sw), mgstr->priv->view);
353 	gtk_widget_show (mgstr->priv->view);
354 	gtk_box_pack_start (GTK_BOX (vbox), mgstr->priv->sw, TRUE, TRUE, 0);
355 	g_signal_connect_after (G_OBJECT (mgstr->priv->sw), "show",
356 				G_CALLBACK (widget_shown_cb), mgstr);
357 
358 
359 	/* show widgets if they need to be shown */
360 	gtk_widget_show (mgstr->priv->entry);
361 	gtk_widget_show (mgstr->priv->sw);
362 
363 	return vbox;
364 }
365 
366 static void
widget_shown_cb(GtkWidget * wid,GdauiEntryString * mgstr)367 widget_shown_cb (GtkWidget *wid, GdauiEntryString *mgstr)
368 {
369 	if ((wid == mgstr->priv->entry) && mgstr->priv->multiline)
370 		gtk_widget_hide (mgstr->priv->entry);
371 
372 	if ((wid == mgstr->priv->sw) && !mgstr->priv->multiline)
373 		gtk_widget_hide (mgstr->priv->sw);
374 }
375 
376 
377 static void
real_set_value(GdauiEntryWrapper * mgwrap,const GValue * value)378 real_set_value (GdauiEntryWrapper *mgwrap, const GValue *value)
379 {
380 	GdauiEntryString *mgstr;
381 	GdaDataHandler *dh;
382 
383 	PangoLayout *layout;
384 	gchar *text;
385 
386 	g_return_if_fail (GDAUI_IS_ENTRY_STRING (mgwrap));
387 	mgstr = GDAUI_ENTRY_STRING (mgwrap);
388 	g_return_if_fail (mgstr->priv);
389 
390 	dh = gdaui_data_entry_get_handler (GDAUI_DATA_ENTRY (mgwrap));
391 
392 	/* do we need to go into multi line mode ? */
393 	text = gda_data_handler_get_str_from_value (dh, value);
394 	layout = gtk_widget_create_pango_layout (GTK_WIDGET (mgwrap), text);
395 	if (pango_layout_get_line_count (layout) > 1)
396 		g_object_set (G_OBJECT (mgwrap), "multiline", TRUE, NULL);
397 	g_object_unref (G_OBJECT (layout));
398 
399 	/* fill the single line widget */
400 	if (value) {
401 		if (gda_value_is_null ((GValue *) value))
402 			gdaui_entry_set_text (GDAUI_ENTRY (mgstr->priv->entry), NULL);
403 		else
404 			gdaui_entry_set_text (GDAUI_ENTRY (mgstr->priv->entry), text);
405 	}
406 	else
407 		gdaui_entry_set_text (GDAUI_ENTRY (mgstr->priv->entry), NULL);
408 
409 	/* fill the multiline widget */
410 	if (value) {
411 		if (gda_value_is_null ((GValue *) value) || !text)
412                         gtk_text_buffer_set_text (mgstr->priv->buffer, "", -1);
413 		else
414 			gtk_text_buffer_set_text (mgstr->priv->buffer, text, -1);
415 	}
416 	else
417 		gtk_text_buffer_set_text (mgstr->priv->buffer, "", -1);
418 
419 	g_free (text);
420 }
421 
422 static GValue *
real_get_value(GdauiEntryWrapper * mgwrap)423 real_get_value (GdauiEntryWrapper *mgwrap)
424 {
425 	GValue *value;
426 	GdauiEntryString *mgstr;
427 	GdaDataHandler *dh;
428 
429 	g_return_val_if_fail (GDAUI_IS_ENTRY_STRING (mgwrap), NULL);
430 	mgstr = GDAUI_ENTRY_STRING (mgwrap);
431 	g_return_val_if_fail (mgstr->priv, NULL);
432 
433 	dh = gdaui_data_entry_get_handler (GDAUI_DATA_ENTRY (mgwrap));
434 	if (! mgstr->priv->multiline) {
435 		gchar *cstr;
436 		cstr = gdaui_entry_get_text (GDAUI_ENTRY (mgstr->priv->entry));
437 		value = gda_data_handler_get_value_from_str (dh, cstr, gdaui_data_entry_get_value_type (GDAUI_DATA_ENTRY (mgwrap)));
438 		g_free (cstr);
439 	}
440 	else {
441 		GtkTextIter start, end;
442 		gchar *str;
443 		gtk_text_buffer_get_start_iter (mgstr->priv->buffer, &start);
444 		gtk_text_buffer_get_end_iter (mgstr->priv->buffer, &end);
445 		str = gtk_text_buffer_get_text (mgstr->priv->buffer, &start, &end, FALSE);
446 		value = gda_data_handler_get_value_from_str (dh, str, gdaui_data_entry_get_value_type (GDAUI_DATA_ENTRY (mgwrap)));
447 		g_free (str);
448 	}
449 
450 	if (!value) {
451 		/* in case the gda_data_handler_get_value_from_str() returned an error because
452 		   the contents of the GtkEntry cannot be interpreted as a GValue */
453 		value = gda_value_new_null ();
454 	}
455 
456 	return value;
457 }
458 
459 static void
connect_signals(GdauiEntryWrapper * mgwrap,GCallback modify_cb,GCallback activate_cb)460 connect_signals(GdauiEntryWrapper *mgwrap, GCallback modify_cb, GCallback activate_cb)
461 {
462 	GdauiEntryString *mgstr;
463 
464 	g_return_if_fail (GDAUI_IS_ENTRY_STRING (mgwrap));
465 	mgstr = GDAUI_ENTRY_STRING (mgwrap);
466 	g_return_if_fail (mgstr->priv);
467 
468 	mgstr->priv->entry_change_sig = g_signal_connect (G_OBJECT (mgstr->priv->entry), "changed",
469 							  modify_cb, mgwrap);
470 	g_signal_connect (G_OBJECT (mgstr->priv->entry), "activate",
471 			  activate_cb, mgwrap);
472 
473 	g_signal_connect (G_OBJECT (mgstr->priv->buffer), "changed",
474 			  modify_cb, mgwrap);
475 	/* FIXME: how does the user "activates" the GtkTextView widget ? */
476 }
477 
478 static void
set_editable(GdauiEntryWrapper * mgwrap,gboolean editable)479 set_editable (GdauiEntryWrapper *mgwrap, gboolean editable)
480 {
481 	GdauiEntryString *mgstr;
482 
483 	g_return_if_fail (GDAUI_IS_ENTRY_STRING (mgwrap));
484 	mgstr = GDAUI_ENTRY_STRING (mgwrap);
485 	g_return_if_fail (mgstr->priv);
486 
487 	gtk_editable_set_editable (GTK_EDITABLE (mgstr->priv->entry), editable);
488 	gtk_text_view_set_editable (GTK_TEXT_VIEW (mgstr->priv->view), editable);
489 }
490 
491 static void
grab_focus(GdauiEntryWrapper * mgwrap)492 grab_focus (GdauiEntryWrapper *mgwrap)
493 {
494 	GdauiEntryString *mgstr;
495 
496 	g_return_if_fail (GDAUI_IS_ENTRY_STRING (mgwrap));
497 	mgstr = GDAUI_ENTRY_STRING (mgwrap);
498 	g_return_if_fail (mgstr->priv);
499 
500 	if (mgstr->priv->multiline)
501 		gtk_widget_grab_focus (mgstr->priv->view);
502 	else
503 		gtk_widget_grab_focus (mgstr->priv->entry);
504 }
505 
506 /*
507  * GtkCellEditable interface
508  */
509 static void
gtk_cell_editable_entry_editing_done_cb(G_GNUC_UNUSED GtkEntry * entry,GdauiEntryString * mgstr)510 gtk_cell_editable_entry_editing_done_cb (G_GNUC_UNUSED GtkEntry *entry, GdauiEntryString *mgstr)
511 {
512 	gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (mgstr));
513 }
514 
515 static void
gtk_cell_editable_entry_remove_widget_cb(G_GNUC_UNUSED GtkEntry * entry,GdauiEntryString * mgstr)516 gtk_cell_editable_entry_remove_widget_cb (G_GNUC_UNUSED GtkEntry *entry, GdauiEntryString *mgstr)
517 {
518 	gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (mgstr));
519 }
520 
521 static void
gdaui_entry_string_start_editing(GtkCellEditable * iface,GdkEvent * event)522 gdaui_entry_string_start_editing (GtkCellEditable *iface, GdkEvent *event)
523 {
524 	GdauiEntryString *mgstr;
525 
526 	g_return_if_fail (GDAUI_IS_ENTRY_STRING (iface));
527 	mgstr = GDAUI_ENTRY_STRING (iface);
528 	g_return_if_fail (mgstr->priv);
529 
530 	mgstr->priv->editing_canceled = FALSE;
531 	g_object_set (G_OBJECT (mgstr->priv->entry), "has-frame", FALSE, "xalign", 0., NULL);
532 	gtk_text_view_set_border_window_size (GTK_TEXT_VIEW (mgstr->priv->view), GTK_TEXT_WINDOW_LEFT, 0);
533 	gtk_text_view_set_border_window_size (GTK_TEXT_VIEW (mgstr->priv->view), GTK_TEXT_WINDOW_RIGHT, 0);
534 	gtk_text_view_set_border_window_size (GTK_TEXT_VIEW (mgstr->priv->view), GTK_TEXT_WINDOW_TOP, 0);
535 	gtk_text_view_set_border_window_size (GTK_TEXT_VIEW (mgstr->priv->view), GTK_TEXT_WINDOW_BOTTOM, 0);
536 	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (mgstr->priv->sw), GTK_SHADOW_NONE);
537 	gtk_container_set_border_width (GTK_CONTAINER (mgstr->priv->sw), 0);
538 
539 	gtk_cell_editable_start_editing (GTK_CELL_EDITABLE (mgstr->priv->entry), event);
540 	g_signal_connect (mgstr->priv->entry, "editing-done",
541 			  G_CALLBACK (gtk_cell_editable_entry_editing_done_cb), mgstr);
542 	g_signal_connect (mgstr->priv->entry, "remove-widget",
543 			  G_CALLBACK (gtk_cell_editable_entry_remove_widget_cb), mgstr);
544 	gdaui_entry_shell_refresh (GDAUI_ENTRY_SHELL (mgstr));
545 
546 	gtk_widget_grab_focus (mgstr->priv->entry);
547 	gtk_widget_queue_draw (GTK_WIDGET (mgstr));
548 }
549 
550 /*
551  * Options handling
552  */
553 static void
set_entry_options(GdauiEntryString * mgstr,const gchar * options)554 set_entry_options (GdauiEntryString *mgstr, const gchar *options)
555 {
556 	g_assert (mgstr->priv);
557 
558 	if (options && *options) {
559                 GdaQuarkList *params;
560                 const gchar *str;
561 
562                 params = gda_quark_list_new_from_string (options);
563 
564 		str = gda_quark_list_find (params, "MAX_SIZE");
565 		if (str)
566 			mgstr->priv->maxsize = atoi (str);
567 
568 		str = gda_quark_list_find (params, "MULTILINE");
569 		if (str) {
570 			if ((*str == 't') || (*str == 'T'))
571 				mgstr->priv->multiline = TRUE;
572 			else
573 				mgstr->priv->multiline = FALSE;
574 
575 		}
576 
577 		str = gda_quark_list_find (params, "HIDDEN");
578 		if (str) {
579 			if ((*str == 't') || (*str == 'T'))
580 				mgstr->priv->hidden = TRUE;
581 			else
582 				mgstr->priv->hidden = FALSE;
583 		}
584 
585 		if (mgstr->priv->entry) {
586 			if (mgstr->priv->multiline) {
587 				gtk_widget_hide (mgstr->priv->entry);
588 				gtk_widget_show (mgstr->priv->sw);
589 			}
590 			else {
591 				gtk_widget_show (mgstr->priv->entry);
592 				gtk_widget_hide (mgstr->priv->sw);
593 				gtk_entry_set_visibility (GTK_ENTRY (mgstr->priv->entry),
594 							  !mgstr->priv->hidden);
595 			}
596 		}
597                 gda_quark_list_free (params);
598 		sync_entry_options (mgstr);
599         }
600 }
601 
602 /* sets the correct options for mgstr->priv->entry if it exists */
603 static void
sync_entry_options(GdauiEntryString * mgstr)604 sync_entry_options (GdauiEntryString *mgstr)
605 {
606 	if (!mgstr->priv->entry)
607 		return;
608 
609 	g_object_set (G_OBJECT (mgstr->priv->entry),
610 		      "max-length", mgstr->priv->maxsize,
611 		      NULL);
612 	g_signal_emit_by_name (mgstr->priv->entry, "changed");
613 }
614