1 /*
2  * $Id: parseOptions.c,v 1.34 2005/01/01 15:27:54 baum Exp $
3  *
4  * This file implements tcl parsing and setting
5  *
6  * Copyright (c) 2001 - 2005 Peter G. Baum  http://www.dr-baum.net
7  *
8  * See the file "license.terms" for information on usage and redistribution
9  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
10  *
11  */
12 
13 /*
14    History:
15    2013-11: renamed doOnButtonClicked to doOnToolButtonClicked
16    2011-11: -onIconPress %t now returns entry text content. Added %b to review mouse button info.
17    2009-12: added %g to those callback with %w substitutions, returns 'glade name'
18         08: added padding big, small, default
19         03: don't use Tcl_GetIndexFromObjStruct any more, since it is
20             broken for cached values in 8.4
21    2003-02: new functions for dndTarget, onDropData and onDragData
22         11: new gnoclOptGeneric: this removes redundancies
23    2002-07-01: Begin of developement
24 */
25 
26 #include "gnocl.h"
27 #include "gnoclparams.h"
28 
29 /* global used to store a pointer to the text/entry popupmenu */
30 GtkMenu *popupMenu;
31 
32 
33 /* add to parseOptions */
34 
35 /**
36 \brief
37 \author
38 \date
39 \note
40 **/
getOptions(Tcl_Interp * interp,GnoclOption * options)41 static int getOptions ( Tcl_Interp *interp, GnoclOption *options )
42 {
43 
44 	GnoclOption *opts = options;
45 
46 	for ( ; opts->optName; ++opts )
47 	{
48 		Tcl_AppendResult ( interp, opts->optName, " ", NULL );
49 	}
50 
51 	return TCL_OK;
52 }
53 
54 /**
55 \brief
56 \author
57 \date
58 \note
59 **/
getCommands(Tcl_Interp * interp,char * cmds[])60 static int getCommands ( Tcl_Interp *interp, char *cmds[] )
61 {
62 	gint i = 0;
63 
64 	while ( cmds[i] != NULL )
65 	{
66 		Tcl_AppendResult ( interp, cmds[i], " ", NULL );
67 		i++;
68 	}
69 
70 	return TCL_OK;
71 }
72 
73 /**
74 \brief	Return a list of commands or options belonging to specific package widget command.
75 \author
76 \date
77 \note
78 **/
gnoclGetCmdsAndOpts(Tcl_Interp * interp,char * cmds[],GnoclOption * options,Tcl_Obj * const objv[],int objc)79 int gnoclGetCmdsAndOpts ( Tcl_Interp *interp, char *cmds[], GnoclOption *options, Tcl_Obj * const objv[], int objc  )
80 {
81 	if ( objc != 2 )
82 	{
83 		return TCL_ERROR;
84 	}
85 
86 	if ( strcmp ( Tcl_GetString ( objv[1] ), "commands" ) == 0 )
87 	{
88 		getCommands ( interp, cmds );
89 		return TCL_OK;
90 	}
91 
92 	if ( strcmp ( Tcl_GetString ( objv[1] ), "options" ) == 0 )
93 	{
94 		getOptions ( interp, options );
95 		return TCL_OK;
96 	}
97 
98 	return TCL_ERROR;
99 }
100 
101 /**
102 \brief	Replaces default label with custom label widget.
103 **/
gnoclOptToolButtonLabelWidget(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)104 int gnoclOptToolButtonLabelWidget ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
105 {
106 	GtkToolButton *button;
107 	GtkWidget *label_widget;
108 	const char *txt;
109 
110 	button = obj;
111 	txt = Tcl_GetString ( opt->val.obj );
112 
113 #ifdef DEBUG_PARSEOPTIONS
114 	g_print ( "%s = %s\n", __FUNCTION__, txt );
115 #endif
116 
117 	label_widget = gnoclGetWidgetFromName ( txt, interp );
118 	//gtk_frame_set_label_widget ( frame, label_widget );
119 
120 	gtk_tool_button_set_label_widget ( button, label_widget );
121 
122 	return TCL_OK;
123 }
124 
125 /**
126 \brief	Replaces default icon custom icon widget.
127 **/
gnoclOptToolButtonIconWidget(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)128 int gnoclOptToolButtonIconWidget ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
129 {
130 	GtkToolButton *button;
131 	GtkWidget *icon_widget;
132 	const char *txt;
133 
134 	button = obj;
135 	txt = Tcl_GetString ( opt->val.obj );
136 
137 #ifdef DEBUG_PARSEOPTIONS
138 	g_print ( "%s = %s\n", __FUNCTION__, txt );
139 #endif
140 
141 	icon_widget = gnoclGetWidgetFromName ( txt, interp );
142 
143 	gtk_tool_button_set_icon_widget ( button, icon_widget );
144 
145 	return TCL_OK;
146 }
147 
148 /**
149 \brief	Replaces default label with custom label widget.
150 **/
gnoclOptFrameLabelWidget(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)151 int gnoclOptFrameLabelWidget ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
152 {
153 	GtkFrame *frame;
154 	GtkWidget *label_widget;
155 	const char *txt;
156 
157 	frame = obj;
158 	txt = Tcl_GetString ( opt->val.obj );
159 
160 #ifdef DEBUG_PARSEOPTIONS
161 	g_print ( "%s = %s\n", __FUNCTION__, txt );
162 #endif
163 
164 	label_widget = gnoclGetWidgetFromName ( txt, interp );
165 	gtk_frame_set_label_widget ( frame, label_widget );
166 
167 	return TCL_OK;
168 }
169 
170 /**
171 \brief      Utility function to determine which events types have occured.
172 **/
_eventType_(int type)173 static int _eventType_ ( int type )
174 {
175 	char *str;
176 
177 	switch ( type )
178 	{
179 		case GDK_NOTHING:
180 			str = "nothing"; break;
181 		case GDK_DELETE:
182 			str = "delete_event"; break;
183 		case GDK_DESTROY:
184 			str = "destroy_event"; break;
185 		case GDK_EXPOSE:
186 			str = "expose_event"; break;
187 		case GDK_MOTION_NOTIFY:
188 			str = "motion_notify_event"; break;
189 		case GDK_BUTTON_PRESS:
190 			str = "button_press_event"; break;
191 		case GDK_2BUTTON_PRESS:
192 			str = "button2press"; break;
193 		case GDK_3BUTTON_PRESS:
194 			str = "button3press"; break;
195 		case GDK_BUTTON_RELEASE:
196 			str = "button_release_event"; break;
197 		case GDK_KEY_PRESS:
198 			str = "key_press_event"; break;
199 		case GDK_KEY_RELEASE:
200 			str = "key_release_event"; break;
201 		case GDK_ENTER_NOTIFY:
202 			str = "enter_notify_event"; break;
203 		case GDK_LEAVE_NOTIFY:
204 			str = "leave_notify_event"; break;
205 		case GDK_FOCUS_CHANGE:
206 			str = "focus_event"; break;
207 		case GDK_CONFIGURE:
208 			str = "configure_event"; break;
209 		case GDK_MAP:
210 			str = "map_event"; break;
211 		case GDK_UNMAP:
212 			str = "unmap_event"; break;
213 		case GDK_PROPERTY_NOTIFY:
214 			str = "property_notify_event"; break;
215 		case GDK_SELECTION_CLEAR:
216 			str = "selection_clear_event"; break;
217 		case GDK_SELECTION_REQUEST:
218 			str = "selection_request_event"; break;
219 		case GDK_SELECTION_NOTIFY:
220 			str = "selection_notify_event"; break;
221 		case GDK_PROXIMITY_IN:
222 			str = "proximity_in_event"; break;
223 		case GDK_PROXIMITY_OUT:
224 			str = "proximity_out_event"; break;
225 		case GDK_DRAG_ENTER:
226 			str = "drag_enter"; break;
227 		case GDK_DRAG_LEAVE:
228 			str = "drag_leave"; break;
229 		case GDK_DRAG_MOTION:
230 			str = "drag_motion"; break;
231 		case GDK_DRAG_STATUS:
232 			str = "drag_status"; break;
233 		case GDK_DROP_START:
234 			str = "drop_start"; break;
235 		case GDK_DROP_FINISHED:
236 			str = "drop-finished"; break;
237 		case GDK_CLIENT_EVENT:
238 			str = "client_event"; break;
239 		case GDK_VISIBILITY_NOTIFY:
240 			str = "visibility_notify_event"; break;
241 		case GDK_NO_EXPOSE:
242 			str = "no_expose_event"; break;
243 		case GDK_SCROLL:
244 			str = "scroll_event"; break;
245 		case GDK_WINDOW_STATE:
246 			str = "window_state_event"; break;
247 		case GDK_SETTING:
248 			str = "setting"; break;
249 		case GDK_OWNER_CHANGE:
250 			str = "owner_change"; break;
251 		case GDK_GRAB_BROKEN:
252 			str = "grab_broken_event"; break;
253 		default:
254 			str = "unknown";  break;
255 	}
256 
257 #ifdef DEBUG_PARSEOPTIONS
258 	g_print ( "Event Type = %s %d\n", str, type );
259 #endif
260 }
261 
262 
263 static GHashTable *sizeGroupTables[3] = { NULL, NULL, NULL };
264 
265 /**
266 \brief	This is a copy from Tcl_GetIndexFromObjStruct, but without cached values, since this is broken in Tcl
267 \note  	This function is copyrighted by the Regents of the University of
268     	California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState
269     	Corporation and other parties.
270 **/
271 /* this is a copy from Tcl_GetIndexFromObjStruct, but without
272    cached values, since this is broken in Tcl
273 
274    This function is copyrighted by the Regents of the University of
275    California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState
276    Corporation and other parties.
277 */
gnoclGetIndexFromObjStruct(Tcl_Interp * interp,Tcl_Obj * objPtr,char ** tablePtr,int offset,char * msg,int flags,int * indexPtr)278 int gnoclGetIndexFromObjStruct ( Tcl_Interp *interp, Tcl_Obj *objPtr, char **tablePtr, int offset, char *msg, int flags, int *indexPtr )
279 #if 0
280 Tcl_Interp *interp;     /* Used for error reporting if not NULL. */
281 Tcl_Obj *objPtr;        /* Object containing the string to lookup. */
282 char **tablePtr;        /* The first string in the table. The second
283                              * string will be at this address plus the
284                              * offset, the third plus the offset again,
285                              * etc. The last entry must be NULL
286                              * and there must not be duplicate entries. */
287 int offset;             /* The number of bytes between entries */
288 char *msg;              /* Identifying word to use in error messages. */
289 int flags;              /* 0 or TCL_EXACT */
290 int *indexPtr;          /* Place to store resulting integer index. */
291 #endif
292 {
293 	int index, length, i, numAbbrev;
294 	char *key, *p1, *p2, **entryPtr;
295 	Tcl_Obj *resultPtr;
296 
297 	/*
298 	 * Lookup the value of the object in the table.  Accept unique
299 	 * abbreviations unless TCL_EXACT is set in flags.
300 	 */
301 
302 	key = Tcl_GetStringFromObj ( objPtr, &length );
303 	index = -1;
304 	numAbbrev = 0;
305 
306 	/*
307 	 * The key should not be empty, otherwise it's not a match.
308 	 */
309 
310 	if ( key[0] == '\0' )
311 	{
312 		goto error;
313 	}
314 
315 	for ( entryPtr = tablePtr, i = 0; *entryPtr != NULL;
316 			entryPtr = ( char ** ) ( ( long ) entryPtr + offset ), i++ )
317 	{
318 		for ( p1 = key, p2 = *entryPtr; *p1 == *p2; p1++, p2++ )
319 		{
320 			if ( *p1 == 0 )
321 			{
322 				index = i;
323 				goto done;
324 			}
325 		}
326 
327 		if ( *p1 == 0 )
328 		{
329 			/*
330 			 * The value is an abbreviation for this entry.  Continue
331 			 * checking other entries to make sure it's unique.  If we
332 			 * get more than one unique abbreviation, keep searching to
333 			 * see if there is an exact match, but remember the number
334 			 * of unique abbreviations and don't allow either.
335 			 */
336 
337 			numAbbrev++;
338 			index = i;
339 		}
340 	}
341 
342 	if ( ( flags & TCL_EXACT ) || ( numAbbrev != 1 ) )
343 	{
344 		goto error;
345 	}
346 
347 done:
348 
349 	*indexPtr = index;
350 
351 	return TCL_OK;
352 
353 error:
354 
355 	if ( interp != NULL )
356 	{
357 		int count;
358 		resultPtr = Tcl_GetObjResult ( interp );
359 		Tcl_AppendStringsToObj ( resultPtr,
360 								 ( numAbbrev > 1 ) ? "ambiguous " : "bad ", msg, " \"",
361 								 key, "\": must be ", *tablePtr, ( char * ) NULL );
362 
363 		for ( entryPtr = ( char ** ) ( ( long ) tablePtr + offset ), count = 0; *entryPtr != NULL;
364 				entryPtr = ( char ** ) ( ( long ) entryPtr + offset ), count++ )
365 		{
366 			if ( ( * ( ( char ** ) ( ( long ) entryPtr + offset ) ) ) == NULL )
367 			{
368 				Tcl_AppendStringsToObj ( resultPtr,
369 										 ( count > 0 ) ? ", or " : " or ", *entryPtr,
370 										 ( char * ) NULL );
371 			}
372 
373 			else
374 			{
375 				Tcl_AppendStringsToObj ( resultPtr, ", ", *entryPtr, ( char * ) NULL );
376 			}
377 		}
378 	}
379 
380 	return TCL_ERROR;
381 }
382 
383 
384 
385 /**
386 \brief	Sets widget properties.
387 **/
gnoclOptGeneric(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,const char * optName,const char * txt[],const int types[],Tcl_Obj ** ret)388 int gnoclOptGeneric ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, const char *optName, const char *txt[], const int types[], Tcl_Obj **ret )
389 {
390 	if ( ret == NULL ) /* set value */
391 	{
392 		int idx;
393 
394 		if ( Tcl_GetIndexFromObj ( interp, opt->val.obj, txt, optName, TCL_EXACT, &idx ) != TCL_OK )
395 		{
396 			return TCL_ERROR;
397 		}
398 
399 		g_object_set ( obj, opt->propName, types[idx], NULL );
400 	}
401 
402 	else /* get value */
403 	{
404 		gint val;
405 		int  k;
406 		g_object_get ( obj, opt->propName, &val, NULL );
407 
408 		for ( k = 0; txt[k]; ++k )
409 		{
410 			if ( types[k] == val )
411 			{
412 				*ret = Tcl_NewStringObj ( txt[k], -1 );
413 				return TCL_OK;
414 			}
415 		}
416 
417 		Tcl_SetResult ( interp, "Unknown setting for parameter", TCL_STATIC );
418 
419 		return TCL_ERROR;
420 	}
421 
422 	return TCL_OK;
423 }
424 
425 
426 /**
427 \brief
428 **/
gnoclOptAnchor(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)429 int gnoclOptAnchor ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
430 {
431 
432 	const char *txt[] = { "center",
433 						  "N", "NW", "NE",
434 						  "S", "SW", "SE",
435 						  "W", "E", NULL
436 						};
437 	const int types[] = { GTK_ANCHOR_CENTER,
438 						  GTK_ANCHOR_NORTH, GTK_ANCHOR_NORTH_WEST, GTK_ANCHOR_NORTH_EAST,
439 						  GTK_ANCHOR_SOUTH, GTK_ANCHOR_SOUTH_WEST, GTK_ANCHOR_SOUTH_EAST,
440 						  GTK_ANCHOR_WEST, GTK_ANCHOR_EAST
441 						};
442 
443 	assert ( sizeof ( GTK_SHADOW_NONE ) == sizeof ( int ) );
444 
445 	return gnoclOptGeneric ( interp, opt, obj, "anchor", txt, types, ret );
446 }
447 
448 /**
449 \brief  Set current folder for file/folder chooser dialogs buttons
450 **/
gnoclOptCurrentFolder(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)451 int gnoclOptCurrentFolder ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
452 {
453 
454 	gtk_file_chooser_set_current_folder ( GTK_FILE_CHOOSER ( obj ), Tcl_GetString ( opt->val.obj ) );
455 
456 	return TCL_OK;
457 }
458 
459 /**
460 \brief  Checks the shadow type requested against the list of supported types.
461 **/
gnoclOptShadow(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)462 int gnoclOptShadow ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
463 {
464 
465 	const char *txt[] = { "none", "in", "out", "etchedIn", "etchedOut", NULL };
466 	const int types[] = { GTK_SHADOW_NONE, GTK_SHADOW_IN, GTK_SHADOW_OUT, GTK_SHADOW_ETCHED_IN, GTK_SHADOW_OUT };
467 
468 	assert ( sizeof ( GTK_SHADOW_NONE ) == sizeof ( int ) );
469 
470 	return gnoclOptGeneric ( interp, opt, obj, "shadow-type", txt, types, ret );
471 }
472 
473 /**
474 \brief  This is simply returning, so the arrows are being set elsewhere!
475 **/
gnoclOptAngle(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)476 int gnoclOptAngle (	Tcl_Interp *interp,	GnoclOption *opt,	GObject *obj,	Tcl_Obj **ret )
477 {
478 
479 	return 0;
480 
481 	const char *txt[] = { "up", "down", "left", "right", "none", NULL };
482 	const int types[] = { GTK_ARROW_UP, GTK_ARROW_DOWN, GTK_ARROW_LEFT, GTK_ARROW_RIGHT, GTK_ARROW_NONE};
483 
484 	assert ( sizeof ( GTK_ARROW_RIGHT ) == sizeof ( int ) );
485 
486 	return gnoclOptGeneric ( interp, opt, obj, "arrow", txt, types, ret );
487 }
488 
489 
490 /**
491 \brief  Set the default widget for a toplevel window.
492 **/
gnoclOptDefaultWidget(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)493 int gnoclOptDefaultWidget ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
494 {
495 
496 	GtkWidget *widget = gnoclGetWidgetFromName ( Tcl_GetString ( opt->val.obj ), interp );
497 
498 	gtk_window_set_default ( obj, widget );
499 
500 	return TCL_OK;
501 }
502 
503 /**
504 \brief      This is simply returning, so the arrows are being set elsewhere!
505 **/
gnoclOptArrow(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)506 int gnoclOptArrow ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
507 {
508 
509 	return 0;
510 
511 	const char *txt[] = { "up", "down", "left", "right", "none", NULL };
512 	const int types[] = { GTK_ARROW_UP, GTK_ARROW_DOWN, GTK_ARROW_LEFT, GTK_ARROW_RIGHT, GTK_ARROW_NONE};
513 
514 	assert ( sizeof ( GTK_ARROW_RIGHT ) == sizeof ( int ) );
515 
516 	return gnoclOptGeneric ( interp, opt, obj, "arrow", txt, types, ret );
517 }
518 
519 
520 /**
521 \brief	Set relief for  button widgets etc.
522 **/
gnoclOptRelief(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)523 int gnoclOptRelief ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
524 {
525 	const char *txt[] = { "normal", "half", "none", NULL };
526 	const int types[] = { GTK_RELIEF_NORMAL, GTK_RELIEF_HALF, GTK_RELIEF_NONE };
527 
528 	assert ( sizeof ( GTK_RELIEF_NORMAL ) == sizeof ( int ) );
529 
530 	return gnoclOptGeneric ( interp, opt, obj, "relief", txt, types, ret );
531 }
532 
533 /**
534 \brief	Set relief for toolbar buttons.
535 **/
536 
gnoclOptButtonRelief(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)537 int gnoclOptButtonRelief ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
538 {
539 	const char *txt[] = { "normal", "half", "none", NULL };
540 	const int types[] = { GTK_RELIEF_NORMAL, GTK_RELIEF_HALF, GTK_RELIEF_NONE };
541 
542 
543 	static const gchar *rc_string =
544 	{
545 		"style \"normal\"\n"
546 		"{\n"
547 		"   GtkToolbar::button-relief = GTK_RELIEF_NORMAL \n"
548 		"}\n"
549 		"\n"
550 		"class \"GtkToolbar\" style \"normal\"\n"
551 	};
552 
553 	gtk_rc_parse_string ( rc_string );
554 
555 	return TCL_OK;
556 
557 }
558 
559 /**
560 \brief
561 **/
gnoclOptPangoStretch(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)562 int gnoclOptPangoStretch ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
563 {
564 	const char *txt[] = { "ultraCondensed", "extraCondensed", "condensed",
565 						  "semiCondensed", "normal", "semiExpanded", "expanded",
566 						  "extraExpanded", "ultraExpanded", NULL
567 						};
568 	const int types[] = { PANGO_STRETCH_ULTRA_CONDENSED,
569 						  PANGO_STRETCH_EXTRA_CONDENSED, PANGO_STRETCH_CONDENSED,
570 						  PANGO_STRETCH_SEMI_CONDENSED, PANGO_STRETCH_NORMAL,
571 						  PANGO_STRETCH_SEMI_EXPANDED, PANGO_STRETCH_EXPANDED,
572 						  PANGO_STRETCH_EXTRA_EXPANDED, PANGO_STRETCH_ULTRA_EXPANDED
573 						};
574 
575 	assert ( sizeof ( PANGO_STRETCH_ULTRA_CONDENSED ) == sizeof ( int ) );
576 
577 	return gnoclOptGeneric ( interp, opt, obj, "stretch", txt, types, ret );
578 }
579 
580 
581 /**
582 \brief
583 **/
gnoclOptPangoWeight(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)584 int gnoclOptPangoWeight ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
585 {
586 	const char *txt[] = { "ultralight", "light", "normal", "bold", "ultrabold",
587 						  "heavy", NULL
588 						};
589 	const int types[] = { PANGO_WEIGHT_ULTRALIGHT,
590 						  PANGO_WEIGHT_LIGHT, PANGO_WEIGHT_NORMAL, PANGO_WEIGHT_BOLD,
591 						  PANGO_WEIGHT_ULTRABOLD, PANGO_WEIGHT_HEAVY
592 						};
593 
594 	assert ( sizeof ( PANGO_WEIGHT_ULTRALIGHT ) == sizeof ( int ) );
595 
596 	return gnoclOptGeneric ( interp, opt, obj, "weight", txt, types, ret );
597 }
598 
599 
600 /**
601 \brief
602 **/
gnoclOptPangoVariant(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)603 int gnoclOptPangoVariant ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
604 {
605 	const char *txt[] = { "normal", "smallCaps", NULL };
606 	const int types[] = { PANGO_VARIANT_NORMAL, PANGO_VARIANT_SMALL_CAPS };
607 
608 	assert ( sizeof ( PANGO_VARIANT_SMALL_CAPS ) == sizeof ( int ) );
609 
610 	return gnoclOptGeneric ( interp, opt, obj, "variant", txt, types, ret );
611 }
612 
613 
614 /**
615 \brief
616 **/
gnoclOptPangoStyle(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)617 int gnoclOptPangoStyle ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
618 {
619 	const char *txt[] = { "normal", "oblique", "italic", NULL };
620 	const int types[] = { PANGO_STYLE_NORMAL, PANGO_STYLE_OBLIQUE, PANGO_STYLE_ITALIC };
621 
622 	assert ( sizeof ( PANGO_STYLE_NORMAL ) == sizeof ( int ) );
623 
624 	return gnoclOptGeneric ( interp, opt, obj, "style", txt, types, ret );
625 }
626 
627 
628 /**
629 \brief	Set wrapmode options for rendering treelist text cells
630 **/
gnoclOptPangoWrapMode(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)631 int gnoclOptPangoWrapMode ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
632 {
633 
634 	const char *mode[] = { "word", "char", "wordChar", NULL };
635 	const int types[] = {  PANGO_WRAP_WORD, PANGO_WRAP_CHAR, PANGO_WRAP_WORD_CHAR};
636 
637 	assert ( sizeof ( PANGO_WRAP_WORD ) == sizeof ( int ) );
638 
639 	return gnoclOptGeneric ( interp, opt, obj, "wrap-mode", mode, types, ret );
640 
641 }
642 
643 /**
644 \brief
645 \author     Peter G Baum
646 \date
647 \since
648 **/
gnoclOptPangoScaledInt(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)649 int gnoclOptPangoScaledInt ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
650 {
651 	int i;
652 
653 	if ( Tcl_GetIntFromObj ( interp, opt->val.obj, &i ) != TCL_OK )
654 	{
655 		return TCL_ERROR;
656 	}
657 
658 	g_object_set ( obj, opt->propName, i * PANGO_SCALE, NULL );
659 
660 	return TCL_OK;
661 }
662 
663 /*
664 typedef enum {
665   PANGO_ELLIPSIZE_NONE,
666   PANGO_ELLIPSIZE_START,
667   PANGO_ELLIPSIZE_MIDDLE,
668   PANGO_ELLIPSIZE_END
669 } PangoEllipsizeMode;
670 */
671 /**
672 \brief      Set ellipsize property for label widgets
673 \author     William J Giddings
674 \date       14/Jan/2010
675 **/
gnoclOptEllipsize(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)676 int gnoclOptEllipsize ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
677 {
678 	const char *txt[] = { "none", "start", "middle", "end", NULL };
679 	const int types[] = { PANGO_ELLIPSIZE_NONE, PANGO_ELLIPSIZE_START, PANGO_ELLIPSIZE_MIDDLE, PANGO_ELLIPSIZE_END };
680 
681 	assert ( sizeof ( PANGO_ELLIPSIZE_END ) == sizeof ( int ) );
682 
683 	return gnoclOptGeneric ( interp, opt, obj, "ellipsize", txt, types,  ret );
684 }
685 
686 /**
687 \brief
688 \author     Peter G Baum
689 \date
690 \since
691 **/
gnoclOptJustification(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)692 int gnoclOptJustification ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
693 {
694 	const char *txt[] = { "left", "right", "center", "fill", NULL };
695 	const int types[] = { GTK_JUSTIFY_LEFT, GTK_JUSTIFY_RIGHT, GTK_JUSTIFY_CENTER, GTK_JUSTIFY_FILL };
696 
697 	assert ( sizeof ( GTK_JUSTIFY_FILL ) == sizeof ( int ) );
698 
699 	return gnoclOptGeneric ( interp, opt, obj, "justification", txt, types,  ret );
700 }
701 
702 /**
703 \brief
704 \author     Peter G Baum
705 \date
706 \since
707 **/
gnoclOptScale(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)708 int gnoclOptScale ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
709 {
710 	double d;
711 
712 	if ( Tcl_GetDoubleFromObj ( NULL, opt->val.obj, &d ) != TCL_OK )
713 	{
714 		const char *txt[] = { "xx-small", "x-small", "small", "medium",
715 							  "large", "x-large", "xx-large", NULL
716 							};
717 		const double types[] = { PANGO_SCALE_XX_SMALL, PANGO_SCALE_X_SMALL,
718 								 PANGO_SCALE_SMALL, PANGO_SCALE_MEDIUM, PANGO_SCALE_LARGE,
719 								 PANGO_SCALE_X_LARGE, PANGO_SCALE_XX_LARGE
720 							   };
721 
722 		int idx;
723 
724 		if ( Tcl_GetIndexFromObj ( NULL, opt->val.obj, txt, NULL,
725 								   TCL_EXACT, &idx ) != TCL_OK )
726 		{
727 			Tcl_AppendResult ( interp, "Unknown scale \"",
728 							   Tcl_GetString ( opt->val.obj ),
729 							   "\", must be a floating point value or one of xx-small, "
730 							   "x-small, small, medium, large, x-large, or xx-large.", NULL );
731 			return TCL_ERROR;
732 		}
733 
734 		d = types[idx];
735 	}
736 
737 	g_object_set ( obj, opt->propName, d, NULL );
738 
739 	return TCL_OK;
740 }
741 
742 /**
743 \brief
744 \author     Peter G Baum
745 \date
746 \since
747 **/
gnoclGetPadding(Tcl_Interp * interp,Tcl_Obj * obj,int * pad)748 int gnoclGetPadding ( Tcl_Interp *interp, Tcl_Obj *obj, int *pad )
749 {
750 	if ( Tcl_GetIntFromObj ( NULL, obj, pad ) != TCL_OK )
751 	{
752 		const char *txt[] = { "small", "normal", "big", NULL };
753 		const int vals[] = { GNOCL_PAD_SMALL, GNOCL_PAD, GNOCL_PAD_BIG };
754 
755 		int idx;
756 
757 		if ( Tcl_GetIndexFromObj ( NULL, obj, txt, NULL,
758 								   TCL_EXACT, &idx ) != TCL_OK )
759 		{
760 			Tcl_AppendResult ( interp, "Unknown padding \"",
761 							   Tcl_GetString ( obj ),
762 							   "\", must be an integer or one small, normal or big", NULL );
763 			return TCL_ERROR;
764 		}
765 
766 		*pad = vals[idx];
767 	}
768 
769 	return TCL_OK;
770 }
771 
772 /**
773 \brief
774 \author     Peter G Baum
775 \date
776 \since
777 **/
gnoclOptPadding(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)778 int gnoclOptPadding ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
779 {
780 	int pad;
781 
782 	if ( ret == NULL ) /* set value */
783 	{
784 		if ( gnoclGetPadding ( interp, opt->val.obj, &pad ) != TCL_OK )
785 		{
786 			return TCL_ERROR;
787 		}
788 
789 		g_object_set ( obj, opt->propName, pad, NULL );
790 	}
791 
792 	else /* get value */
793 	{
794 		g_object_get ( obj, opt->propName, &pad, NULL );
795 		*ret = Tcl_NewIntObj ( pad );
796 	}
797 
798 	return TCL_OK;
799 }
800 
801 /**
802 \brief	Set orientation of widget based upon new API
803 \notes  Called by toolbar and ??
804 **/
gnoclOptOrientation(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)805 int gnoclOptOrientation ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
806 {
807 
808 	if ( ret == NULL ) /* set value */
809 	{
810 
811 		if ( strcmp ( Tcl_GetString ( opt->val.obj ), "horizontal" ) == 0 )
812 		{
813 
814 			gtk_orientable_set_orientation ( GTK_ORIENTABLE ( obj ), GTK_ORIENTATION_HORIZONTAL );
815 
816 		}
817 
818 		else if ( strcmp ( Tcl_GetString ( opt->val.obj ), "vertical" ) == 0 )
819 		{
820 
821 			gtk_orientable_set_orientation ( GTK_ORIENTABLE ( obj ), GTK_ORIENTATION_VERTICAL );
822 		}
823 
824 		else
825 		{
826 			return TCL_ERROR;
827 		}
828 
829 	}
830 
831 	return TCL_OK;
832 }
833 
834 /**
835 \brief
836 \author     Peter G Baum
837 \date
838 \since
839 **/
gnoclOptUnderline(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)840 int gnoclOptUnderline ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
841 {
842 	const char *txt[] = { "none", "single", "double", "low", "error", NULL };
843 	const int types[] = { PANGO_UNDERLINE_NONE, PANGO_UNDERLINE_SINGLE,
844 						  PANGO_UNDERLINE_DOUBLE, PANGO_UNDERLINE_LOW, PANGO_UNDERLINE_ERROR
845 						};
846 
847 	assert ( sizeof ( PANGO_UNDERLINE_LOW ) == sizeof ( int ) );
848 
849 	return gnoclOptGeneric ( interp, opt, obj, "underline", txt, types, ret );
850 }
851 
852 /**
853 \brief
854 \author     Peter G Baum
855 \date
856 \since
857 **/
gnoclOptWrapmode(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)858 int gnoclOptWrapmode ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
859 {
860 	const char *txt[] = { "none", "char", "word", NULL };
861 	const int types[] = { GTK_WRAP_NONE, GTK_WRAP_CHAR, GTK_WRAP_WORD };
862 
863 	assert ( sizeof ( PANGO_VARIANT_SMALL_CAPS ) == sizeof ( int ) );
864 
865 	return gnoclOptGeneric ( interp, opt, obj, "wrap mode", txt, types, ret );
866 }
867 
868 /**
869 \brief
870 \author     Peter G Baum
871 \date
872 \since
873 **/
gnoclOptPosition(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)874 int gnoclOptPosition ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
875 {
876 	const char *txt[] = { "left", "right", "top", "bottom", NULL };
877 	const int types[] = { GTK_POS_LEFT, GTK_POS_RIGHT, GTK_POS_TOP, GTK_POS_BOTTOM };
878 
879 	assert ( sizeof ( PANGO_VARIANT_SMALL_CAPS ) == sizeof ( int ) );
880 
881 	return gnoclOptGeneric ( interp, opt, obj, "position", txt, types, ret );
882 }
883 
884 
885 
886 /**
887 \bug
888     With window this produces:
889     (gnocl:2370): Gtk-CRITICAL **: file gtkwidget.c: line 4891
890     (gtk_widget_get_parent_window): assertion `widget->parent != NULL' failed
891 
892     (gnocl:2370): Gdk-CRITICAL **: file gdkwindow-x11.c: line 2363
893     (gdk_window_set_cursor): assertion `window != NULL' failed
894 
895     with eventBox the cursor is set for the whole window, not only for the
896     eventBox.
897 */
898 #if 1
899 
900 /* FIXME:
901 
902 with window this produces:
903    (gnocl:2370): Gtk-CRITICAL **: file gtkwidget.c: line 4891
904    (gtk_widget_get_parent_window): assertion `widget->parent != NULL' failed
905 
906    (gnocl:2370): Gdk-CRITICAL **: file gdkwindow-x11.c: line 2363
907    (gdk_window_set_cursor): assertion `window != NULL' failed
908 
909 with eventBox the cursor is set for the whole window, not only for the
910 eventBox.
911 */
912 
gnoclOptCursor(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)913 int gnoclOptCursor ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
914 {
915 #ifdef DEBUG_PARSEOPTIONS
916 	g_print ( "gnoclOptCursor\n" );
917 #endif
918 
919 	typedef struct
920 	{
921 		const char *name;
922 		GdkCursorType id;
923 	} CursorNameToId;
924 
925 	const CursorNameToId cursors[] =
926 	{
927 		{ "xCursor", GDK_X_CURSOR },
928 		{ "arrow", GDK_ARROW },
929 		{ "basedArrowDown", GDK_BASED_ARROW_DOWN },
930 		{ "basedArrowUp", GDK_BASED_ARROW_UP },
931 		{ "boat", GDK_BOAT },
932 		{ "bogosity", GDK_BOGOSITY },
933 		{ "bottomLeftCorner", GDK_BOTTOM_LEFT_CORNER },
934 		{ "bottomRightCorner", GDK_BOTTOM_RIGHT_CORNER },
935 		{ "bottomSide", GDK_BOTTOM_SIDE },
936 		{ "bottomTee", GDK_BOTTOM_TEE },
937 		{ "boxSpiral", GDK_BOX_SPIRAL },
938 		{ "centerPtr", GDK_CENTER_PTR },
939 		{ "circle", GDK_CIRCLE },
940 		{ "clock", GDK_CLOCK },
941 		{ "coffeeMug", GDK_COFFEE_MUG },
942 		{ "cross", GDK_CROSS },
943 		{ "crossReverse", GDK_CROSS_REVERSE },
944 		{ "crosshair", GDK_CROSSHAIR },
945 		{ "diamondCross", GDK_DIAMOND_CROSS },
946 		{ "dot", GDK_DOT },
947 		{ "dotbox", GDK_DOTBOX },
948 		{ "doubleArrow", GDK_DOUBLE_ARROW },
949 		{ "draftLarge", GDK_DRAFT_LARGE },
950 		{ "draftSmall", GDK_DRAFT_SMALL },
951 		{ "drapedBox", GDK_DRAPED_BOX },
952 		{ "exchange", GDK_EXCHANGE },
953 		{ "fleur", GDK_FLEUR },
954 		{ "gobbler", GDK_GOBBLER },
955 		{ "gumby", GDK_GUMBY },
956 		{ "hand1", GDK_HAND1 },
957 		{ "hand2", GDK_HAND2 },
958 		{ "heart", GDK_HEART },
959 		{ "icon", GDK_ICON },
960 		{ "ironCross", GDK_IRON_CROSS },
961 		{ "leftPtr", GDK_LEFT_PTR },
962 		{ "leftSide", GDK_LEFT_SIDE },
963 		{ "leftTee", GDK_LEFT_TEE },
964 		{ "leftbutton", GDK_LEFTBUTTON },
965 		{ "llAngle", GDK_LL_ANGLE },
966 		{ "lrAngle", GDK_LR_ANGLE },
967 		{ "man", GDK_MAN },
968 		{ "middlebutton", GDK_MIDDLEBUTTON },
969 		{ "mouse", GDK_MOUSE },
970 		{ "pencil", GDK_PENCIL },
971 		{ "pirate", GDK_PIRATE },
972 		{ "plus", GDK_PLUS },
973 		{ "questionArrow", GDK_QUESTION_ARROW },
974 		{ "rightPtr", GDK_RIGHT_PTR },
975 		{ "rightSide", GDK_RIGHT_SIDE },
976 		{ "rightTee", GDK_RIGHT_TEE },
977 		{ "rightbutton", GDK_RIGHTBUTTON },
978 		{ "rtlLogo", GDK_RTL_LOGO },
979 		{ "sailboat", GDK_SAILBOAT },
980 		{ "sbDownArrow", GDK_SB_DOWN_ARROW },
981 		{ "sbHDoubleArrow", GDK_SB_H_DOUBLE_ARROW },
982 		{ "sbLeftArrow", GDK_SB_LEFT_ARROW },
983 		{ "sbRightArrow", GDK_SB_RIGHT_ARROW },
984 		{ "sbUpArrow", GDK_SB_UP_ARROW },
985 		{ "sbVDoubleArrow", GDK_SB_V_DOUBLE_ARROW },
986 		{ "shuttle", GDK_SHUTTLE },
987 		{ "sizing", GDK_SIZING },
988 		{ "spider", GDK_SPIDER },
989 		{ "spraycan", GDK_SPRAYCAN },
990 		{ "star", GDK_STAR },
991 		{ "target", GDK_TARGET },
992 		{ "tcross", GDK_TCROSS },
993 		{ "topLeftArrow", GDK_TOP_LEFT_ARROW },
994 		{ "topLeftCorner", GDK_TOP_LEFT_CORNER },
995 		{ "topRightCorner", GDK_TOP_RIGHT_CORNER },
996 		{ "topSide", GDK_TOP_SIDE },
997 		{ "topTee", GDK_TOP_TEE },
998 		{ "trek", GDK_TREK },
999 		{ "ulAngle", GDK_UL_ANGLE },
1000 		{ "umbrella", GDK_UMBRELLA },
1001 		{ "urAngle", GDK_UR_ANGLE },
1002 		{ "watch", GDK_WATCH },
1003 		{ "xterm", GDK_XTERM },
1004 		{ "last", GDK_LAST_CURSOR},
1005 		{ "blank", GDK_BLANK_CURSOR},
1006 
1007 		/* type of cursors constructed with gdk_cursor_new_from_pixmap() or gdk_cursor_new_from_pixbuf() */
1008 		{ "pixmap", GDK_CURSOR_IS_PIXMAP}
1009 	};
1010 
1011 	int idx;
1012 
1013 
1014 	if ( gnoclGetIndexFromObjStruct ( interp, opt->val.obj, ( char ** ) &cursors[0].name, sizeof ( CursorNameToId ), "cursor", TCL_EXACT, &idx ) != TCL_OK )
1015 	{
1016 		return TCL_ERROR;
1017 	}
1018 
1019 	if ( 1 )
1020 	{
1021 		/* this fails for some reason */
1022 		//gdk_window_set_cursor ( gtk_widget_get_parent_window ( GTK_WIDGET ( obj ) ), gdk_cursor_new ( cursors[idx].id ) );
1023 		gdk_window_set_cursor ( GTK_WIDGET ( obj )->window , gdk_cursor_new ( cursors[idx].id ) );
1024 	}
1025 
1026 	return TCL_OK;
1027 }
1028 
1029 #endif
1030 
1031 
1032 /**
1033  */
keyvalToString(guint keyval)1034 static const char *keyvalToString ( guint keyval )
1035 {
1036 
1037 	static GHashTable *keysyms = NULL;
1038 
1039 	if ( keysyms == NULL )
1040 	{
1041 
1042 		const struct
1043 		{
1044 			const char *name; guint key;
1045 		} syms[] =
1046 
1047 		{
1048 #include "keysyms.h"
1049 		};
1050 		unsigned int k;
1051 		keysyms = g_hash_table_new ( g_direct_hash, g_direct_equal );
1052 
1053 		for ( k = 0; k < sizeof ( syms ) / sizeof ( *syms ); ++k )
1054 			g_hash_table_insert ( keysyms, GUINT_TO_POINTER ( syms[k].key ),
1055 								  ( gpointer ) syms[k].name );
1056 	}
1057 
1058 	return g_hash_table_lookup ( keysyms, GUINT_TO_POINTER ( keyval ) );
1059 }
1060 
1061 
1062 
1063 /**
1064 \brief
1065 \author     Peter G Baum
1066 \date
1067 **/
getShortValue(Tcl_Interp * interp,Tcl_Obj * list,int idx,int * p)1068 static int getShortValue ( Tcl_Interp *interp,	Tcl_Obj *list,	int idx, int *p )
1069 {
1070 	int val;
1071 	Tcl_Obj *tp;
1072 
1073 	if ( Tcl_ListObjIndex ( interp, list, idx, &tp ) != TCL_OK  )
1074 	{
1075 		return TCL_ERROR;
1076 	}
1077 
1078 	if ( Tcl_GetIntFromObj ( NULL, tp, &val ) != TCL_OK )
1079 	{
1080 		double d;
1081 
1082 		if ( Tcl_GetDoubleFromObj ( NULL, tp, &d ) != TCL_OK )
1083 		{
1084 			Tcl_AppendResult ( interp,
1085 							   "expected integer or double, but got \"",
1086 							   Tcl_GetString ( tp ), "\"", NULL );
1087 			return TCL_ERROR;
1088 		}
1089 
1090 		val = d * 0xFFFF;
1091 	}
1092 
1093 	if ( val < .0 || val > 0xFFFF )
1094 	{
1095 		Tcl_SetResult ( interp, "color value must be between 0 and 65535", TCL_STATIC );
1096 		return TCL_ERROR;
1097 	}
1098 
1099 	*p = val;
1100 
1101 	return TCL_OK;
1102 }
1103 
1104 
1105 
1106 /**
1107 \brief
1108 \author
1109 \date
1110 **/
getRGBA(Tcl_Interp * interp,Tcl_Obj * obj,int * r,int * g,int * b,int * a)1111 static int getRGBA ( Tcl_Interp *interp, Tcl_Obj *obj, int *r, int *g, int *b, int *a )
1112 {
1113 	int no;
1114 
1115 	if ( Tcl_ListObjLength ( interp, obj, &no ) != TCL_OK  || no < 0 || no > 4 )
1116 	{
1117 		Tcl_SetResult ( interp, "color must be either \"name\" or a list "
1118 						"consisting of \"name alpha\", \"r g b\", or \"r g b alpha\"",
1119 						TCL_STATIC );
1120 		{
1121 			return TCL_ERROR;
1122 		}
1123 	}
1124 
1125 	if ( no == 0 ) /* transparent */
1126 	{
1127 		*r = *g = *b = *a = 0;
1128 	}
1129 
1130 	else if ( no < 3 )
1131 	{
1132 		Tcl_Obj *tp = obj;
1133 		GdkColor color;
1134 
1135 		if ( no == 2 )
1136 		{
1137 			if ( Tcl_ListObjIndex ( interp, obj, 0, &tp ) != TCL_OK )
1138 				return TCL_ERROR;
1139 		}
1140 
1141 		/* take as string and reformat as a GdkColor structure */
1142 
1143 		if ( gdk_color_parse ( Tcl_GetString ( tp ), &color ) == 0 )
1144 		{
1145 			Tcl_AppendResult ( interp, "unknown color \"", Tcl_GetString ( obj ), "\".", ( char * ) NULL );
1146 			return TCL_ERROR;
1147 		}
1148 
1149 		*r = color.red;
1150 		*g = color.green;
1151 		*b = color.blue;
1152 
1153 		if ( no == 2 )
1154 		{
1155 			if ( getShortValue ( interp, obj, 1, a ) != TCL_OK )
1156 				return TCL_ERROR;
1157 		}
1158 
1159 		else
1160 			*a = 0xFFFF;
1161 	}
1162 
1163 	else
1164 	{
1165 		if ( getShortValue ( interp, obj, 0, r ) != TCL_OK
1166 				|| getShortValue ( interp, obj, 1, g ) != TCL_OK
1167 				|| getShortValue ( interp, obj, 2, b ) != TCL_OK )
1168 			return TCL_ERROR;
1169 
1170 		if ( no == 4 )
1171 		{
1172 			if ( getShortValue ( interp, obj, 3, a ) != TCL_OK )
1173 				return TCL_ERROR;
1174 		}
1175 
1176 		else
1177 			*a = 0xFFFF;
1178 	}
1179 
1180 	return TCL_OK;
1181 }
1182 
1183 /**
1184 \brief Take colour values from a string format and assign them to location
1185         addressed by pointer *color.
1186 \author
1187 \date
1188 **/
getGdkColor(Tcl_Interp * interp,Tcl_Obj * obj,GdkColor * color)1189 int getGdkColor ( Tcl_Interp *interp, Tcl_Obj *obj, GdkColor *color )
1190 {
1191 	int r, g, b, a;
1192 
1193 	if ( getRGBA ( interp, obj, &r, &g, &b, &a ) != TCL_OK )
1194 	{
1195 		return TCL_ERROR;
1196 	}
1197 
1198 	/* TODO? if a != 0xFFFF: alpha not supported? */
1199 	color->red = r;
1200 
1201 	color->green = g;
1202 
1203 	color->blue = b;
1204 
1205 	return TCL_OK;
1206 }
1207 
1208 /**
1209 \brief  Set the colour attribute of an object. Prior to setting, the format
1210         of the colour parameter if checked by the function getGdkColor.
1211 \author
1212 \date
1213 **/
gnoclOptGdkColor(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)1214 int gnoclOptGdkColor ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
1215 {
1216 	GdkColor color;
1217 
1218 	if ( getGdkColor ( interp, opt->val.obj, &color ) == TCL_OK )
1219 	{
1220 		g_object_set ( obj, opt->propName, &color, NULL );
1221 		return TCL_OK;
1222 	}
1223 
1224 	return TCL_ERROR;
1225 }
1226 
1227 /**
1228  */
gnoclOptRGBAColor(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)1229 int gnoclOptRGBAColor ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
1230 {
1231 	int r, g, b, a;
1232 
1233 	if ( getRGBA ( interp, opt->val.obj, &r, &g, &b, &a ) == TCL_OK )
1234 	{
1235 		guint col = ( guint ) ( ( ( r & 0xFF00 ) << 16 ) |
1236 								( ( g & 0xFF00 ) << 8 ) | ( b & 0xFF00 ) | ( a >> 8 ) );
1237 		g_object_set ( obj, opt->propName, col, NULL );
1238 		return TCL_OK;
1239 	}
1240 
1241 	return TCL_ERROR;
1242 }
1243 
1244 /**
1245 \brief
1246 **/
gnoclOptArrowTooltip(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)1247 int gnoclOptArrowTooltip ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
1248 {
1249 
1250 	const char *text = Tcl_GetString ( opt->val.obj );
1251 
1252 	gtk_menu_tool_button_set_arrow_tooltip_text ( GTK_WIDGET ( obj ), text );
1253 
1254 	return TCL_OK;
1255 }
1256 
1257 
1258 /**
1259 \brief
1260 **/
gnoclOptIconTooltip(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)1261 int gnoclOptIconTooltip ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
1262 {
1263 #ifdef DEBUG_PARSEOPTIONS
1264 	g_print ( "%s %s %s\n", __FUNCTION__, opt->propName, Tcl_GetString ( opt->val.obj ) );
1265 #endif
1266 
1267 	assert ( *opt->propName == 'P' || *opt->propName == 'S' );
1268 
1269 	const char *txt = Tcl_GetString ( opt->val.obj );
1270 
1271 	if ( *opt->propName == 'P' )
1272 	{
1273 		gtk_entry_set_icon_tooltip_markup   ( GTK_ENTRY ( obj ), GTK_ENTRY_ICON_PRIMARY, txt );
1274 		return  TCL_OK;
1275 	}
1276 
1277 	if ( *opt->propName == 'S' )
1278 	{
1279 		gtk_entry_set_icon_tooltip_text   ( GTK_ENTRY ( obj ), GTK_ENTRY_ICON_SECONDARY, txt );
1280 		return  TCL_OK;
1281 	}
1282 
1283 
1284 	return TCL_ERROR;
1285 
1286 }
1287 
1288 
1289 /**
1290 /brief      Set tooltip for specified widget.
1291 /author     Peter G Baum
1292 /note       http://developer.gnome.org/gtk/stable/GtkTooltip.html
1293 /todo		parse markup string for various options
1294 */
gnoclOptTooltip(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)1295 int gnoclOptTooltip ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
1296 {
1297 	assert ( opt->propName == NULL || *opt->propName  == '\0' );
1298 	assert ( strcmp ( opt->optName, "-tooltip" ) == 0 );
1299 
1300 	if ( ret == NULL ) /* set value */
1301 	{
1302 		const char *txt = Tcl_GetString ( opt->val.obj );
1303 		GtkTooltips *tt = gnoclGetTooltips();
1304 
1305 		/* #ifdef GNOCL_USE_GNOME
1306 		   if( GTK_CHECK_TYPE( widget, GTK_TYPE_ITEM ) )
1307 		   {
1308 		      g_signal_connect ( obj, "select",
1309 		            G_CALLBACK( putHintInAppBar ),
1310 		            g_memdup( txt, strlen( txt ) + 1 ) );
1311 
1312 		      g_signal_connect( obj, "deselect",
1313 		            G_CALLBACK( removeHintFromAppBar), obj );
1314 		   }
1315 		   else
1316 		#endif */
1317 
1318 		if ( *txt )
1319 		{
1320 			//gtk_tooltips_set_tip ( tt, GTK_WIDGET ( obj ), txt, NULL );
1321 			//gtk_widget_set_tooltip_text ( GTK_WIDGET ( obj ), txt );
1322 			gtk_widget_set_tooltip_markup ( GTK_WIDGET ( obj ), txt );
1323 		}
1324 
1325 		else
1326 		{
1327 			//gtk_tooltips_set_tip ( tt, GTK_WIDGET ( obj ), NULL, NULL );
1328 			//gtk_widget_set_tooltip_text ( GTK_WIDGET ( obj ), NULL );
1329 			gtk_widget_set_tooltip_markup ( GTK_WIDGET ( obj ), NULL );
1330 		}
1331 	}
1332 
1333 	else /* get value */
1334 	{
1335 		GtkTooltipsData *td = gtk_tooltips_data_get ( GTK_WIDGET ( obj ) );
1336 
1337 		if ( td && td->tip_text )
1338 			*ret = Tcl_NewStringObj ( td->tip_text, -1 );
1339 		else
1340 			*ret = Tcl_NewStringObj ( "", 0 );
1341 	}
1342 
1343 	return TCL_OK;
1344 }
1345 
1346 
1347 
1348 /**
1349 **/
modifyWidgetGdkColor(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,void (* func)(GtkWidget *,GtkStateType,const GdkColor *),glong offset,Tcl_Obj ** ret)1350 int modifyWidgetGdkColor ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, void ( *func ) ( GtkWidget *, GtkStateType, const GdkColor * ), glong offset, Tcl_Obj **ret )
1351 {
1352 
1353 #ifdef DEBUG_PARSEOPTIONS
1354 	g_print ( "parseOptions/modifyWidgetGdkColor\n" );
1355 #endif
1356 
1357 	GtkStateType type;
1358 
1359 	switch ( *opt->propName )
1360 	{
1361 		case 'n': type = GTK_STATE_NORMAL; break;
1362 		case 'a': type = GTK_STATE_ACTIVE; break;
1363 		case 'p': type = GTK_STATE_PRELIGHT; break;
1364 		case 's': type = GTK_STATE_SELECTED; break;
1365 		case 'i': type = GTK_STATE_INSENSITIVE; break;
1366 		default:     assert ( 0 );
1367 	}
1368 
1369 	if ( ret == NULL ) /* set value */
1370 	{
1371 		GdkColor color;
1372 
1373 		if ( getGdkColor ( interp, opt->val.obj, &color ) != TCL_OK )
1374 		{
1375 			return TCL_ERROR;
1376 		}
1377 
1378 		( *func ) ( GTK_WIDGET ( obj ), type, &color );
1379 	}
1380 
1381 	else /* get value */
1382 	{
1383 		/* gtk_widget_get_modifier_style() FIXME: where are the differences?
1384 		   gtk_widget_get_style( )
1385 		   gtk_rc_get_style */
1386 		/*
1387 		GtkRcStyle *style = gtk_widget_get_modifier_style( GTK_WIDGET( obj ) );
1388 		GtkStyle *style = gtk_widget_get_style( GTK_WIDGET( obj ) );
1389 		*/
1390 		GtkStyle *style = gtk_rc_get_style ( GTK_WIDGET ( obj ) );
1391 		GdkColor *cp = ( GdkColor * ) G_STRUCT_MEMBER_P ( style, offset );
1392 		GdkColor color = cp[type];
1393 		*ret = Tcl_NewListObj ( 0, NULL );
1394 		Tcl_ListObjAppendElement ( NULL, *ret, Tcl_NewIntObj ( color.red ) );
1395 		Tcl_ListObjAppendElement ( NULL, *ret, Tcl_NewIntObj ( color.green ) );
1396 		Tcl_ListObjAppendElement ( NULL, *ret, Tcl_NewIntObj ( color.blue ) );
1397 	}
1398 
1399 	return TCL_OK;
1400 }
1401 
1402 
1403 /**
1404  */
gnoclOptGdkColorBg(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)1405 int gnoclOptGdkColorBg ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
1406 {
1407 	return modifyWidgetGdkColor ( interp, opt, obj, gtk_widget_modify_bg, G_STRUCT_OFFSET ( GtkStyle, bg ), ret );
1408 }
1409 
1410 /**
1411 **/
gnoclOptGdkColorFg(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)1412 int gnoclOptGdkColorFg ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
1413 {
1414 	return modifyWidgetGdkColor ( interp, opt, obj, gtk_widget_modify_fg, G_STRUCT_OFFSET ( GtkStyle, fg ), ret );
1415 }
1416 
1417 /**
1418  */
gnoclOptGdkColorText(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)1419 int gnoclOptGdkColorText ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
1420 {
1421 	return modifyWidgetGdkColor ( interp, opt, obj, gtk_widget_modify_text, G_STRUCT_OFFSET ( GtkStyle, text ), ret );
1422 }
1423 
1424 /**
1425  */
gnoclOptGdkColorBase(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)1426 int gnoclOptGdkColorBase ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
1427 {
1428 	return modifyWidgetGdkColor ( interp, opt, obj, gtk_widget_modify_base, G_STRUCT_OFFSET ( GtkStyle, base ), ret );
1429 }
1430 
1431 /**
1432  */
gnoclOptGdkBaseFont(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)1433 int gnoclOptGdkBaseFont ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
1434 {
1435 
1436 	char *fnt = Tcl_GetStringFromObj ( opt->val.obj, NULL );
1437 	PangoFontDescription *font_desc = pango_font_description_from_string ( fnt );
1438 
1439 	gtk_widget_modify_font ( GTK_WIDGET ( obj ), font_desc );
1440 	pango_font_description_free ( font_desc );
1441 
1442 	return TCL_OK;
1443 }
1444 
1445 /**
1446  */
gnoclGetGdkBaseFont(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)1447 char *gnoclGetGdkBaseFont ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
1448 {
1449 
1450 	char *fnt = Tcl_GetStringFromObj ( opt->val.obj, NULL );
1451 	PangoFontDescription *font_desc = pango_font_description_from_string ( fnt );
1452 
1453 	gtk_widget_modify_font ( GTK_WIDGET ( obj ), font_desc );
1454 	pango_font_description_free ( font_desc );
1455 
1456 	return fnt;
1457 }
1458 
1459 
1460 /**
1461  */
1462 /* -----------------
1463    group <-> sizeGroup mapping
1464 -------------------- */
groupToIdx(GtkSizeGroupMode mode)1465 static int groupToIdx ( GtkSizeGroupMode mode )
1466 {
1467 	switch ( mode )
1468 	{
1469 		case GTK_SIZE_GROUP_HORIZONTAL: return 1;
1470 		case GTK_SIZE_GROUP_VERTICAL:   return 2;
1471 		default: assert ( mode == GTK_SIZE_GROUP_BOTH );
1472 	}
1473 
1474 	return 0;
1475 }
1476 
1477 
1478 /**
1479  */
destroySizeGroup(gpointer data,GObject * obj)1480 static void destroySizeGroup (  gpointer data,  GObject *obj )
1481 {
1482 	const char   *name = data;
1483 	assert ( groupToIdx ( GTK_SIZE_GROUP_BOTH ) == 0 );
1484 	g_hash_table_remove ( sizeGroupTables[0], name );
1485 }
1486 
1487 /**
1488  */
destroyWidthGroup(gpointer data,GObject * obj)1489 static void destroyWidthGroup ( gpointer data,  GObject *obj )
1490 {
1491 	const char   *name = data;
1492 	assert ( groupToIdx ( GTK_SIZE_GROUP_HORIZONTAL ) == 1 );
1493 	g_hash_table_remove ( sizeGroupTables[1], name );
1494 }
1495 
1496 /**
1497 \brief
1498 \author
1499 \date
1500 \note
1501 **/
destroyHeightGroup(gpointer data,GObject * obj)1502 static void destroyHeightGroup (    gpointer data,  GObject *obj )
1503 {
1504 	const char   *name = data;
1505 	assert ( groupToIdx ( GTK_SIZE_GROUP_VERTICAL ) == 2 );
1506 	g_hash_table_remove ( sizeGroupTables[2], name );
1507 }
1508 
1509 /**
1510 \brief
1511 \author
1512 \date
1513 \note
1514 **/
addSizeGroup(GtkWidget * widget,GtkSizeGroupMode mode,const char * name)1515 static int addSizeGroup (   GtkWidget *widget,  GtkSizeGroupMode mode,  const char *name )
1516 {
1517 	int new = 0;
1518 	GHashTable   *table = sizeGroupTables[groupToIdx ( mode ) ];
1519 	GtkSizeGroup *group = g_hash_table_lookup ( table, name );
1520 
1521 	if ( group == NULL )
1522 	{
1523 		GWeakNotify destroyFunc[3] = { destroySizeGroup,
1524 									   destroyWidthGroup, destroyHeightGroup
1525 									 };
1526 		char *str = g_strdup ( name );
1527 		group = gtk_size_group_new ( mode );
1528 		g_hash_table_insert ( table, str, ( gpointer ) group );
1529 		g_object_weak_ref ( G_OBJECT ( group ),
1530 							destroyFunc[groupToIdx ( mode ) ], str );
1531 		new = 1;
1532 	}
1533 
1534 	gtk_size_group_add_widget ( group, widget );
1535 
1536 	g_object_set_data_full ( G_OBJECT ( widget ), "gnocl::sizeGroup",
1537 							 g_strdup ( name ), g_free );
1538 
1539 	if ( new )
1540 		g_object_unref ( group );
1541 
1542 	return 0;
1543 }
1544 
1545 /**
1546 \brief
1547 \author
1548 \date
1549 \note
1550 **/
getSizeGroup(GtkWidget * widget,GtkSizeGroupMode mode)1551 static const char *getSizeGroup (   GtkWidget *widget,  GtkSizeGroupMode mode )
1552 {
1553 	return g_object_get_data ( G_OBJECT ( widget ), "gnocl::sizeGroup" );
1554 }
1555 
1556 /**
1557 \brief
1558 \author
1559 \date
1560 \note
1561 **/
removeSizeGroup(GtkWidget * widget,GtkSizeGroupMode mode)1562 static int removeSizeGroup ( GtkWidget *widget, GtkSizeGroupMode mode )
1563 {
1564 	const char *name = getSizeGroup ( widget, mode );
1565 	GtkSizeGroup *group;
1566 
1567 	if ( name == NULL )
1568 		return 0;
1569 
1570 	group = g_hash_table_lookup ( sizeGroupTables[groupToIdx ( mode ) ], name );
1571 
1572 	if ( group == NULL )
1573 		return 0;
1574 
1575 	gtk_size_group_remove_widget ( group, widget );
1576 
1577 	g_object_set_data ( G_OBJECT ( widget ), "gnocl::sizeGroup", NULL );
1578 
1579 	return 1;
1580 }
1581 
1582 /**
1583 \brief
1584 \author
1585 \date
1586 \note
1587 **/
gnoclOptSizeGroup(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)1588 int gnoclOptSizeGroup ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
1589 {
1590 	GtkSizeGroupMode mode = GTK_SIZE_GROUP_BOTH;
1591 
1592 	switch ( opt->optName[1] )
1593 	{
1594 		case 'w':   mode = GTK_SIZE_GROUP_HORIZONTAL; break;
1595 		case 'h':   mode = GTK_SIZE_GROUP_VERTICAL;   break;
1596 		default: assert ( opt->optName[1] == 's' );
1597 	}
1598 
1599 	if ( sizeGroupTables[groupToIdx ( mode ) ] == NULL )
1600 	{
1601 		sizeGroupTables[groupToIdx ( mode ) ] =
1602 			g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, NULL );
1603 	}
1604 
1605 	if ( ret == NULL ) /* set value */
1606 	{
1607 		const char *group = Tcl_GetString ( opt->val.obj );
1608 
1609 		if ( *group )
1610 		{
1611 			addSizeGroup ( GTK_WIDGET ( obj ), mode, group  );
1612 		}
1613 
1614 		else
1615 		{
1616 			removeSizeGroup ( GTK_WIDGET ( obj ), mode );
1617 		}
1618 	}
1619 
1620 	else              /* get value */
1621 	{
1622 		const char *group = getSizeGroup ( GTK_WIDGET ( obj ), mode );
1623 
1624 		if ( group )
1625 		{
1626 			*ret = Tcl_NewStringObj ( group, -1 );
1627 		}
1628 
1629 		else
1630 		{
1631 			*ret = Tcl_NewStringObj ( "", 0 );
1632 		}
1633 	}
1634 
1635 	return TCL_OK;
1636 }
1637 
1638 /**
1639 \brief
1640 \author
1641 \date
1642 \note	used in megawigets such as labelEntry
1643 **/
gnoclOptWidthGroup(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)1644 int gnoclOptWidthGroup ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
1645 {
1646 	GtkSizeGroupMode mode = GTK_SIZE_GROUP_HORIZONTAL;
1647 
1648 	if ( sizeGroupTables[groupToIdx ( mode ) ] == NULL )
1649 	{
1650 		sizeGroupTables[groupToIdx ( mode ) ] =
1651 			g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, NULL );
1652 	}
1653 
1654 	if ( ret == NULL ) /* set value */
1655 	{
1656 		const char *group = Tcl_GetString ( opt->val.obj );
1657 
1658 		if ( *group )
1659 		{
1660 			addSizeGroup ( GTK_WIDGET ( obj ), mode, group  );
1661 		}
1662 
1663 		else
1664 		{
1665 			removeSizeGroup ( GTK_WIDGET ( obj ), mode );
1666 		}
1667 	}
1668 
1669 	else              /* get value */
1670 	{
1671 		const char *group = getSizeGroup ( GTK_WIDGET ( obj ), mode );
1672 
1673 		if ( group )
1674 		{
1675 			*ret = Tcl_NewStringObj ( group, -1 );
1676 		}
1677 
1678 		else
1679 		{
1680 			*ret = Tcl_NewStringObj ( "", 0 );
1681 		}
1682 	}
1683 
1684 	return TCL_OK;
1685 }
1686 
1687 /**
1688 \brief
1689 \author
1690 \date
1691 \note
1692 **/
optAlign(Tcl_Interp * interp,Tcl_Obj * obj,int isHor,gfloat * f)1693 static int optAlign ( Tcl_Interp *interp, Tcl_Obj *obj, int isHor,  gfloat *f )
1694 {
1695 	double d = -1;
1696 
1697 	if ( Tcl_GetDoubleFromObj ( NULL, obj, &d ) != TCL_OK )
1698 	{
1699 		char *txt = Tcl_GetString ( obj );
1700 
1701 		if ( strcmp ( txt, isHor ? "left" : "top" ) == 0 )
1702 		{
1703 			d = .0;
1704 		}
1705 
1706 		else if ( strcmp ( txt, "center" ) == 0 )
1707 		{
1708 			d = 0.5;
1709 		}
1710 
1711 		else if ( strcmp ( txt, isHor ? "right" : "bottom" ) == 0 )
1712 		{
1713 			d = 1.;
1714 		}
1715 	}
1716 
1717 	if ( d < .0 || d > 1. )
1718 	{
1719 		if ( interp )
1720 		{
1721 			if ( isHor )
1722 				Tcl_SetResult ( interp, "Horizontal alignement must be either "
1723 								"a double value between 0 and 1 or "
1724 								"\"left\", \"center\", or \"right\"",
1725 								TCL_STATIC );
1726 			else
1727 				Tcl_SetResult ( interp, "Horizontal alignement must be either "
1728 								"a double value between 0 and 1 or "
1729 								"\"top\", \"center\", or \"bottom\"",
1730 								TCL_STATIC );
1731 		}
1732 
1733 		return TCL_ERROR;
1734 	}
1735 
1736 	*f = d;
1737 
1738 	return TCL_OK;
1739 }
1740 
1741 /**
1742 \brief
1743 \author
1744 \date
1745 \note       - a list with one element for x and one for y
1746             or - a double
1747             or - one of the predifined strings
1748 **/
gnoclGetBothAlign(Tcl_Interp * interp,Tcl_Obj * obj,gfloat * xAlign,gfloat * yAlign)1749 int gnoclGetBothAlign ( Tcl_Interp *interp, Tcl_Obj *obj,   gfloat *xAlign, gfloat *yAlign )
1750 {
1751 	int    len = 0;
1752 	double d;
1753 
1754 	if ( Tcl_GetDoubleFromObj ( NULL, obj, &d ) == TCL_OK )
1755 	{
1756 		*xAlign = d;
1757 		*yAlign = d;
1758 	}
1759 
1760 	else if ( Tcl_ListObjLength ( NULL, obj, &len ) == TCL_OK && len == 2 )
1761 	{
1762 		Tcl_Obj *tp;
1763 
1764 		if ( Tcl_ListObjIndex ( NULL, obj, 0, &tp ) != TCL_OK )
1765 		{
1766 			goto cleanExit;
1767 		}
1768 
1769 		if ( optAlign ( interp, tp, 0, xAlign ) != TCL_OK )
1770 		{
1771 			goto cleanExit;
1772 		}
1773 
1774 		if ( Tcl_ListObjIndex ( NULL, obj, 1, &tp ) != TCL_OK )
1775 		{
1776 			goto cleanExit;
1777 		}
1778 
1779 		if ( optAlign ( NULL, tp, 1, yAlign ) != TCL_OK )
1780 		{
1781 			goto cleanExit;
1782 		}
1783 	}
1784 
1785 	else if ( len == 1 )
1786 	{
1787 		const char *txt[] = { "topLeft", "top", "topRight",
1788 							  "left", "center", "right",
1789 							  "bottomLeft", "bottom", "bottomRight",
1790 							  NULL
1791 							};
1792 
1793 		int idx;
1794 
1795 		if ( Tcl_GetIndexFromObj ( NULL, obj, txt, NULL, TCL_EXACT, &idx ) != TCL_OK )
1796 		{
1797 			goto cleanExit;
1798 		}
1799 
1800 		*xAlign = ( idx % 3 ) * 0.5;
1801 
1802 		*yAlign = ( idx / 3 ) * 0.5;
1803 	}
1804 
1805 	return TCL_OK;
1806 
1807 cleanExit:
1808 	Tcl_SetResult ( interp, "Alignment must be either a list with "
1809 					"the vertical and horizontal alignment or one of "
1810 					"\"topLeft\", \"top\", \"topRight\", "
1811 					"\"left\", \"center\", \"right\", "
1812 					"\"bottomLeft\", \"bottom\", or \"bottomRight\"", TCL_STATIC );
1813 	return TCL_ERROR;
1814 
1815 }
1816 
1817 /**
1818 \brief
1819 \author
1820 \date
1821 \note
1822 **/
gnoclOptBothAlign(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)1823 int gnoclOptBothAlign ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
1824 {
1825 	gfloat xAlign, yAlign;
1826 	char *p;
1827 	char buffer[32];
1828 	strcpy ( buffer, opt->propName );
1829 	p = strchr ( buffer, '?' );
1830 
1831 	if ( ret == NULL ) /* set value */
1832 	{
1833 		if ( gnoclGetBothAlign ( interp, opt->val.obj, &xAlign, &yAlign ) == TCL_OK )
1834 		{
1835 			*p = 'x';
1836 			g_object_set ( obj, buffer, xAlign, NULL );
1837 			*p = 'y';
1838 			g_object_set ( obj, buffer, yAlign, NULL );
1839 
1840 			return TCL_OK;
1841 		}
1842 	}
1843 
1844 	else /* get value */
1845 	{
1846 		const double eps = 0.00001;
1847 		const char *vert = NULL;
1848 		const char *hor = NULL;
1849 		*p = 'x';
1850 		g_object_get ( obj, buffer, &xAlign, NULL );
1851 		*p = 'y';
1852 		g_object_get ( obj, buffer, &yAlign, NULL );
1853 
1854 		if ( fabs ( yAlign ) < eps )
1855 			vert = "top";
1856 		else if ( fabs ( yAlign - 0.5 ) < eps )
1857 			vert = "";
1858 		else if ( fabs ( yAlign - 1.0 ) < eps )
1859 			vert = "bottom";
1860 
1861 		if ( vert != NULL )
1862 		{
1863 			if ( fabs ( xAlign ) < eps )
1864 				hor = *vert ? "Left" : "left";
1865 			else if ( fabs ( xAlign - 0.5 ) < eps )
1866 				hor = *vert ? "" : "center";
1867 			else if ( fabs ( xAlign - 1.0 ) < eps )
1868 				hor = *vert ? "Right" : "right";
1869 		}
1870 
1871 		if ( vert != NULL  && hor != NULL )
1872 		{
1873 			*ret = Tcl_NewStringObj ( vert, -1 );
1874 			Tcl_AppendToObj ( *ret, hor, -1 );
1875 		}
1876 
1877 		else
1878 		{
1879 			*ret = Tcl_NewListObj ( 0, NULL );
1880 			Tcl_ListObjAppendElement ( NULL, *ret, Tcl_NewDoubleObj ( xAlign ) );
1881 			Tcl_ListObjAppendElement ( NULL, *ret, Tcl_NewDoubleObj ( yAlign ) );
1882 		}
1883 
1884 		return TCL_OK;
1885 	}
1886 
1887 	return TCL_ERROR;
1888 }
1889 
1890 /**
1891 \brief
1892 \author
1893 \date
1894 \note
1895 **/
gnoclOptWidget(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)1896 int gnoclOptWidget ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
1897 {
1898 	GtkWidget *widget = NULL;
1899 
1900 	if ( ret == NULL ) /* set value */
1901 	{
1902 		const char *str = Tcl_GetString ( opt->val.obj );
1903 
1904 		if ( *str != 0 )
1905 		{
1906 			widget = gnoclChildNotPacked ( str, interp );
1907 
1908 			if ( widget == NULL )
1909 			{
1910 				return TCL_ERROR;
1911 			}
1912 		}
1913 
1914 		g_object_set ( obj, opt->propName, widget, NULL );
1915 	}
1916 
1917 	else /* get value */
1918 	{
1919 		g_object_get ( obj, opt->propName, &widget, NULL );
1920 
1921 		if ( widget )
1922 		{
1923 			*ret = Tcl_NewStringObj ( gnoclGetNameFromWidget ( widget ), -1 );
1924 		}
1925 
1926 		else
1927 		{
1928 			*ret = Tcl_NewStringObj ( "", 0 );
1929 		}
1930 	}
1931 
1932 	return TCL_OK;
1933 }
1934 
1935 /**
1936 \brief      Returns the name of the objects parent widget.
1937 \author     WJG
1938 \date       06/12/08
1939 \note       Function isn't working properly. Code originally sorted in button.c, transfered to text.c
1940 */
gnoclGetParent(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)1941 int gnoclGetParent ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
1942 {
1943 
1944 	GtkWidget * parent;
1945 
1946 	parent = gtk_widget_get_ancestor ( GTK_WIDGET ( obj ), GTK_TYPE_BOX );
1947 	obj = Tcl_NewStringObj ( gnoclGetNameFromWidget ( parent ), -1 );
1948 	Tcl_SetObjResult ( interp, obj );
1949 	return TCL_OK;
1950 }
1951 
1952 /**
1953 \brief      Set the specified widget width to the require size in pixels based
1954             upon the current style of the widget. This is called to set those
1955             Gtk+ widgets which do not have a default
1956             "width-chars" property: e.g GtkComboBox.
1957 \author     William J Giddings
1958 \date       18/Feb/09
1959 \see        http://www.gtkforums.com/viewtopic.php?t=3495&highlight=width
1960 */
gnoclOptCharWidth(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)1961 int gnoclOptCharWidth ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
1962 {
1963 #ifdef DEBUG_PARSEOPTIONS
1964 	g_print ( "gnoclOptCharWidth\n" );
1965 #endif
1966 	PangoLayout *layout;
1967 	gint w, h, l;
1968 
1969 	gchar text[2] = "X";
1970 
1971 	// char *len = Tcl_GetStringFromObj ( opt->val.obj, NULL );
1972 	l = atoi ( Tcl_GetStringFromObj ( opt->val.obj, NULL ) );
1973 #ifdef DEBUG_PARSEOPTIONS
1974 	g_print ( "l = %d\n", l );
1975 #endif
1976 
1977 	//layout = gtk_widget_create_pango_layout ( GTK_WIDGET ( obj ) ,text);
1978 
1979 	layout = gtk_widget_create_pango_layout ( GTK_WIDGET ( gtk_label_new ( "" ) ), text );
1980 
1981 	pango_layout_get_pixel_size ( layout, &w, &h );
1982 	g_object_unref ( layout );
1983 
1984 	l = l * w + 30;
1985 #ifdef DEBUG_PARSEOPTIONS
1986 	printf ( "w = %d ; l = %d\n", w );
1987 #endif
1988 
1989 
1990 	if ( 1 )
1991 	{
1992 		gtk_widget_set_size_request ( GTK_WIDGET ( obj ), l, -1 );
1993 	}
1994 
1995 	return TCL_OK;
1996 }
1997 
1998 /**
1999 \brief
2000 \author
2001 \date
2002 \note
2003 **/
gnoclOptHeightRequest(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)2004 int gnoclOptHeightRequest ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
2005 {
2006 
2007 	gint width, height;
2008 
2009 
2010 	if ( Tcl_GetIntFromObj ( interp, opt->val.obj, &height ) != TCL_OK )
2011 	{
2012 		return TCL_ERROR;
2013 	}
2014 
2015 	gtk_widget_set_size_request ( GTK_WIDGET ( obj ), -1, height );
2016 
2017 
2018 }
2019 
2020 /**
2021 \brief
2022 \author
2023 \date
2024 \note
2025 **/
gnoclOptChild(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)2026 int gnoclOptChild ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
2027 {
2028 	if ( ret == NULL ) /* set value */
2029 	{
2030 		const char *str = Tcl_GetString ( opt->val.obj );
2031 
2032 		if ( *str == 0 )
2033 		{
2034 			GtkWidget *widget = gtk_bin_get_child ( GTK_BIN ( obj ) );
2035 
2036 			if ( widget != NULL )
2037 			{
2038 				gtk_container_remove ( GTK_CONTAINER ( obj ), widget );
2039 			}
2040 		}
2041 
2042 		else
2043 		{
2044 			GtkWidget *widget = gnoclChildNotPacked ( str, interp );
2045 
2046 			if ( widget == NULL )
2047 			{
2048 				return TCL_ERROR;
2049 			}
2050 
2051 			gtk_container_add ( GTK_CONTAINER ( obj ), widget );
2052 		}
2053 
2054 	}
2055 
2056 	else /* get value */
2057 	{
2058 		GtkWidget *child = gtk_bin_get_child ( GTK_BIN ( obj ) );
2059 
2060 		if ( child )
2061 		{
2062 			*ret = Tcl_NewStringObj ( gnoclGetNameFromWidget ( child ), -1 );
2063 		}
2064 
2065 		else
2066 		{
2067 			*ret = Tcl_NewStringObj ( "", 0 );
2068 		}
2069 	}
2070 
2071 	return TCL_OK;
2072 }
2073 
2074 /**
2075 \brief
2076 \author
2077 \date
2078 \note
2079 **/
gnoclOptHalign(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)2080 int gnoclOptHalign ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
2081 {
2082 	if ( ret == NULL ) /* set value */
2083 	{
2084 		gfloat d;
2085 
2086 		if ( optAlign ( interp, opt->val.obj, 1, &d ) != TCL_OK )
2087 			return TCL_ERROR;
2088 
2089 		g_object_set ( obj, opt->propName, d, NULL );
2090 	}
2091 
2092 	else /* get value */
2093 	{
2094 		const double eps = 0.00001;
2095 		gfloat align;
2096 		g_object_get ( obj, opt->propName, &align, NULL );
2097 
2098 		if ( fabs ( align ) < eps )
2099 		{
2100 			*ret = Tcl_NewStringObj ( "left", -1 );
2101 		}
2102 
2103 		else if ( fabs ( align - 0.5 ) < eps )
2104 		{
2105 			*ret = Tcl_NewStringObj ( "center", -1 );
2106 		}
2107 
2108 		else if ( fabs ( align - 1.0 ) < eps )
2109 		{
2110 			*ret = Tcl_NewStringObj ( "right", -1 );
2111 		}
2112 
2113 		else
2114 		{
2115 			*ret = Tcl_NewDoubleObj ( align );
2116 		}
2117 	}
2118 
2119 	return TCL_OK;
2120 }
2121 
2122 /**
2123 \brief
2124 \author
2125 \date
2126 \note
2127 **/
destroyCmdData(gpointer data,GClosure * closure)2128 static void destroyCmdData ( gpointer data, GClosure *closure )
2129 {
2130 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
2131 
2132 	g_free ( cs->command );
2133 	g_free ( cs );
2134 }
2135 
2136 /**
2137 \brief		a generic widget signal handler
2138 \author
2139 \date
2140 \note      07-Dec-09   Added %g option to return glade name as part of mark-up string.
2141 **/
doCommand(GtkWidget * widget,gpointer data)2142 static void doCommand ( GtkWidget *widget, gpointer data )
2143 {
2144 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
2145 
2146 	/* if we have set the result, we are in the middle of
2147 	   error handling. In this case don't call any callbacks
2148 	   (especially onDestroy!) because this overrides the result. */
2149 
2150 	//if ( *cs->interp->result == '\0' )
2151 	//if ( *Tcl_GetStringResult(cs->interp) == '\0' )
2152 	//{
2153 	GnoclPercSubst ps[] =
2154 	{
2155 		{ 'w', GNOCL_STRING },  /* widget */
2156 		{ 'g', GNOCL_STRING },  /* gladeName */
2157 		{ 0 }
2158 	};
2159 
2160 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
2161 	ps[1].val.str = gtk_widget_get_name ( GTK_WIDGET ( widget ) );
2162 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
2163 	//}
2164 }
2165 
2166 /**
2167 \brief
2168 \author
2169 \date
2170 \note
2171 **/
gnoclGetOptCmd(GObject * obj,const char * signal)2172 const char *gnoclGetOptCmd ( GObject *obj, const char *signal )
2173 {
2174 	/* there really should be a GTK+ command
2175 	   cs = g_signal_get_data( obj, signal ); */
2176 	return g_object_get_data ( obj, signal );
2177 }
2178 
2179 /**
2180 \brief      Destroys all connections for a particular object, with the given
2181             user-data. Apparently this uses deprecated library functions, see the
2182             following for more info.
2183 \see        http://library.gnome.org/devel/gtk/stable/gtk-Signals.html
2184 **/
gnoclDisconnect(GObject * obj,const char * signal,GCallback handler)2185 int gnoclDisconnect ( GObject *obj, const char *signal, GCallback handler )
2186 {
2187 	/* we must match func and ID since more than one signal can call
2188 	   the same func if they use the same percent substitutions */
2189 	g_signal_handlers_disconnect_matched ( obj,
2190 										   ( GSignalMatchType ) ( G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_ID ),
2191 										   g_signal_lookup ( signal, G_OBJECT_TYPE ( obj ) ),
2192 										   0, NULL, ( gpointer * ) handler, NULL );
2193 	g_object_set_data ( obj, signal, NULL );
2194 
2195 	return 0;
2196 }
2197 
2198 
2199 /**
2200 \brief
2201 \author
2202 \date
2203 \note       The signals connected here are those of the GtkWidget base class.
2204 \see        See http://library.gnome.org/devel/gtk/stable/GtkWidget.html
2205 \note
2206             Signals specific to particular wigdets, e.g. textBuffer insert-at-cursor
2207             need different handlers. These, however, are triggered not by user
2208             interaction, but under program control. e.g. after a menu operation
2209             to paste, the relevant signal would be emitted a callback function
2210             then needs to be added, with a func similar to gnoclConnectOptCmd and
2211             gnoclConnectSignalCmd. It looks as though gnoclConnectOptCmd will
2212             connect the signal with a command... -onPaste .... ensure that
2213             textBuffer pointer and not textView is passed....
2214 **/
gnoclConnectOptCmd(Tcl_Interp * interp,GObject * obj,const char * signal,GCallback handler,GnoclOption * opt,void * data,Tcl_Obj ** ret)2215 int gnoclConnectOptCmd ( Tcl_Interp *interp, GObject *obj, const char *signal, GCallback handler, GnoclOption *opt, void *data, Tcl_Obj **ret )
2216 {
2217 #ifdef DEBUG_PARSEOPTIONS
2218 	g_print ( "%s %s %s\n", __FUNCTION__, gnoclGetNameFromWidget ( GTK_WIDGET ( obj ) ), signal );
2219 #endif
2220 
2221 	if ( ret == NULL ) /* set value */
2222 	{
2223 		assert ( opt->type == GNOCL_OBJ );
2224 
2225 		if ( opt->status == GNOCL_STATUS_CHANGED )
2226 		{
2227 			const char *cmd = Tcl_GetString ( opt->val.obj );
2228 
2229 			gnoclDisconnect ( obj, signal, handler );
2230 
2231 			if ( cmd && *cmd )
2232 			{
2233 				/* TODO? remember here already the name of the widget.
2234 				         We then don't have to look it up in every event.
2235 				         Problem: name must be registered before first
2236 				         configure, so gnoclRegisterWidget does not work any more.
2237 				*/
2238 
2239 				GnoclCommandData *cs = g_new ( GnoclCommandData, 1 );
2240 				cs->command = g_strdup ( cmd );
2241 				cs->interp = interp;
2242 				cs->data = data;
2243 				g_signal_connect_data ( obj, signal, handler, cs, destroyCmdData, ( GConnectFlags ) 0 );
2244 				g_object_set_data ( obj, signal, ( gpointer ) cs->command );
2245 			}
2246 
2247 			else
2248 				g_object_set_data ( obj, signal, NULL );
2249 		}
2250 	}
2251 
2252 	else /* get value */
2253 	{
2254 		const char *cmd = gnoclGetOptCmd ( obj, signal );
2255 
2256 		if ( cmd )
2257 			*ret = Tcl_NewStringObj ( cmd, -1 );
2258 		else
2259 			*ret = Tcl_NewStringObj ( "", 0 );
2260 	}
2261 
2262 	return TCL_OK;
2263 }
2264 
2265 /**
2266 \brief This is for all callbacks which have only %w as substitution
2267 **/
gnoclOptCommand(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)2268 int gnoclOptCommand ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
2269 {
2270 	assert ( opt->type == GNOCL_OBJ );
2271 
2272 	return gnoclConnectOptCmd ( interp, obj, opt->propName, G_CALLBACK ( doCommand ), opt, NULL, ret );
2273 }
2274 
2275 
2276 /**
2277 \brief
2278 **/
doOnMoveHandle(GtkWidget * widget,GtkScrollType scroll_type,gpointer user_data)2279 static void doOnMoveHandle ( GtkWidget *widget, GtkScrollType scroll_type, gpointer user_data )
2280 {
2281 #ifdef DEBUG_PARSEOPTIONS
2282 	g_print ( "%s\n", __FUNCTION__ );
2283 #endif
2284 
2285 	// g_print ("%s\n",__FUNCTION__);
2286 
2287 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
2288 
2289 	GnoclPercSubst ps[] =
2290 	{
2291 		{ 'w', GNOCL_STRING },  /* widget */
2292 		{ 'g', GNOCL_STRING },  /* glade name */
2293 		{ 'p', GNOCL_INT}, 		/* handle position */
2294 		{ 0 }
2295 	};
2296 
2297 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
2298 	ps[1].val.str = gtk_widget_get_name ( widget );
2299 	ps[2].val.i = gtk_paned_get_position ( widget );
2300 
2301 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
2302 }
2303 
2304 
2305 
2306 /**
2307 \brief React to movement of the paned window handle throught key bindings
2308 **/
gnoclOptMoveHandle(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)2309 int gnoclOptMoveHandle ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
2310 {
2311 	// g_print ("%s\n",__FUNCTION__);
2312 	assert ( strcmp ( opt->optName, "-onHandleMoved" ) == 0 );
2313 	return gnoclConnectOptCmd ( interp, obj, "move-handle", G_CALLBACK ( doOnMoveHandle ), opt, NULL, ret );
2314 
2315 }
2316 
2317 /**
2318 \brief
2319 **/
gnoclOptData(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)2320 int gnoclOptData ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
2321 {
2322 	const char *dataID = "gnocl::data";
2323 
2324 	assert ( opt->type == GNOCL_OBJ );
2325 
2326 	if ( ret == NULL ) /* set value */
2327 	{
2328 		const char *data = Tcl_GetString ( opt->val.obj );
2329 
2330 		if ( data && *data )
2331 		{
2332 			g_object_set_data_full ( obj, dataID, g_strdup ( data ), g_free );
2333 		}
2334 
2335 		else
2336 		{
2337 			g_object_set_data ( obj, dataID, NULL );
2338 		}
2339 	}
2340 
2341 	else /* get value */
2342 	{
2343 		const char *data = g_object_get_data ( obj, dataID );
2344 
2345 		if ( data )
2346 		{
2347 			*ret = Tcl_NewStringObj ( data, -1 );
2348 		}
2349 
2350 		else
2351 		{
2352 			*ret = Tcl_NewStringObj ( "", 0 );
2353 		}
2354 	}
2355 
2356 	return TCL_OK;
2357 }
2358 
2359 /**
2360 \brief
2361 **/
doOnScroll(GtkWidget * widget,GdkEventScroll * event,gpointer data)2362 static gboolean doOnScroll ( GtkWidget *widget, GdkEventScroll *event, gpointer data )
2363 {
2364 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
2365 
2366 	GnoclPercSubst ps[] =
2367 	{
2368 		{ 'w', GNOCL_STRING },  /* widget */
2369 		{ 't', GNOCL_STRING },  /* event type */
2370 		{ 'x', GNOCL_INT },     /* pointer x-pos in window */
2371 		{ 'y', GNOCL_INT },     /* pointer y-pos in window */
2372 		{ 'X', GNOCL_INT },     /* pointer x-pos on screen */
2373 		{ 'Y', GNOCL_INT },     /* pointer y-pos on screen */
2374 		{ 's', GNOCL_INT },     /* state */
2375 		{ 'd', GNOCL_STRING },  /* direction */
2376 		{ 'g', GNOCL_STRING },  /* widget glade name */
2377 		{ 0 }
2378 	};
2379 
2380 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
2381 	ps[1].val.str = "scroll";
2382 	ps[2].val.i = event->x;
2383 	ps[3].val.i = event->y;
2384 	ps[4].val.i = event->x_root;
2385 	ps[5].val.i = event->y_root;
2386 	ps[6].val.i = event->state;
2387 	ps[7].val.str = gtk_widget_get_name ( widget );
2388 
2389 	switch ( event->direction )
2390 	{
2391 		case GDK_SCROLL_UP:
2392 			{
2393 				ps[7].val.str = "up";
2394 				break;
2395 			}
2396 
2397 		case GDK_SCROLL_DOWN:
2398 			{
2399 				ps[7].val.str = "down";
2400 				break;
2401 			}
2402 
2403 		case GDK_SCROLL_LEFT:
2404 			{
2405 				ps[7].val.str = "left";
2406 				break;
2407 			}
2408 
2409 		case GDK_SCROLL_RIGHT:
2410 			{
2411 				ps[7].val.str = "right";
2412 				break;
2413 			}
2414 	}
2415 
2416 
2417 	if ( gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 ) == TCL_OK )
2418 	{
2419 		int del;
2420 
2421 		if ( Tcl_GetBooleanFromObj ( NULL, Tcl_GetObjResult ( cs->interp ), &del ) == TCL_OK && del == 0 )
2422 		{
2423 			return TRUE;
2424 		}
2425 	}
2426 
2427 	return FALSE;
2428 }
2429 
2430 /**
2431 \brief
2432 **/
doOnDelete(GtkWidget * widget,GdkEvent * event,gpointer data)2433 static gboolean doOnDelete ( GtkWidget *widget, GdkEvent *event, gpointer data )
2434 {
2435 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
2436 
2437 	GnoclPercSubst ps[] =
2438 	{
2439 		{ 'w', GNOCL_STRING },  /* widget */
2440 		{ 'g', GNOCL_STRING },  /* glade name */
2441 		{ 0 }
2442 	};
2443 
2444 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
2445 	ps[1].val.str = gtk_widget_get_name ( widget );
2446 
2447 	if ( gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 ) == TCL_OK )
2448 	{
2449 		int del;
2450 
2451 		if ( Tcl_GetBooleanFromObj ( NULL, Tcl_GetObjResult ( cs->interp ), &del ) == TCL_OK && del == 0 )
2452 		{
2453 			return TRUE;  /* ignore delete */
2454 		}
2455 	}
2456 
2457 	return FALSE; /* proceed: destroy widget */
2458 }
2459 
2460 /**
2461 \brief
2462 \note       based upon doOnDelete
2463 **/
doOnExpose(GtkWidget * widget,GdkEvent * event,gpointer data)2464 static gboolean doOnExpose ( GtkWidget *widget, GdkEvent *event, gpointer data )
2465 {
2466 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
2467 
2468 	GnoclPercSubst ps[] =
2469 	{
2470 		{ 'w', GNOCL_STRING },  /* widget */
2471 		{ 'g', GNOCL_STRING },  /* glade name */
2472 		{ 0 }
2473 	};
2474 
2475 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
2476 	ps[1].val.str = gtk_widget_get_name ( widget );
2477 
2478 	if ( gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 ) == TCL_OK )
2479 	{
2480 		int del;
2481 
2482 		if ( Tcl_GetBooleanFromObj ( NULL, Tcl_GetObjResult ( cs->interp ), &del ) == TCL_OK && del == 0 )
2483 		{
2484 			return TRUE;  /* ignore delete */
2485 		}
2486 	}
2487 
2488 	return FALSE; /* proceed: destroy widget */
2489 }
2490 
2491 /**
2492 \brief      Respond to expose-event signal.
2493 \note       Developed for use with gnocl::openGL
2494 **/
gnoclOptOnExpose(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)2495 int gnoclOptOnExpose ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
2496 {
2497 	assert ( strcmp ( opt->optName, "-onExpose" ) == 0 );
2498 	return gnoclConnectOptCmd ( interp, obj, "expose-event", G_CALLBACK ( doOnExpose ), opt, NULL, ret );
2499 }
2500 
2501 
2502 /**
2503 \brief
2504 **/
gnoclOptOnDelete(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)2505 int gnoclOptOnDelete ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
2506 {
2507 	assert ( strcmp ( opt->optName, "-onDelete" ) == 0 );
2508 	return gnoclConnectOptCmd ( interp, obj, "delete-event", G_CALLBACK ( doOnDelete ), opt, NULL, ret );
2509 }
2510 
2511 /**
2512 \brief
2513 **/
doOnQueryToolTip(GtkWidget * widget,gint x,gint y,gboolean keyboard_mode,GtkTooltip * tooltip,gpointer user_data)2514 static void doOnQueryToolTip ( GtkWidget *widget, gint x, gint y, gboolean keyboard_mode, GtkTooltip *tooltip, gpointer user_data )
2515 {
2516 #ifdef DEBUG_PARSEOPTIONS
2517 	g_print ( "%s\n", __FUNCTION__ );
2518 #endif
2519 
2520 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
2521 	GtkTextIter *iter;
2522 
2523 	//GtkTextWindowType win;
2524 	gint buffer_x;
2525 	gint buffer_y;
2526 
2527 	//gtk_text_view_window_to_buffer_coords ( GTK_TEXT_VIEW  ( widget ), GTK_TEXT_WINDOW_WIDGET, x, y, &buffer_x, &buffer_y );
2528 
2529 	//gtk_text_view_get_iter_at_location  ( GTK_TEXT_VIEW  ( widget ), iter, buffer_x, buffer_y );
2530 
2531 	GnoclPercSubst ps[] =
2532 	{
2533 		{ 'w', GNOCL_STRING },  /* widget */
2534 		{ 'g', GNOCL_STRING },  /* glade name */
2535 		{ 'x', GNOCL_INT },
2536 		{ 'y', GNOCL_INT },
2537 		{ 'm', GNOCL_INT },
2538 		{ 'r', GNOCL_INT },
2539 		{ 'c', GNOCL_INT },
2540 		{ 0 }
2541 	};
2542 
2543 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
2544 	ps[1].val.str = gtk_widget_get_name ( widget );
2545 	ps[2].val.i = x;
2546 	ps[3].val.i = y;
2547 	ps[4].val.i = keyboard_mode;
2548 
2549 	//ps[5].val.i = gtk_text_iter_get_line ( iter );
2550 	//ps[6].val.i = gtk_text_iter_get_line_offset ( iter );
2551 
2552 
2553 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
2554 }
2555 
2556 
2557 /**
2558 \brief
2559 **/
gnoclOptOnQueryToolTip(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)2560 int gnoclOptOnQueryToolTip ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
2561 {
2562 	assert ( strcmp ( opt->optName, "-onQueryTooltip" ) == 0 );
2563 	return gnoclConnectOptCmd ( interp, obj, "query-tooltip", G_CALLBACK ( doOnQueryToolTip ), opt, NULL, ret );
2564 }
2565 
2566 /**
2567 \brief
2568 **/
doOnShowHelp(GtkWidget * widget,GtkWidgetHelpType arg1,gpointer data)2569 static void doOnShowHelp ( GtkWidget *widget, GtkWidgetHelpType arg1, gpointer data )
2570 {
2571 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
2572 
2573 	GnoclPercSubst ps[] =
2574 	{
2575 		{ 'w', GNOCL_STRING },  /* widget */
2576 		{ 'h', GNOCL_STRING },
2577 		{ 'g', GNOCL_STRING },  /* glade name */
2578 		{ 0 }
2579 	};
2580 
2581 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
2582 	ps[1].val.str = ( arg1 == GTK_WIDGET_HELP_TOOLTIP ? "tooltip" : "whatsThis" );
2583 	ps[2].val.str = gtk_widget_get_name ( widget );
2584 
2585 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
2586 }
2587 
2588 /**
2589 \brief
2590 **/
gnoclOptOnShowHelp(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)2591 int gnoclOptOnShowHelp ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
2592 {
2593 	assert ( strcmp ( opt->optName, "-onShowHelp" ) == 0 );
2594 	return gnoclConnectOptCmd ( interp, obj, "show-help", G_CALLBACK ( doOnShowHelp ), opt, NULL, ret );
2595 }
2596 
2597 /**
2598 \brief
2599 \todo    gnocl::buttonStateToList -> {MOD1 MOD3 BUTTON2...}
2600 **/
doOnMotion(GtkWidget * widget,GdkEventMotion * event,gpointer data)2601 static void doOnMotion ( GtkWidget *widget, GdkEventMotion *event, gpointer data )
2602 {
2603 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
2604 
2605 	GnoclPercSubst ps[] =
2606 	{
2607 		{ 'w', GNOCL_STRING },  /* widget */
2608 		{ 'x', GNOCL_INT },
2609 		{ 'y', GNOCL_INT },
2610 		{ 'X', GNOCL_INT },
2611 		{ 'Y', GNOCL_INT },
2612 		{ 's', GNOCL_INT },
2613 		{ 'g', GNOCL_STRING },  /* glade name */
2614 
2615 		/* textview specific options */
2616 		{ 'r', GNOCL_INT },
2617 		{ 'c', GNOCL_INT },
2618 		{ 0 }
2619 	};
2620 
2621 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
2622 	ps[1].val.i = event->x;
2623 	ps[2].val.i = event->y;
2624 	ps[3].val.i = event->x_root;
2625 	ps[4].val.i = event->y_root;
2626 	ps[5].val.i = event->state;
2627 	ps[6].val.str = gtk_widget_get_name ( widget );
2628 	ps[7].val.i = -1;
2629 	ps[8].val.i = -1;
2630 
2631 	gchar *type =  G_OBJECT_TYPE_NAME ( widget );
2632 
2633 	//g_print ( "Widget type: %s\n", type );
2634 
2635 	if ( strcmp ( type, "GtkUndoView" ) == 0 || strcmp ( type, "GtkTextView" ) == 0 )
2636 	{
2637 		GtkTextIter iter;
2638 		gint bx, by; /* buffer coordinates */
2639 		gint line, row;
2640 		gtk_text_view_window_to_buffer_coords ( widget, GTK_TEXT_WINDOW_WIDGET, event->x, event->y, &bx, &by );
2641 		gtk_text_view_get_iter_at_location ( widget, &iter, bx, by );
2642 		ps[7].val.i = gtk_text_iter_get_line ( &iter );
2643 		ps[8].val.i = gtk_text_iter_get_line_offset ( &iter );
2644 	}
2645 
2646 	/* TODO: gnocl::buttonStateToList -> {MOD1 MOD3 BUTTON2...} */
2647 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
2648 }
2649 
2650 /**
2651 \brief      Handler function for a GtkTextView "backspace" signal.
2652 \note
2653 **/
doOnBackSpace(GtkWidget * widget,gpointer data)2654 static void doOnBackSpace ( GtkWidget *widget, gpointer data )
2655 {
2656 
2657 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
2658 
2659 	GnoclPercSubst ps[] =
2660 	{
2661 		{ 'w', GNOCL_STRING },  /* widget */
2662 		{ 'g', GNOCL_STRING },  /* glade name */
2663 		{ 'e', GNOCL_STRING },  /* signal/event name */
2664 		{ 0 }
2665 	};
2666 
2667 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
2668 	ps[1].val.str = gtk_widget_get_name ( widget );
2669 	ps[2].val.str = "backspace";
2670 
2671 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
2672 
2673 }
2674 /**
2675 \brief      Handler function for a GtkEntry "preedit-changed" signal.
2676 \note
2677 **/
doOnPreEditChanged(GtkWidget * widget,gchar * preedit,gpointer data)2678 static void doOnPreEditChanged ( GtkWidget *widget, gchar *preedit, gpointer data )
2679 {
2680 
2681 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
2682 
2683 	GnoclPercSubst ps[] =
2684 	{
2685 		{ 'w', GNOCL_STRING },  /* widget */
2686 		{ 'g', GNOCL_STRING },  /* glade name */
2687 		{ 't', GNOCL_STRING },  /* signal/event name */
2688 		{ 0 }
2689 	};
2690 
2691 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
2692 	ps[1].val.str = gtk_widget_get_name ( widget );
2693 	ps[2].val.str = preedit;
2694 
2695 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
2696 
2697 }
2698 /**
2699 \brief      Connect GtkTextView "backspace" event to its handler.
2700 \note
2701 **/
gnoclOptOnBackSpace(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)2702 int gnoclOptOnBackSpace ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
2703 {
2704 	assert ( strcmp ( opt->optName, "-onBackSpace" ) == 0 );
2705 	return gnoclConnectOptCmd ( interp, obj, "backspace", G_CALLBACK ( doOnBackSpace ), opt, NULL, ret );
2706 }
2707 
2708 /**
2709 \brief
2710 \author     William J Giddings
2711 \date       15/Jan/2010
2712 \note
2713 \todo       Next step: How to get additional details from a signal?
2714             Substituation values would be:
2715                 %w   widget name
2716                 %t   type of event
2717                 %s   state of modifiers
2718 **/
doOnSelectAll(GtkWidget * widget,gboolean select,gpointer data)2719 static int doOnSelectAll ( GtkWidget *widget, gboolean select, gpointer data )
2720 {
2721 
2722 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
2723 
2724 	GnoclPercSubst ps[] =
2725 	{
2726 		{ 'w', GNOCL_STRING },  /* widget */
2727 		{ 'g', GNOCL_STRING },  /* glade name */
2728 		{ 's', GNOCL_INT },     /* either selected, or deselected */
2729 		{ 'e', GNOCL_STRING },  /* signal/event name */
2730 		{ 0 }
2731 	};
2732 
2733 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
2734 	ps[1].val.str = gtk_widget_get_name ( widget );
2735 	ps[2].val.i = select;
2736 	ps[3].val.str = "select-all";
2737 
2738 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
2739 
2740 }
2741 
2742 /**
2743 \brief
2744 **/
gnoclOptOnSelectAll(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)2745 int gnoclOptOnSelectAll ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
2746 {
2747 #ifdef DEBUG_PARSEOPTIONS
2748 	g_print ( "gnoclOptOnSelectAll\n" );
2749 #endif
2750 
2751 	assert ( strcmp ( opt->optName, "-onSelectAll" ) == 0 );
2752 
2753 	return gnoclConnectOptCmd ( interp, obj, "select-all", G_CALLBACK ( doOnSelectAll ), opt, NULL, ret );
2754 }
2755 
2756 
2757 /**
2758 \brief
2759 **/
doOnDeleteFromCursor(GtkTextView * text_view,GtkDeleteType type,gint count,gpointer user_data)2760 static gboolean doOnDeleteFromCursor ( GtkTextView *text_view, GtkDeleteType type, gint count, gpointer user_data )
2761 {
2762 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
2763 
2764 	GnoclPercSubst ps[] =
2765 	{
2766 		{ 'w', GNOCL_STRING },  /* widget */
2767 		{ 'g', GNOCL_STRING },  /* glade name */
2768 		{ 'n', GNOCL_INT }, 	/* the number of type units to delete */
2769 		{ 't', GNOCL_STRING }, 	/* the delete type, int */
2770 		{ 'T', GNOCL_STRING }, 	/* the delete type, string */
2771 		{ 0 }
2772 	};
2773 
2774 	ps[0].val.str = gnoclGetNameFromWidget ( text_view );
2775 	ps[1].val.str = gtk_widget_get_name ( GTK_WIDGET ( text_view ) );
2776 	ps[2].val.i = count;
2777 	ps[3].val.i = type;
2778 
2779 	switch ( type )
2780 	{
2781 		case GTK_DELETE_CHARS:
2782 			ps[4].val.str = "chars";
2783 			break;
2784 
2785 		case GTK_DELETE_WORD_ENDS:
2786 			ps[4].val.str = "word-ends";
2787 			break;
2788 
2789 		case GTK_DELETE_WORDS:
2790 			ps[4].val.str = "words";
2791 			break;
2792 
2793 		case GTK_DELETE_DISPLAY_LINES:
2794 			ps[4].val.str = "display-lines";
2795 			break;
2796 
2797 		case GTK_DELETE_PARAGRAPH_ENDS:
2798 			ps[4].val.str = "paragraph-ends";
2799 			break;
2800 
2801 		case GTK_DELETE_PARAGRAPHS:
2802 			ps[4].val.str = "paragraphs";
2803 			break;
2804 
2805 		case GTK_DELETE_WHITESPACE:
2806 			ps[4].val.str = "whitespace";
2807 			break;
2808 
2809 		default: {}
2810 	}
2811 
2812 	if ( gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 ) == TCL_OK )
2813 	{
2814 		int del;
2815 
2816 		if ( Tcl_GetBooleanFromObj ( NULL, Tcl_GetObjResult ( cs->interp ), &del ) == TCL_OK && del == 0 )
2817 		{
2818 			return TRUE;  /* ignore delete */
2819 		}
2820 	}
2821 
2822 	return FALSE; /* proceed: destroy widget */
2823 }
2824 
2825 
2826 /**
2827 \author     William J Giddings
2828 \date       02/06/08
2829 \note      Handle entry delete
2830 **/
gnoclOptOnDeleteFromCursor(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)2831 int gnoclOptOnDeleteFromCursor ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
2832 {
2833 #ifdef DEBUG_PARSEOPTIONS
2834 	g_print ( "gnoclOptOnDeleteFromCursor\n" );
2835 #endif
2836 
2837 	assert ( strcmp ( opt->optName, "-onDeleteFromCursor" ) == 0 );
2838 
2839 	return gnoclConnectOptCmd ( interp, obj, "delete-from-cursor", G_CALLBACK ( doOnDeleteFromCursor ), opt, NULL, ret );
2840 }
2841 
2842 
2843 /**
2844 \brief
2845 \author     William J Giddings
2846 \date       15/Jan/2010
2847 \note		Used by both text, entry and treeview widgets
2848 \todo
2849 
2850 
2851   GTK_MOVEMENT_LOGICAL_POSITIONS, move by forw/back graphemes
2852   GTK_MOVEMENT_VISUAL_POSITIONS,  move by left/right graphemes
2853   GTK_MOVEMENT_WORDS,             move by forward/back words
2854   GTK_MOVEMENT_DISPLAY_LINES,     move up/down lines (wrapped lines)
2855   GTK_MOVEMENT_DISPLAY_LINE_ENDS, move up/down lines (wrapped lines)
2856   GTK_MOVEMENT_PARAGRAPHS,        move up/down paragraphs (newline-ended lines)
2857   GTK_MOVEMENT_PARAGRAPH_ENDS,    move to either end of a paragraph
2858   GTK_MOVEMENT_PAGES,	          move by pages
2859   GTK_MOVEMENT_BUFFER_ENDS,       move to ends of the buffer
2860   GTK_MOVEMENT_HORIZONTAL_PAGES   move horizontally by pages
2861 
2862 **/
doOnMoveCursor(GtkWidget * widget,GtkMovementStep step,gint count,gint extend_selection,gpointer data)2863 static int doOnMoveCursor ( GtkWidget *widget, GtkMovementStep step, gint count, gint extend_selection, gpointer data )
2864 {
2865 
2866 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
2867 
2868 	GnoclPercSubst ps[] =
2869 	{
2870 
2871 		{ 'w', GNOCL_STRING },  /* widget */
2872 		{ 'g', GNOCL_STRING },  /* glade name */
2873 		{ 'c', GNOCL_INT},		/* count */
2874 		{ 's', GNOCL_STRING },  /* step */
2875 		{ 'x', GNOCL_BOOL},		/* extended selection */
2876 		{ 0 }
2877 	};
2878 
2879 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
2880 	ps[1].val.str = gtk_widget_get_name ( widget );
2881 
2882 	switch ( step )
2883 	{
2884 		case GTK_MOVEMENT_LOGICAL_POSITIONS:
2885 			{
2886 				//move by forw/back graphemes
2887 				ps[2].val.str = "gf/b";
2888 			}
2889 			break;
2890 
2891 		case GTK_MOVEMENT_VISUAL_POSITIONS:
2892 			{
2893 				//move by left/right graphemes
2894 				ps[2].val.str = "gl/r";
2895 			}
2896 			break;
2897 
2898 
2899 		case GTK_MOVEMENT_WORDS:
2900 			{
2901 				//move by forward/back words
2902 				ps[2].val.str = "wf/b";
2903 			}
2904 			break;
2905 
2906 		case GTK_MOVEMENT_DISPLAY_LINES:
2907 			{
2908 				//move up/down lines (wrapped lines)
2909 				ps[2].val.str = "dlu/d";
2910 			}
2911 			break;
2912 
2913 		case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
2914 			{
2915 				//move up/down lines (wrapped lines)
2916 				ps[2].val.str = "dleu/d";
2917 			}
2918 			break;
2919 
2920 		case GTK_MOVEMENT_PARAGRAPHS:
2921 			{
2922 				//move up/down paragraphs (newline-ended lines)
2923 				ps[2].val.str = "pu/d";
2924 			}
2925 			break;
2926 
2927 		case GTK_MOVEMENT_PARAGRAPH_ENDS:
2928 			{
2929 				//move to either end of a paragraph
2930 				ps[2].val.str = "pend";
2931 			}
2932 			break;
2933 
2934 		case GTK_MOVEMENT_PAGES:
2935 			{
2936 				//move by pages
2937 				ps[2].val.str = "p";
2938 			}
2939 			break;
2940 		case GTK_MOVEMENT_BUFFER_ENDS:
2941 			{
2942 				//move to ends of the buffer
2943 				ps[2].val.str = "eob";
2944 			}
2945 			break;
2946 		case GTK_MOVEMENT_HORIZONTAL_PAGES:
2947 			{
2948 				//move horizontally by pages
2949 				ps[2].val.str = "hp";
2950 			}
2951 			break;
2952 
2953 		default: {}
2954 	}
2955 
2956 
2957 	ps[3].val.i = count;
2958 	ps[4].val.i = extend_selection;
2959 
2960 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
2961 
2962 }
2963 
2964 /**
2965 \brief      Handler function for a GtkTextView "backspace" signal.
2966 \note
2967 **/
doOnActivateCurrentLink(GtkWidget * widget,gpointer data)2968 static void doOnActivateCurrentLink ( GtkWidget *widget, gpointer data )
2969 {
2970 
2971 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
2972 
2973 	GnoclPercSubst ps[] =
2974 	{
2975 		{ 'w', GNOCL_STRING },  /* widget */
2976 		{ 'g', GNOCL_STRING },  /* glade name */
2977 		{ 0 }
2978 	};
2979 
2980 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
2981 	ps[1].val.str = gtk_widget_get_name ( widget );
2982 
2983 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
2984 
2985 }
2986 
2987 /**
2988 \brief      Handler function for a GtkTextView "backspace" signal.
2989 \note
2990 **/
doOnActivateLink(GtkWidget * widget,gchar * uri,gpointer data)2991 static void doOnActivateLink ( GtkWidget *widget, gchar *uri, gpointer data )
2992 {
2993 
2994 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
2995 
2996 	GnoclPercSubst ps[] =
2997 	{
2998 		{ 'w', GNOCL_STRING },  /* widget */
2999 		{ 'g', GNOCL_STRING },  /* glade name */
3000 		{ 'u', GNOCL_STRING },  /* glade name */
3001 		{ 0 }
3002 	};
3003 
3004 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
3005 	ps[1].val.str = gtk_widget_get_name ( widget );
3006 	ps[2].val.str = uri;
3007 
3008 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
3009 
3010 }
3011 
3012 
3013 /**
3014 \author     William J Giddings
3015 \date       28/08/13
3016 \note		Called by gnocl::label widget
3017 * 			A keybinding signal which gets emitted when the user activates a link in the label.
3018 **/
gnoclOptOnActivateCurrentLink(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)3019 int gnoclOptOnActivateCurrentLink ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
3020 {
3021 
3022 	return gnoclConnectOptCmd ( interp, obj, "activate-current-link" , G_CALLBACK ( doOnActivateCurrentLink ), opt, NULL, ret );
3023 }
3024 
3025 
3026 /**
3027 \author     William J Giddings
3028 \date       28/08/13
3029 \note		Called by gnocl::label widget
3030 **/
gnoclOptOnActivateLink(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)3031 int gnoclOptOnActivateLink ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
3032 {
3033 
3034 	return gnoclConnectOptCmd ( interp, obj, "activate-link", G_CALLBACK ( doOnActivateLink ), opt, NULL, ret );
3035 }
3036 
3037 
3038 /**
3039 \author     William J Giddings
3040 \date       02/06/08
3041 \note		Used by both text, entry and treeview widgets, other widgets will have their own handler, e.g. iconview.
3042 **/
gnoclOptOnMoveCursor(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)3043 int gnoclOptOnMoveCursor ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
3044 {
3045 
3046 	return gnoclConnectOptCmd ( interp, obj,   "move-cursor" , G_CALLBACK ( doOnMoveCursor ), opt, NULL, ret );
3047 }
3048 
3049 /**
3050 \brief
3051 \author     William J Giddings
3052 \date       15/Jan/2010
3053 \note		Used by both text and entry widgets
3054 \todo
3055 
3056 
3057   GTK_SCROLL_STEPS,
3058   GTK_SCROLL_PAGES,
3059   GTK_SCROLL_ENDS,
3060   GTK_SCROLL_HORIZONTAL_STEPS,
3061   GTK_SCROLL_HORIZONTAL_PAGES,
3062   GTK_SCROLL_HORIZONTAL_ENDS
3063 
3064 
3065 **/
doOnMoveViewport(GtkTextView * text_view,GtkScrollStep step,gint count,gpointer user_data)3066 static int doOnMoveViewport ( GtkTextView  *text_view, GtkScrollStep step, gint count, gpointer user_data )
3067 {
3068 
3069 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
3070 
3071 	GnoclPercSubst ps[] =
3072 	{
3073 
3074 		{ 'w', GNOCL_STRING },  /* widget */
3075 		{ 'g', GNOCL_STRING },  /* glade name */
3076 		{ 'c', GNOCL_INT},		/* count */
3077 		{ 't', GNOCL_INT },  	/* step, int */
3078 		{ 'T', GNOCL_STRING},  	/* step, string */
3079 		{ 0 }
3080 	};
3081 
3082 	ps[0].val.str = gnoclGetNameFromWidget ( text_view );
3083 	ps[1].val.str = gtk_widget_get_name ( GTK_WIDGET ( text_view ) );
3084 	ps[2].val.i = count;
3085 	ps[3].val.i = step;
3086 
3087 	switch ( step )
3088 	{
3089 		case GTK_SCROLL_STEPS:
3090 			ps[4].val.str = "steps";
3091 			break;
3092 
3093 		case GTK_SCROLL_PAGES:
3094 			ps[4].val.str = "pages";
3095 			break;
3096 
3097 		case GTK_SCROLL_ENDS:
3098 			ps[4].val.str = "scroll-ends";
3099 			break;
3100 
3101 		case GTK_SCROLL_HORIZONTAL_STEPS:
3102 			ps[4].val.str = "horizontal-steps";
3103 			break;
3104 
3105 		case GTK_SCROLL_HORIZONTAL_PAGES:
3106 			ps[4].val.str = "horizontal-pages";
3107 			break;
3108 
3109 		case GTK_SCROLL_HORIZONTAL_ENDS:
3110 			ps[4].val.str = "horizontal-ends";
3111 			break;
3112 
3113 		default: {}
3114 	}
3115 
3116 
3117 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
3118 
3119 }
3120 
3121 /**
3122 \author     William J Giddings
3123 \date       02/06/08
3124 \note
3125 **/
gnoclOptOnMoveViewport(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)3126 int gnoclOptOnMoveViewport ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
3127 {
3128 	assert ( strcmp ( opt->optName, "-onMoveViewport" ) == 0 );
3129 
3130 	return gnoclConnectOptCmd ( interp, obj,   "move-viewport" , G_CALLBACK ( doOnMoveViewport ), opt, NULL, ret );
3131 }
3132 
3133 /**
3134 \author     William J Giddings
3135 \date       02/06/08
3136 \note      ????
3137 **/
gnoclOptOnPageHorizontally(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)3138 int gnoclOptOnPageHorizontally ( Tcl_Interp *interp, GnoclOption *opt,
3139 								 GObject *obj, Tcl_Obj **ret )
3140 {
3141 	assert ( strcmp ( opt->optName, "-onPageHorizontally" ) == 0 );
3142 
3143 	char warmMsg[] = "WARNING: Text widget option -onPageHorizontally."
3144 					 "This signal should not be used anymore, instead use the \"move-cursor\""
3145 					 "signal with the GTK_MOVEMENT_HORIZONTAL_PAGES granularity.";
3146 
3147 	Tcl_SetResult ( interp, warmMsg, TCL_STATIC );
3148 	return TCL_OK;
3149 }
3150 
3151 /**
3152 \brief     Handles the 'set-anchor' signal.
3153 \author    William J Giddings
3154 \date      30/04/2010
3155 \since     0.9.95
3156 \note      Used by: gnome::text
3157 \**/
doOnSetAnchor(GtkTextView * text_view,gpointer user_data)3158 static void doOnSetAnchor ( GtkTextView *text_view, gpointer user_data )
3159 {
3160 
3161 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
3162 	GtkTextIter iter;
3163 	GtkTextBuffer *buffer;
3164 	gint row, col;
3165 
3166 	GnoclPercSubst ps[] =
3167 	{
3168 		{ 'w', GNOCL_STRING },  /* widget name */
3169 		{ 'g', GNOCL_STRING },  /* glade name */
3170 		{ 'r', GNOCL_INT},		/* row */
3171 		{ 'c', GNOCL_INT},		/* col */
3172 		{ 0 }
3173 	};
3174 
3175 	ps[0].val.str = gnoclGetNameFromWidget ( text_view );
3176 	ps[1].val.str = gtk_widget_get_name ( GTK_WIDGET ( text_view ) );
3177 
3178 	/* convenience call, get the position of the insertion */
3179 	buffer = gtk_text_view_get_buffer ( text_view );
3180 	gtk_text_buffer_get_iter_at_mark ( buffer, &iter, gtk_text_buffer_get_insert ( buffer ) );
3181 	row = gtk_text_iter_get_line ( &iter );
3182 	col = gtk_text_iter_get_line_offset ( &iter );
3183 
3184 	ps[2].val.i = row;
3185 	ps[3].val.i = col;
3186 
3187 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
3188 }
3189 
3190 /**
3191 \author     William J Giddings
3192 \date       02/06/08
3193 \note      ????
3194 **/
gnoclOptOnSetAnchor(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)3195 int gnoclOptOnSetAnchor ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )  /* stub */
3196 {
3197 	/* check the name of the signal is correct for this function */
3198 	assert ( strcmp ( opt->optName, "-onSetAnchor" ) == 0 );
3199 
3200 	/* connect the signal with its callback function */
3201 	return gnoclConnectOptCmd ( interp, obj, "set-anchor", G_CALLBACK ( doOnSetAnchor ), opt, NULL, ret );
3202 }
3203 
3204 
3205 /**
3206 \brief     Handles the 'set-anchor' signal.
3207 \author    William J Giddings
3208 \date      30/04/2010
3209 \since     0.9.95
3210 \note      Used by: gnome::text
3211 \todo		NEEDS COMPLETION
3212 \**/
doOnScrollAdjustments(GtkTextView * horizontal,GtkAdjustment * vertical,GtkAdjustment * arg2,gpointer user_data)3213 static void doOnScrollAdjustments ( GtkTextView *horizontal, GtkAdjustment *vertical, GtkAdjustment *arg2, gpointer user_data )
3214 {
3215 
3216 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
3217 	GtkTextIter iter;
3218 	GtkTextBuffer *buffer;
3219 	gint row, col;
3220 
3221 	GnoclPercSubst ps[] =
3222 	{
3223 		{ 'w', GNOCL_STRING },  /* widget name */
3224 		{ 'g', GNOCL_STRING },  /* glade name */
3225 		{ 0 }
3226 	};
3227 
3228 	ps[0].val.str = gnoclGetNameFromWidget ( horizontal );
3229 	ps[1].val.str = gtk_widget_get_name ( GTK_WIDGET ( horizontal ) );
3230 
3231 
3232 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
3233 }
3234 
3235 
3236 /**
3237 \brief
3238 \author		William J Giddings
3239 \date		30/04/2010
3240 \note
3241 **/
gnoclOptOnScrollAdjustments(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)3242 int gnoclOptOnScrollAdjustments ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
3243 {
3244 	/* check the name of the signal is correct for this function */
3245 	assert ( strcmp ( opt->optName, "-onSetScrollAdjustments" ) == 0 );
3246 
3247 	/* connect the signal with its callback function */
3248 	return gnoclConnectOptCmd ( interp, obj, "set-scroll-adjustments" , G_CALLBACK ( doOnScrollAdjustments ), opt, NULL, ret );
3249 }
3250 
3251 
3252 /**
3253 \brief     Handles the "toggle-overwrite" signal.
3254 \author    William J Giddings
3255 \date      30/04/2010
3256 \since     0.9.95
3257 \note      Used by: gnome::text
3258 \**/
doOnToggleOverWrite(GtkTextView * text_view,gpointer user_data)3259 static void doOnToggleOverWrite ( GtkTextView *text_view, gpointer user_data )
3260 {
3261 
3262 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
3263 
3264 	GnoclPercSubst ps[] =
3265 	{
3266 		{ 'w', GNOCL_STRING },  /* widget name */
3267 		{ 'g', GNOCL_STRING },  /* glade name */
3268 		{ 's', GNOCL_INT }, 	/* overwritable?, boolean*/
3269 		{ 0 }
3270 	};
3271 
3272 	ps[0].val.str = gnoclGetNameFromWidget ( text_view );
3273 	ps[1].val.str = gtk_widget_get_name ( GTK_WIDGET ( text_view ) );
3274 	ps[1].val.str = gtk_text_view_get_overwrite ( text_view );
3275 
3276 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
3277 }
3278 
3279 /**
3280 \brief
3281 \author
3282 \date
3283 \note
3284 **/
gnoclOptOnToggleOverwrite(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)3285 int gnoclOptOnToggleOverwrite ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
3286 {
3287 	/* check the name of the signal is correct for this function */
3288 	assert ( strcmp ( opt->optName, "-onToggleOverWrite" ) == 0 );
3289 
3290 	/* connect the signal with its callback function */
3291 	return gnoclConnectOptCmd ( interp, obj, "toggle-overwrite" , G_CALLBACK ( doOnToggleOverWrite ), opt, NULL, ret );
3292 }
3293 
3294 /**
3295 \brief
3296 \author
3297 \date
3298 \note
3299 **/
gnoclOptOnPreEditChanged(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)3300 int gnoclOptOnPreEditChanged ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
3301 {
3302 	//return TCL_OK;
3303 	assert ( strcmp ( opt->optName, "-onPreeditChanged" ) == 0 );
3304 	return gnoclConnectOptCmd ( interp, obj,  "preedit-changed" , G_CALLBACK ( doOnPreEditChanged ), opt, NULL, ret );
3305 }
3306 /**
3307 \brief
3308 \author
3309 \date
3310 \note
3311 **/
gnoclOptOnBackspace(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)3312 int gnoclOptOnBackspace ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
3313 {
3314 	//return TCL_OK;
3315 	assert ( strcmp ( opt->optName, "-onBackspace" ) == 0 );
3316 	return gnoclConnectOptCmd ( interp, obj,  "backspace" , G_CALLBACK ( doOnBackSpace ), opt, NULL, ret );
3317 }
3318 
3319 /**
3320 \brief
3321 **/
doOnNotify(GObject * gobject,GParamSpec * pspec,gpointer user_data)3322 static void doOnNotify ( GObject *gobject, GParamSpec *pspec, gpointer user_data )
3323 {
3324 #ifdef DEBUG_PARSEOPTIONS
3325 	g_print ( "%s\n", __FUNCTION__ );
3326 #endif
3327 
3328 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
3329 
3330 	GnoclPercSubst ps[] =
3331 	{
3332 		{ 'w', GNOCL_STRING },  /* widget name */
3333 		{ 'g', GNOCL_STRING },  /* glade name */
3334 
3335 		{ 0 }
3336 	};
3337 
3338 	GtkWidget * treeView;
3339 
3340 	treeView = gtk_tree_view_column_get_tree_view  ( GTK_TREE_VIEW_COLUMN ( gobject ) );
3341 
3342 	ps[0].val.str = gnoclGetNameFromWidget ( GTK_WIDGET ( treeView ) );
3343 	ps[1].val.str = gtk_widget_get_name ( GTK_WIDGET ( treeView ) );
3344 
3345 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
3346 }
3347 
3348 /**
3349 \brief	Implement notification event for object property changes
3350 **/
gnoclOptNotify(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)3351 int gnoclOptNotify ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
3352 {
3353 #ifdef DEBUG_PARSEOPTIONS
3354 	g_print ( "%s\n", __FUNCTION__ );
3355 #endif
3356 
3357 	return gnoclConnectOptCmd ( interp, obj,  "notify", G_CALLBACK ( doOnNotify ), opt, NULL, ret );
3358 
3359 }
3360 
3361 /**
3362 \brief
3363 **/
gnoclWinfoNotify(Tcl_Interp * interp,GObject * obj,gchar * command)3364 int gnoclWinfoNotify ( Tcl_Interp *interp, GObject *obj, gchar *command )
3365 {
3366 
3367 	gnoclDisconnect ( obj, "notify", G_CALLBACK ( doOnNotify ) );
3368 
3369 	command = g_strdup ( command );
3370 
3371 	GnoclCommandData *cs = g_new ( GnoclCommandData, 1 );
3372 	cs->command = g_strdup ( command );
3373 	cs->interp = interp;
3374 
3375 	g_signal_connect_data ( obj, "notify", G_CALLBACK ( doOnNotify ), cs, destroyCmdData, ( GConnectFlags ) 0 );
3376 	g_object_set_data ( obj, signal, ( gpointer ) cs->command );
3377 
3378 	return TCL_OK;
3379 
3380 }
3381 
3382 
3383 /**
3384 \brief      Enable motion events for during any button press
3385 \author     William J Giddings
3386 \date       18/Feb/2010
3387 \note
3388 **/
gnoclOptOnButtonMotion(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)3389 int gnoclOptOnButtonMotion ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
3390 {
3391 	assert ( strcmp ( opt->optName, "-onButtonMotion" ) == 0 );
3392 	return gnoclConnectOptCmd ( interp, obj, "motion-notify-event", G_CALLBACK ( doOnMotion ), opt, NULL, ret );
3393 }
3394 
3395 /**
3396 \brief
3397 \author
3398 \date
3399 \note
3400 **/
gnoclOptOnMotion(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)3401 int gnoclOptOnMotion ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
3402 {
3403 	assert ( strcmp ( opt->optName, "-onMotion" ) == 0 || strcmp ( opt->optName, "-onPointerMotion" ) == 0 );
3404 	return gnoclConnectOptCmd ( interp, obj, "motion-notify-event", G_CALLBACK ( doOnMotion ), opt, NULL, ret );
3405 }
3406 
3407 /**
3408 \brief      Yet to be annotated
3409 \author     William J Giddings
3410 \date       10/05/09
3411 **/
doOnMoveFocus(GtkWidget * widget,int direction,gpointer data)3412 static gboolean doOnMoveFocus  ( GtkWidget *widget, int direction, gpointer data )
3413 {
3414 
3415 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
3416 
3417 	GnoclPercSubst ps[] =
3418 	{
3419 		{ 'w', GNOCL_STRING },  /* widget */
3420 		{ 'd', GNOCL_STRING },  /* widget */
3421 		{ 'g', GNOCL_STRING },  /* glade name */
3422 		{ 0 }
3423 	};
3424 
3425 	gchar *str;
3426 
3427 	switch ( direction )
3428 	{
3429 		case GTK_DIR_TAB_FORWARD:
3430 			{
3431 				sprintf ( str, "tab-forward" );
3432 				break;
3433 			}
3434 
3435 		case GTK_DIR_TAB_BACKWARD:
3436 			{
3437 				sprintf ( str, "tab-backward" );
3438 				break;
3439 			}
3440 
3441 		case GTK_DIR_UP:
3442 			{
3443 				sprintf ( str, "dir-up" );
3444 				break;
3445 			}
3446 
3447 		case GTK_DIR_DOWN:
3448 			{
3449 				sprintf ( str, "dir-down" );
3450 				break;
3451 			}
3452 
3453 		case GTK_DIR_LEFT:
3454 			{
3455 				sprintf ( str, "dir-left" );
3456 				break;
3457 			}
3458 
3459 		case GTK_DIR_RIGHT:
3460 			{
3461 				sprintf ( str, "dir-right" );
3462 				break;
3463 			}
3464 	}
3465 
3466 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
3467 	ps[1].val.str = str;
3468 	ps[2].val.str = gtk_widget_get_name ( GTK_WIDGET ( widget ) );
3469 
3470 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
3471 	return 0;
3472 }
3473 
3474 /**
3475 \brief      Yet to be annotated
3476 \author     William J Giddings
3477 \date       10/05/09
3478 **/
gnoclOptOnMoveFocus(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)3479 int gnoclOptOnMoveFocus ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
3480 {
3481 	assert ( strcmp ( opt->optName, "-onMoveFocus" ) == 0 );
3482 	return gnoclConnectOptCmd ( interp, obj, "move-focus", G_CALLBACK ( doOnMoveFocus ), opt, NULL, ret );
3483 }
3484 
doOnEnterLeave(GtkWidget * widget,GdkEventCrossing * event,gpointer data)3485 static gboolean doOnEnterLeave ( GtkWidget *widget, GdkEventCrossing *event, gpointer data )
3486 {
3487 
3488 	/*
3489 	typedef enum
3490 	{
3491 	  GTK_DIR_TAB_FORWARD,
3492 	  GTK_DIR_TAB_BACKWARD,
3493 	  GTK_DIR_UP,
3494 	  GTK_DIR_DOWN,
3495 	  GTK_DIR_LEFT,
3496 	  GTK_DIR_RIGHT
3497 	} GtkDirectionType;
3498 	*/
3499 
3500 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
3501 
3502 	GnoclPercSubst ps[] =
3503 	{
3504 		{ 'w', GNOCL_STRING },  /* widget */
3505 		{ 'x', GNOCL_INT },
3506 		{ 'y', GNOCL_INT },
3507 		{ 'X', GNOCL_INT },
3508 		{ 'Y', GNOCL_INT },
3509 		{ 's', GNOCL_INT },
3510 		{ 'g', GNOCL_STRING },  /* glade name */
3511 		{ 0 }
3512 	};
3513 
3514 
3515 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
3516 	ps[1].val.i = event->x;
3517 	ps[2].val.i = event->y;
3518 	ps[3].val.i = event->x_root;
3519 	ps[4].val.i = event->y_root;
3520 	ps[5].val.i = event->state;
3521 	ps[6].val.str = gtk_widget_get_name ( GTK_WIDGET ( widget ) );
3522 
3523 	/* TODO: gnocl::buttonStateToList -> {MOD1 MOD3 BUTTON2...} */
3524 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
3525 	return 0;
3526 }
3527 
3528 /**
3529 \brief      Callback function to focus change event.
3530 \author     William J Giddings
3531 \date       15/10/08
3532 **/
doOnFocus(GtkWidget * widget,GdkEventFocus * event,gpointer data)3533 static gboolean doOnFocus ( GtkWidget *widget, GdkEventFocus *event, gpointer data )
3534 {
3535 
3536 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
3537 
3538 	GnoclPercSubst ps[] =
3539 	{
3540 		{ 't', GNOCL_STRING },  /* toplevel */
3541 		{ 'p', GNOCL_STRING },  /* parent */
3542 		{ 'w', GNOCL_STRING },  /* widget */
3543 		{ 'g', GNOCL_STRING },  /* glade name */
3544 		{ 0 }
3545 	};
3546 
3547 	ps[0].val.str = gnoclGetNameFromWidget ( gtk_widget_get_toplevel ( widget ) );
3548 	ps[1].val.str = gnoclGetNameFromWidget ( gtk_widget_get_parent ( widget ) );
3549 	ps[2].val.str = gnoclGetNameFromWidget ( widget );
3550 	ps[3].val.str = gtk_widget_get_name ( GTK_WIDGET ( widget ) );
3551 
3552 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
3553 	return 0;
3554 }
3555 
3556 /**
3557 \brief
3558 \author
3559 \date
3560 \note
3561 **/
gnoclOptOnFocus(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)3562 int gnoclOptOnFocus ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
3563 {
3564 
3565 	switch  ( *opt->propName )
3566 	{
3567 		case 'I':
3568 			{
3569 
3570 				return gnoclConnectOptCmd ( interp, obj, "focus-in-event", G_CALLBACK ( doOnFocus ), opt, NULL, ret );
3571 				break;
3572 			}
3573 
3574 		case 'O':
3575 			{
3576 				return gnoclConnectOptCmd ( interp, obj, "focus-out-event", G_CALLBACK ( doOnFocus ), opt, NULL, ret );
3577 				break;
3578 			}
3579 
3580 		default:
3581 			{
3582 				// assert( 0 );
3583 				return TCL_ERROR;
3584 			}
3585 	}
3586 }
3587 
3588 /*
3589 int gnoclOptOnFocus ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
3590 {
3591     assert ( *opt->propName == 'I' || *opt->propName == 'O' );
3592     return gnoclConnectOptCmd ( interp, obj, *opt->propName == 'I' ?  "focus-in-event" : "focus-out-event", G_CALLBACK ( doOnFocus ), opt, NULL, ret );
3593 }
3594 */
3595 
3596 /**
3597 \brief
3598 \author
3599 \date
3600 \note
3601 **/
gnoclOptOnEnterLeave(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)3602 int gnoclOptOnEnterLeave ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
3603 {
3604 	assert ( strcmp ( opt->optName, "-onEnter" ) == 0 || strcmp ( opt->optName, "-onLeave" ) == 0 );
3605 	return gnoclConnectOptCmd ( interp, obj, opt->optName[3] == 'E' ? "enter-notify-event" : "leave-notify-event", G_CALLBACK ( doOnEnterLeave ), opt, NULL, ret );
3606 }
3607 
3608 /**
3609 \brief
3610 \author     William J Giddings
3611 \date       10/05/09
3612 **/
gnoclOptOnProximityInOut(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)3613 int gnoclOptOnProximityInOut ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
3614 {
3615 	assert ( strcmp ( opt->optName, "-onProximityIn" ) == 0 || strcmp ( opt->optName, "-onProximityOut" ) == 0 );
3616 	return gnoclConnectOptCmd ( interp, obj, opt->optName[3] == 'I' ? "proximity-in-event" : "proximity-out-event", G_CALLBACK ( doOnEnterLeave ), opt, NULL, ret );
3617 }
3618 
3619 
3620 
3621 /**
3622 \brief	callback handler for GTK_BUTTON widgets
3623 **/
doOnColorSet(GtkWidget * color_button,gpointer user_data)3624 static void doOnColorSet   ( GtkWidget *color_button, gpointer user_data )
3625 {
3626 #ifdef DEBUG_PARSEOPTIONS
3627 	g_print ( "%s\n", __FUNCTION__ );
3628 #endif
3629 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
3630 
3631 	gchar str1[32], str2[32], str3[32], str4[32], str5[32];
3632 	gint r, g, b;
3633 	gdouble h, s, v;
3634 
3635 	GnoclPercSubst ps[] =
3636 	{
3637 		{ 'w', GNOCL_STRING },  /* widget */
3638 		{ 'g', GNOCL_STRING },  /* glade name */
3639 		{ 'd', GNOCL_STRING },  /* data */
3640 		{ 'C', GNOCL_STRING },  /* colour selected 0-65535*/
3641 		{ 'c', GNOCL_STRING },  /* colour selected 0-255*/
3642 		{ 'x', GNOCL_STRING },  /* colour selected 00-FF*/
3643 		{ 'f', GNOCL_STRING },  /* colour selected 0-1.0*/
3644 		{ 'h', GNOCL_STRING },  /* colour as HSV*/
3645 		{ 0 }
3646 	};
3647 
3648 	const char *dataID = "gnocl::data";
3649 	ButtonParams *para = g_object_get_data ( G_OBJECT ( color_button ), dataID );
3650 
3651 	GdkColor color;
3652 
3653 	gtk_color_button_get_color ( color_button, &color );
3654 
3655 	ps[0].val.str = gnoclGetNameFromWidget ( color_button );
3656 	ps[1].val.str = gtk_widget_get_name ( color_button );
3657 	ps[2].val.str = g_object_get_data ( color_button, "gnocl::data" );
3658 
3659 	r = 255 * color.red / 65535; g =  255 * color.green / 65535; b = 255 * color.blue / 65535;
3660 
3661 	gtk_rgb_to_hsv  ( ( float ) r / 255.0, ( float ) g / 255, ( float ) b / 255, &h, &s, &v );
3662 
3663 	sprintf ( str1, "%d %d %d", color.red, color.green, color.blue );
3664 	sprintf ( str2, "%d %d %d", r, g, b );
3665 	sprintf ( str3, "#%02X%02X%02X", r, g, b );
3666 	sprintf ( str4, "%1.5f %1.5f %1.5f", ( float ) r / 255.0, ( float ) g / 255, ( float ) b / 255 );
3667 	sprintf ( str5, "%.0f %.0f %.0f", 100 * h, 100 * s, 100 * v );
3668 
3669 	ps[3].val.str = str1;
3670 	ps[4].val.str = str2;
3671 	ps[5].val.str = str3;
3672 	ps[6].val.str = str4;
3673 	ps[7].val.str = str5;
3674 
3675 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
3676 
3677 }
3678 
3679 
3680 /**
3681 \brief	callback handler for GTK_BUTTON widgets
3682 **/
doOnClicked(GtkWidget * button,gpointer user_data)3683 static void doOnClicked   ( GtkWidget *button, gpointer user_data )
3684 {
3685 #ifdef DEBUG_PARSEOPTIONS
3686 	g_print ( "%s\n", __FUNCTION__ );
3687 #endif
3688 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
3689 
3690 	GnoclPercSubst ps[] =
3691 	{
3692 		{ 'w', GNOCL_STRING },  /* widget */
3693 		{ 'p', GNOCL_STRING },  /* parent */
3694 		{ 'g', GNOCL_STRING },  /* glade name */
3695 		{ 'd', GNOCL_STRING },  /* data */
3696 		{ 0 }
3697 	};
3698 
3699 	const char *dataID = "gnocl::data";
3700 	ButtonParams *para = g_object_get_data ( G_OBJECT ( button ), dataID );
3701 
3702 	ps[0].val.str = gnoclGetNameFromWidget ( button );
3703 	ps[1].val.str = gnoclGetNameFromWidget ( gtk_widget_get_parent ( button ) );
3704 	ps[2].val.str = gtk_widget_get_name ( button );
3705 	ps[3].val.str = g_object_get_data ( button, "gnocl::data" );
3706 
3707 
3708 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
3709 
3710 }
3711 
3712 /**
3713 \brief
3714 	widget button, *** NOT ** mouse button
3715 **/
doOnToolButtonClicked(GtkToolButton * toolbutton,gpointer user_data)3716 static void doOnToolButtonClicked ( GtkToolButton *toolbutton, gpointer user_data )
3717 {
3718 #ifdef DEBUG_PARSEOPTIONS
3719 	g_print ( "%s\n", __FUNCTION__ );
3720 #endif
3721 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
3722 
3723 	GnoclPercSubst ps[] =
3724 	{
3725 		{ 'w', GNOCL_STRING },  /* widget */
3726 		{ 'g', GNOCL_STRING },  /* glade name */
3727 		{ 'p', GNOCL_STRING },  /* parent */
3728 		{ 'd', GNOCL_STRING },  /* data */
3729 		{ 0 }
3730 	};
3731 
3732 	const char *dataID = "gnocl::para";
3733 	ButtonParams *para = g_object_get_data ( G_OBJECT ( toolbutton ), dataID );
3734 
3735 	ps[0].val.str = gnoclGetNameFromWidget ( toolbutton );
3736 	ps[1].val.str = gtk_widget_get_name ( GTK_WIDGET ( toolbutton ) );
3737 	ps[2].val.str = gtk_widget_get_parent ( GTK_WIDGET ( toolbutton ) );
3738 
3739 	ps[3].val.str = para->data;
3740 
3741 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
3742 
3743 }
3744 
3745 
3746 /**
3747 \brief
3748 **/
doOnInteractiveSearch(GtkTreeView * treeview,gpointer user_data)3749 static void doOnInteractiveSearch   ( GtkTreeView *treeview, gpointer user_data )
3750 {
3751 #ifdef DEBUG_PARSEOPTIONS
3752 	g_print ( "%s\n", __FUNCTION__ );
3753 #endif
3754 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
3755 
3756 	GtkEntry *entry = gtk_tree_view_get_search_entry ( treeview );
3757 
3758 
3759 	GnoclPercSubst ps[] =
3760 	{
3761 		{ 'w', GNOCL_STRING },  /* widget */
3762 		{ 'g', GNOCL_STRING },  /* glade name */
3763 		{ 'c', GNOCL_INT},  	/* search column */
3764 		{ 'e', GNOCL_STRING },  /* search entry widget */
3765 		{ 0 }
3766 	};
3767 
3768 
3769 
3770 	ps[0].val.str = gnoclGetNameFromWidget ( treeview );
3771 	ps[1].val.str = gtk_widget_get_name ( GTK_WIDGET ( treeview ) );
3772 	ps[2].val.i = gtk_tree_view_get_search_column ( treeview );;
3773 
3774 	if ( entry != NULL )
3775 	{
3776 		ps[3].val.str = gnoclGetNameFromWidget ( entry );
3777 	}
3778 
3779 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
3780 
3781 }
3782 
3783 /**
3784 \brief
3785 **/
doOnColumnClicked(GtkTreeViewColumn * treeviewcolumn,gpointer user_data)3786 static void doOnColumnClicked ( GtkTreeViewColumn *treeviewcolumn, gpointer user_data )
3787 {
3788 #ifdef DEBUG_PARSEOPTIONS
3789 	g_print ( "%s\n", __FUNCTION__ );
3790 #endif
3791 
3792 	GtkWidget *tree;
3793 	gint col;
3794 
3795 	tree = gtk_tree_view_column_get_tree_view ( treeviewcolumn );
3796 
3797 	g_object_get ( tree, "search-column", &col, NULL );
3798 
3799 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
3800 
3801 	GnoclPercSubst ps[] =
3802 	{
3803 		{ 'w', GNOCL_STRING },  /* widget */
3804 		{ 'c', GNOCL_INT },  	/* active column number */
3805 		{ 0 }
3806 	};
3807 
3808 	ps[0].val.str = gnoclGetNameFromWidget ( tree );
3809 	ps[1].val.i = col;
3810 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
3811 
3812 }
3813 
3814 /**
3815 \brief	Handle entry icon signals.
3816 **/
doOnIconPress(GtkWidget * entry,GtkEntryIconPosition icon_pos,GdkEvent * event,gpointer user_data)3817 static void doOnIconPress ( GtkWidget *entry, GtkEntryIconPosition icon_pos, GdkEvent  *event, gpointer user_data )
3818 {
3819 #ifdef DEBUG_PARSEOPTIONS
3820 	g_print ( "%s %d\n", __FUNCTION__, icon_pos );
3821 #endif
3822 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
3823 
3824 	GnoclPercSubst ps[] =
3825 	{
3826 		{ 'w', GNOCL_STRING },  /* widget */
3827 		{ 'b', GNOCL_STRING },
3828 		{ 'p', GNOCL_STRING },  /* icon position */
3829 		{ 'g', GNOCL_STRING },  /* glade name */
3830 		{ 't', GNOCL_STRING },  /* glade name */
3831 		{ 0 }
3832 	};
3833 
3834 	ps[0].val.str = gnoclGetNameFromWidget ( entry );
3835 
3836 	switch ( event->type )
3837 	{
3838 		case GDK_BUTTON_PRESS:   ps[1].val.str = "buttonPress"; break;
3839 		case GDK_2BUTTON_PRESS:  ps[1].val.str = "button2Press"; break;
3840 		case GDK_3BUTTON_PRESS:  ps[1].val.str = "button3Press"; break;
3841 		case GDK_BUTTON_RELEASE: ps[1].val.str = "buttonRelease"; break;
3842 		default:  assert ( 0 ); break;
3843 	}
3844 
3845 	if ( icon_pos )
3846 	{
3847 		ps[2].val.str = "secondary";
3848 	}
3849 
3850 	else
3851 	{
3852 		ps[2].val.str = "primary";
3853 	}
3854 
3855 
3856 	ps[3].val.str = gtk_widget_get_name ( GTK_WIDGET ( entry ) );
3857 
3858 	ps[4].val.str = gtk_entry_get_text  ( GTK_WIDGET ( entry ) );
3859 
3860 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
3861 }
3862 
3863 
3864 /**
3865 \brief
3866 	Handle mouse button presses -not a button widget click.
3867 **/
doOnMouseButton(GtkWidget * widget,GdkEventButton * event,gpointer data)3868 static void doOnMouseButton ( GtkWidget *widget, GdkEventButton *event, gpointer data )
3869 {
3870 #ifdef DEBUG_PARSEOPTIONS
3871 	g_print ( "%s\n", __FUNCTION__ );
3872 #endif
3873 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
3874 
3875 	GnoclPercSubst ps[] =
3876 	{
3877 		{ 'w', GNOCL_STRING },  /* widget */
3878 		{ 't', GNOCL_STRING },
3879 		{ 'x', GNOCL_INT },
3880 		{ 'y', GNOCL_INT },
3881 		{ 'X', GNOCL_INT },
3882 		{ 'Y', GNOCL_INT },
3883 		{ 'b', GNOCL_INT },
3884 		{ 's', GNOCL_INT },
3885 		{ 'g', GNOCL_STRING },  /* glade name */
3886 		{ 'e', GNOCL_STRING },  /* event type */
3887 		{ 0 }
3888 	};
3889 
3890 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
3891 	ps[8].val.str = gtk_widget_get_name ( widget );
3892 
3893 
3894 	switch ( event->type )
3895 	{
3896 		case GDK_BUTTON_PRESS:
3897 			{
3898 				ps[1].val.str = "buttonPress";
3899 			}
3900 			break;
3901 		case GDK_2BUTTON_PRESS:
3902 			{
3903 				ps[1].val.str = "button2Press";
3904 			} break;
3905 		case GDK_3BUTTON_PRESS:
3906 			{
3907 				ps[1].val.str = "button3Press";
3908 			}
3909 			break;
3910 		case GDK_BUTTON_RELEASE:
3911 			{
3912 				ps[1].val.str = "buttonRelease";
3913 			} break;
3914 		default:  assert ( 0 ); break;
3915 	}
3916 
3917 	ps[2].val.i = event->x;
3918 	ps[3].val.i = event->y;
3919 	ps[4].val.i = event->x_root;
3920 	ps[5].val.i = event->y_root;
3921 	ps[6].val.i = event->button;
3922 	ps[7].val.i = event->state;
3923 
3924 	ps[9].val.str = "button-press-event";
3925 
3926 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
3927 }
3928 
3929 
3930 /**
3931 \brief
3932 **/
doOnUndoRedo(GtkWidget * widget,gpointer data)3933 static void doOnUndoRedo ( GtkWidget *widget, gpointer data )
3934 {
3935 #ifdef DEBUG_PARSEOPTIONS
3936 	g_print ( "%s\n", __FUNCTION__ );
3937 #endif
3938 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
3939 
3940 	GnoclPercSubst ps[] =
3941 	{
3942 		{ 'w', GNOCL_STRING },  /* widget */
3943 		{ 'g', GNOCL_STRING },  /* glade name */
3944 		{ 'u', GNOCL_INT },  	/* flag denoting whether further undos possible */
3945 		{ 'r', GNOCL_INT },  	/* flag denoting whether further redos possible */
3946 		{ 0 }
3947 	};
3948 
3949 
3950 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
3951 	ps[1].val.str = gtk_widget_get_name ( widget );
3952 	//ps[2].val.i = gtk_source_undo_manager_can_undo ( GTK_UNDO_VIEW ( widget )->undo_manager_ );
3953 	//ps[3].val.i = gtk_source_undo_manager_can_redo ( GTK_UNDO_VIEW ( widget )->undo_manager_ );
3954 
3955 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
3956 }
3957 
3958 
3959 /**
3960 \brief
3961 \author
3962 \date
3963 \note
3964 **/
doOnFontSet(GtkWidget * widget,gpointer data)3965 static void doOnFontSet ( GtkWidget *widget, gpointer data )
3966 {
3967 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
3968 
3969 	GnoclPercSubst ps[] =
3970 	{
3971 		{ 'w', GNOCL_STRING },  /* widget */
3972 		{ 'f', GNOCL_STRING },  /* widget */
3973 		{ 0 }
3974 	};
3975 
3976 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
3977 	ps[1].val.str = gtk_font_button_get_font_name ( widget );
3978 
3979 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
3980 
3981 }
3982 
3983 /**
3984 \brief
3985 \author
3986 \date
3987 \note
3988 **/
doOnFolderSet(GtkWidget * widget,gpointer data)3989 static void doOnFolderSet ( GtkWidget *widget, gpointer data )
3990 {
3991 #ifdef DEBUG_PARSEOPTIONS
3992 	g_print ( "%s\n", __FUNCTION__ );
3993 #endif
3994 
3995 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
3996 
3997 	GnoclPercSubst ps[] =
3998 	{
3999 		{ 'w', GNOCL_STRING },  /* widget */
4000 		{ 'f', GNOCL_STRING },  /* widget */
4001 		{ 0 }
4002 	};
4003 
4004 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
4005 	ps[1].val.str = gtk_file_chooser_get_filename ( widget );
4006 
4007 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
4008 
4009 }
4010 
4011 /**
4012 \brief	Return name of item selected in a file/folder chooser button operation
4013 **/
doOnFileSet(GtkWidget * widget,gpointer data)4014 static void doOnFileSet ( GtkWidget *widget, gpointer data )
4015 {
4016 
4017 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
4018 
4019 	GnoclPercSubst ps[] =
4020 	{
4021 		{ 'w', GNOCL_STRING },  /* widget */
4022 		{ 'f', GNOCL_STRING },  /* widget */
4023 		{ 'g', GNOCL_STRING },  /* glade name */
4024 		{ 0 }
4025 	};
4026 
4027 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
4028 	ps[1].val.str = gtk_file_chooser_get_filename ( widget );
4029 	ps[2].val.str = gtk_widget_get_name ( widget );
4030 
4031 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
4032 
4033 }
4034 
4035 /**
4036 \brief
4037 \author
4038 \date
4039 \note
4040 **/
doOnLinkButton(GtkWidget * widget,gpointer data)4041 static void doOnLinkButton ( GtkWidget *widget, gpointer data )
4042 {
4043 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
4044 
4045 	GnoclPercSubst ps[] =
4046 	{
4047 		{ 'w', GNOCL_STRING },  /* widget */
4048 		{ 'u', GNOCL_STRING },  /* widget */
4049 		{ 'g', GNOCL_STRING },  /* glade name */
4050 		{ 0 }
4051 	};
4052 
4053 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
4054 	ps[1].val.str =  gtk_link_button_get_uri ( widget );
4055 	ps[2].val.str = gtk_widget_get_name ( widget );
4056 
4057 #ifdef DEBUG_PARSEOPTIONS
4058 	g_print ( "label = %s uri= %s\n", gnoclGetNameFromWidget ( widget ), gtk_link_button_get_uri ( widget ) );
4059 #endif
4060 
4061 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
4062 
4063 }
4064 
4065 /**
4066 \brief      Called from gnoclOptOnEvent, this is handles how event signals are processed and
4067             values substituted into % values for further processing by Tcl scripts.
4068 \author     William J Giddings
4069 \date       01/11/2009
4070 \note		Events only apply to windows and not object such as tags. <--- WRONG
4071 **/
doOnEvent(GtkTextTag * texttag,GObject * widget,GdkEvent * event,GtkTextIter * arg2,gpointer data)4072 static void doOnEvent (	GtkTextTag *texttag, GObject *widget, GdkEvent *event, GtkTextIter *arg2, gpointer data )
4073 {
4074 
4075 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
4076 
4077 	GnoclPercSubst ps[] =
4078 	{
4079 
4080 		{ 'w', GNOCL_STRING },  /* 0 */
4081 		{ 't', GNOCL_STRING },  /* 1 */
4082 		{ 'x', GNOCL_INT },     /* 2 */
4083 		{ 'y', GNOCL_INT },     /* 3 */
4084 		{ 's', GNOCL_INT },     /* 4 */
4085 		{ 'b', GNOCL_INT },     /* 5 */
4086 		{ 'n', GNOCL_STRING },  /* 6 */
4087 		{ 'X', GNOCL_INT },     /* 7 */
4088 		{ 'Y', GNOCL_INT },     /* 8 */
4089 		{ 'g', GNOCL_STRING },  /* 9 glade name */
4090 		{ 'd', GNOCL_STRING },  /* 10 */
4091 		{ 0 }
4092 	};
4093 
4094 	/* initialize with default values */
4095 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
4096 	ps[9].val.str = gtk_widget_get_name ( GTK_WIDGET ( widget ) );
4097 	ps[10].val.str = g_object_get_data ( texttag, "gnocl::data" );
4098 
4099 	/* most of these events are not reported by the tag */
4100 
4101 	/*
4102 	 * _eventType_ ( event->type );
4103 	 */
4104 
4105 	/* set some initial values */
4106 	switch ( event->type )
4107 	{
4108 			/* these are not reported, it would be useful if they were, could do roll-over effects */
4109 		case GDK_ENTER_NOTIFY:
4110 			{
4111 				ps[1].val.str = "enterNotify";
4112 			}
4113 			break;
4114 		case GDK_LEAVE_NOTIFY:
4115 			{
4116 				ps[1].val.str = "leaveNotify";
4117 			}
4118 			break;
4119 			/* this is reported */
4120 		case GDK_MOTION_NOTIFY:
4121 			{
4122 				ps[1].val.str = "motionNotify";
4123 				ps[2].val.i = event->motion.x;
4124 				ps[3].val.i = event->motion.y;
4125 				ps[4].val.i = event->motion.state;
4126 				ps[7].val.i = event->motion.x_root;
4127 				ps[8].val.i = event->motion.y_root;
4128 			}
4129 			break;
4130 		case GDK_BUTTON_PRESS:
4131 		case GDK_2BUTTON_PRESS:
4132 		case GDK_3BUTTON_PRESS:
4133 		case GDK_BUTTON_RELEASE:
4134 			{
4135 				switch ( event->type )
4136 				{
4137 					case GDK_BUTTON_PRESS:      ps[1].val.str = "buttonPress"; break;
4138 					case GDK_2BUTTON_PRESS:     ps[1].val.str = "button2Press"; break;
4139 					case GDK_3BUTTON_PRESS:     ps[1].val.str = "button3Press"; break;
4140 					case GDK_BUTTON_RELEASE:    ps[1].val.str = "buttonRelease"; break;
4141 					default:                    assert ( 0 ); break;
4142 				}
4143 
4144 				ps[2].val.i = event->button.x;
4145 				ps[3].val.i = event->button.y;
4146 				ps[4].val.i = event->button.state;
4147 				ps[5].val.i = event->button.button;
4148 				ps[7].val.i = event->button.x_root;
4149 				ps[8].val.i = event->button.y_root;
4150 			}
4151 			break;
4152 
4153 		default:
4154 			{
4155 				// assert( 1 );
4156 				ps[1].val.str = "unknownEvent";
4157 			}
4158 
4159 	}
4160 
4161 	/* assign values to remaining elements of the array */
4162 	ps[2].val.i = event->button.x;
4163 	ps[3].val.i = event->button.y;
4164 	ps[4].val.i = event->button.state;
4165 	ps[5].val.i = event->button.button;
4166 	ps[7].val.i = event->button.x_root;
4167 	ps[8].val.i = event->button.y_root;
4168 
4169 	ps[6].val.str = texttag->name;
4170 
4171 	/* other settings, mouse pointer etc can be obtained from the window structure */
4172 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
4173 }
4174 
4175 /**
4176 \brief
4177 \author
4178 \date
4179 \note
4180 **/
gnoclOptOnScroll(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)4181 int gnoclOptOnScroll ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
4182 {
4183 	assert ( strcmp ( opt->optName, "-onScroll" ) == 0 );
4184 	return gnoclConnectOptCmd ( interp, obj, "scroll-event", G_CALLBACK ( doOnScroll ), opt, NULL, ret );
4185 }
4186 
4187 /**
4188 \brief
4189 \author
4190 \date
4191 \note
4192 **/
gnoclOptOnEvent(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)4193 int gnoclOptOnEvent ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
4194 {
4195 	assert ( strcmp ( opt->optName, "-onEvent" ) == 0 );
4196 	return gnoclConnectOptCmd ( interp, obj, "event", G_CALLBACK ( doOnEvent ), opt, NULL, ret );
4197 }
4198 
4199 /**
4200 \brief
4201 \author     William J Giddings
4202 \date
4203 \note       This is no longer used but may prove a useful later.
4204             The function was originally developed as an event handler for
4205             text tag bingings. However, only a limited set of the events listed below
4206             are supported by the Gtk text tag.
4207 **/
XXXXXdoOnEvent(GtkTextTag * texttag,GObject * arg1,GdkEvent * event,GtkTextIter * arg2,gpointer data)4208 static void XXXXXdoOnEvent (
4209 	GtkTextTag *texttag,
4210 	GObject *arg1,
4211 	GdkEvent *event,
4212 	GtkTextIter *arg2,
4213 	gpointer data )
4214 {
4215 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
4216 
4217 	GnoclPercSubst ps[] =
4218 	{
4219 		{ 't', GNOCL_STRING },
4220 		{ 'w', GNOCL_STRING },
4221 		{ 'x', GNOCL_INT },
4222 		{ 'y', GNOCL_INT },
4223 		{ 'b', GNOCL_INT },
4224 		{ 'X', GNOCL_INT },
4225 		{ 'Y', GNOCL_INT },
4226 		{ 's', GNOCL_INT },
4227 		{ 'g', GNOCL_STRING },  /* glade name */
4228 		{ 0 }
4229 	};
4230 
4231 	/* most of these events are not reported by the tag */
4232 
4233 	switch ( event->type )
4234 	{
4235 
4236 			/* these are reported */
4237 		case GDK_MOTION_NOTIFY:
4238 			ps[0].val.str = "motionNotify";
4239 			// ps[1].val.str = ((GdkEventButton*)event)->window ;
4240 			ps[2].val.i = ( ( GdkEventButton* ) event )->x;
4241 			ps[3].val.i = ( ( GdkEventButton* ) event )->y;
4242 			ps[4].val.i = ( ( GdkEventButton* ) event )->button;
4243 			ps[5].val.i = ( ( GdkEventButton* ) event )->x_root;
4244 			ps[6].val.i = ( ( GdkEventButton* ) event )->y_root;
4245 			ps[7].val.i = ( ( GdkEventButton* ) event )->state;
4246 			break;
4247 		case GDK_BUTTON_PRESS:
4248 		case GDK_2BUTTON_PRESS:
4249 		case GDK_3BUTTON_PRESS:
4250 		case GDK_BUTTON_RELEASE:
4251 
4252 			switch ( event->type )
4253 			{
4254 				case GDK_BUTTON_PRESS:      ps[0].val.str = "buttonPress"; break;
4255 				case GDK_2BUTTON_PRESS:     ps[0].val.str = "doubleButtonPress"; break;
4256 				case GDK_3BUTTON_PRESS:     ps[0].val.str = "tripleButtonPress"; break;
4257 				case GDK_BUTTON_RELEASE:    ps[0].val.str = "buttonRelease"; break;
4258 				default:  assert ( 0 ); break;
4259 			}
4260 
4261 			// ps[1].val.str = ((GdkEventButton*)event)->window ;
4262 			ps[2].val.i = ( ( GdkEventButton* ) event )->x;
4263 			ps[3].val.i = ( ( GdkEventButton* ) event )->y;
4264 			ps[4].val.i = ( ( GdkEventButton* ) event )->button;
4265 			ps[5].val.i = ( ( GdkEventButton* ) event )->x_root;
4266 			ps[6].val.i = ( ( GdkEventButton* ) event )->y_root;
4267 			ps[7].val.i = ( ( GdkEventButton* ) event )->state;
4268 
4269 			break;
4270 
4271 			/* these are not */
4272 		case GDK_NOTHING:           ps[0].val.str = "nothing"; break;
4273 
4274 		case GDK_DELETE:            ps[0].val.str = "delete"; break;
4275 
4276 		case GDK_DESTROY:           ps[0].val.str = "destroy"; break;
4277 
4278 		case GDK_EXPOSE:            ps[0].val.str = "expose"; break;
4279 
4280 		case GDK_KEY_PRESS:         ps[0].val.str = "keyPress"; break;
4281 
4282 		case GDK_KEY_RELEASE:       ps[0].val.str = "keyRelease"; break;
4283 
4284 		case GDK_ENTER_NOTIFY:      ps[0].val.str = "enterNotify"; break;
4285 
4286 		case GDK_LEAVE_NOTIFY:      ps[0].val.str = "leaveNotify"; break;
4287 
4288 		case GDK_FOCUS_CHANGE:      ps[0].val.str = "focusChange"; break;
4289 
4290 		case GDK_CONFIGURE:         ps[0].val.str = "configure"; break;
4291 
4292 		case GDK_MAP:               ps[0].val.str = "map"; break;
4293 
4294 		case GDK_UNMAP:             ps[0].val.str = "unmap"; break;
4295 
4296 		case GDK_PROPERTY_NOTIFY:   ps[0].val.str = "propertyNotify"; break;
4297 
4298 		case GDK_SELECTION_CLEAR:   ps[0].val.str = "selectionClear"; break;
4299 
4300 		case GDK_SELECTION_REQUEST: ps[0].val.str = "selectrionRequest"; break;
4301 
4302 		case GDK_SELECTION_NOTIFY:  ps[0].val.str = "selectionNotify"; break;
4303 
4304 		case GDK_PROXIMITY_IN:      ps[0].val.str = "proximityIn"; break;
4305 
4306 		case GDK_PROXIMITY_OUT:     ps[0].val.str = "proximityOut"; break;
4307 
4308 		case GDK_DRAG_ENTER:        ps[0].val.str = "dragEnter"; break;
4309 
4310 		case GDK_DRAG_LEAVE:        ps[0].val.str = "dragLeave"; break;
4311 
4312 		case GDK_DRAG_MOTION:       ps[0].val.str = "dragMotion"; break;
4313 
4314 		case GDK_DRAG_STATUS:       ps[0].val.str = "dragStatus"; break;
4315 
4316 		case GDK_DROP_START:        ps[0].val.str = "dropStart"; break;
4317 
4318 		case GDK_DROP_FINISHED:     ps[0].val.str = "dropFinished"; break;
4319 
4320 		case GDK_CLIENT_EVENT:      ps[0].val.str = "clientEvent"; break;
4321 
4322 		case GDK_VISIBILITY_NOTIFY: ps[0].val.str = "visibilityNotify"; break;
4323 
4324 		case GDK_NO_EXPOSE:         ps[0].val.str = "noExpose"; break;
4325 
4326 		case GDK_SCROLL:            ps[0].val.str = "scroll"; break;
4327 
4328 		case GDK_WINDOW_STATE:      ps[0].val.str = "windowState"; break;
4329 
4330 		case GDK_SETTING:           ps[0].val.str = "setting"; break;
4331 
4332 		case GDK_OWNER_CHANGE:      ps[0].val.str = "ownerChange"; break;
4333 
4334 		case GDK_GRAB_BROKEN:       ps[0].val.str = "grabBroken"; break;
4335 
4336 		default: assert ( 1 ); break;
4337 	}
4338 
4339 
4340 
4341 	/* other settings, mouse pointer etc can be obtained from the window structure */
4342 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
4343 }
4344 
4345 
4346 /**
4347 \brief	Signal handler for colorButton widget
4348 **/
gnoclOptOnColorSet(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)4349 int gnoclOptOnColorSet ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
4350 {
4351 	return gnoclConnectOptCmd ( interp, obj, "color-set", G_CALLBACK ( doOnColorSet ), opt, NULL, ret );
4352 }
4353 
4354 /**
4355 \brief
4356 **/
gnoclOptOnClicked(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)4357 int gnoclOptOnClicked ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
4358 {
4359 	return gnoclConnectOptCmd ( interp, obj, "clicked", G_CALLBACK ( doOnClicked ), opt, NULL, ret );
4360 }
4361 
4362 /**
4363 \brief
4364 **/
gnoclOptOnButtonClicked(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)4365 int gnoclOptOnButtonClicked ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
4366 {
4367 	return gnoclConnectOptCmd ( interp, obj, "clicked", G_CALLBACK ( doOnToolButtonClicked ), opt, NULL, ret );
4368 }
4369 
4370 
4371 /**
4372 \brief
4373 **/
gnoclOptOnInteractiveSearch(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)4374 int gnoclOptOnInteractiveSearch ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
4375 {
4376 	return gnoclConnectOptCmd ( interp, obj,  "start-interactive-search", G_CALLBACK ( doOnInteractiveSearch ), opt, NULL, ret );
4377 }
4378 
4379 
4380 /**
4381 \brief
4382 **/
gnoclOptOnColumnClicked(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)4383 int gnoclOptOnColumnClicked ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
4384 {
4385 	return gnoclConnectOptCmd ( interp, obj, "clicked", G_CALLBACK ( doOnColumnClicked ), opt, NULL, ret );
4386 }
4387 
4388 
4389 /**
4390 \brief Respond to entry icon signals.
4391 **/
gnoclOptOnIconPress(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)4392 int gnoclOptOnIconPress ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
4393 {
4394 	assert ( *opt->propName == 'R' || *opt->propName == 'P' );
4395 	return gnoclConnectOptCmd ( interp, obj, *opt->propName == 'P' ?  "icon-press" : "icon-release", G_CALLBACK ( doOnIconPress ), opt, NULL, ret );
4396 }
4397 
4398 
4399 
4400 /**
4401 \brief
4402 Handle mouse button event
4403 **/
gnoclOptOnButton(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)4404 int gnoclOptOnButton ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
4405 {
4406 	assert ( *opt->propName == 'R' || *opt->propName == 'P' );
4407 	return gnoclConnectOptCmd ( interp, obj, *opt->propName == 'P' ?  "button-press-event" : "button-release-event", G_CALLBACK ( doOnMouseButton ), opt, NULL, ret );
4408 }
4409 
4410 /**
4411 \brief
4412 **/
gnoclOptOnUndoRedo(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)4413 int gnoclOptOnUndoRedo ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
4414 {
4415 	assert ( *opt->propName == 'U' || *opt->propName == 'R' );
4416 	return gnoclConnectOptCmd ( interp, obj, *opt->propName == 'U' ?  "undo" : "redo", G_CALLBACK ( doOnUndoRedo ), opt, NULL, ret );
4417 }
4418 
4419 
4420 
4421 
4422 /**
4423 \brief
4424 \author     William J Giddings
4425 \date       29/Dec/09
4426 **/
gnoclOptOnFontSet(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)4427 int gnoclOptOnFontSet ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
4428 {
4429 	return gnoclConnectOptCmd ( interp, obj, "font-set", G_CALLBACK ( doOnFontSet ), opt, NULL, ret );
4430 }
4431 
4432 /**
4433 \brief
4434 \author     William J Giddings
4435 \date       21/Jan/2010
4436 **/
gnoclOptOnFileSet(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)4437 int gnoclOptOnFileSet ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
4438 {
4439 
4440 	return gnoclConnectOptCmd ( interp, obj, "file-set", G_CALLBACK ( doOnFileSet ), opt, NULL, ret );
4441 }
4442 
4443 /**
4444 \brief
4445 \author     William J Giddings
4446 \date       21/Jan/2010
4447 **/
gnoclOptOnFolderSet(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)4448 int gnoclOptOnFolderSet ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
4449 {
4450 #ifdef DEBUG_PARSEOPTIONS
4451 	g_printf ( "gnoclOptOnFolderSet\n" );
4452 #endif
4453 	return gnoclConnectOptCmd ( interp, obj, "file-set", G_CALLBACK ( doOnFolderSet ), opt, NULL, ret );
4454 }
4455 
4456 
4457 /**
4458 \brief
4459 \author
4460 \date
4461 \note
4462 **/
gnoclOptOnLinkButton(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)4463 int gnoclOptOnLinkButton ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
4464 {
4465 
4466 	/* check the name of the signal is correct for this function */
4467 	assert ( strcmp ( opt->optName, "-onClicked" ) == 0 );
4468 
4469 	return gnoclConnectOptCmd ( interp, obj, "clicked", G_CALLBACK ( doOnLinkButton ), opt, NULL, ret );
4470 }
4471 
4472 /*
4473     the following are handlers for GTKTextBuffer signals insert-text, delete-range
4474 */
4475 /**
4476 \brief
4477 \author
4478 \date
4479 \note
4480 **/
doOnCopyClipboard(GtkTextBuffer * textbuffer,gpointer user_data)4481 static void doOnCopyClipboard ( GtkTextBuffer *textbuffer, gpointer user_data )
4482 {
4483 
4484 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
4485 
4486 	GnoclPercSubst ps[] =
4487 	{
4488 		{ 't', GNOCL_STRING },  /* text inserted */
4489 		{ 0 }
4490 	};
4491 
4492 	ps[0].val.str   = "copy";
4493 
4494 
4495 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
4496 }
4497 /**
4498 \brief
4499 \author
4500 \date
4501 \note
4502 **/
doOnCutClipboard(GtkTextBuffer * textbuffer,gpointer user_data)4503 static void doOnCutClipboard ( GtkTextBuffer *textbuffer, gpointer user_data )
4504 {
4505 
4506 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
4507 
4508 	GnoclPercSubst ps[] =
4509 	{
4510 		{ 't', GNOCL_STRING },  /* text inserted */
4511 		{ 0 }
4512 	};
4513 
4514 	ps[0].val.str   = "cut";
4515 
4516 
4517 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
4518 }
4519 
4520 /**
4521 \brief
4522 \author
4523 \date
4524 \note
4525 **/
doOnPasteClipboard(GtkTextBuffer * textbuffer,gpointer user_data)4526 static void doOnPasteClipboard ( GtkTextBuffer *textbuffer, gpointer user_data )
4527 {
4528 
4529 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
4530 
4531 	GnoclPercSubst ps[] =
4532 	{
4533 		{ 't', GNOCL_STRING },  /* text inserted */
4534 		{ 0 }
4535 	};
4536 
4537 	ps[0].val.str   = "paste";
4538 
4539 
4540 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
4541 }
4542 
4543 
4544 
4545 
4546 /**
4547 \brief      The paste-done signal is emitted after paste operation has been completed.
4548 \author     William J Giddings
4549 \date       15/Jan/2010
4550 \note       This is useful to properly scroll the view to the end of the pasted text.
4551 **/
doOnPasteDone(GtkTextBuffer * textbuffer,GtkClipboard * arg1,gpointer user_data)4552 static void doOnPasteDone ( GtkTextBuffer *textbuffer, GtkClipboard *arg1, gpointer user_data )
4553 {
4554 
4555 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
4556 
4557 	GtkTextMark *mark;
4558 	GtkTextIter *iter;
4559 
4560 	GnoclPercSubst ps[] =
4561 	{
4562 		{ 'w', GNOCL_STRING },  /* widget */
4563 		{ 'r', GNOCL_INT },     /* row */
4564 		{ 'c', GNOCL_INT },     /* column */
4565 		{ 0 }
4566 	};
4567 
4568 	/* obtain the new insert mark, ie the end of the pasted  block */
4569 	mark = gtk_text_buffer_get_insert ( textbuffer );
4570 	gtk_text_buffer_get_iter_at_mark ( textbuffer, iter, mark );
4571 
4572 	ps[0].val.str = gnoclGetNameFromWidget ( textbuffer );
4573 	ps[1].val.i     = gtk_text_iter_get_line ( iter );
4574 	ps[2].val.i     = gtk_text_iter_get_line_offset ( iter );
4575 
4576 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
4577 }
4578 
4579 
4580 /**
4581 \brief
4582 \author
4583 \date
4584 \note
4585 **/
doOnTextInsert(GtkTextBuffer * textbuffer,GtkTextIter * location,gchar * text,gint len,gpointer user_data)4586 static void doOnTextInsert (
4587 	GtkTextBuffer *textbuffer,
4588 	GtkTextIter *location,
4589 	gchar *text,
4590 	gint len,
4591 	gpointer user_data )
4592 {
4593 
4594 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
4595 	GtkTextIter *iter;
4596 
4597 	GnoclPercSubst ps[] =
4598 	{
4599 		{ 'w', GNOCL_STRING },  /* widget */
4600 		{ 't', GNOCL_STRING },  /* text inserted */
4601 		{ 'r', GNOCL_INT },     /* row into which text inserted */
4602 		{ 'c', GNOCL_INT },     /* column into which text inserted */
4603 		{ 'l', GNOCL_INT },     /* row into which text inserted */
4604 		{ 0 }
4605 	};
4606 
4607 	ps[0].val.str = gnoclGetNameFromWidget ( textbuffer );
4608 	ps[1].val.str   = text;
4609 	ps[2].val.i     = gtk_text_iter_get_line ( location );
4610 	ps[3].val.i     = gtk_text_iter_get_line_offset ( location );
4611 	ps[4].val.i     = len;
4612 
4613 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
4614 }
4615 
4616 /**
4617 \brief      Respond to the input to GtkEntry widget before updating widget contents.
4618 \note       Use this signal to preprocess input for validation, undo/redo operations etc.
4619 \author     William J Giddings
4620 \date       26-Apr-09
4621 **/
doOnInsertAtCursor(GtkEntry * entry,gchar * arg1,gpointer user_data)4622 static void doOnInsertAtCursor ( GtkEntry *entry, gchar *arg1, gpointer user_data )
4623 {
4624 #ifdef DEBUG_PARSEOPTIONS
4625 	g_print ( "doOnEntryInsertText 1 %s\n", arg1 );
4626 #endif
4627 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
4628 
4629 	GnoclPercSubst ps[] =
4630 	{
4631 		{ 'w', GNOCL_STRING },  /* widget */
4632 		{ 'g', GNOCL_STRING },  /* glade name */
4633 		{ 't', GNOCL_STRING },  /* text inserted */
4634 		{ 0 }
4635 	};
4636 
4637 	ps[0].val.str = gnoclGetNameFromWidget ( GTK_WIDGET ( entry ) );
4638 	ps[1].val.str = gtk_widget_get_name ( GTK_WIDGET ( entry ) );
4639 	ps[2].val.str = arg1;
4640 
4641 #ifdef DEBUG_PARSEOPTIONS
4642 	g_print ( "doOnEntryInsertText 2\n" );
4643 	g_print ( "doOnEntryInsertText 3 : %s %s\n", ps[0].val.str,  ps[1].val.str );
4644 #endif
4645 	/* this line here is the problem! causing a memory segmentation problem */
4646 
4647 	if ( 1 )
4648 	{
4649 		gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
4650 	}
4651 
4652 }
4653 
4654 /**
4655 \brief
4656 \author     William J Giddings
4657 \date       26-Apr-09
4658 **/
gnoclOptOnInsertAtCursor(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)4659 int gnoclOptOnInsertAtCursor ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
4660 {
4661 #ifdef DEBUG_PARSEOPTIONS
4662 	g_print ( "gnoclOptOnInsertAtCursor 1\n" );
4663 #endif
4664 	/* check the name of the signal is correct for this function */
4665 	assert ( strcmp ( opt->optName, "-onInsert" ) == 0 );
4666 #ifdef DEBUG_PARSEOPTIONS
4667 	g_print ( "gnoclOptOnInsertAtCursor 2\n" );
4668 #endif
4669 
4670 	/* connect the signal with its callback function */
4671 	return gnoclConnectOptCmd ( interp, GTK_ENTRY  ( obj ), "insert-at-cursor", G_CALLBACK ( doOnInsertAtCursor ), opt, NULL, ret );
4672 
4673 }
4674 
4675 /**
4676 \brief
4677 \author
4678 \date
4679 \note
4680 **/
doOnMarkSet(GtkTextBuffer * textbuffer,GtkTextIter * location,GtkTextMark * mark,gpointer user_data)4681 static void doOnMarkSet (
4682 	GtkTextBuffer *textbuffer,
4683 	GtkTextIter *location,
4684 	GtkTextMark *mark,
4685 	gpointer user_data )
4686 {
4687 
4688 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
4689 
4690 	GnoclPercSubst ps[] =
4691 	{
4692 		{ 'r', GNOCL_INT },     /* length of text inserted */
4693 		{ 'c', GNOCL_INT },     /* row into which text inserted */
4694 		{ 'n', GNOCL_STRING },  /* column into which text inserted */
4695 		{ 0 }
4696 	};
4697 
4698 	ps[0].val.i     = gtk_text_iter_get_line ( location );
4699 	ps[1].val.i     = gtk_text_iter_get_line_offset ( location );
4700 	ps[2].val.str   = gtk_text_mark_get_name ( mark );
4701 
4702 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
4703 }
4704 
4705 /**
4706 \brief
4707 \author
4708 \date
4709 \note
4710 **/
doOnChildAttached(GtkHandleBox * handlebox,GtkWidget * widget,gpointer user_data)4711 static void doOnChildAttached ( GtkHandleBox *handlebox, GtkWidget *widget, gpointer user_data )
4712 {
4713 
4714 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
4715 
4716 	GnoclPercSubst ps[] =
4717 	{
4718 		{ 'w', GNOCL_STRING },
4719 		{ 'h', GNOCL_STRING },
4720 		{ 'g', GNOCL_STRING },  /* glade name */
4721 		{ 0 }
4722 	};
4723 
4724 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
4725 	ps[1].val.str = gnoclGetNameFromWidget ( handlebox );
4726 	ps[2].val.str = gtk_widget_get_name ( widget );
4727 
4728 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
4729 }
4730 
4731 /**
4732 \brief
4733 \author
4734 \date
4735 \note
4736 **/
doOnChildDetached(GtkHandleBox * handlebox,GtkWidget * widget,gpointer user_data)4737 static void doOnChildDetached (	GtkHandleBox *handlebox, GtkWidget *widget,	gpointer user_data )
4738 {
4739 
4740 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
4741 
4742 	GnoclPercSubst ps[] =
4743 	{
4744 		{ 'w', GNOCL_STRING },
4745 		{ 'h', GNOCL_STRING },
4746 		{ 'g', GNOCL_STRING },  /* glade name */
4747 		{ 0 }
4748 	};
4749 
4750 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
4751 	ps[1].val.str = gnoclGetNameFromWidget ( handlebox );
4752 	ps[2].val.str = gtk_widget_get_name ( widget );
4753 
4754 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
4755 }
4756 
4757 /**
4758 \brief
4759 \author
4760 \date
4761 \note
4762 **/
doOnMarkDelete(GtkTextBuffer * textbuffer,GtkTextMark * mark,gpointer user_data)4763 static void doOnMarkDelete (	GtkTextBuffer *textbuffer,	GtkTextMark *mark,	gpointer user_data )
4764 {
4765 
4766 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
4767 
4768 	GnoclPercSubst ps[] =
4769 	{
4770 		{ 'n', GNOCL_STRING },  /* column into which text inserted */
4771 		{ 0 }
4772 	};
4773 
4774 	ps[0].val.str   = gtk_text_mark_get_name ( mark );
4775 
4776 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
4777 }
4778 
4779 /**
4780 \brief
4781 \author
4782 \date
4783 \note
4784 **/
doOnBeginUserAction(GtkTextBuffer * textbuffer,gpointer user_data)4785 static void doOnBeginUserAction (	GtkTextBuffer *textbuffer,	gpointer user_data )
4786 {
4787 
4788 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
4789 
4790 	GnoclPercSubst ps[] =
4791 	{
4792 		{ 'b', GNOCL_INT },     /* begin, return */
4793 		{ 0 }
4794 	};
4795 
4796 	ps[0].val.i = 1;
4797 
4798 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
4799 }
4800 
4801 /**
4802 \brief
4803 **/
doOnInsertChildAnchor(GtkTextBuffer * textbuffer,GtkTextIter * location,GtkTextChildAnchor * anchor,gpointer user_data)4804 static void doOnInsertChildAnchor ( GtkTextBuffer *textbuffer, GtkTextIter *location, GtkTextChildAnchor *anchor, gpointer user_data )
4805 {
4806 
4807 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
4808 
4809 	GnoclPercSubst ps[] =
4810 	{
4811 		{ 'a', GNOCL_STRING},   /* anchor applied */
4812 		{ 'r', GNOCL_INT },     /* start (r)ow from which tag was applied */
4813 		{ 'c', GNOCL_INT },     /* start (c)ol from which tag was applied */
4814 		{ 'a', GNOCL_INT },     /*  */
4815 		{ 0 }
4816 	};
4817 
4818 	// ps[0].val.str    = anchor->name;
4819 	ps[0].val.i     = gtk_text_iter_get_line ( location );
4820 	ps[1].val.i     = gtk_text_iter_get_line_offset ( location );
4821 
4822 
4823 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
4824 }
4825 
4826 /**
4827 \brief
4828 **/
doOnEndUserAction(GtkTextBuffer * textbuffer,gpointer user_data)4829 static void doOnEndUserAction ( GtkTextBuffer *textbuffer, gpointer user_data )
4830 {
4831 
4832 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
4833 
4834 	GnoclPercSubst ps[] =
4835 	{
4836 		{ 'e', GNOCL_INT },     /* end, return */
4837 		{ 0 }
4838 	};
4839 
4840 	ps[0].val.i = 1;
4841 
4842 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
4843 }
4844 
4845 /**
4846 \brief
4847 **/
doOnChanged(GtkTextBuffer * textbuffer,gpointer user_data)4848 static void doOnChanged ( GtkTextBuffer *textbuffer, gpointer user_data )
4849 {
4850 
4851 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
4852 
4853 	GnoclPercSubst ps[] =
4854 	{
4855 		{ 'c', GNOCL_INT },     /* changed, return */
4856 		{ 0 }
4857 	};
4858 
4859 	ps[0].val.i = 1;
4860 
4861 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
4862 }
4863 
4864 /**
4865 \brief
4866 **/
gnoclOptOnChanged(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)4867 int gnoclOptOnChanged ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
4868 {
4869 
4870 	/* check the name of the signal is correct for this function */
4871 	assert ( strcmp ( opt->optName, "-onChanged" ) == 0 );
4872 
4873 	/* get a pointer to the textbuffer for this textview widget */
4874 	GtkTextBuffer *buffer;
4875 	buffer =  gtk_text_view_get_buffer ( obj );
4876 
4877 	/* connect the signal with its callback function */
4878 	return gnoclConnectOptCmd ( interp, buffer, "changed", G_CALLBACK ( doOnChanged ), opt, NULL, ret );
4879 }
4880 
4881 
4882 /**
4883 \brief
4884 \author
4885 \date
4886 \note
4887 **/
4888 /* check this function format with the Gtk refeerence docs, the format is probabaly wrong */
doOnValueChanged(GtkScaleButton * button,gdouble value,gpointer user_data)4889 static void doOnValueChanged ( GtkScaleButton *button, gdouble value, gpointer user_data )
4890 {
4891 
4892 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
4893 
4894 	GnoclPercSubst ps[] =
4895 	{
4896 		{ 'w', GNOCL_STRING }, /* widget */
4897 		{ 'v', GNOCL_DOUBLE }, /* value */
4898 		{ 'g', GNOCL_STRING }, /* glade name */
4899 		{ 0 }
4900 	};
4901 
4902 	ps[0].val.str = gnoclGetNameFromWidget ( button );
4903 	ps[1].val.d = value;
4904 	ps[2].val.str = gtk_widget_get_name ( GTK_WIDGET ( button ) );
4905 
4906 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
4907 
4908 }
4909 
4910 /**
4911 \brief      Return formmated string to the Tcl interpreter.
4912 \author     William J Giddingd
4913 \date       11/05/09
4914 **/
doOnVisibility(GtkWidget * widget,GdkEventVisibility * event,gpointer data)4915 static gboolean doOnVisibility ( GtkWidget *widget, GdkEventVisibility *event, gpointer  data )
4916 {
4917 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
4918 
4919 	GnoclPercSubst ps[] =
4920 	{
4921 		{ 'w', GNOCL_STRING },  /* widget */
4922 		{ 'v', GNOCL_STRING },  /* visibility  */
4923 		{ 'g', GNOCL_STRING },  /* glade name */
4924 		{ 'e', GNOCL_STRING },  /* signal/event name */
4925 		{ 0 }
4926 	};
4927 
4928 
4929 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
4930 	ps[2].val.str = gtk_widget_get_name ( widget );
4931 
4932 	switch ( event->state )
4933 	{
4934 		case GDK_VISIBILITY_FULLY_OBSCURED:
4935 			{
4936 				ps[1].val.str = "none";
4937 				break;
4938 			}
4939 
4940 		case GDK_VISIBILITY_PARTIAL:
4941 			{
4942 				ps[1].val.str = "partial";
4943 				break;
4944 			}
4945 
4946 		case GDK_VISIBILITY_UNOBSCURED:
4947 			{
4948 				ps[1].val.str = "all";
4949 				break;
4950 			}
4951 	}
4952 
4953 	ps[3].val.str = "visibility-notify-event";
4954 
4955 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
4956 
4957 }
4958 
4959 /**
4960 \brief
4961 \author
4962 \date
4963 \note
4964 **/
doOnModified(GtkTextBuffer * textbuffer,gpointer user_data)4965 static void doOnModified (
4966 	GtkTextBuffer *textbuffer,
4967 	gpointer user_data )
4968 {
4969 
4970 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
4971 
4972 	GnoclPercSubst ps[] =
4973 	{
4974 		{ 'c', GNOCL_INT },     /* changed, return */
4975 		{ 0 }
4976 	};
4977 
4978 	ps[0].val.i = 1;
4979 
4980 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
4981 }
4982 
4983 
4984 /**
4985 \brief
4986 \author
4987 \date
4988 \note
4989 **/
doOnApplyTag(GtkTextBuffer * textbuffer,GtkTextTag * tag,GtkTextIter * start,GtkTextIter * end,gpointer user_data)4990 static void doOnApplyTag (	GtkTextBuffer *textbuffer,	GtkTextTag *tag,	GtkTextIter *start,	GtkTextIter *end,	gpointer user_data )
4991 {
4992 
4993 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
4994 
4995 	GnoclPercSubst ps[] =
4996 	{
4997 		{ 't', GNOCL_STRING },  /* tag applied */
4998 		{ 'r', GNOCL_INT },     /* start (r)ow from which tag was applied */
4999 		{ 'c', GNOCL_INT },     /* start (c)ol from which tag was applied */
5000 		{ 'l', GNOCL_INT },     /* end (l)ine to which tag was applied */
5001 		{ 'o', GNOCL_INT },     /* end (o)ffset to which tag was applied */
5002 		{ 0 }
5003 	};
5004 
5005 	ps[0].val.str   = tag->name;
5006 	ps[1].val.i     = gtk_text_iter_get_line ( start );
5007 	ps[2].val.i     = gtk_text_iter_get_line_offset ( start );
5008 	ps[3].val.i     = gtk_text_iter_get_line ( end );
5009 	ps[4].val.i     = gtk_text_iter_get_line_offset ( end );
5010 
5011 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
5012 }
5013 
5014 /**
5015 \brief
5016 \author
5017 \date
5018 \note
5019 **/
doOnRemoveTag(GtkTextBuffer * textbuffer,GtkTextTag * tag,GtkTextIter * start,GtkTextIter * end,gpointer user_data)5020 static void doOnRemoveTag (	GtkTextBuffer *textbuffer,	GtkTextTag *tag,	GtkTextIter *start,	GtkTextIter *end,	gpointer user_data )
5021 {
5022 
5023 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
5024 
5025 	GnoclPercSubst ps[] =
5026 	{
5027 		{ 't', GNOCL_STRING },  /* tag removed */
5028 		{ 'r', GNOCL_INT },     /* start (r)ow from which tag was applied */
5029 		{ 'c', GNOCL_INT },     /* start (c)ol from which tag was applied */
5030 		{ 'l', GNOCL_INT },     /* end (l)ine to which tag was applied */
5031 		{ 'o', GNOCL_INT },     /* end (o)ffset to which tag was applied */
5032 		{ 0 }
5033 	};
5034 
5035 	ps[0].val.str   = tag->name;
5036 	ps[1].val.i     = gtk_text_iter_get_line ( start );
5037 	ps[2].val.i     = gtk_text_iter_get_line_offset ( start );
5038 	ps[3].val.i     = gtk_text_iter_get_line ( end );
5039 	ps[4].val.i     = gtk_text_iter_get_line_offset ( end );
5040 
5041 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
5042 }
5043 
5044 /**
5045 \brief      Respond to a textBuffer delete-range signal.
5046  *  WJG 29/07/08
5047  *  void user_function (
5048  *      GtkTextBuffer *textbuffer,
5049  *      GtkTextIter   *start,
5050  *      GtkTextIter   *end,
5051  *      gpointer       user_data)
5052  */
doOnDeleteRange(GtkTextBuffer * textbuffer,GtkTextIter * start,GtkTextIter * end,gpointer user_data)5053 static void doOnDeleteRange (
5054 	GtkTextBuffer *textbuffer,
5055 	GtkTextIter   *start,
5056 	GtkTextIter   *end,
5057 	gpointer       user_data )
5058 {
5059 #ifdef DEBUG_PARSEOPTIONS
5060 	g_print ( "doOnDeleteRange >1\n" ) ;
5061 #endif
5062 
5063 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
5064 
5065 	GnoclPercSubst ps[] =
5066 	{
5067 		{ 'r', GNOCL_INT },     /* start (r)ow from which text was deleted */
5068 		{ 'c', GNOCL_INT },     /* start (c)ol from which text was deleted */
5069 		{ 'l', GNOCL_INT },     /* end (l)ine from which text was deleted */
5070 		{ 'o', GNOCL_INT },     /* end (o)ffset from which text was deleted */
5071 		{ 't', GNOCL_STRING },  /* the text deleted */
5072 		{ 0 }
5073 	};
5074 
5075 	ps[0].val.i     = gtk_text_iter_get_line ( start );
5076 	ps[1].val.i     = gtk_text_iter_get_line_offset ( start );
5077 	ps[2].val.i     = gtk_text_iter_get_line ( end );
5078 	ps[3].val.i     = gtk_text_iter_get_line_offset ( end );
5079 	ps[4].val.str   = gtk_text_buffer_get_text ( textbuffer, start, end, 0 );
5080 
5081 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
5082 }
5083 
5084 /**
5085 \brief
5086 \author
5087 \date
5088 \note
5089 **/
doOnKey(GtkWidget * widget,GdkEventKey * event,gpointer data)5090 static void doOnKey ( GtkWidget *widget, GdkEventKey *event, gpointer data )
5091 {
5092 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
5093 
5094 	GnoclPercSubst ps[] =
5095 	{
5096 		{ 'w', GNOCL_STRING },  /* widget */
5097 		{ 'k', GNOCL_INT },     /* keycode */
5098 		{ 'K', GNOCL_STRING },  /* keycode as symbol */
5099 		{ 'a', GNOCL_OBJ },     /* character */
5100 		{ 's', GNOCL_INT },     /* state of modifiers */
5101 		{ 'g', GNOCL_STRING },  /* glade name */
5102 		{ 'e', GNOCL_STRING },  /* event/signal name */
5103 		{ 0 }
5104 	};
5105 
5106 	guint32 unicode = gdk_keyval_to_unicode ( event->keyval );
5107 
5108 	ps[0].val.str   = gnoclGetNameFromWidget ( widget );
5109 	ps[1].val.i     = event->keyval;
5110 	ps[2].val.str   = keyvalToString ( event->keyval );
5111 	ps[3].val.obj   = unicode ?  Tcl_NewUnicodeObj ( ( Tcl_UniChar * ) & unicode, 1 ) : Tcl_NewStringObj ( "", 0 );
5112 	ps[4].val.i     = event->state;
5113 	ps[5].val.str   = gtk_widget_get_name ( widget );
5114 
5115 	if ( event->type == GDK_KEY_PRESS )
5116 	{
5117 		ps[6].val.str = "key_press_event";
5118 	}
5119 
5120 	if ( event->type == GDK_KEY_RELEASE )
5121 	{
5122 		ps[6].val.str = "key_release_event";
5123 	}
5124 
5125 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
5126 }
5127 
5128 /**
5129 \brief
5130 \author
5131 \date
5132 \note
5133 **/
gnoclOptOnKeyPress(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)5134 int gnoclOptOnKeyPress ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
5135 {
5136 	assert ( strcmp ( opt->optName, "-onKeyPress" ) == 0 );
5137 	return gnoclConnectOptCmd ( interp, obj, "key-press-event", G_CALLBACK ( doOnKey ), opt, NULL, ret );
5138 }
5139 
5140 /**
5141 \brief
5142 \author
5143 \date
5144 \note
5145 **/
gnoclOptOnKeyRelease(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)5146 int gnoclOptOnKeyRelease ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
5147 {
5148 	assert ( strcmp ( opt->optName, "-onKeyRelease" ) == 0 );
5149 	return gnoclConnectOptCmd ( interp, obj, "key-release-event", G_CALLBACK ( doOnKey ), opt, NULL, ret );
5150 }
5151 
5152 /**
5153 \brief      Respond to a textBuffer signal to handle inserted text.
5154 \author
5155 \date
5156 \note
5157 **/
gnoclOptOnApplyTag(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)5158 int gnoclOptOnApplyTag ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
5159 {
5160 
5161 	/* check the name of the signal is correct for this function */
5162 	assert ( strcmp ( opt->optName, "-onApplyTag" ) == 0 );
5163 
5164 	/* get a pointer to the textbuffer for this textview widget */
5165 	GtkTextBuffer *buffer;
5166 	buffer =  gtk_text_view_get_buffer ( obj );
5167 
5168 	/* connect the signal with its callback function */
5169 	return gnoclConnectOptCmd ( interp, buffer, "apply-tag", G_CALLBACK ( doOnApplyTag ), opt, NULL, ret );
5170 }
5171 
5172 /**
5173 \brief      Respond to a textBuffer signal to handle inserted text.
5174 \author     WJG
5175 \date
5176 **/
gnoclOptOnClipboard(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)5177 int gnoclOptOnClipboard ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
5178 {
5179 
5180 	switch  ( *opt->propName )
5181 	{
5182 			/* these three are for the GtkTextView */
5183 		case 'X':
5184 			{
5185 
5186 				return gnoclConnectOptCmd ( interp, obj, "cut-clipboard"  , G_CALLBACK ( doOnCutClipboard ), opt, NULL, ret );
5187 			}
5188 			break;
5189 		case 'C':
5190 			{
5191 				return gnoclConnectOptCmd ( interp, obj, "copy-clipboard", G_CALLBACK ( doOnCopyClipboard ), opt, NULL, ret );
5192 			}
5193 			break;
5194 		case 'P':
5195 			{
5196 				return gnoclConnectOptCmd ( interp, obj, "paste-clipboard", G_CALLBACK ( doOnPasteClipboard ), opt, NULL, ret );
5197 			}
5198 			break;
5199 		default:
5200 			{
5201 				// assert( 0 );
5202 				return TCL_ERROR;
5203 			}
5204 	}
5205 }
5206 
5207 /**
5208 \brief      Respond to a textBuffer signal to handle inserted text.
5209 \author     WJG
5210 \date
5211 **/
gnoclOptOnPasteDone(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)5212 int gnoclOptOnPasteDone ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
5213 {
5214 
5215 	/* check the name of the signal is correct for this function */
5216 	assert ( strcmp ( opt->optName, "-onPasteDone" ) == 0 );
5217 
5218 	/* get a pointer to the textbuffer for this textview widget */
5219 	GtkTextBuffer *buffer;
5220 	buffer =  gtk_text_view_get_buffer ( obj );
5221 
5222 	return gnoclConnectOptCmd ( interp, buffer, "paste-done", G_CALLBACK ( doOnPasteDone ), opt, NULL, ret );
5223 }
5224 
5225 /**
5226 \brief      Respond to a textBuffer signal to handle inserted text.
5227 \author     WJG
5228  */
gnoclOptOnTextInsert(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)5229 int gnoclOptOnTextInsert ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
5230 {
5231 
5232 	/* check the name of the signal is correct for this function */
5233 	assert ( strcmp ( opt->optName, "-onInsertText" ) == 0 );
5234 
5235 	/* get a pointer to the textbuffer for this textview widget */
5236 	GtkTextBuffer *buffer;
5237 	buffer =  gtk_text_view_get_buffer ( obj );
5238 
5239 	/* connect the signal with its callback function */
5240 	return gnoclConnectOptCmd ( interp, buffer, "insert-text", G_CALLBACK ( doOnTextInsert ), opt, NULL, ret );
5241 }
5242 
5243 /**
5244 \brief      Respond to a textBuffer signal to handle inserted text.
5245 \author     WJG
5246 \date
5247 **/
gnoclOptOnMarkSet(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)5248 int gnoclOptOnMarkSet ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
5249 {
5250 
5251 	/* check the name of the signal is correct for this function */
5252 	assert ( strcmp ( opt->optName, "-onMarkSet" ) == 0 );
5253 
5254 	/* get a pointer to the textbuffer for this textview widget */
5255 	GtkTextBuffer *buffer;
5256 	buffer =  gtk_text_view_get_buffer ( obj );
5257 
5258 	/* connect the signal with its callback function */
5259 	return gnoclConnectOptCmd ( interp, buffer, "mark-set", G_CALLBACK ( doOnMarkSet ), opt, NULL, ret );
5260 }
5261 
5262 /**
5263 \brief      Respond to a textBuffer signal to handle mark deletion.
5264 **/
gnoclOptOnMarkDelete(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)5265 int gnoclOptOnMarkDelete ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
5266 {
5267 
5268 	/* check the name of the signal is correct for this function */
5269 	assert ( strcmp ( opt->optName, "-onMarkDelete" ) == 0 );
5270 
5271 	/* get a pointer to the textbuffer for this textview widget */
5272 	GtkTextBuffer *buffer;
5273 	buffer =  gtk_text_view_get_buffer ( obj );
5274 
5275 	/* connect the signal with its callback function */
5276 	return gnoclConnectOptCmd ( interp, buffer, "mark-delete", G_CALLBACK ( doOnMarkDelete ), opt, NULL, ret );
5277 }
5278 
5279 /**
5280 \brief      Respond to a textBuffer signal to handle inserted text.
5281 **/
gnoclOptOnBeginUserAction(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)5282 int gnoclOptOnBeginUserAction ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
5283 {
5284 
5285 	/* check the name of the signal is correct for this function */
5286 	assert ( strcmp ( opt->optName, "-onBeginUserAction" ) == 0 );
5287 
5288 	/* get a pointer to the textbuffer for this textview widget */
5289 	GtkTextBuffer *buffer;
5290 	buffer =  gtk_text_view_get_buffer ( obj );
5291 
5292 	/* connect the signal with its callback function */
5293 	return gnoclConnectOptCmd ( interp, buffer, "begin-user-action", G_CALLBACK ( doOnBeginUserAction ), opt, NULL, ret );
5294 }
5295 
5296 /**
5297 \brief  Respond to a textBuffer signal to handle inserted text.
5298 **/
gnoclOptOnEndUserAction(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)5299 int gnoclOptOnEndUserAction ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
5300 {
5301 
5302 	/* check the name of the signal is correct for this function */
5303 	assert ( strcmp ( opt->optName, "-onEndUserAction" ) == 0 );
5304 
5305 	/* get a pointer to the textbuffer for this textview widget */
5306 	GtkTextBuffer *buffer;
5307 	buffer =  gtk_text_view_get_buffer ( obj );
5308 
5309 	/* connect the signal with its callback function */
5310 	return gnoclConnectOptCmd ( interp, buffer, "end-user-action", G_CALLBACK ( doOnEndUserAction ), opt, NULL, ret );
5311 }
5312 
5313 /**
5314 \brief Respond to a textBuffer signal to handle inserted text.
5315 **/
gnoclOptOnInsertChildAnchor(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)5316 int gnoclOptOnInsertChildAnchor ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
5317 {
5318 
5319 	/* check the name of the signal is correct for this function */
5320 	assert ( strcmp ( opt->optName, "-onInsertChildAnchor" ) == 0 );
5321 
5322 	/* get a pointer to the textbuffer for this textview widget */
5323 	GtkTextBuffer *buffer;
5324 	buffer =  gtk_text_view_get_buffer ( obj );
5325 
5326 	/* connect the signal with its callback function */
5327 	return gnoclConnectOptCmd ( interp, buffer, "insert-child-anchor", G_CALLBACK ( doOnInsertChildAnchor ), opt, NULL, ret );
5328 }
5329 
5330 /**
5331 \brief
5332 \author
5333 \date
5334 \note
5335 **/
gnoclOptOnValueChanged(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)5336 int gnoclOptOnValueChanged ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
5337 {
5338 
5339 	/* check the name of the signal is correct for this function */
5340 	assert ( strcmp ( opt->optName, "-onValueChanged" ) == 0 );
5341 
5342 	/* connect the signal with its callback function */
5343 	return gnoclConnectOptCmd ( interp, obj, "value-changed", G_CALLBACK ( doOnValueChanged ), opt, NULL, ret );
5344 
5345 }
5346 
5347 /**
5348 \brief      Implement signal handler for the "visibility-notify-event" event.
5349 \note       This only applies to widget and not windows. It tests to see of the widget toplevel is obscured.
5350 \author     William J Giddings
5351 \date       11/05/09
5352 **/
gnoclOptOnVisibility(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)5353 int gnoclOptOnVisibility ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
5354 {
5355 #ifdef DEBUG_PARSEOPTIONS
5356 	g_print ( "gnoclOptOnVisibility\n" );
5357 #endif
5358 	assert ( strcmp ( opt->optName, "-onVisibility" ) == 0 );
5359 	return gnoclConnectOptCmd ( interp, obj, "visibility-notify-event", G_CALLBACK ( doOnVisibility ), opt, NULL, ret );
5360 }
5361 
5362 
5363 
5364 /**
5365 \brief
5366 \author
5367 \date
5368 \note
5369 **/
gnoclOptOnModified(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)5370 int gnoclOptOnModified ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
5371 {
5372 
5373 	/* check the name of the signal is correct for this function */
5374 	assert ( strcmp ( opt->optName, "-onModified" ) == 0 );
5375 
5376 	/* get a pointer to the textbuffer for this textview widget */
5377 	GtkTextBuffer *buffer;
5378 	buffer =  gtk_text_view_get_buffer ( obj );
5379 
5380 	/* connect the signal with its callback function */
5381 	return gnoclConnectOptCmd ( interp, buffer, "modify-changed", G_CALLBACK ( doOnModified ), opt, NULL, ret );
5382 }
5383 
5384 /**
5385 \brief
5386 \author
5387 \date
5388 \note
5389 **/
gnoclOptApplyTag(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)5390 int gnoclOptApplyTag ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
5391 {
5392 
5393 	/* check the name of the signal is correct for this function */
5394 	assert ( strcmp ( opt->optName, "-onApplyTag" ) == 0 );
5395 
5396 	/* get a pointer to the textbuffer for this textview widget */
5397 	GtkTextBuffer *buffer;
5398 	buffer =  gtk_text_view_get_buffer ( obj );
5399 
5400 	/* connect the signal with its callback function */
5401 	return gnoclConnectOptCmd ( interp, buffer, "apply-tag", G_CALLBACK ( doOnApplyTag ), opt, NULL, ret );
5402 }
5403 
5404 /**
5405 \brief
5406 \author
5407 \date
5408 \note
5409 **/
gnoclOptOnRemoveTag(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)5410 int gnoclOptOnRemoveTag ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
5411 {
5412 
5413 	/* check the name of the signal is correct for this function */
5414 	assert ( strcmp ( opt->optName, "-onRemoveTag" ) == 0 );
5415 
5416 	/* get a pointer to the textbuffer for this textview widget */
5417 	GtkTextBuffer *buffer;
5418 	buffer =  gtk_text_view_get_buffer ( obj );
5419 
5420 	/* connect the signal with its callback function */
5421 	return gnoclConnectOptCmd ( interp, buffer, "remove-tag", G_CALLBACK ( doOnRemoveTag ), opt, NULL, ret );
5422 }
5423 
5424 /**
5425 \brief
5426 \author
5427 \date
5428 \note
5429 **/
gnoclOptOnChildAttached(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)5430 int gnoclOptOnChildAttached ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
5431 {
5432 
5433 	assert ( strcmp ( opt->optName, "-onAttached" ) == 0 );
5434 	return gnoclConnectOptCmd ( interp, obj, "child-attached", G_CALLBACK ( doOnChildAttached ), opt, NULL, ret );
5435 }
5436 
5437 /**
5438 \brief
5439 \author
5440 \date
5441 \note
5442 **/
gnoclOptOnChildDetached(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)5443 int gnoclOptOnChildDetached ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
5444 {
5445 	assert ( strcmp ( opt->optName, "-onDetached" ) == 0 );
5446 	return gnoclConnectOptCmd ( interp, obj, "child-detached", G_CALLBACK ( doOnChildDetached ), opt, NULL, ret );
5447 }
5448 
5449 /**
5450 \brief
5451 \author
5452 \date
5453 \note
5454 **/
gnoclOptOnDeleteRange(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)5455 int gnoclOptOnDeleteRange ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
5456 {
5457 
5458 	GtkTextBuffer *buffer;
5459 
5460 	buffer =  gtk_text_view_get_buffer ( obj );
5461 
5462 	assert ( strcmp ( opt->optName, "-onDeleteRange" ) == 0 );
5463 	return gnoclConnectOptCmd ( interp, buffer, "delete-range", G_CALLBACK ( doOnDeleteRange ), opt, NULL, ret );
5464 }
5465 
5466 /**
5467 \brief
5468 \author
5469 \date
5470 \note
5471 **/
onDragEnd(GtkWidget * widget,GdkDragContext * context,gpointer data)5472 static void onDragEnd ( GtkWidget *widget, GdkDragContext *context, gpointer data )
5473 {
5474 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
5475 
5476 	/* if we have set the result, we are in the middle of
5477 	   error handling. In this case don't call any callbacks
5478 	   (especially onDestroy!) because this overrides the result. */
5479 
5480 	//if ( *cs->interp->result == '\0' )
5481 	//if ( *Tcl_GetStringResult(cs->interp) == '\0' )
5482 	//{
5483 	GnoclPercSubst ps[] =
5484 	{
5485 		{ 'w', GNOCL_STRING },  /* widget */
5486 		{ 'g', GNOCL_STRING },  /* gladeName */
5487 		{ 0 }
5488 	};
5489 
5490 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
5491 	ps[1].val.str = gtk_widget_get_name ( GTK_WIDGET ( widget ) );
5492 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
5493 }
5494 
5495 
5496 /**
5497 \brief
5498 \author
5499 \date
5500 \note
5501 **/
onDragBegin(GtkWidget * widget,GdkDragContext * context,gpointer data)5502 static void onDragBegin ( GtkWidget *widget, GdkDragContext *context, gpointer data )
5503 {
5504 	/* TODO: set custom icon */
5505 	/* DragData *para = (DragData *)data; */
5506 	gtk_drag_set_icon_default ( context );
5507 }
5508 
5509 /**
5510 \brief
5511 \author
5512 \date
5513 \note
5514 **/
onDragDataGet(GtkWidget * widget,GdkDragContext * context,GtkSelectionData * selectionData,guint info,guint32 time,gpointer data)5515 static void onDragDataGet ( GtkWidget *widget, GdkDragContext *context, GtkSelectionData *selectionData, guint info, guint32 time, gpointer data )
5516 {
5517 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
5518 
5519 	GnoclPercSubst ps[] =
5520 	{
5521 		{ 'T', GNOCL_OBJ },     /* 0 types of target */
5522 		{ 't', GNOCL_INT },     /* 1 time */
5523 		{ 'w', GNOCL_STRING },  /* 2 widget */
5524 		{ 'g', GNOCL_STRING },  /* glade name */
5525 		{ 0 }
5526 	};
5527 
5528 	gchar *name = gdk_atom_name ( selectionData->target );
5529 	ps[0].val.obj = Tcl_NewStringObj ( name, -1 );
5530 	ps[1].val.i = time;
5531 	ps[2].val.str = gnoclGetNameFromWidget ( widget );
5532 	ps[3].val.str = gtk_widget_get_name ( widget );
5533 	/*
5534 	   context->targets is a GList with all targets of the source.
5535 	   The first one, which is present in target is used and copied
5536 	   to selectionData->target
5537 	*/
5538 
5539 	if ( gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 ) == TCL_OK )
5540 	{
5541 		Tcl_Obj *res = Tcl_GetObjResult ( cs->interp );
5542 
5543 		int len;
5544 		unsigned char *pd = Tcl_GetByteArrayFromObj ( res, &len );
5545 		/* FIXME: format (number of bits in a unit) is 16, why?,
5546 		          what is a "unit"? */
5547 		gtk_selection_data_set ( selectionData, gdk_atom_intern ( name, FALSE ), 16, ( guchar * ) pd, len );
5548 	}
5549 
5550 	g_free ( name );
5551 }
5552 
5553 /**
5554 \brief
5555 \author
5556 \date
5557 \note
5558 **/
onDragDataReceived(GtkWidget * widget,GdkDragContext * context,gint x,gint y,GtkSelectionData * selectionData,guint info,guint32 time,gpointer data)5559 static void onDragDataReceived ( GtkWidget *widget, GdkDragContext *context,
5560 								 gint x, gint y, GtkSelectionData *selectionData, guint info,
5561 								 guint32 time, gpointer data )
5562 {
5563 	GnoclCommandData *cs = ( GnoclCommandData * ) data;
5564 
5565 	GnoclPercSubst ps[] =
5566 	{
5567 		{ 'd', GNOCL_OBJ },     /* 0 data */
5568 		{ 'l', GNOCL_INT },     /* 1 length of data */
5569 		{ 't', GNOCL_INT },     /* 2 time */
5570 		{ 'T', GNOCL_STRING },  /* 3 type */
5571 		{ 'w', GNOCL_STRING },  /* 4 widget */
5572 		{ 'x', GNOCL_INT },     /* 5 x */
5573 		{ 'y', GNOCL_INT },     /* 6 y */
5574 		{ 'g', GNOCL_STRING },  /* 7 glade name */
5575 		{ 0 }
5576 	};
5577 
5578 	int      ret;
5579 	gboolean del = 0;
5580 
5581 	ps[0].val.obj = Tcl_NewByteArrayObj ( selectionData->data, selectionData->length );
5582 	ps[1].val.i = selectionData->length;
5583 	ps[2].val.i = time;
5584 	ps[3].val.str = gdk_atom_name ( selectionData->type );
5585 	ps[4].val.str = gnoclGetNameFromWidget ( widget );
5586 	ps[5].val.i = x;
5587 	ps[6].val.i = y;
5588 	ps[7].val.str = gtk_widget_get_name ( widget );
5589 
5590 #ifdef DEBUG_PARSEOPTIONS
5591 	g_print ( "selection: \"%s\" target: \"%s\" type: \"%s\" data: \"%s\"\n",
5592 			  gdk_atom_name ( selectionData->selection ),
5593 			  gdk_atom_name ( selectionData->target ),
5594 			  gdk_atom_name ( selectionData->type ),
5595 			  selectionData->data );
5596 #endif
5597 
5598 	ret = gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
5599 
5600 	if ( ret == TCL_OK )
5601 	{
5602 		/* delete drag data if tcl function returns "delete" */
5603 		Tcl_Obj *res = Tcl_GetObjResult ( cs->interp );
5604 		char *str = Tcl_GetString ( res );
5605 
5606 		if ( strcmp ( str, "delete" ) == 0 )
5607 			del = 1;
5608 	}
5609 
5610 	gtk_drag_finish ( context, ret == TCL_OK, del, time );
5611 
5612 	g_free ( ( char * ) ps[3].val.str );
5613 }
5614 
5615 /**
5616 \brief
5617 \author
5618 \date
5619 \note
5620 **/
gnoclOptOnDragData(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)5621 int gnoclOptOnDragData ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
5622 {
5623 	int err = gnoclConnectOptCmd ( interp, obj, "drag_begin", G_CALLBACK ( onDragBegin ), opt, NULL, ret );
5624 	/*
5625 	g_signal_connect( G_OBJECT( widget ), "drag_end", G_CALLBACK( dragEnd ), para );
5626 	*/
5627 
5628 	if ( err == TCL_OK )
5629 	{
5630 		err = gnoclConnectOptCmd ( interp, obj, "drag_data_get", G_CALLBACK ( onDragDataGet ), opt, NULL, ret );
5631 	}
5632 
5633 	return err;
5634 }
5635 
5636 /**
5637 \brief
5638 \author
5639 \date
5640 \note
5641 **/
gnoclOptOnDragEnd(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)5642 int gnoclOptOnDragEnd ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
5643 {
5644 	int err = gnoclConnectOptCmd ( interp, obj, "drag_end", G_CALLBACK ( onDragEnd ), opt, NULL, ret );
5645 
5646 	return err;
5647 }
5648 
5649 
5650 /**
5651 \brief
5652 \author
5653 \date
5654 \note
5655 **/
gnoclOptOnDropData(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)5656 int gnoclOptOnDropData ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
5657 {
5658 	return gnoclConnectOptCmd ( interp, obj, "drag_data_received", G_CALLBACK ( onDragDataReceived ), opt, NULL, ret );
5659 }
5660 
5661 /**
5662 \brief
5663 \author
5664 \date
5665 \note
5666 **/
gnoclOptIcons(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)5667 int gnoclOptIcons ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
5668 {
5669 	const char *icons = Tcl_GetString ( opt->val.obj );
5670 
5671 	/* set a default list of icons */
5672 	static char *icons_[] =
5673 	{
5674 		GTK_STOCK_ZOOM_100
5675 	};
5676 
5677 #ifdef DEBUG_PARSEOPTIONS
5678 	g_print ( "GnoclOptIcons, there are some problems here setting up the icons\n" );
5679 	g_print ( "opt = %s val = %s \n", opt->optName, icons );
5680 #endif
5681 
5682 	if ( 1 )
5683 	{
5684 		return TCL_OK;
5685 	}
5686 
5687 	//gtk_scale_button_set_icons ( GTK_SCALE_BUTTON ( obj ), GTK_STOCK_ZOOM_IN );
5688 	gtk_scale_button_set_icons ( GTK_SCALE_BUTTON ( obj ), icons_ );
5689 }
5690 
5691 /*
5692     const char *txt[] = { "left", "right", "center", "fill", NULL };
5693     const int types[] = { GTK_JUSTIFY_LEFT, GTK_JUSTIFY_RIGHT, GTK_JUSTIFY_CENTER, GTK_JUSTIFY_FILL };
5694 
5695     assert ( sizeof ( GTK_JUSTIFY_FILL ) == sizeof ( int ) );
5696 
5697     return gnoclOptGeneric ( interp, opt, obj, "justification", txt, types,  ret );
5698 */
5699 
5700 /**
5701 \brief
5702 \author
5703 \date
5704 \note
5705 **/
gnoclOptIcon(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)5706 int gnoclOptIcon ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
5707 {
5708 	GnoclStringType type = gnoclGetStringType ( opt->val.obj );
5709 
5710 	switch ( type )
5711 	{
5712 		case GNOCL_STR_EMPTY:
5713 			{
5714 				gtk_window_set_icon ( GTK_WINDOW ( obj ), NULL );
5715 			}
5716 
5717 			break;
5718 		case GNOCL_STR_FILE:
5719 			{
5720 				GdkPixbuf *pix = gnoclPixbufFromObj ( interp, opt );
5721 
5722 				if ( pix == NULL )
5723 				{
5724 					return TCL_ERROR;
5725 				}
5726 
5727 				gtk_window_set_icon ( GTK_WINDOW ( obj ), pix );
5728 			}
5729 
5730 			break;
5731 		default:
5732 			{
5733 				Tcl_AppendResult ( interp, "Unknown type for \"", Tcl_GetString ( opt->val.obj ), "\" must be of type FILE (%/) or empty", NULL );
5734 			}
5735 
5736 			return TCL_ERROR;
5737 	}
5738 
5739 	return TCL_OK;
5740 }
5741 
5742 /**
5743 \brief
5744 \author
5745 \date
5746 \note
5747 **/
gnoclOptLabelFull(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)5748 int gnoclOptLabelFull ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
5749 {
5750 	if ( ret == NULL ) /* set value */
5751 	{
5752 		GnoclStringType type = gnoclGetStringType ( opt->val.obj );
5753 		char *txt = gnoclGetString ( opt->val.obj );
5754 
5755 		g_object_set ( obj, opt->propName, txt, NULL );
5756 
5757 #ifdef DEBUG_PARSEOPTIONS
5758 		g_print ( "opt->propName %s type %d\n", opt->propName, type );
5759 #endif
5760 
5761 		/* TODO? pango_parse_markup for error message */
5762 		g_object_set ( obj, "use-markup", ( gboolean ) ( ( type & GNOCL_STR_MARKUP ) != 0 ), NULL );
5763 
5764 		g_object_set ( obj, "use-underline", ( gboolean ) ( ( type & GNOCL_STR_UNDERLINE ) != 0 ), NULL );
5765 	}
5766 
5767 	else /* get value */
5768 	{
5769 		char *txt;
5770 		gboolean markup, underline;
5771 		Tcl_Obj *txtObj;
5772 		g_object_get ( obj, opt->propName, &txt, "use-markup", &markup, "use-underline", &underline, NULL );
5773 		txtObj = Tcl_NewStringObj ( txt, -1 );
5774 
5775 		if ( markup )
5776 		{
5777 			*ret = Tcl_NewStringObj ( "%<", 2 );
5778 			Tcl_AppendObjToObj ( *ret, txtObj );
5779 		}
5780 
5781 		else if ( underline )
5782 		{
5783 			*ret = Tcl_NewStringObj ( "%_", 2 );
5784 			Tcl_AppendObjToObj ( *ret, txtObj );
5785 		}
5786 
5787 		else
5788 			*ret = txtObj;
5789 	}
5790 
5791 	return TCL_OK;
5792 }
5793 
5794 /**
5795 \brief
5796 \author
5797 \date
5798 \note
5799 **/
gnoclOptDnDTargets(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)5800 int gnoclOptDnDTargets ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
5801 {
5802 	const int isSource = ( opt->propName[0] == 's' );
5803 
5804 	if ( ret == NULL ) /* set value */
5805 	{
5806 		int no;
5807 
5808 		Tcl_ListObjLength ( interp, opt->val.obj, &no );
5809 
5810 		if ( no == 0 )
5811 		{
5812 			if ( isSource )
5813 				gtk_drag_source_unset ( GTK_WIDGET ( obj ) );
5814 			else
5815 				gtk_drag_dest_unset ( GTK_WIDGET ( obj ) );
5816 		}
5817 
5818 		else
5819 		{
5820 			/* TODO: GDK_ACTION_COPY, GDK_ACTION_MOVE, GDK_ACTION_LINK
5821 			         GDK_BUTTON2_MASK ...
5822 			   for example:
5823 			         { -action {COPY MOVE LINK} target1 target2 }
5824 			         { -buttons {1 3 5} target1 target2 }
5825 			*/
5826 			int k;
5827 			GtkTargetEntry *targets = g_new ( GtkTargetEntry, no );
5828 
5829 			for ( k = 0; k < no; ++k )
5830 			{
5831 				Tcl_Obj *pobj;
5832 
5833 				if ( Tcl_ListObjIndex ( interp, opt->val.obj, k, &pobj ) != TCL_OK )
5834 				{
5835 					g_free ( targets );
5836 					return TCL_ERROR;
5837 				}
5838 
5839 				targets[k].target = Tcl_GetString ( pobj );
5840 
5841 				/* TODO: GTK_TARGET_SAME_APP, GTK_TARGET_SAME_WIDGET */
5842 				targets[k].flags = 0;
5843 				targets[k].info = k;
5844 			}
5845 
5846 			if ( isSource )
5847 				gtk_drag_source_set ( GTK_WIDGET ( obj ), GDK_BUTTON1_MASK,
5848 									  targets, no, GDK_ACTION_COPY );
5849 			else
5850 				gtk_drag_dest_set ( GTK_WIDGET ( obj ), GTK_DEST_DEFAULT_ALL,
5851 									targets, no, GDK_ACTION_COPY );
5852 
5853 			g_free ( targets );
5854 		}
5855 	}
5856 
5857 	else /* get value */
5858 	{
5859 		GtkTargetList *targets;
5860 
5861 		if ( isSource )
5862 			return TCL_OK;         /* FIXME: how to retrieve source targets? */
5863 		else
5864 			targets = gtk_drag_dest_get_target_list ( GTK_WIDGET ( obj ) );
5865 
5866 		*ret = Tcl_NewListObj ( 0, NULL );
5867 
5868 		if ( targets != NULL )
5869 		{
5870 			GList *p = targets->list;
5871 
5872 			for ( ; p != NULL; p = p->next )
5873 			{
5874 				GtkTargetPair *pair = p->data;
5875 				char *name = gdk_atom_name ( pair->target );
5876 				Tcl_ListObjAppendElement ( interp, *ret,
5877 										   Tcl_NewStringObj ( name, -1 ) );
5878 				g_free ( name );
5879 			}
5880 		}
5881 	}
5882 
5883 	return TCL_OK;
5884 }
5885 
5886 /**
5887 \brief	Parse strings of options and value pairs and assign those values
5888 		to matching Gtk object properties specified in the options list.
5889 \date
5890 \note
5891 \param	interp	pointer to Tcl Interpreter for the script\n
5892 		opt		pointer to object options array\n
5893 		obj		pointer to Gdk object for which properties are to be set (eg a Gtk widget)\n
5894 		no		offset of object options within a consolidated list of options\n
5895 **/
gnoclSetOptions(Tcl_Interp * interp,GnoclOption * opts,GObject * obj,int no)5896 int gnoclSetOptions ( Tcl_Interp *interp, GnoclOption *opts, GObject *obj, int no )
5897 {
5898 
5899 	int k;
5900 	GnoclOption *pop = opts;
5901 
5902 	/* step through the options list */
5903 	for ( k = 0; pop->optName && ( no == -1 || k < no ); ++k, ++pop )
5904 	{
5905 
5906 #ifdef DEBUG_PARSEOPTIONS
5907 		g_print ( "testing for set %s %s\n", pop->optName, pop->propName );
5908 #endif
5909 
5910 		if ( pop->status == GNOCL_STATUS_CHANGED && pop->propName )
5911 		{
5912 
5913 #ifdef DEBUG_PARSEOPTIONS
5914 			g_print ( "before setting %s\n", pop->optName );
5915 #endif
5916 
5917 			switch ( pop->type )
5918 			{
5919 				case GNOCL_BOOL:
5920 					{
5921 						g_object_set ( obj, pop->propName, pop->val.b, NULL );
5922 					}
5923 					break;
5924 				case GNOCL_INT:
5925 					{
5926 						g_object_set ( obj, pop->propName, pop->val.i, NULL );
5927 					}
5928 					break;
5929 				case GNOCL_DOUBLE:
5930 					{
5931 						g_object_set ( obj, pop->propName, pop->val.d, NULL );
5932 					}
5933 					break;
5934 				case GNOCL_STRING:
5935 					{
5936 						g_object_set ( obj, pop->propName, pop->val.str, NULL );
5937 					}
5938 					break;
5939 				case GNOCL_OBJ:
5940 				case GNOCL_LIST:
5941 					{
5942 						if ( ( *pop->func ) ( interp, pop, obj, NULL ) != TCL_OK )
5943 						{
5944 #ifdef DEBUG_PARSEOPTIONS
5945 							g_print ( "Error here... gnoclSetOptions/GNOCL_LIST\n" );
5946 #endif
5947 
5948 							pop->status = GNOCL_STATUS_SET_ERROR;
5949 
5950 							return TCL_ERROR;
5951 
5952 						}
5953 					}
5954 					break;
5955 
5956 				default:    assert ( 0 );
5957 			}
5958 
5959 			pop->status = GNOCL_STATUS_SET;
5960 		}
5961 	}
5962 
5963 	return TCL_OK;
5964 }
5965 
5966 /**
5967 \brief
5968 \author
5969 \date
5970 \note
5971 **/
5972 /* this is used for setting options in multiple canvas items via tags */
gnoclResetSetOptions(GnoclOption * opts)5973 int gnoclResetSetOptions ( GnoclOption *opts )
5974 {
5975 	GnoclOption *pop;
5976 
5977 	/* reset status */
5978 
5979 	for ( pop = opts; pop->optName; ++pop )
5980 	{
5981 		if ( pop->status == GNOCL_STATUS_SET )
5982 		{
5983 			pop->status = GNOCL_STATUS_CHANGED;
5984 		}
5985 	}
5986 
5987 	return 0;
5988 }
5989 
5990 /**
5991 \brief      Parse the list of options passed from the interpreter script
5992 			and assign these array accessible to module code.
5993 **/
gnoclParseOptions(Tcl_Interp * interp,int objc,Tcl_Obj * const objv[],GnoclOption * opts)5994 int gnoclParseOptions ( Tcl_Interp *interp, int objc, Tcl_Obj * const objv[], GnoclOption *opts )
5995 {
5996 	int k;
5997 	GnoclOption *pop;
5998 
5999 	/* reset status */
6000 	for ( pop = opts; pop->optName; ++pop )
6001 	{
6002 		pop->status = 0;
6003 	}
6004 
6005 	/* Parse all Options */
6006 	for ( k = 1; k < objc; k += 2 )
6007 	{
6008 		int idx;
6009 
6010 		if ( gnoclGetIndexFromObjStruct ( interp, objv[k], ( char ** ) &opts[0].optName, sizeof ( GnoclOption ), "option", TCL_EXACT, &idx ) != TCL_OK )
6011 		{
6012 			return -1;
6013 		}
6014 
6015 #ifdef DEBUG_PARSEOPTIONS
6016 		g_print ( "parsing %s -> %s %d\n", Tcl_GetString ( objv[k] ), opts[idx].optName, opts[idx].status );
6017 #endif
6018 
6019 		if ( k == objc - 1 )
6020 		{
6021 			Tcl_AppendResult ( interp, "no value given for parameter \"", Tcl_GetString ( objv[k] ) , "\"", ( char * ) NULL );
6022 			return -1;
6023 		}
6024 
6025 		pop = opts + idx;
6026 
6027 		if ( pop->status != 0 )
6028 		{
6029 			Tcl_AppendResult ( interp, "parameter \"", Tcl_GetString ( objv[k] ) , "\" defined more than once", ( char * ) NULL );
6030 			pop->status = GNOCL_STATUS_CHANGED_ERROR;
6031 			return TCL_ERROR;
6032 		}
6033 
6034 		/* parse types, assign to structure members */
6035 		switch ( pop->type )
6036 		{
6037 			case GNOCL_STRING: /* option is a string */
6038 				{
6039 					int txtLen;
6040 					const char *txt = gnoclGetStringFromObj ( objv[k+1], &txtLen );
6041 					pop->val.str = g_memdup ( txt, txtLen + 1 );
6042 				}
6043 
6044 				break;
6045 			case GNOCL_BOOL: /* option is a boolean */
6046 				{
6047 					int val;
6048 
6049 					if ( Tcl_GetBooleanFromObj ( interp, objv[k+1], &val ) != TCL_OK )
6050 					{
6051 						pop->status = GNOCL_STATUS_CHANGED_ERROR;
6052 						return TCL_ERROR;
6053 					}
6054 
6055 					pop->val.b = val;
6056 				}
6057 
6058 				break;
6059 			case GNOCL_INT:	/* option is an integer */
6060 				{
6061 					if ( Tcl_GetIntFromObj ( interp, objv[k+1], &pop->val.i ) != TCL_OK )
6062 					{
6063 						pop->status = GNOCL_STATUS_CHANGED_ERROR;
6064 						return TCL_ERROR;
6065 					}
6066 				}
6067 
6068 				break;
6069 			case GNOCL_DOUBLE: /* option is a float */
6070 				{
6071 					if ( Tcl_GetDoubleFromObj ( interp, objv[k+1], &pop->val.d ) != TCL_OK )
6072 					{
6073 						pop->status = GNOCL_STATUS_CHANGED_ERROR;
6074 						return TCL_ERROR;
6075 					}
6076 				}
6077 
6078 				break;
6079 			case GNOCL_OBJ:  /* option is a ???? */
6080 				{
6081 					pop->val.obj = objv[k+1];
6082 					Tcl_IncrRefCount ( pop->val.obj );
6083 				}
6084 
6085 				break;
6086 			case GNOCL_LIST:  /* option is a list */
6087 				{
6088 					int len;
6089 
6090 					if ( Tcl_ListObjLength ( interp, objv[k+1], &len ) != TCL_OK )
6091 					{
6092 						pop->status = GNOCL_STATUS_CHANGED_ERROR;
6093 						return TCL_ERROR;
6094 					}
6095 
6096 					pop->val.obj = objv[k+1];
6097 
6098 					Tcl_IncrRefCount ( pop->val.obj );
6099 				}
6100 
6101 				break;
6102 			default:
6103 				assert ( 0 );
6104 		}
6105 
6106 		pop->status = GNOCL_STATUS_CHANGED;
6107 	}
6108 
6109 	return TCL_OK;
6110 }
6111 
6112 /**
6113 \brief   Check the validity options passed to the interpretor to either create or configure a widget.
6114 \author
6115 \date
6116 \note
6117 **/
gnoclParseAndSetOptions(Tcl_Interp * interp,int objc,Tcl_Obj * const objv[],GnoclOption * opts,GObject * obj)6118 int gnoclParseAndSetOptions ( Tcl_Interp *interp, int objc, Tcl_Obj * const objv[], GnoclOption *opts,	GObject *obj )
6119 {
6120 	if ( gnoclParseOptions ( interp, objc, objv, opts ) != TCL_OK )
6121 	{
6122 		return TCL_ERROR;
6123 	}
6124 
6125 	return gnoclSetOptions ( interp, opts, obj, -1 );
6126 }
6127 
6128 /**
6129 \brief
6130 \author
6131 \date
6132 \note
6133 **/
gnoclClearOptions(GnoclOption * opts)6134 int gnoclClearOptions ( GnoclOption *opts )
6135 {
6136 	for ( ; opts->optName; ++opts )
6137 	{
6138 		if ( opts->status > GNOCL_STATUS_CHANGED_ERROR )
6139 		{
6140 			switch ( opts->type )
6141 			{
6142 				case GNOCL_STRING:
6143 					g_free ( opts->val.str );
6144 					break;
6145 				case GNOCL_LIST:
6146 				case GNOCL_OBJ:
6147 
6148 					if ( opts->val.obj != NULL )
6149 						Tcl_DecrRefCount ( opts->val.obj );
6150 
6151 					break;
6152 
6153 				default:
6154 					break;
6155 			}
6156 		}
6157 
6158 		opts->status = 0;
6159 	}
6160 
6161 	return TCL_OK;
6162 }
6163 
6164 /**
6165 \brief
6166 \author
6167 \date
6168 \note
6169 **/
gnoclGetOptions(Tcl_Interp * interp,GnoclOption * options)6170 int gnoclGetOptions ( Tcl_Interp *interp, GnoclOption *options )
6171 {
6172 
6173 	GnoclOption *opts = options;
6174 
6175 	for ( ; opts->optName; ++opts )
6176 	{
6177 		// g_print ("%s\n",opts->optName);
6178 		Tcl_AppendResult ( interp, opts->optName, " ", NULL );
6179 	}
6180 
6181 	return TCL_OK;
6182 }
6183 
6184 /**
6185 \brief
6186 \author
6187 \date
6188 \note
6189 **/
gnoclGetCommands(Tcl_Interp * interp,char * cmds[])6190 int gnoclGetCommands ( Tcl_Interp *interp, char *cmds[] )
6191 {
6192 	gint i = 0;
6193 
6194 	while ( cmds[i] != NULL )
6195 	{
6196 		Tcl_AppendResult ( interp, cmds[i], " ", NULL );
6197 		i++;
6198 	}
6199 
6200 	return TCL_OK;
6201 }
6202 
6203 
6204 /**
6205 \brief		Notify script that cget not available for specific option.
6206 \author		Peter G Baum
6207 \date
6208 \note
6209 **/
gnoclCgetNotImplemented(Tcl_Interp * interp,GnoclOption * opt)6210 int gnoclCgetNotImplemented ( Tcl_Interp *interp, GnoclOption *opt )
6211 {
6212 	Tcl_AppendResult ( interp,
6213 					   "Command \"cget\" for option \"",
6214 					   opt->optName,
6215 					   "\" is not yet implemented."
6216 					   "\nPlease mail the author, if you need it.", NULL );
6217 	return TCL_ERROR;
6218 }
6219 
6220 /**
6221 \brief		Return value from pre-set options.
6222 \author
6223 \date
6224 \note
6225 **/
gnoclCget(Tcl_Interp * interp,int objc,Tcl_Obj * const objv[],GObject * gObj,GnoclOption * opts,int * idx)6226 int gnoclCget (	Tcl_Interp *interp, int objc, Tcl_Obj * const objv[], GObject *gObj, GnoclOption *opts, int *idx )
6227 {
6228 	if ( objc != 3 )
6229 	{
6230 		Tcl_WrongNumArgs ( interp, 2, objv, "option" );
6231 		return GNOCL_CGET_ERROR;
6232 	}
6233 
6234 	return gnoclCgetOne ( interp, objv[2], gObj, opts, idx );
6235 }
6236 
6237 /**
6238 \note   Should this be move to the text.c module?
6239 **/
gnoclTagCget(Tcl_Interp * interp,int objc,Tcl_Obj * const objv[],GObject * gObj,GnoclOption * opts,int * idx)6240 int gnoclTagCget (	Tcl_Interp *interp, int objc, Tcl_Obj * const objv[], GObject *gObj, GnoclOption *opts, int *idx )
6241 {
6242 
6243 #ifdef DEBUG_TEXT
6244 	g_print ( "%s 1) option = %s\n", __FUNCTION__, Tcl_GetString ( objv[4] ) );
6245 #endif
6246 
6247 
6248 
6249 	if ( objc != 5 )
6250 	{
6251 #ifdef DEBUG_TEXT
6252 		g_print ( "%s 2)\n", __FUNCTION__ );
6253 #endif
6254 		Tcl_WrongNumArgs ( interp, 5, objv, "option" );
6255 		return GNOCL_CGET_ERROR;
6256 	}
6257 
6258 #ifdef DEBUG_TEXT
6259 	g_print ( "%s 3) %s %d\n", __FUNCTION__, Tcl_GetString ( objv[4] ), idx );
6260 #endif
6261 	return gnoclCgetOne ( interp, objv[4], gObj, opts, idx );
6262 }
6263 
6264 
6265 /**
6266 \brief
6267 \author
6268 \date
6269 \note
6270 **/
gnoclCgetOne(Tcl_Interp * interp,Tcl_Obj * obj,GObject * gObj,GnoclOption * opts,int * idx)6271 int gnoclCgetOne ( 	Tcl_Interp *interp,	Tcl_Obj *obj, GObject *gObj, GnoclOption *opts, int *idx )
6272 {
6273 
6274 #ifdef DEBUG_PARSEOPTIONS
6275 	g_print ( "%s 1)\n", __FUNCTION__ );
6276 #endif
6277 
6278 	GnoclOption *pop;
6279 
6280 	if ( gnoclGetIndexFromObjStruct ( interp, obj, ( char ** ) &opts[0].optName, sizeof ( GnoclOption ), "option", TCL_EXACT, idx ) != TCL_OK )
6281 	{
6282 
6283 		return GNOCL_CGET_ERROR;
6284 	}
6285 
6286 	pop = opts + *idx;
6287 
6288 	if ( pop->propName )
6289 	{
6290 		switch ( pop->type )
6291 		{
6292 			case GNOCL_STRING:
6293 				{
6294 
6295 					Tcl_Obj *obj;
6296 					gchar   *val;
6297 					g_object_get ( gObj, pop->propName, &val, NULL );
6298 					obj = Tcl_NewStringObj ( val, -1 );
6299 					g_free ( val );
6300 					Tcl_SetObjResult ( interp, obj );
6301 				}
6302 
6303 				return GNOCL_CGET_HANDLED;
6304 			case GNOCL_BOOL:
6305 				{
6306 
6307 					gboolean val;
6308 					g_object_get ( gObj, pop->propName, &val, NULL );
6309 					Tcl_SetObjResult ( interp, Tcl_NewBooleanObj ( val ) );
6310 				}
6311 
6312 				return GNOCL_CGET_HANDLED;
6313 			case GNOCL_INT:
6314 				{
6315 					gint val;
6316 					g_object_get ( gObj, pop->propName, &val, NULL );
6317 					Tcl_SetObjResult ( interp, Tcl_NewIntObj ( val ) );
6318 				}
6319 
6320 				return GNOCL_CGET_HANDLED;
6321 			case GNOCL_DOUBLE:
6322 				{
6323 					gdouble val;
6324 					g_object_get ( gObj, pop->propName, &val, NULL );
6325 					Tcl_SetObjResult ( interp, Tcl_NewDoubleObj ( val ) );
6326 				}
6327 
6328 				return GNOCL_CGET_HANDLED;
6329 
6330 			case GNOCL_OBJ:
6331 				{
6332 #ifdef DEBUG_PARSEOPTIONS
6333 					g_print ( "%s WE HAVE AN OBJECT\n", __FUNCTION__ );
6334 #endif
6335 				}
6336 			default:
6337 				{
6338 
6339 					Tcl_Obj *obj = NULL;
6340 
6341 					if ( ( *pop->func ) ( interp, pop, gObj, &obj ) != TCL_OK )
6342 						return GNOCL_CGET_ERROR;
6343 
6344 					if ( obj == NULL )
6345 					{
6346 						gnoclCgetNotImplemented ( interp, pop );
6347 						return GNOCL_CGET_ERROR;
6348 					}
6349 
6350 					Tcl_SetObjResult ( interp, obj );
6351 				}
6352 
6353 				return GNOCL_CGET_HANDLED;
6354 		}
6355 	}
6356 
6357 	return GNOCL_CGET_NOTHANDLED;
6358 }
6359 
6360 
6361 /*********************************************************************/
6362 
6363 /**
6364 \brief	"populate-popup" signal handler.
6365 **/
doOnPopulatePopup(GtkWidget * widget,GtkMenu * menu,gpointer user_data)6366 static void doOnPopulatePopup ( GtkWidget *widget, GtkMenu *menu, gpointer user_data )
6367 {
6368 	GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
6369 
6370 	/* set global variable to hold location of the popup menu */
6371 	popupMenu = menu;
6372 
6373 	GnoclPercSubst ps[] =
6374 	{
6375 		{ 'w', GNOCL_STRING },  /* name of widget */
6376 		{ 'g', GNOCL_STRING },  /* glade name */
6377 		{ 'd', GNOCL_STRING },  /* data */
6378 		{ 0 }
6379 	};
6380 
6381 	ps[0].val.str = gnoclGetNameFromWidget ( widget );
6382 	ps[1].val.str = gtk_widget_get_name ( GTK_WIDGET ( widget ) );
6383 	ps[2].val.str = g_object_get_data ( widget, "gnocl::data" );
6384 
6385 	gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
6386 
6387 }
6388 
6389 /**
6390 \brief	Setup to populate-popup signal handler.
6391 **/
gnoclOptOnPopulatePopup(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)6392 int gnoclOptOnPopulatePopup (
6393 	Tcl_Interp *interp,
6394 	GnoclOption *opt,
6395 	GObject *obj,
6396 	Tcl_Obj **ret )
6397 {
6398 
6399 	return gnoclConnectOptCmd ( interp, obj, "populate-popup", G_CALLBACK ( doOnPopulatePopup ), opt, NULL, ret );
6400 
6401 }
6402 
6403 
6404 /**
6405 \brief	Add menuitem to the popup menu.
6406 **/
gnoclPopupMenuAddItem(Tcl_Interp * interp,gchar * str)6407 void gnoclPopupMenuAddItem ( Tcl_Interp *interp, gchar *str )
6408 {
6409 #ifdef DEBUG_TEXT
6410 	g_print ( "%s\n", __FUNCTION__ );
6411 #endif
6412 
6413 
6414 	GtkWidget *item;
6415 
6416 	item = gnoclGetWidgetFromName ( str, interp );
6417 
6418 	gtk_menu_shell_append ( GTK_MENU_SHELL ( popupMenu ), item );
6419 	gtk_widget_show ( item );
6420 }
6421 
6422 /**
6423 \brief	Add a submenu to an existing popup menu item.
6424 **/
gnoclPopupMenuAddSubMenu(Tcl_Interp * interp,gchar * str1,gchar * str2)6425 void gnoclPopupMenuAddSubMenu ( Tcl_Interp *interp, gchar *str1, gchar *str2 )
6426 {
6427 #ifdef DEBUG_TEXT
6428 	g_print ( "%s\n", __FUNCTION__ );
6429 #endif
6430 
6431 
6432 	GtkWidget *item, *submenu;
6433 	GtkWidget *i;
6434 
6435 	item = gnoclGetWidgetFromName ( str1, interp );
6436 
6437 	submenu = gnoclGetWidgetFromName ( str2, interp );
6438 
6439 	gtk_menu_item_set_submenu ( GTK_MENU_ITEM ( item ), submenu ) ;
6440 
6441 }
6442 
6443 /**
6444 \brief	Add separator to the popup menu.
6445 **/
gnoclPopupMenuAddSeparator(Tcl_Interp * interp)6446 void gnoclPopupMenuAddSeparator ( Tcl_Interp *interp )
6447 {
6448 #ifdef DEBUG_TEXT
6449 	g_print ( "%s\n", __FUNCTION__ );
6450 #endif
6451 
6452 	GtkWidget *item;
6453 
6454 	item = gtk_separator_menu_item_new();
6455 	gtk_menu_shell_append ( GTK_MENU_SHELL ( popupMenu ), item );
6456 	gtk_widget_show ( item );
6457 
6458 }
6459