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