1 /*
2 * $Id: text.c,v 1.7 2005-01-01 15:27:54 baum Exp $
3 *
4 * This file implements the text widget
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 * Modification of the the GtkSourceView undo/redo provided by Ross Burton (ross@burtonini.com)
12 */
13
14 /**
15 * CURRENTLY ACCEPTS :
16 * $w get markup start end
17 * $w get start end -markup 1
18 **/
19
20
21 /*
22 to do
23 document
24 -acceptTab
25 -tabs
26 */
27 /*
28 History:
29 2013-07: added command, options
30 2013-05: added -onDragEnd
31 2013-04: resolved problem with tag sub-command "ranges"
32 2013-02: serialize command now returns buffer data as string
33 2013-01: added subcommands isToplevelFocus and hasGlobalFocus
34 2012-12 corrected -accepttTab to -acceptsTab
35 2012-11 added -data option to text tag
36 fixed problems with:
37 getIndex subcommand
38 tag get subcommand
39 added %r(ow) %c(col) substitution string parameters for
40 -onMotion signal handler
41 2012-10 added -onDestroy
42 2012-09 cget -baseFont implemented
43 resetUndo
44 2012-08 migrated to the use of TextParams to hold widget details
45 implemented -variable option
46 2012-07 added grabFocus, same effect as setting the -hasFocus option
47 2012-06 added selectionBounds to get widget command.
48 2011-07 added tag sub-commands
49 names, raise, lower
50 insert command now detects pango markup text
51 added -markupTags
52 2011-06 added tag -underline option 'error'
53 2011-06 added -hasToolTip, -onQueryTooltip,
54 added tag options
55 -data
56 2011-04 added tag options
57 -marginAccumulate -backgroundFullHeight -backgroundStipple
58 -direction -editable -foregroundStipple -indent -language
59 -leftMargin -name -pixelsInsideWrap -rightMargin -rise
60 -scale -tabs -variant -weight
61 2011-04 added -inputMethod, -onPreeditChanged
62 2011-02 added undo/redo functionality
63 2010-05 added tag option -paragraph
64 2010-04 added -onDeleteFromCursor, -onInsertAtCursor, -onMoveCursor, -onMoveViewport
65 added lorem - insert some dummy text for preview purposes
66 2010-03 added getIndex, return line / char info at location x y in textview
67 2010-01 added -buffer
68 2010-01 added -doOnCutClipboard, -doOnCopyClipboard, -doOnPasteClipboard
69 2009-01 added -text option to allow plain text creation at startup
70 2008-04 renamed function gnoclOptOnInsertText to gnoclOptOnTextInsert
71 2009-04 added commands save, load, (aka serialize, deserialize)
72 2009-02 added -onScroll and -widthRequest
73 added commands search and replace
74 2009-01 added -heightRequest
75 2008-06 added new options -onEntry and -onLeave
76 (required modification of the text widget signal mask)
77 2008-06 added <id> getSelectionBounds, returns range currently selected
78 <id> -onInsertText script
79 [not finnished] 2008-03: XYgetCursor -retrive row/col position under window coordinates, XY
80 [not finnished] 2008-03: cget retrieve current setting for specified option, based upon entry.c
81
82 2008-03: added tag delete <tagname> command
83 2008-03: added command 'class', return class of widget, ie. text
84 2007-11: extened tag command to include apply / remove
85 2007-11: added extended list of tag options to include
86 -onEvent
87 2007-10: added new options to the text widget
88 -baseFont
89 -baseColor
90 -onButtonPress
91 -onButtonRelease
92 -onKeyPress
93 -onKeyRelease
94 -onMotion
95 -dropTargets -test this option
96 -dragTargets -test this option
97 2003-03: added scrollToPosition
98 11: switched from GnoclWidgetOptions to GnoclOption
99 2002-05: transition to gtk 2.0: move from gtkText to gtkTextView
100 2001-06: Begin of developement
101
102 TODO:
103 * set a clear pango mode, ie no other tags a can be created, non-deleted
104 * marks
105 */
106
107 /**
108 \page page_text gnocl::text
109 \htmlinclude text.html
110 **/
111
112 #include "gnocl.h"
113 #include "gnoclparams.h"
114 #include "./textUndo/undo_manager.h"
115
116 static int textFunc ( ClientData data, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[] );
117 static int cget ( Tcl_Interp *interp, GtkTextView *text, GnoclOption options[], int idx );
118 static void gnoclGetTagRanges ( Tcl_Interp * interp, GtkTextBuffer * buffer, gchar * tagName );
119 static void getTagName ( GtkTextTag *tag, gpointer data );
120 static void gnoclGetTagProperties ( GtkTextTag * tag, Tcl_Obj *resList );
121
122 static int setTextVariable ( TextParams *para, const char *val );
123 static void changedFunc ( GtkWidget *widget, gpointer data );
124 static void destroyFunc ( GtkWidget *widget, gpointer data );
125 static int setVal ( GtkTextBuffer *buffer, const char *txt );
126 static char *traceFunc ( ClientData data, Tcl_Interp *interp, const char *name1, const char *name2, int flags );
127 static int doCommand ( TextParams *para, const char *val, int background );
128
129 static gint usemarkup = 0;
130
131
132 /***********************************************************************
133 * trace funcs
134 ***********************************************************************/
135
136 /**
137 \brief
138 **/
destroyFunc(GtkWidget * widget,gpointer data)139 static void destroyFunc ( GtkWidget *widget, gpointer data )
140 {
141 #ifdef DEBUG_TEXT
142 printf ( "%s\n", __FUNCTION__ );
143 #endif
144
145
146 TextParams *para = ( TextParams * ) data;
147
148 gnoclForgetWidgetFromName ( para->name );
149 Tcl_DeleteCommand ( para->interp, para->name );
150
151 gnoclAttachOptCmdAndVar (
152 NULL, ¶->onChanged,
153 NULL, ¶->textVariable,
154 "changed", G_OBJECT ( para->textView ),
155 G_CALLBACK ( changedFunc ), para->interp, traceFunc, para );
156
157 g_free ( para->textVariable );
158 g_free ( para->name );
159 g_free ( para );
160 }
161
162 /**
163 \brief
164 **/
changedFunc(GtkWidget * widget,gpointer data)165 static void changedFunc ( GtkWidget *widget, gpointer data )
166 {
167 #ifdef DEBUG_TEXT
168 printf ( "%s\n", __FUNCTION__ );
169 #endif
170
171 TextParams *para = ( TextParams * ) data;
172
173 GtkScrolledWindow *scrolled = para->scrolled;
174 GtkTextView *text = GTK_TEXT_VIEW ( gtk_bin_get_child ( GTK_BIN ( scrolled ) ) );
175 GtkTextBuffer *buffer = gtk_text_view_get_buffer ( text );
176
177 GtkTextIter start, end;
178 gtk_text_buffer_get_bounds ( buffer, &start, &end );
179 const char *val = gtk_text_buffer_get_text ( buffer, &start, &end, FALSE );
180
181 //g_print ( "....%s\n", val );
182
183
184 //const char *val = gtk_label_get_text ( para->label );
185 setTextVariable ( para, val );
186 //doCommand ( para, val, 1 );
187 }
188
189 /**
190 \brief
191 **/
setTextVariable(TextParams * para,const char * val)192 static int setTextVariable ( TextParams *para, const char *val )
193 {
194 #ifdef DEBUG_TEXT
195 printf ( "%s\n", __FUNCTION__ );;
196 #endif
197
198
199 if ( para->textVariable && para->inSetVar == 0 )
200 {
201 const char *ret;
202 para->inSetVar = 1;
203 ret = Tcl_SetVar ( para->interp, para->textVariable, val, TCL_GLOBAL_ONLY );
204 para->inSetVar = 0;
205 return ret == NULL ? TCL_ERROR : TCL_OK;
206 }
207
208 return TCL_OK;
209 }
210
211 /**
212 \brief
213 **/
setVal(GtkTextBuffer * buffer,const char * txt)214 static int setVal ( GtkTextBuffer *buffer, const char *txt )
215 {
216 int blocked;
217 blocked = g_signal_handlers_block_matched ( G_OBJECT ( buffer ), G_SIGNAL_MATCH_FUNC, 0, 0, NULL, ( gpointer * ) changedFunc, NULL );
218 //gtk_label_set_text ( label, txt );
219
220 gtk_text_buffer_set_text ( buffer, txt, -1 );
221
222 //gtk_label_set_markup ( label, txt );
223
224 //OptLabelFull ( label, txt );
225
226 if ( blocked )
227 {
228 g_signal_handlers_unblock_matched ( G_OBJECT ( buffer ), G_SIGNAL_MATCH_FUNC, 0, 0, NULL, ( gpointer * ) changedFunc, NULL );
229 }
230
231 return TCL_OK;
232 }
233
234 /**
235 \brief
236 **/
traceFunc(ClientData data,Tcl_Interp * interp,const char * name1,const char * name2,int flags)237 static char *traceFunc ( ClientData data, Tcl_Interp *interp, const char *name1, const char *name2, int flags )
238 {
239 TextParams *para = ( TextParams * ) data;
240
241 GtkScrolledWindow *scrolled = para->scrolled;
242 GtkTextView *text = GTK_TEXT_VIEW ( gtk_bin_get_child ( GTK_BIN ( scrolled ) ) );
243 GtkTextBuffer *buffer = gtk_text_view_get_buffer ( text );
244
245
246 if ( para->inSetVar == 0 && name1 )
247 {
248 const char *txt = name1 ? Tcl_GetVar2 ( interp, name1, name2, 0 ) : NULL;
249
250 if ( txt )
251 {
252 setVal ( buffer, txt );
253 doCommand ( para, txt, 1 );
254 }
255 }
256
257 return NULL;
258 }
259
260 /**
261 \brief
262 **/
doCommand(TextParams * para,const char * val,int background)263 static int doCommand ( TextParams *para, const char *val, int background )
264 {
265 if ( para->onChanged )
266 {
267 GnoclPercSubst ps[] =
268 {
269 { 'w', GNOCL_STRING }, /* widget */
270 { 'v', GNOCL_STRING }, /* value */
271 { 0 }
272 };
273
274 ps[0].val.str = para->name;
275 ps[1].val.str = val;
276
277 return gnoclPercentSubstAndEval ( para->interp, ps, para->onChanged, background );
278 }
279
280 return TCL_OK;
281 }
282
283
284 /***********************************************************************/
stripMarkup(GtkTextBuffer * buffer,GtkTextIter * start,GtkTextIter * end)285 gchar *stripMarkup ( GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end )
286 {
287 GtkTextIter *iter;
288
289 iter = gtk_text_iter_copy ( start );
290
291 gchar *str = NULL;
292 gunichar ch;
293
294 /* parse each position in the selection */
295 while ( gtk_text_iter_equal ( iter, end ) == 0 )
296 {
297 ch = gtk_text_iter_get_char ( iter );
298 str = str_append ( str, ch );
299 gtk_text_iter_forward_cursor_position ( iter ); //OK
300 }
301
302 return str;
303 }
304
305 /**
306 \brief Return text with Pango markup
307 \notes Pango has a weight markup format compared to HTML or the textBuff
308 Basically, it means there are problems when overlapping markup tags.
309 Whatever is opened has to be closed, and then the overlap re-opened.
310
311 eg: this will work
312 The buffer will return this..
313 <b>aaa<i> bbb</b> <u>ccc</u></i> ddd</u>
314 But this is pango!
315 <b>aaa<i> bbb</i></b><i> <u>ccc</u></i><u> ddd</u>
316
317 \date 23/06/13
318 **/
getMarkUpString(Tcl_Interp * interp,GtkTextBuffer * buffer,GtkTextIter * start,GtkTextIter * end)319 Tcl_Obj *getMarkUpString ( Tcl_Interp *interp, GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end )
320 {
321 #if 1
322 g_print ( "%s usemarkup = %d\n", __FUNCTION__, usemarkup );
323 #endif
324
325 Tcl_Obj *res;
326
327 GtkTextIter *iter;
328 gunichar ch;
329 GList *q;
330 GList *onList = NULL, *offList = NULL, *revList = NULL;
331 gchar *tagName = NULL;
332
333 res = Tcl_NewStringObj ( "", 0 );
334 iter = gtk_text_iter_copy ( start );
335
336 /* parse each position in the selection */
337 while ( gtk_text_iter_equal ( iter, end ) == 0 )
338 {
339
340 /* process tagOff before any subsequent tagOn */
341 offList = gtk_text_iter_get_toggled_tags ( iter, 0 );
342 onList = gtk_text_iter_get_toggled_tags ( iter, 1 );
343
344 if ( onList != NULL )
345 {
346 /* get a reverse list */
347 for ( q = onList ; q != NULL; q = q->next )
348 {
349 tagName = ( GTK_TEXT_TAG ( q->data )->name );
350 Tcl_AppendStringsToObj ( res, tagName, ( char * ) NULL );
351 }
352 }
353
354 if ( offList != NULL )
355 {
356 /* get off tags */
357 onList = gtk_text_iter_get_tags ( iter );
358
359 for ( q = onList ; q != NULL; q = q->next )
360 {
361 tagName = ( GTK_TEXT_TAG ( q->data )->name );
362 revList = g_slist_prepend ( revList, tagName );
363 }
364
365 /* turn off tags in order of priority, ie reverse the list */
366 for ( q = revList ; q != NULL; q = q->next )
367 {
368 tagName = q->data ;
369
370 if ( strncmp ( tagName, "<span", 5 ) == 0 )
371 {
372 tagName = "span";
373 }
374
375 Tcl_AppendStringsToObj ( res, str_replace ( tagName, "<", "</" ), ( char * ) NULL );
376 }
377
378 for ( q = offList ; q != NULL; q = q->next )
379 {
380 tagName = ( GTK_TEXT_TAG ( q->data )->name );
381
382 if ( strncmp ( tagName, "<span", 5 ) == 0 )
383 {
384 tagName = "<span>";
385 }
386
387 Tcl_AppendStringsToObj ( res, str_replace ( tagName, "<", "</" ), ( char * ) NULL );
388 }
389
390 for ( q = onList ; q != NULL; q = q->next )
391 {
392 tagName = ( GTK_TEXT_TAG ( q->data )->name );
393 Tcl_AppendStringsToObj ( res, tagName, ( char * ) NULL );
394 }
395
396 g_slist_free ( onList ); onList = NULL;
397 g_slist_free ( revList ); revList = NULL;
398 g_slist_free ( offList ); offList = NULL;
399
400 }
401
402 /* end of markup block */
403
404 /* get character */
405 ch = gtk_text_iter_get_char ( iter );
406 Tcl_AppendStringsToObj ( res, &ch, ( char * ) NULL );
407
408 /* turnOff span? */
409 gtk_text_iter_forward_cursor_position ( iter ); //OK
410 }
411
412 /* terminate tags at end of line */
413 if ( gtk_text_iter_backward_to_tag_toggle ( iter, NULL ) )
414 {
415 offList = gtk_text_iter_get_tags ( iter );
416
417 if ( 1 )
418 {
419 for ( q = offList ; q != NULL; q = q->next )
420 {
421 tagName = ( GTK_TEXT_TAG ( q->data )->name );
422 revList = g_slist_prepend ( revList, tagName );
423 }
424
425
426 for ( q = revList ; q != NULL; q = q->next )
427 {
428 tagName = q->data ;
429
430 if ( strncmp ( tagName, "<span", 5 ) == 0 )
431 {
432 tagName = "<span>";
433 }
434
435 Tcl_AppendStringsToObj ( res, str_replace ( tagName, "<", "</" ), ( char * ) NULL );
436 }
437 }
438
439 else
440 {
441 for ( q = offList ; q != NULL; q = q->next )
442 {
443 tagName = ( GTK_TEXT_TAG ( q->data )->name );
444
445 if ( strncmp ( tagName, "<span", 5 ) == 0 )
446 {
447 tagName = "<span>";
448 }
449
450 Tcl_AppendStringsToObj ( res, str_replace ( tagName, "<", "</" ), ( char * ) NULL );
451 }
452 }
453 }
454
455 gtk_text_iter_free ( iter );
456
457 g_slist_free ( onList ); onList = NULL;
458 g_slist_free ( revList ); revList = NULL;
459 g_slist_free ( offList ); offList = NULL;
460
461 #ifdef DEBUG_TEXT
462 g_print ( "done!\n" );
463 #endif
464
465 //g_print ( "TEXT = %s\n", Tcl_GetStringFromObj ( res, NULL ) );
466
467 gchar *text = NULL;
468
469 if ( pango_parse_markup ( Tcl_GetStringFromObj ( res, NULL ), -1 , NULL, NULL, &text, NULL, NULL ) == 0 )
470 {
471 g_print ( "WARNING! Malformed Pango Strings: %s\n", text );
472 Tcl_SetStringObj ( res, "", 0 );
473 Tcl_AppendStringsToObj ( res, gtk_text_buffer_get_text ( buffer, start, end, 0 ), ( char * ) NULL );
474
475 }
476
477 return res;
478 }
479
480
481
482 /**
483 \brief Return text with Pango markup -WORKING VERSION
484 **/
getMarkUpString_(Tcl_Interp * interp,GtkTextBuffer * buffer,GtkTextIter * start,GtkTextIter * end)485 Tcl_Obj *getMarkUpString_ ( Tcl_Interp *interp, GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end )
486 {
487 #ifdef DEBUG_TEXT
488 g_print ( "%s usemarkup = %d\n", __FUNCTION__, usemarkup );
489 #endif
490
491 Tcl_Obj *res;
492
493 GtkTextIter *iter;
494 gunichar ch;
495 GList *p, *q, *list;
496
497 GList *onList = NULL, *offList = NULL, *revList = NULL;
498
499 gchar *tagName = NULL;
500 gchar *onTag = NULL;
501 gchar *offTag = NULL;
502
503 gchar openList[128] = "";
504 gchar closeList[128] = "";
505
506 res = Tcl_NewStringObj ( "", 0 );
507
508 iter = gtk_text_iter_copy ( start );
509
510 /* parse each position in the selection */
511 while ( gtk_text_iter_equal ( iter, end ) == 0 )
512 {
513
514 /* process tagOff before any subsequent tagOn */
515 offList = gtk_text_iter_get_toggled_tags ( iter, 0 );
516 onList = gtk_text_iter_get_toggled_tags ( iter, 1 );
517
518 if ( onList != NULL )
519 {
520
521 /* get a reverse list */
522 for ( q = onList ; q != NULL; q = q->next )
523 {
524 tagName = ( GTK_TEXT_TAG ( q->data )->name );
525 revList = g_slist_prepend ( revList, tagName );
526 Tcl_AppendStringsToObj ( res, tagName, ( char * ) NULL );
527 }
528
529
530 for ( q = revList ; q != NULL; q = q->next )
531 {
532 tagName = q->data ;
533 }
534
535 g_slist_free ( revList );
536 revList = NULL;
537
538 }
539
540 if ( offList != NULL )
541 {
542 /* turn off tags */
543 onList = gtk_text_iter_get_tags ( iter );
544
545 for ( q = onList ; q != NULL; q = q->next )
546 {
547 tagName = ( GTK_TEXT_TAG ( q->data )->name );
548 revList = g_slist_prepend ( revList, tagName );
549 }
550
551 for ( q = revList ; q != NULL; q = q->next )
552 {
553 Tcl_AppendStringsToObj ( res, str_replace ( q->data, "<", "</" ), ( char * ) NULL );
554 }
555
556 for ( q = offList ; q != NULL; q = q->next )
557 {
558 tagName = ( GTK_TEXT_TAG ( q->data )->name );
559 Tcl_AppendStringsToObj ( res, str_replace ( tagName, "<", "</" ), ( char * ) NULL );
560 }
561
562 for ( q = onList ; q != NULL; q = q->next )
563 {
564 tagName = ( GTK_TEXT_TAG ( q->data )->name );
565 Tcl_AppendStringsToObj ( res, tagName, ( char * ) NULL );
566 }
567
568 g_slist_free ( onList ); onList = NULL;
569 g_slist_free ( revList ); revList = NULL;
570 g_slist_free ( offList ); offList = NULL;
571
572 }
573
574 /* end of markup block */
575
576 /* get character */
577 ch = gtk_text_iter_get_char ( iter );
578 Tcl_AppendStringsToObj ( res, &ch, ( char * ) NULL );
579
580 /* turnOff span? */
581 gtk_text_iter_forward_cursor_position ( iter ); //OK
582 }
583
584 /* terminate tags at end of line */
585 if ( gtk_text_iter_backward_to_tag_toggle ( iter, NULL ) )
586 {
587 offList = gtk_text_iter_get_tags ( iter );
588
589 for ( q = offList ; q != NULL; q = q->next )
590 {
591 tagName = ( GTK_TEXT_TAG ( q->data )->name );
592
593 Tcl_AppendStringsToObj ( res, str_replace ( tagName, "<", "</" ), ( char * ) NULL );
594 }
595 }
596
597 gtk_text_iter_free ( iter );
598
599 g_slist_free ( onList ); onList = NULL;
600 g_slist_free ( revList ); revList = NULL;
601 g_slist_free ( offList ); offList = NULL;
602
603 #ifdef DEBUG_TEXT
604 g_print ( "done!\n" );
605 #endif
606
607 return res;
608 }
609
610 /**
611 \brief Serialize the content of the textbuffer in an ascii format
612 \note Currently supports tags only.
613 **/
dumpAll(Tcl_Interp * interp,GtkTextBuffer * buffer,GtkTextIter * start,GtkTextIter * end)614 static Tcl_Obj *dumpAll ( Tcl_Interp *interp, GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end )
615 {
616
617 #ifdef DEBUG_TEXT
618 g_print ( "%s\n", __FUNCTION__ );
619 #endif
620
621 Tcl_Obj *res;
622
623 GtkTextIter *iter;
624 gunichar ch;
625 GSList *p, *onList, *offList;
626
627 gchar *tagName = NULL;
628 gchar *onTag = NULL;
629 gchar *offTag = NULL;
630
631 gint l;
632
633 res = Tcl_NewStringObj ( "", 0 );
634
635 iter = gtk_text_iter_copy ( start );
636
637 while ( gtk_text_iter_equal ( iter, end ) == 0 )
638 {
639 /* process tagOff before any subsequent tagOn */
640 offList = gtk_text_iter_get_toggled_tags ( iter, 0 );
641
642 for ( p = offList; p != NULL; p = p->next )
643 {
644 tagName = ( GTK_TEXT_TAG ( p->data )->name );
645 l = strlen ( tagName );
646 char str[l-2];
647 strncpy ( str, tagName + 2, l - 1 );
648 Tcl_AppendStringsToObj ( res, tagName, ( char * ) NULL );
649 }
650
651 /* process tagOn */
652
653
654 onList = gtk_text_iter_get_toggled_tags ( iter, 1 );
655
656 for ( p = onList; p != NULL; p = p->next )
657 {
658 tagName = ( GTK_TEXT_TAG ( p->data )->name );
659 Tcl_AppendStringsToObj ( res, tagName, ( char * ) NULL );
660 }
661
662 /* get character */
663 ch = gtk_text_iter_get_char ( iter );
664 Tcl_AppendStringsToObj ( res, &ch, ( char * ) NULL );
665
666 /* turnOff span? */
667 gtk_text_iter_forward_char ( iter );
668 }
669
670 gtk_text_iter_free ( iter );
671
672
673 #ifdef DEBUG_TEXT
674 g_print ( "done!\n" );
675 #endif
676
677 return res;
678 }
679
680
681
682
683 /**
684 \brief Return a Tcl list of text attributes.
685 GtkJustification justification;
686 GtkTextDirection direction;
687 PangoFontDescription *font;
688 gdouble font_scale;
689 gint left_margin;
690 gint indent;
691 gint right_margin;
692 gint pixels_above_lines;
693 gint pixels_below_lines;
694 gint pixels_inside_wrap;
695 PangoTabArray *tabs;
696 GtkWrapMode wrap_mode;
697 PangoLanguage *language;
698 guint invisible : 1;
699 guint bg_full_height : 1;
700 guint editable : 1;
701 guint realized : 1;
702
703 **/
getAttributes(Tcl_Interp * interp,GtkTextAttributes * values)704 static getAttributes ( Tcl_Interp *interp, GtkTextAttributes *values )
705 {
706 #ifdef DEBUG_TEXT
707 g_print ( " % s\n", __FUNCTION__ );
708 #endif
709
710
711 Tcl_Obj *resList;
712
713 resList = Tcl_NewListObj ( 0, NULL );
714
715 gchar *justify;
716 gchar *direction;
717 gchar *font;
718
719 justify = "left";
720 direction = "none";
721 font = "";
722
723 font = pango_font_description_to_string ( values->font );
724
725 switch ( values->justification )
726 {
727 case GTK_JUSTIFY_LEFT:
728 {
729 justify = "left";
730 }
731 break;
732 case GTK_JUSTIFY_RIGHT:
733 {
734 justify = "right";
735 } break;
736 case GTK_JUSTIFY_CENTER:
737 {
738 justify = "center";
739 } break;
740 case GTK_JUSTIFY_FILL:
741 {
742 justify = "fill";
743 } break;
744 default:
745 {
746
747 #ifdef DEBUG_TEXT
748 g_print ( "no justify %s\n", __FUNCTION__ );
749 #endif
750
751 }
752 }
753
754 switch ( values->direction )
755 {
756 case GTK_TEXT_DIR_NONE:
757 {
758 direction = "none";
759 }
760 break;
761 case GTK_TEXT_DIR_LTR:
762 {
763 direction = "left - to - right";
764 }
765 break;
766 case GTK_TEXT_DIR_RTL:
767 {
768 direction = "right - to - left";
769 }
770 break;
771 default:
772 {
773 #ifdef DEBUG_TEXT
774 g_print ( "no direction %s\n", __FUNCTION__ );
775 #endif
776
777 }
778 }
779
780
781 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewStringObj ( "justification", -1 ) );
782 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewStringObj ( justify, -1 ) );
783
784 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewStringObj ( "direction", -1 ) );
785 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewStringObj ( direction, -1 ) );
786
787 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewStringObj ( "font", -1 ) );
788 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewStringObj ( font, -1 ) );
789
790 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewStringObj ( "font_scale", -1 ) );
791 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewDoubleObj ( values->font_scale ) );
792
793 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewStringObj ( "left_margin", -1 ) );
794 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewIntObj ( values->left_margin ) );
795
796 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewStringObj ( "indent", -1 ) );
797 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewIntObj ( values->indent ) );
798
799 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewStringObj ( "right_margin", -1 ) );
800 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewIntObj ( values->right_margin ) );
801
802 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewStringObj ( "pixels_above_lines", -1 ) );
803 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewIntObj ( values-> pixels_above_lines ) );
804
805 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewStringObj ( "pixels_below_lines", -1 ) );
806 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewIntObj ( values->pixels_below_lines ) );
807
808 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewStringObj ( "pixels_inside_wrap", -1 ) );
809 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewIntObj ( values->pixels_inside_wrap ) );
810
811 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewStringObj ( "tabs", -1 ) );
812 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewStringObj ( "tab - array", -1 ) );
813
814 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewStringObj ( "wrap_mode", -1 ) );
815 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewStringObj ( "wrap", -1 ) );
816
817 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewStringObj ( "language", -1 ) );
818 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewStringObj ( "text - language", -1 ) );
819
820 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewStringObj ( "invisible", -1 ) );
821 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewIntObj ( values->invisible ) );
822
823 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewStringObj ( "bg_full_height", -1 ) );
824 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewIntObj ( values->bg_full_height ) );
825
826 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewStringObj ( "editable", -1 ) );
827 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewIntObj ( 1 ) );
828
829 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewStringObj ( "realized", -1 ) );
830 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewIntObj ( values->realized ) );
831
832 Tcl_SetObjResult ( interp, resList );
833
834 }
835
836
837 /**
838 \brief Search through the GtkTextBuffer from startPos to endPos.
839 If a match is found, add it to a list of row col indices.
840 When search complete, return the list to the calling function.
841 **/
searchWord(GtkTextBuffer * buffer,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[],int cmdNo,int isTextWidget)842 static int searchWord ( GtkTextBuffer *buffer, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[], int cmdNo, int isTextWidget )
843 {
844
845 listParameters ( objc, objv, __FUNCTION__ );
846
847 int res, row1, col1, row2, col2;
848 GtkTextIter start, begin, end;
849 Tcl_Obj *resList;
850
851 resList = Tcl_NewListObj ( 0, NULL );
852
853 /* default with the start of the buffer */
854 gtk_text_buffer_get_start_iter ( buffer, &start );
855
856 while ( gtk_text_iter_forward_search ( &start, ( gchar* ) Tcl_GetString ( objv[cmdNo+2] ), 0, &begin, &end, NULL ) != NULL )
857 {
858 #ifdef DEBUG_TEXT
859 g_print ( "* search forwards % s\n", ( gchar* ) Tcl_GetString ( objv[cmdNo+2] ) );
860 #endif
861 /* return the index of the found location */
862 row1 = gtk_text_iter_get_line ( &begin );
863 col1 = gtk_text_iter_get_line_offset ( &begin );
864 row2 = gtk_text_iter_get_line ( &end );
865 col2 = gtk_text_iter_get_line_offset ( &end );
866
867 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewIntObj ( row1 ) );
868 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewIntObj ( col1 ) );
869 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewIntObj ( row2 ) );
870 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewIntObj ( col2 ) );
871
872 start = end;
873
874 }
875
876 Tcl_SetObjResult ( interp, resList );
877
878 /* return the total number of items returned in the list */
879 return TCL_OK;
880 }
881
882 /**
883 \brief
884 **/
gnoclOptText(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)885 static int gnoclOptText ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
886 {
887 GtkWidget *container;
888 container = gtk_widget_get_parent ( obj );
889
890 #ifdef DEBUG_TEXT
891 g_print ( "INSERT SOME INITIAL TEXT\n" );
892 #endif
893
894 return TCL_OK;
895 }
896
897 /**
898 \brief Set equidistant tab stops meausure in pixels.
899 http://developer.gnome.org/pango/stable/pango-Tab-Stops.html
900 **/
gnoclOptTabs(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)901 static int gnoclOptTabs ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
902 {
903
904 #ifdef DEBUG_TEXT
905 g_print ( "%s SET SOME INITIAL TABS\n", __FUNCTION__ );
906 #endif
907
908 gint pos;
909
910 Tcl_GetIntFromObj ( interp, opt->val.obj, &pos );
911
912 PangoTabArray *tab_array = pango_tab_array_new_with_positions ( 1, TRUE, PANGO_TAB_LEFT, pos );
913 gtk_text_view_set_tabs ( GTK_TEXT_VIEW ( obj ), tab_array );
914
915 /*
916 * An alternative way...
917 */
918 /*
919 PangoTabArray *tab_array;
920 gint initial_size,tab_index, location;
921 PangoTabAlign alignment;
922
923 initial_size = 2;
924
925 tab_array = pango_tab_array_new (initial_size,1);
926
927 pango_tab_array_set_tab (tab_array,0,PANGO_TAB_LEFT, 100);
928 pango_tab_array_set_tab (tab_array,1,PANGO_TAB_LEFT, 200);
929
930 gtk_text_view_set_tabs ( GTK_TEXT_VIEW ( obj ), tab_array );
931
932 pango_tab_array_free (tab_array);
933 */
934 return TCL_OK;
935 }
936
937 /**
938 \brief Set text tag attribute.
939 \notes Keywords:
940 raise
941 lower
942 top
943 bottom
944 **/
gnoclOptTextTagPriority(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)945 static int gnoclOptTextTagPriority ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
946 {
947
948 #ifdef DEBUG_TEXT
949 debugStep ( __FUNCTION__, 1.0 );
950 #endif
951
952 static char *opts[] =
953 {
954 "raise", "lower", "top", "bottom",
955 NULL
956 };
957
958 static enum popupOptionsIdx
959 {
960 raiseIdx, lowerIdx, topIdx, bottomIdx
961 };
962
963 gint idx;
964
965 gint priority;
966
967 gint max;
968
969 GtkTextTag *tag;
970
971 tag = GTK_TEXT_TAG ( obj );
972
973 max = gtk_text_tag_table_get_size ( tag->table );
974
975 priority = gtk_text_tag_get_priority ( tag );
976
977 getIdx ( opts, Tcl_GetStringFromObj ( opt->val.obj, NULL ), &idx );
978
979 switch ( idx )
980 {
981 case raiseIdx:
982 {
983 priority++;
984 }
985 break;
986 case lowerIdx:
987 {
988 priority--;
989 }
990 break;
991 case topIdx:
992 {
993 priority = max - 1;
994 }
995 break;
996 case bottomIdx:
997 {
998 priority = 0;
999 }
1000 break;
1001 default:
1002 {
1003 Tcl_GetIntFromObj ( interp, opt->val.obj, &priority );
1004 }
1005 }
1006
1007 /* check limits */
1008 if ( priority < 0 )
1009 {
1010 priority = 0;
1011 }
1012
1013 if ( priority >= max )
1014 {
1015 priority--;
1016 }
1017
1018 gtk_text_tag_set_priority ( tag, priority );
1019
1020 return TCL_OK;
1021 }
1022
1023 /**
1024 \brief Set text tag attribute.
1025 **/
gnoclOptTagBackgroundStipple(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)1026 static int gnoclOptTagBackgroundStipple ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
1027 {
1028 GtkWidget *container;
1029 container = gtk_widget_get_parent ( obj );
1030
1031 #ifdef DEBUG_TEXT
1032 debugStep ( __FUNCTION__, 1.0 );
1033 g_print ( "Feature not yet implemented\n" );
1034 #endif
1035
1036 return TCL_OK;
1037 }
1038
1039 /**
1040 \brief Set text tag attribute.
1041 **/
gnoclOptTagTextDirection(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)1042 static int gnoclOptTagTextDirection ( Tcl_Interp *interp, GnoclOption *opt, GObject *obj, Tcl_Obj **ret )
1043 {
1044
1045 #ifdef DEBUG_TEXT
1046 debugStep ( __FUNCTION__, 1.0 );
1047 #endif
1048
1049 /* options: leftRight | rightLeft | none */
1050
1051 /*
1052 typedef enum
1053 {
1054 GTK_TEXT_DIR_NONE,
1055 GTK_TEXT_DIR_LTR,
1056 GTK_TEXT_DIR_RTL,
1057 } GtkTextDirection;
1058 */
1059
1060 int idx;
1061
1062 const char *txt[] = { "none", "leftRight", "rightLeft", NULL };
1063
1064 if ( Tcl_GetIndexFromObj ( NULL, opt->val.obj, txt, NULL, TCL_EXACT, &idx ) != TCL_OK )
1065 {
1066 Tcl_AppendResult ( interp, "Unknown direction \"", Tcl_GetString ( opt->val.obj ), "\". Must be one of none, leftRight or rightLeft.", NULL );
1067 return TCL_ERROR;
1068 }
1069
1070 g_object_set ( obj, opt->propName, idx, NULL );
1071
1072 return TCL_OK;
1073 }
1074
1075 /**
1076 \brief Set text tag attribute.
1077 **/
gnoclOptTextTagForegroundStipple(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)1078 static int gnoclOptTextTagForegroundStipple ( Tcl_Interp * interp, GnoclOption * opt, GObject * obj, Tcl_Obj **ret )
1079 {
1080 GtkWidget *container;
1081 container = gtk_widget_get_parent ( obj );
1082
1083 #ifdef DEBUG_TEXT
1084 debugStep ( __FUNCTION__, 1.0 );
1085 g_print ( "Feature not yet implemented\n" );
1086 #endif
1087
1088 return TCL_OK;
1089 }
1090
1091 /**
1092 \brief Set text tag attribute.
1093 **/
gnocOptTextTagLanguage(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)1094 static int gnocOptTextTagLanguage ( Tcl_Interp * interp, GnoclOption * opt, GObject * obj, Tcl_Obj **ret )
1095 {
1096
1097 gchar *lang;
1098 gint i;
1099
1100 lang = Tcl_GetStringFromObj ( opt->val.obj, NULL );
1101
1102 #ifdef DEBUG_TEXT
1103 debugStep ( __FUNCTION__, 1.0 );
1104 g_print ( "Language = %s\n", lang );
1105 #endif
1106
1107 i = getLanguage ( lang );
1108
1109 #ifdef DEBUG_TEXT
1110 g_print ( "idx = %d\n", i );
1111 #endif
1112
1113
1114
1115 return TCL_OK;
1116 }
1117
1118 /**
1119 \brief Set text tag attribute.
1120 **/
gnoclOptTextTagTabs(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)1121 static int gnoclOptTextTagTabs ( Tcl_Interp * interp, GnoclOption * opt, GObject * obj, Tcl_Obj **ret )
1122 {
1123
1124
1125 #ifdef DEBUG_TEXT
1126 debugStep ( __FUNCTION__, 1.0 );
1127 g_print ( "Feature not yet implemented\n" );
1128 #endif
1129
1130 return TCL_OK;
1131 }
1132
1133 /**
1134 \brief Set text tag attribute.
1135 **/
gnoclOptTextTagVariant(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)1136 static int gnoclOptTextTagVariant ( Tcl_Interp * interp, GnoclOption * opt, GObject * obj, Tcl_Obj **ret )
1137 {
1138
1139 #ifdef DEBUG_TEXT
1140 debugStep ( __FUNCTION__, 1.0 );
1141 g_print ( "Feature not yet implemented\n" );
1142 #endif
1143
1144 return TCL_OK;
1145 }
1146
1147
1148 /**
1149 \brief
1150 */
doOnTextEnterLeave(GtkWidget * widget,GdkEventMotion * event,gpointer data)1151 static gboolean doOnTextEnterLeave ( GtkWidget * widget, GdkEventMotion * event, gpointer data )
1152 {
1153 GnoclCommandData *cs = ( GnoclCommandData * ) data;
1154
1155 GnoclPercSubst ps[] =
1156 {
1157 { 'w', GNOCL_STRING }, /* widget */
1158 { 0 }
1159 };
1160
1161 ps[0].val.str = gnoclGetNameFromWidget ( widget );
1162
1163 /* TODO: gnocl::buttonStateToList -> {MOD1 MOD3 BUTTON2...} */
1164 gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
1165 return 0;
1166 }
1167
1168
1169 /**
1170 \brief Add default set of tag with pango compliant tagnames.
1171 **/
gnoclOptMarkupTags(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)1172 static int gnoclOptMarkupTags ( Tcl_Interp * interp, GnoclOption * opt, GObject * obj, Tcl_Obj **ret )
1173 {
1174 #ifdef DEBUG_TEXT
1175 g_print ( "%s %d\n", __FUNCTION__, Tcl_GetString ( opt->val.obj ) );
1176 #endif
1177
1178 extern gint usemarkup;
1179
1180 assert ( strcmp ( opt->optName, "-markupTags" ) == 0 );
1181
1182 /* modify this to destroy tags */
1183 if ( strcmp ( Tcl_GetString ( opt->val.obj ), "1" ) == 0 )
1184 {
1185 usemarkup = 1;
1186 /* create default markup tag set */
1187 }
1188
1189 else
1190 {
1191 return TCL_OK;
1192 usemarkup = 1;
1193 /* delete markup tags */
1194 }
1195
1196 #ifdef DEBUG_TEXT
1197 g_print ( "usemarkup = %d\n", usemarkup );
1198 #endif
1199
1200 GtkTextBuffer *buffer = gtk_text_view_get_buffer ( GTK_TEXT_VIEW ( obj ) );
1201
1202 /* convenience tags */
1203 // 'b','i','s','u','tt','sub','sup','small','big'
1204 gtk_text_buffer_create_tag ( buffer, "<b>", "weight", PANGO_WEIGHT_BOLD, NULL );
1205 gtk_text_buffer_create_tag ( buffer, "<i>", "style", PANGO_STYLE_ITALIC, NULL );
1206 gtk_text_buffer_create_tag ( buffer, "<s>", "strikethrough", 1, NULL );
1207 gtk_text_buffer_create_tag ( buffer, "<u>", "underline", PANGO_UNDERLINE_SINGLE, NULL );
1208 gtk_text_buffer_create_tag ( buffer, "<tt>", "font", "Monospace", NULL );
1209 gtk_text_buffer_create_tag ( buffer, "<sub>", "scale", PANGO_SCALE_SMALL, "rise", -10, NULL );
1210 gtk_text_buffer_create_tag ( buffer, "<sup>", "scale", PANGO_SCALE_SMALL, "rise", +10, NULL );
1211 gtk_text_buffer_create_tag ( buffer, "<small>", "scale", PANGO_SCALE_SMALL, NULL );
1212 gtk_text_buffer_create_tag ( buffer, "<big>", "scale", PANGO_SCALE_LARGE, NULL );
1213
1214 /* foreground colours */
1215 // 'red', 'green', 'blue', 'cyan', 'magenta', 'yellow', 'black', 'gray', 'white'
1216 gtk_text_buffer_create_tag ( buffer, "<span foreground='red'>", "foreground", "red", NULL );
1217 gtk_text_buffer_create_tag ( buffer, "<span foreground='green'>", "foreground", "green", NULL );
1218 gtk_text_buffer_create_tag ( buffer, "<span foreground='blue'>", "foreground", "blue", NULL );
1219
1220 gtk_text_buffer_create_tag ( buffer, "<span foreground='black'>", "foreground", "black", NULL );
1221 gtk_text_buffer_create_tag ( buffer, "<span foreground='gray'>", "foreground", "gray", NULL );
1222 gtk_text_buffer_create_tag ( buffer, "<span foreground='white'>", "foreground", "white", NULL );
1223
1224 /* background colours */
1225 // 'red', 'green', 'blue', 'cyan', 'magenta', 'yellow', 'black', 'gray', 'white'
1226 gtk_text_buffer_create_tag ( buffer, "<span background='cyan'>", "background", "cyan", NULL );
1227 gtk_text_buffer_create_tag ( buffer, "<span background='magenta'>", "background", "magenta", NULL );
1228 gtk_text_buffer_create_tag ( buffer, "<span background='yellow'>", "background", "yellow", NULL );
1229 gtk_text_buffer_create_tag ( buffer, "<span background='orange'>", "background", "orange", NULL );
1230
1231
1232 gtk_text_buffer_create_tag ( buffer, "<span background='black'>", "background", "black", NULL );
1233 gtk_text_buffer_create_tag ( buffer, "<span background='gray'>", "background", "gray", NULL );
1234 gtk_text_buffer_create_tag ( buffer, "<span background='white'>", "background", "white", NULL );
1235
1236 /* default typefaces */
1237 // 'serif' or 'sans'
1238 gtk_text_buffer_create_tag ( buffer, "<span face='sans'>", "font", "serif", NULL );
1239 gtk_text_buffer_create_tag ( buffer, "<span face='serif'>", "font", "sans", NULL );
1240
1241 /* font scaling */
1242 // 'xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large'
1243 gtk_text_buffer_create_tag ( buffer, "<span size='xx-small'>", "scale", PANGO_SCALE_XX_SMALL, NULL );
1244 gtk_text_buffer_create_tag ( buffer, "<span size='x-small'>" , "scale", PANGO_SCALE_X_SMALL, NULL );
1245 gtk_text_buffer_create_tag ( buffer, "<span size='small'>" , "scale", PANGO_SCALE_SMALL, NULL );
1246 gtk_text_buffer_create_tag ( buffer, "<span size='medium'>" , "scale", PANGO_SCALE_MEDIUM, NULL );
1247 gtk_text_buffer_create_tag ( buffer, "<span size='large'>" , "scale", PANGO_SCALE_LARGE, NULL );
1248 gtk_text_buffer_create_tag ( buffer, "<span size='x-large'>" , "scale", PANGO_SCALE_X_LARGE, NULL );
1249 gtk_text_buffer_create_tag ( buffer, "<span size='xx-large'>", "scale", PANGO_SCALE_XX_LARGE, NULL );
1250
1251 /* font weight */
1252 //'ultralight', 'light', 'normal', 'bold', 'ultrabold', 'heavy'
1253 gtk_text_buffer_create_tag ( buffer, "<span weight='light'>" , "weight", PANGO_WEIGHT_LIGHT, NULL );
1254 gtk_text_buffer_create_tag ( buffer, "<span weight='normal'>" , "weight", PANGO_WEIGHT_NORMAL, NULL );
1255 gtk_text_buffer_create_tag ( buffer, "<span weight='bold'>" , "weight", PANGO_WEIGHT_BOLD, NULL );
1256 gtk_text_buffer_create_tag ( buffer, "<span weight='ultrabold'>", "weight", PANGO_WEIGHT_ULTRABOLD, NULL );
1257 gtk_text_buffer_create_tag ( buffer, "<span weight='heavy'>" , "weight", PANGO_WEIGHT_HEAVY, NULL );
1258
1259 /* variant */
1260 // 'normal' or 'smallcaps'
1261 gtk_text_buffer_create_tag ( buffer, "<span variant='normal'>" , "variant", PANGO_VARIANT_NORMAL, NULL );
1262 gtk_text_buffer_create_tag ( buffer, "<span variant='smallcaps'>" , "variant", PANGO_VARIANT_SMALL_CAPS, NULL );
1263
1264 /* stretch */
1265 // 'ultracondensed', 'extracondensed', 'condensed', 'semicondensed', 'normal', 'semiexpanded', 'expanded', 'extraexpanded', 'ultraexpanded'
1266 gtk_text_buffer_create_tag ( buffer, "<span stretch='ultracondensed'>" , "stretch", PANGO_STRETCH_ULTRA_CONDENSED, NULL );
1267 gtk_text_buffer_create_tag ( buffer, "<span stretch='extracondensed'>" , "stretch", PANGO_STRETCH_EXTRA_CONDENSED, NULL );
1268 gtk_text_buffer_create_tag ( buffer, "<span stretch='condensed'>" , "stretch", PANGO_STRETCH_CONDENSED, NULL );
1269 gtk_text_buffer_create_tag ( buffer, "<span stretch='normal'>" , "stretch", PANGO_STRETCH_NORMAL, NULL );
1270 gtk_text_buffer_create_tag ( buffer, "<span stretch='semicondensed'>" , "stretch", PANGO_STRETCH_SEMI_CONDENSED, NULL );
1271 gtk_text_buffer_create_tag ( buffer, "<span stretch='expanded'>" , "stretch", PANGO_STRETCH_EXPANDED, NULL );
1272 gtk_text_buffer_create_tag ( buffer, "<span stretch='extraexpanded'>" , "stretch", PANGO_STRETCH_EXTRA_EXPANDED, NULL );
1273 gtk_text_buffer_create_tag ( buffer, "<span stretch='ultraexpanded'>" , "stretch", PANGO_STRETCH_ULTRA_EXPANDED, NULL );
1274
1275 /* underline */
1276 // 'none', 'single', 'double', 'low', 'error'
1277 gtk_text_buffer_create_tag ( buffer, "<span underline='none'>" , "underline", PANGO_UNDERLINE_NONE, NULL );
1278 gtk_text_buffer_create_tag ( buffer, "<span underline='single'>" , "underline", PANGO_UNDERLINE_SINGLE, NULL );
1279 gtk_text_buffer_create_tag ( buffer, "<span underline='double'>" , "underline", PANGO_UNDERLINE_DOUBLE, NULL );
1280 gtk_text_buffer_create_tag ( buffer, "<span underline='low'>" , "underline", PANGO_UNDERLINE_LOW, NULL );
1281 gtk_text_buffer_create_tag ( buffer, "<span underline='error'>" , "underline", PANGO_UNDERLINE_ERROR, NULL );
1282
1283 return TCL_OK;
1284 }
1285
1286 /**
1287 \brief
1288 **/
gnoclOptTextOnEnterLeave(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)1289 static int gnoclOptTextOnEnterLeave ( Tcl_Interp * interp, GnoclOption * opt, GObject * obj, Tcl_Obj **ret )
1290 {
1291 GtkWidget *container;
1292 container = gtk_widget_get_parent ( obj );
1293
1294 assert ( strcmp ( opt->optName, "-onEnter" ) == 0 || strcmp ( opt->optName, "-onLeave" ) == 0 );
1295 return gnoclConnectOptCmd ( interp, obj, opt->optName[3] == 'E' ? "enter-notify-event" : "leave-notify-event", G_CALLBACK ( doOnTextEnterLeave ), opt, NULL, ret );
1296 }
1297
1298 /**
1299 \brief
1300 **/
getBitmapMask(gchar * filename)1301 static GdkBitmap *getBitmapMask ( gchar * filename )
1302 {
1303 GdkPixbuf *pbuf;
1304 GdkBitmap *ret;
1305 GError *err = NULL;
1306
1307 g_return_val_if_fail ( filename != NULL, NULL );
1308
1309 pbuf = gdk_pixbuf_new_from_file ( filename, &err );
1310
1311 if ( err != NULL )
1312 {
1313 g_warning ( "%s", err->message );
1314 g_error_free ( err );
1315 return NULL;
1316 }
1317
1318 /* you may want to change the threshold, depending on your image */
1319 gdk_pixbuf_render_pixmap_and_mask ( pbuf, NULL, &ret, 1 );
1320
1321 //g_object_unref ( pbuf );
1322
1323 return ret;
1324 }
1325
1326
1327 /**
1328 \brief
1329 **/
doOnInsertPixbuf(GtkTextBuffer * textbuffer,GtkTextIter * location,GdkPixbuf * pixbuf,gpointer user_data)1330 static void doOnInsertPixbuf ( GtkTextBuffer * textbuffer, GtkTextIter * location, GdkPixbuf * pixbuf, gpointer user_data )
1331 {
1332 GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
1333
1334 GnoclPercSubst ps[] =
1335 {
1336 { 'w', GNOCL_STRING }, /* widget */
1337 { 'r', GNOCL_INT }, /* row */
1338 { 'c', GNOCL_INT }, /* column */
1339 { 'p', GNOCL_INT }, /* pixbuf */
1340 { 0 }
1341 };
1342
1343 ps[0].val.str = gnoclGetNameFromWidget ( textbuffer );
1344 ps[1].val.i = gtk_text_iter_get_line ( location );
1345 ps[2].val.i = gtk_text_iter_get_line_offset ( location );
1346 ps[3].val.str = gnoclGetNameFromPixBuf ( pixbuf );
1347
1348 gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
1349 }
1350
1351
1352 /**
1353 \brief
1354 \author William J Giddings
1355 \date 30-Apr-09
1356 **/
gnoclOptOnInsertPB(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)1357 int gnoclOptOnInsertPB ( Tcl_Interp * interp, GnoclOption * opt, GObject * obj, Tcl_Obj **ret )
1358 {
1359
1360 /* check the name of the signal is correct for this function */
1361 assert ( strcmp ( opt->optName, "-onInsertPixBuf" ) == 0 );
1362
1363 /* connect the signal with its callback function */
1364 return gnoclConnectOptCmd ( interp, GTK_ENTRY ( obj ), "insert-pixbuf", G_CALLBACK ( doOnInsertPixbuf ), opt, NULL, ret );
1365
1366 }
1367
1368 /**
1369 \brief Handles the "toggle-cursor-visible" signal.
1370 \author William J Giddings
1371 \date 30/04/2010
1372 \since 0.9.95
1373 \note Used by: gnome::text, Default Binding F7.
1374 \**/
doOnToggleCursorVisible(GtkTextView * text_view,gpointer user_data)1375 static void doOnToggleCursorVisible ( GtkTextView * text_view, gpointer user_data )
1376 {
1377
1378 GnoclCommandData *cs = ( GnoclCommandData * ) user_data;
1379
1380 GnoclPercSubst ps[] =
1381 {
1382 { 'w', GNOCL_STRING }, /* widget name */
1383 { 'g', GNOCL_STRING }, /* glade name */
1384 { 'v', GNOCL_INT }, /* visibility, boolean */
1385 { 0 }
1386 };
1387
1388 ps[0].val.str = gnoclGetNameFromWidget ( text_view );
1389 ps[1].val.str = gtk_widget_get_name ( GTK_WIDGET ( text_view ) );
1390 ps[2].val.i = gtk_text_view_get_cursor_visible ( text_view );
1391
1392 gnoclPercentSubstAndEval ( cs->interp, ps, cs->command, 1 );
1393 }
1394
1395 /**
1396 \brief
1397 \author William J Giddings
1398 \date 30/04/2010
1399 \note
1400 **/
gnoclOptOnToggleCursorVisible(Tcl_Interp * interp,GnoclOption * opt,GObject * obj,Tcl_Obj ** ret)1401 int gnoclOptOnToggleCursorVisible ( Tcl_Interp * interp, GnoclOption * opt, GObject * obj, Tcl_Obj **ret )
1402 {
1403 /* check the name of the signal is correct for this function */
1404 assert ( strcmp ( opt->optName, "-onToggleCursorVisible" ) == 0 );
1405
1406 /* connect the signal with its callback function */
1407 return gnoclConnectOptCmd ( interp, obj, "toggle-cursor-visible" , G_CALLBACK ( doOnToggleCursorVisible ), opt, NULL, ret );
1408 }
1409
1410 /**
1411 \brief
1412 Description yet to be added.
1413 \note
1414 As long as the options for the GtkScrolledWindow are not set
1415 automatically, we don't need any special handling in gnoclSetOptions.
1416 */
1417 static const int scrollBarIdx = 0;
1418 static const int textIdx = 1;
1419 static const int bufferIdx = 2;
1420 static const int useUndoIdx = 3;
1421 static const int dataIdx = 4;
1422 static const int baseColorIdx = 5;
1423 static const int variableIdx = 6;
1424 static const int onChangedIdx = 7;
1425 static const int baseFontIdx = 8;
1426 static const int tooltipIdx = 9;
1427
1428 static GnoclOption textOptions[] =
1429 {
1430 /* textView */
1431
1432 /* gnocl-specific options - cget implemented */
1433 { "-scrollbar", GNOCL_OBJ, NULL },
1434 { "-text", GNOCL_STRING, NULL},
1435 { "-buffer", GNOCL_STRING, NULL},
1436 { "-useUndo", GNOCL_STRING, NULL},
1437 { "-data", GNOCL_OBJ, "", gnoclOptData },
1438 { "-baseColor", GNOCL_OBJ, "normal", gnoclOptGdkColorBase },
1439 { "-variable", GNOCL_STRING, NULL },
1440 { "-onChanged", GNOCL_STRING, NULL },
1441 { "-baseFont", GNOCL_OBJ, "Sans 14", gnoclOptGdkBaseFont },
1442 { "-tooltip", GNOCL_OBJ, "", gnoclOptTooltip },
1443
1444 /* GtkTextView properties
1445 "accepts-tab" gboolean : Read / Write
1446 "buffer" GtkTextBuffer* : Read / Write
1447 "cursor-visible" gboolean X
1448 "editable" gboolean X
1449 "indent" gint X
1450 "justification" GtkJustification X
1451 "left-margin" gint X
1452 "overwrite" gboolean : Read / Write
1453 "pixels-above-lines" gint X
1454 "pixels-below-lines" gint X
1455 "pixels-inside-wrap" gint X
1456 "right-margin" gint : Read / Write
1457 "tabs" PangoTabArray* : Read / Write
1458 "wrap-mode" GtkWrapMode : Read / Write
1459 */
1460
1461 { "-markupTags", GNOCL_OBJ, "", gnoclOptMarkupTags },
1462 { "-acceptsTab", GNOCL_BOOL, "accepts-tab" },
1463 { "-cursorVisible", GNOCL_BOOL, "cursor_visible" },
1464 { "-editable", GNOCL_BOOL, "editable" },
1465 { "-indent", GNOCL_INT, "indent" },
1466 { "-justify", GNOCL_OBJ, "justification", gnoclOptJustification },
1467 { "-leftMargin", GNOCL_INT, "left_margin" },
1468 { "-inputMethod", GNOCL_STRING, "im-module" },
1469 { "-overwrite", GNOCL_BOOL, "overwrite" },
1470 { "-pixelsBelowLines", GNOCL_INT, "pixels_below_lines" },
1471 { "-pixelsAboveLines", GNOCL_INT, "pixels_above_lines" },
1472 { "-pixelsInsideWrap", GNOCL_INT, "pixels_inside_wrap" },
1473 { "-rightMargin", GNOCL_INT, "right_margin" },
1474 { "-tabs", GNOCL_OBJ, "tabs", gnoclOptTabs}, /* "tabs" */
1475 { "-wrapMode", GNOCL_OBJ, "wrap_mode", gnoclOptWrapmode },
1476
1477 /* GtkTextBuffer properties
1478 "copy-target-list" GtkTargetList* : Read
1479 "cursor-position" gint : Read
1480 "has-selection" gboolean : Read
1481 "paste-target-list" GtkTargetList* : Read
1482 "tag-table" GtkTextTagTable* : Read / Write / Construct Only
1483 "text" gchar* : Read / Write
1484 */
1485
1486 { "-hasFocus", GNOCL_BOOL, "has-focus" },
1487
1488 { "-onShowHelp", GNOCL_OBJ, "", gnoclOptOnShowHelp },
1489 { "-name", GNOCL_STRING, "name" },
1490 { "-visible", GNOCL_BOOL, "visible" },
1491 { "-sensitive", GNOCL_BOOL, "sensitive" },
1492 { "-baseFont", GNOCL_OBJ, "Sans 14", gnoclOptGdkBaseFont },
1493 //{ "-baseColor", GNOCL_OBJ, "normal", gnoclOptGdkColorBase },
1494
1495 /* -------- GtkTextView signals --------*/
1496
1497 /*
1498 "backspace" : Run Last / Action
1499 "copy-clipboard" : Run Last / Action
1500 "cut-clipboard" : Run Last / Action
1501 "delete-from-cursor" : Run Last / Action
1502 "insert-at-cursor" : Run Last / Action
1503 "move-cursor" : Run Last / Action
1504 "move-viewport" : Run Last / Action
1505 "page-horizontally" : Run Last / Action
1506 "paste-clipboard" : Run Last / Action
1507 "populate-popup" : Run Last
1508 "select-all" : Run Last / Action
1509 "set-anchor" : Run Last / Action
1510 "set-scroll-adjustments" : Run Last / Action
1511 "toggle-cursor-visible" : Run Last / Action
1512 "toggle-overwrite" : Run Last / Action
1513
1514 */
1515
1516 { "-onBackspace", GNOCL_OBJ, "", gnoclOptOnBackspace},
1517 { "-onCopyClipboard", GNOCL_OBJ, "C", gnoclOptOnClipboard},
1518 { "-onCutClipboard", GNOCL_OBJ, "X", gnoclOptOnClipboard},
1519 { "-onUndo", GNOCL_OBJ, "U", gnoclOptOnUndoRedo},
1520 { "-onRedo", GNOCL_OBJ, "R", gnoclOptOnUndoRedo},
1521
1522 /* added 29/Apr/2010 */
1523 { "-onDeleteFromCursor", GNOCL_OBJ, "", gnoclOptOnDeleteFromCursor},
1524 { "-onInsertAtCursor", GNOCL_OBJ, "", gnoclOptOnInsertAtCursor},
1525 { "-onMoveCursor", GNOCL_OBJ, "", gnoclOptOnMoveCursor},
1526 { "-onMoveViewport", GNOCL_OBJ, "", gnoclOptOnMoveViewport},
1527 { "-onPageHorizontally", GNOCL_OBJ, "", gnoclOptOnPageHorizontally},
1528 { "-onPasteClipboard", GNOCL_OBJ, "P", gnoclOptOnClipboard},
1529 { "-onSelectAll", GNOCL_OBJ, "", gnoclOptOnSelectAll},
1530 { "-onPreeditChanged", GNOCL_OBJ, "", gnoclOptOnClipboard},
1531
1532 /* added 30/Apr/2010 */
1533 { "-onSetAnchor", GNOCL_OBJ, "", gnoclOptOnSetAnchor},
1534 { "-onSetScrollAdjustments", GNOCL_OBJ, "", gnoclOptOnScrollAdjustments},
1535
1536 /* check parse*.c code, for errors, or re-enter */
1537 { "-onToggleCursorVisible", GNOCL_OBJ, "", gnoclOptOnToggleCursorVisible },
1538 { "-onToggleOverWrite", GNOCL_OBJ, "", gnoclOptOnToggleOverwrite},
1539
1540 /* -------- end of GtkTexView signals */
1541 { "-onButtonPress", GNOCL_OBJ, "P", gnoclOptOnButton },
1542 { "-onButtonRelease", GNOCL_OBJ, "R", gnoclOptOnButton },
1543 { "-onKeyPress", GNOCL_OBJ, "", gnoclOptOnKeyPress },
1544 { "-onKeyRelease", GNOCL_OBJ, "", gnoclOptOnKeyRelease },
1545 { "-onMotion", GNOCL_OBJ, "", gnoclOptOnMotion },
1546 { "-onFocusIn", GNOCL_OBJ, "I", gnoclOptOnFocus },
1547 { "-onFocusOut", GNOCL_OBJ, "O", gnoclOptOnFocus },
1548 { "-onEnter", GNOCL_OBJ, "E", gnoclOptTextOnEnterLeave },
1549 { "-onLeave", GNOCL_OBJ, "L", gnoclOptTextOnEnterLeave },
1550 { "-onPopulatePopup", GNOCL_OBJ, "", gnoclOptOnPopulatePopup },
1551 { "-heightRequest", GNOCL_INT, "height-request" },
1552 { "-widthRequest", GNOCL_INT, "width-request" },
1553
1554 /* -------- GtkTextBuffer signals -------- */
1555 { "-onApplyTag", GNOCL_OBJ, "", gnoclOptOnApplyTag},
1556 { "-onBeginUserAction", GNOCL_OBJ, "", gnoclOptOnBeginUserAction},
1557 { "-onChanged", GNOCL_OBJ, "", gnoclOptOnChanged},
1558 { "-onDeleteRange", GNOCL_OBJ, "", gnoclOptOnDeleteRange},
1559 { "-onEndUserAction", GNOCL_OBJ, "", gnoclOptOnEndUserAction},
1560 { "-onInsertChildAnchor", GNOCL_OBJ, "", gnoclOptOnInsertChildAnchor},
1561 { "-onInsertPixBuf", GNOCL_OBJ, "", gnoclOptOnInsertPB},
1562 { "-onInsertText", GNOCL_OBJ, "", gnoclOptOnTextInsert},
1563 { "-onMarkDelete", GNOCL_OBJ, "", gnoclOptOnMarkDelete},
1564 { "-onMarkSet", GNOCL_OBJ, "", gnoclOptOnMarkSet},
1565 { "-onModified", GNOCL_OBJ, "", gnoclOptOnModified}, /* ie. modified-changed */
1566 { "-onPasteDone", GNOCL_OBJ, "", gnoclOptOnPasteDone}, /* since Gtk+ 2.15 */
1567 { "-onRemoveTag", GNOCL_OBJ, "", gnoclOptOnRemoveTag},
1568
1569 /* inherited GtkWidget features */
1570 { "-onScroll", GNOCL_OBJ, "", gnoclOptOnScroll },
1571 { "-borderWidth", GNOCL_OBJ, "border-width", gnoclOptPadding },
1572
1573 /* drag and drop functionality taken from box.c */
1574 { "-dropTargets", GNOCL_LIST, "t", gnoclOptDnDTargets },
1575 { "-dragTargets", GNOCL_LIST, "s", gnoclOptDnDTargets },
1576 { "-onDropData", GNOCL_OBJ, "", gnoclOptOnDropData },
1577 { "-onDragBegin", GNOCL_OBJ, "", gnoclOptOnDragEnd },
1578 { "-onDragEnd", GNOCL_OBJ, "", gnoclOptOnDragEnd },
1579 { "-onDragData", GNOCL_OBJ, "", gnoclOptOnDragData },
1580 { "-hasTooltip", GNOCL_BOOL, "has-tooltip" },
1581 { "-onQueryTooltip", GNOCL_OBJ, "", gnoclOptOnQueryToolTip },
1582 { "-onDestroy", GNOCL_OBJ, "destroy", gnoclOptCommand },
1583
1584 { NULL }
1585 };
1586
1587 /**
1588 \brief Convert at text index in the form of {row col} into a GtkTextBuffer iter(ator).
1589 \author Peter G Baum
1590 \date 2001-06:
1591 \bug (text_cursor_keyWords_test.tcl:13461): Gtk-WARNING **: Invalid text buffer iterator: either the iterator is uninitialized,
1592 or the characters/pixbufs/widgets in the buffer have been modified since the iterator was created.
1593 You must use marks, character numbers, or line numbers to preserve a position across buffer modifications.
1594 You can apply tags and insert marks without invalidating your iterators,
1595 but any mutation that affects 'indexable' buffer contents (contents that can be referred to by character offset)
1596 will invalidate all outstanding iterators
1597 Causes: moving the inter does not act on the buffer, once the iter has been moved, then it n
1598 \todo Include new keywords
1599 sentenceStart
1600 sentenceEnd
1601 paragraphStart
1602 paragraphEnd
1603 wordStart
1604 wordEnd
1605 lineEnd
1606 \history
1607 2008-06-27 Began implementation of new keywords for text position. See TODO.
1608 */
posToIter(Tcl_Interp * interp,Tcl_Obj * obj,GtkTextBuffer * buffer,GtkTextIter * iter)1609 int posToIter ( Tcl_Interp * interp, Tcl_Obj * obj, GtkTextBuffer * buffer, GtkTextIter * iter )
1610 {
1611 char errMsg[] = "Position must be either a list of row and column "
1612 "or a keyword plus offset";
1613 char errEndOffset[] = "offset to \"end\" must be negative";
1614
1615 int len;
1616
1617 /* error check the arguments passed to the function */
1618
1619 if ( Tcl_ListObjLength ( interp, obj, &len ) != TCL_OK || len < 1 || len > 2 )
1620 {
1621 Tcl_SetResult ( interp, errMsg, TCL_STATIC );
1622 return TCL_ERROR;
1623 }
1624
1625 /* this is right */
1626
1627 if ( len == 2 )
1628 {
1629 int idx[2];
1630 int isEnd[2] = { 0, 0 };
1631 int k;
1632
1633 for ( k = 0; k < 2; ++k )
1634 {
1635 Tcl_Obj *tp;
1636
1637 if ( Tcl_ListObjIndex ( interp, obj, k, &tp ) != TCL_OK )
1638 {
1639 Tcl_SetResult ( interp, errMsg, TCL_STATIC );
1640 return TCL_ERROR;
1641 }
1642
1643 if ( Tcl_GetIntFromObj ( NULL, tp, idx + k ) != TCL_OK )
1644 {
1645 char *txt = Tcl_GetString ( tp );
1646
1647 if ( strncmp ( txt, "end", 3 ) == 0 )
1648 {
1649 if ( gnoclPosOffset ( interp, txt + 3, idx + k ) != TCL_OK )
1650 return TCL_ERROR;
1651
1652 if ( idx[k] > 0 )
1653 {
1654 Tcl_SetResult ( interp, errEndOffset, TCL_STATIC );
1655 return TCL_ERROR;
1656 }
1657
1658 isEnd[k] = 1;
1659 }
1660
1661 else
1662 {
1663 Tcl_AppendResult ( interp, "unknown row or column index \"", txt, "\" must be integer or end plus offset" );
1664 return TCL_ERROR;
1665 }
1666
1667 }
1668 }
1669
1670 gtk_text_buffer_get_start_iter ( buffer, iter );
1671
1672 if ( isEnd[0] )
1673 {
1674 gtk_text_iter_set_line ( iter, -1 );
1675 gtk_text_iter_backward_lines ( iter, -idx[0] );
1676 }
1677
1678 else
1679 gtk_text_iter_set_line ( iter, idx[0] );
1680
1681 if ( isEnd[0] )
1682 {
1683 gtk_text_iter_forward_to_line_end ( iter );
1684 gtk_text_iter_backward_chars ( iter, -idx[1] );
1685 }
1686
1687 else
1688 gtk_text_iter_forward_chars ( iter, idx[1] );
1689 }
1690
1691 else if ( Tcl_GetIntFromObj ( NULL, obj, &len ) == TCL_OK )
1692 {
1693 if ( len < 0 )
1694 {
1695 Tcl_SetResult ( interp, "character offset must be greater zero.", TCL_STATIC );
1696 return TCL_ERROR;
1697 }
1698
1699 gtk_text_buffer_get_iter_at_offset ( buffer, iter, len );
1700 }
1701
1702 else
1703 {
1704 const char *txt = Tcl_GetString ( obj );
1705 const char *last;
1706 int offset;
1707
1708 /* get a fresh iterator, it may have already been altered due to a previous call */
1709 gtk_text_buffer_get_iter_at_mark ( buffer, iter, gtk_text_buffer_get_insert ( buffer ) );
1710
1711
1712 if ( strncmp ( txt, "start", 5 ) == 0 )
1713 {
1714 #ifdef DEBUG_TEXT
1715 g_print ( "checking start\n" );
1716 #endif
1717 gtk_text_buffer_get_start_iter ( buffer, iter );
1718 last = txt + 5;
1719 }
1720
1721 else if ( strncmp ( txt, "end", 3 ) == 0 )
1722 {
1723 #ifdef DEBUG_TEXT
1724 g_print ( "checking end\n" );
1725 #endif
1726 gtk_text_buffer_get_end_iter ( buffer, iter );
1727 last = txt + 3;
1728 }
1729
1730 else if ( strncmp ( txt, "cursor", 6 ) == 0 )
1731 {
1732 #ifdef DEBUG_TEXT
1733 g_print ( "checking cursor\n" );
1734 #endif
1735 last = txt + 6;
1736 gtk_text_buffer_get_iter_at_mark ( buffer, iter, gtk_text_buffer_get_insert ( buffer ) );
1737 }
1738
1739 else if ( strncmp ( txt, "selectionStart", 14 ) == 0 )
1740 {
1741 #ifdef DEBUG_TEXT
1742 g_print ( "checking selectionStart\n" );
1743 #endif
1744 GtkTextIter end;
1745 gtk_text_buffer_get_selection_bounds ( buffer, iter, &end );
1746 last = txt + 14;
1747 }
1748
1749 else if ( strncmp ( txt, "selectionEnd", 12 ) == 0 )
1750 {
1751 #ifdef DEBUG_TEXT
1752 g_print ( "checking selectionEnd\n" );
1753 #endif
1754 GtkTextIter start;
1755 gtk_text_buffer_get_selection_bounds ( buffer, &start, iter );
1756 last = txt + 12;
1757 }
1758
1759 else if ( strncmp ( txt, "wordStart", 9 ) == 0 )
1760 {
1761 #ifdef DEBUG_TEXT
1762 g_print ( "checking wordStart\n" );
1763 #endif
1764 /* get a fresh iterator, it may have already been altered */
1765 //gtk_text_buffer_get_iter_at_mark( buffer, iter, gtk_text_buffer_get_insert( buffer ) );
1766 gtk_text_iter_backward_word_start ( iter );
1767 last = txt + 9;
1768 }
1769
1770 else if ( strncmp ( txt, "wordEnd", 7 ) == 0 )
1771 {
1772 #ifdef DEBUG_TEXT
1773 g_print ( "checking wordEnd\n" );
1774 #endif
1775 /* get a fresh iterator, it may have already been altered */
1776 //gtk_text_buffer_get_iter_at_mark( buffer, iter, gtk_text_buffer_get_insert( buffer ) );
1777 gtk_text_iter_forward_word_end ( iter );
1778 last = txt + 7;
1779 }
1780
1781 /* WJG CURRENTLY WORKING HERE. Nothing happening, also text insert now kaput! */
1782
1783 else if ( strncmp ( txt, "sentenceStart", 13 ) == 0 )
1784 {
1785 #ifdef DEBUG_TEXT
1786 printf ( "checking sentenceStart\n" );
1787 #endif
1788 /* get a fresh iterator, it may have already been altered */
1789 //gtk_text_buffer_get_iter_at_mark( buffer, iter, gtk_text_buffer_get_insert( buffer ) );
1790 gtk_text_iter_backward_sentence_start ( iter );
1791 last = txt + 13;
1792 }
1793
1794 else if ( strncmp ( txt, "sentenceEnd", 11 ) == 0 )
1795 {
1796 #ifdef DEBUG_TEXT
1797 printf ( "checking sentenceEnd\n" );
1798 #endif
1799 /* get a fresh iterator, it may have already been altered */
1800 //gtk_text_buffer_get_iter_at_mark( buffer, iter, gtk_text_buffer_get_insert( buffer ) );
1801 gtk_text_iter_forward_sentence_end ( iter );
1802 last = txt + 11;
1803 }
1804
1805 else if ( strncmp ( txt, "lineStart", 9 ) == 0 )
1806 {
1807 #ifdef DEBUG_TEXT
1808 printf ( "checking lineStart\n" );
1809 #endif
1810 /* move iterator to an offset of 0 */
1811 /* get a fresh iterator, it may have already been altered */
1812 //gtk_text_buffer_get_iter_at_mark( buffer, iter, gtk_text_buffer_get_insert( buffer ) );
1813 gtk_text_iter_backward_visible_line ( iter );
1814 last = txt + 9;
1815 }
1816
1817 else if ( strncmp ( txt, "lineEnd", 7 ) == 0 )
1818 {
1819 #ifdef DEBUG_TEXT
1820 g_print ( "checking lineEnd\n" );
1821 #endif
1822 /* move iterator to the start of the next line, then move back one offset */
1823 /* get a fresh iterator, it may have already been altered */
1824 //gtk_text_buffer_get_iter_at_mark( buffer, iter, gtk_text_buffer_get_insert( buffer ) );
1825 gtk_text_iter_forward_visible_line ( iter );
1826 last = txt + 7;
1827 }
1828
1829 else
1830 {
1831 Tcl_AppendResult ( interp, "unknown index \"", txt,
1832 "\", must be a list of row and column, "
1833 "an integer as character offset, "
1834 "or one of start, end, cursor, wordStart, wordEnd, sentenceStart, sentenceEnd, lineStart, lineEnd, selectionStart, or selectionEnd",
1835 NULL );
1836 return TCL_ERROR;
1837 }
1838
1839 if ( gnoclPosOffset ( interp, last, &offset ) != TCL_OK )
1840 return TCL_ERROR;
1841
1842 if ( offset > 0 )
1843 gtk_text_iter_forward_chars ( iter, offset );
1844 else if ( offset < 0 )
1845 gtk_text_iter_backward_chars ( iter, -offset );
1846 }
1847
1848 return TCL_OK;
1849 }
1850
1851 /**
1852 \brief Apply a lists of tags to the a specified range of text.
1853 **/
applyTag(GtkTextBuffer * buffer,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[],int cmdNo)1854 static int applyTag ( GtkTextBuffer * buffer, Tcl_Interp * interp, int objc, Tcl_Obj * const objv[], int cmdNo )
1855 {
1856 /**
1857 Or, does it appear here?
1858 */
1859 /* declare some variables */
1860 // console error messaging
1861 GnoclOption insertOptions[] =
1862 {
1863 { "-tags", GNOCL_LIST, NULL },
1864 { NULL }
1865 };
1866 const int tagsIdx = 0;
1867 gint startOffset;
1868 gint endOffset;
1869 int ret = TCL_ERROR;
1870
1871 GtkTextIter iter;
1872 GtkTextIter iter2;
1873
1874 /* The arguments passed in the tcl script are in the objv array. These are:
1875 0: {0 0} fromIndex
1876 +1: {0 end} toIndex
1877 +2: -tags
1878 +3: bold cursor taglist
1879 */
1880
1881 /*
1882 printf ( "-2: {%s} \n-1: {%s} \n0: {%s} \n+1: {%s} \n+2: %s \n+3: %s \n",
1883 gnoclGetString ( objv[cmdNo-2] ),
1884 gnoclGetString ( objv[cmdNo-1] ),
1885 gnoclGetString ( objv[cmdNo] ),
1886 gnoclGetString ( objv[cmdNo+1] ),
1887 gnoclGetString ( objv[cmdNo+2] ),
1888 gnoclGetString ( objv[cmdNo+3] ) );
1889 */
1890
1891 // "position text ?-option val ...?"
1892
1893 if ( objc < cmdNo + 2 )
1894 {
1895 Tcl_WrongNumArgs ( interp, cmdNo, objv, "fromIndex toIndex -tags {tag1 tag2...}S" );
1896 return TCL_ERROR;
1897 }
1898
1899 /* determine some value */
1900 // get position of fromIndex within the buffer as in iterator
1901
1902 if ( posToIter ( interp, objv[cmdNo], buffer, &iter ) != TCL_OK )
1903 {
1904 return TCL_ERROR;
1905 }
1906
1907 // get position of toIndex within the buffer as in iterator
1908
1909 if ( posToIter ( interp, objv[cmdNo+1], buffer, &iter2 ) != TCL_OK )
1910 {
1911 return TCL_ERROR;
1912 }
1913
1914 /* parse options, check to see if they are suitable */
1915
1916 if ( gnoclParseOptions ( interp, objc - cmdNo - 1, objv + cmdNo + 1, insertOptions ) != TCL_OK )
1917 {
1918 goto clearExit;
1919 }
1920
1921 startOffset = gtk_text_iter_get_offset ( &iter );
1922
1923 endOffset = gtk_text_iter_get_offset ( &iter2 );
1924
1925 /* add the tags, gets a list and then works through them */
1926
1927 if ( insertOptions[tagsIdx].status == GNOCL_STATUS_CHANGED )
1928 {
1929 GtkTextIter start;
1930 GtkTextIter end;
1931 int k, no;
1932 Tcl_Obj *obj = insertOptions[tagsIdx].val.obj;
1933
1934 /* get the offset position for the inserted text*/
1935 gtk_text_buffer_get_iter_at_offset ( buffer, &start, startOffset );
1936 gtk_text_buffer_get_iter_at_offset ( buffer, &end, endOffset );
1937
1938 if ( Tcl_ListObjLength ( interp, obj, &no ) != TCL_OK )
1939 {
1940 goto clearExit;
1941 }
1942
1943 /* apply each tag in turn */
1944
1945 for ( k = 0; k < no; ++k )
1946 {
1947 Tcl_Obj *tp;
1948
1949 if ( Tcl_ListObjIndex ( interp, obj, k, &tp ) != TCL_OK )
1950 {
1951 Tcl_SetResult ( interp, "Could not read tag list", TCL_STATIC );
1952 goto clearExit;
1953 }
1954
1955 gtk_text_buffer_apply_tag_by_name ( buffer, Tcl_GetString ( tp ), &start, &end );
1956
1957 }
1958 }
1959
1960 ret = TCL_OK;
1961
1962 clearExit:
1963 gnoclClearOptions ( insertOptions );
1964
1965 return ret;
1966 }
1967
1968 /**
1969 \brief Remove specific tag from a tag tagtable
1970 **/
deleteTag(GtkTextTag * tag,gpointer data)1971 static void deleteTag ( GtkTextTag * tag, gpointer data )
1972 {
1973 gtk_text_tag_table_remove ( data, tag );
1974 }
1975
1976
1977 /**
1978 \brief
1979 \note
1980 **/
removeTag(GtkTextBuffer * buffer,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[],int cmdNo)1981 static int removeTag ( GtkTextBuffer * buffer, Tcl_Interp * interp, int objc, Tcl_Obj * const objv[], int cmdNo )
1982 {
1983 /* declare some variables */
1984 // console error messaging
1985 GnoclOption insertOptions[] =
1986 {
1987 { "-tags", GNOCL_LIST, NULL },
1988 { NULL }
1989 };
1990 const int tagsIdx = 0;
1991 gint startOffset;
1992 gint endOffset;
1993 int ret = TCL_ERROR;
1994
1995 GtkTextIter iter;
1996 GtkTextIter iter2;
1997
1998 /* The arguments passed in the tcl script are in the objv array. These are:
1999 0: {0 0} fromIndex
2000 +1: {0 end} toIndex
2001 +2: -tags
2002 +3: bold cursor taglist
2003 */
2004 /*
2005 printf ( "-2: {%s} \n-1: {%s} \n0: {%s} \n+1: {%s} \n+2: %s \n+3: %s \n",
2006 gnoclGetString ( objv[cmdNo-2] ),
2007 gnoclGetString ( objv[cmdNo-1] ),
2008 gnoclGetString ( objv[cmdNo] ),
2009 gnoclGetString ( objv[cmdNo+1] ),
2010 gnoclGetString ( objv[cmdNo+2] ),
2011 gnoclGetString ( objv[cmdNo+3] ) );
2012 */
2013 // "position text ?-option val ...?"
2014
2015 if ( objc < cmdNo + 2 )
2016 {
2017 Tcl_WrongNumArgs ( interp, cmdNo, objv, "fromIndex toIndex -tags {tag1 tag2...}S" );
2018 return TCL_ERROR;
2019 }
2020
2021 /* determine some value */
2022 // get position of fromIndex within the buffer as in iterator
2023
2024 if ( posToIter ( interp, objv[cmdNo], buffer, &iter ) != TCL_OK ) return TCL_ERROR;
2025
2026 // get position of toIndex within the buffer as in iterator
2027 if ( posToIter ( interp, objv[cmdNo+1], buffer, &iter2 ) != TCL_OK ) return TCL_ERROR;
2028
2029 /* parse options, check to see if they are suitable */
2030 if ( gnoclParseOptions ( interp, objc - cmdNo - 1, objv + cmdNo + 1, insertOptions ) != TCL_OK ) goto clearExit;
2031
2032 startOffset = gtk_text_iter_get_offset ( &iter );
2033
2034 endOffset = gtk_text_iter_get_offset ( &iter2 );
2035
2036
2037 /* check for keyword all */
2038
2039
2040 /* add the tags, gets a list and then works through them */
2041 if ( insertOptions[tagsIdx].status == GNOCL_STATUS_CHANGED )
2042 {
2043 GtkTextIter start;
2044 GtkTextIter end;
2045 int k, no;
2046 Tcl_Obj *obj = insertOptions[tagsIdx].val.obj;
2047
2048 /* get the offset position for the inserted text*/
2049 gtk_text_buffer_get_iter_at_offset ( buffer, &start, startOffset );
2050 gtk_text_buffer_get_iter_at_offset ( buffer, &end, endOffset );
2051
2052 if ( Tcl_ListObjLength ( interp, obj, &no ) != TCL_OK ) goto clearExit;
2053
2054 /* apply each tag in turn */
2055 for ( k = 0; k < no; ++k )
2056 {
2057 Tcl_Obj *tp;
2058
2059 if ( Tcl_ListObjIndex ( interp, obj, k, &tp ) != TCL_OK )
2060 {
2061 Tcl_SetResult ( interp, "Could not read tag list", TCL_STATIC );
2062 goto clearExit;
2063 }
2064
2065 gtk_text_buffer_remove_tag_by_name ( buffer, Tcl_GetString ( tp ), &start, &end );
2066
2067 }
2068 }
2069
2070 ret = TCL_OK;
2071
2072 clearExit:
2073 gnoclClearOptions ( insertOptions );
2074
2075 return ret;
2076 }
2077
2078 /**
2079 \brief To implement working bindings to GtkTextMark functions.
2080 \author William J Giddings
2081 \date 31/Jun/2008
2082 \note
2083 **/
markCmd(GtkTextBuffer * buffer,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[],int cmdNo)2084 static int markCmd ( GtkTextBuffer * buffer, Tcl_Interp * interp, int objc, Tcl_Obj * const objv[], int cmdNo )
2085 {
2086 const char *cmds[] = { "create", "configure", "delete", "move", "names", "cget", "getIndex", NULL };
2087 enum cmdIdx { CreateIdx, ConfigureIdx, DeleteIdx, MoveIdx, NamesIdx, CgetIdx, GetIndexIdx };
2088 int idx, row, col;
2089 GtkTextIter iter;
2090 GtkTextMark *mark;
2091 Tcl_Obj *resList;
2092
2093 GnoclOption markOptions[] =
2094 {
2095 { "-visible", GNOCL_BOOL, "invisible" },
2096 { "-gravity", GNOCL_BOOL, "left-gravity" },
2097 { NULL }
2098 };
2099
2100 /* check the script for errors */
2101
2102 if ( objc < cmdNo + 1 )
2103 {
2104 Tcl_WrongNumArgs ( interp, cmdNo, objv, "subcommand ?option val ...?" );
2105 return TCL_ERROR;
2106 }
2107
2108 if ( Tcl_GetIndexFromObj ( interp, objv[cmdNo], cmds, "subcommand", TCL_EXACT, &idx ) != TCL_OK )
2109 {
2110 return TCL_ERROR;
2111 }
2112
2113
2114 switch ( idx )
2115 {
2116 case CreateIdx:
2117 {
2118 char *str;
2119 Tcl_Obj *resList;
2120 #ifdef DEBUG_TEXT
2121 printf ( "markCmd 1> create %sIdx mark: %s position: { %s } \n",
2122 Tcl_GetString ( objv[cmdNo+0] ) ,
2123 Tcl_GetString ( objv[cmdNo+1] ) ,
2124 Tcl_GetString ( objv[cmdNo+2] ) );
2125 #endif
2126
2127 if ( objc < cmdNo + 2 )
2128 {
2129 Tcl_WrongNumArgs ( interp, cmdNo + 1, objv, "mark-name ?option val ...?" );
2130 return TCL_ERROR;
2131 }
2132
2133 /* convert position to inter */
2134
2135 if ( posToIter ( interp, objv[cmdNo+2], buffer, &iter ) != TCL_OK )
2136 {
2137 /* defaul to cursor position */
2138 return TCL_ERROR;
2139 }
2140
2141 gtk_text_buffer_create_mark ( buffer, Tcl_GetString ( objv[cmdNo+1] ), &iter, 0 );
2142
2143 /* return the name of the mark created */
2144 resList = Tcl_NewListObj ( 0, NULL );
2145 str = Tcl_GetString ( objv[cmdNo+1] );
2146 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewStringObj ( str, -1 ) );
2147 Tcl_SetObjResult ( interp, resList );
2148
2149 return TCL_OK ;
2150
2151 }
2152
2153 case ConfigureIdx:
2154 {
2155
2156 if ( objc < cmdNo + 2 )
2157 {
2158 Tcl_WrongNumArgs ( interp, cmdNo + 1, objv, "mark-name ?option val ...?" );
2159 return TCL_ERROR;
2160 }
2161
2162 #ifdef DEBUG_TEXT
2163 printf ( "markCmd ConfigureIdx> %s %s %s %s} \n",
2164 Tcl_GetString ( objv[cmdNo+0] ) ,
2165 Tcl_GetString ( objv[cmdNo+1] ) ,
2166 Tcl_GetString ( objv[cmdNo+2] ) ,
2167 Tcl_GetString ( objv[cmdNo+3] ) );
2168 #endif
2169
2170 mark = gtk_text_buffer_get_mark ( buffer, Tcl_GetString ( objv[cmdNo+1] ) );
2171
2172 /* check the options flag */
2173
2174 if ( strcmp ( Tcl_GetString ( objv[cmdNo+2] ), "-visible" ) )
2175 {
2176 #ifdef DEBUG_TEXT
2177 printf ( "markCmd 3>\n" );
2178 #endif
2179 /* apply the setting */
2180
2181 if ( Tcl_GetString ( objv[cmdNo+3] ) )
2182 {
2183 gtk_text_mark_set_visible ( mark, 1 );
2184 }
2185
2186 else
2187 {
2188 gtk_text_mark_set_visible ( mark, 0 );
2189 }
2190
2191 }
2192
2193 else if ( strcmp ( Tcl_GetString ( objv[cmdNo+2] ), "-gravity" ) )
2194 {
2195 /* NOTE:
2196 * There is no Gtk lib function to reset the gravity of a marker.
2197 * To achieve this, the marker first needs to be deleted and then
2198 * a new recreated with the same name and a complementary left-gravity
2199 * setting. Right-gravity is necessary for right-to-left written scripts
2200 * such as Hebrew and Arabic.
2201 */
2202 #ifdef DEBUG_TEXT
2203 printf ( "markCmd 4>\n" );
2204 #endif
2205 /* apply the setting */
2206
2207 if ( strcmp ( Tcl_GetString ( objv[cmdNo+3] ), "left" ) )
2208 {
2209 gtk_text_mark_set_visible ( mark, 1 );
2210 }
2211
2212 else
2213 /* reverts to default, ie left-gravity 0 */
2214 {
2215 gtk_text_mark_set_visible ( mark, 1 );
2216 }
2217
2218 }
2219
2220 return TCL_OK;
2221
2222 }
2223
2224 case DeleteIdx:
2225 {
2226 gtk_text_buffer_delete_mark_by_name ( buffer, Tcl_GetString ( objv[cmdNo+1] ) );
2227 return TCL_OK;
2228 }
2229
2230 case MoveIdx:
2231 {
2232
2233 /* convert the new position to a GtkTextIter */
2234 posToIter ( interp, objv[cmdNo+2] , buffer, &iter );
2235
2236 /* move names mark to a new location within the buffer */
2237 gtk_text_buffer_move_mark_by_name ( buffer, Tcl_GetString ( objv[cmdNo+1] ), &iter );
2238
2239 return TCL_OK;
2240
2241 }
2242
2243 case NamesIdx:
2244 {
2245 // return a list of all the marks associated with the textBuffer, such a query is not supported within Gtk
2246 }
2247
2248 case CgetIdx: // markCmd
2249 {
2250 /* if cget implmented, then to get the position of a mark
2251 *
2252 * void gtk_text_buffer_get_iter_at_mark (GtkTextBuffer *buffer, GtkTextIter *iter, GtkTextMark *mark);
2253 * gboolean gtk_text_mark_get_visible (GtkTextMark *mark);
2254 * gboolean gtk_text_mark_get_left_gravity (GtkTextMark *mark);
2255 */
2256
2257 }
2258
2259 case GetIndexIdx:
2260 {
2261 #ifdef DEBUG_TEXT
2262 printf ( "GetIndex\n" );
2263 #endif
2264 /* return the index of the named marker */
2265 mark = gtk_text_buffer_get_mark ( buffer, Tcl_GetString ( objv[cmdNo+1] ) );
2266 gtk_text_buffer_get_iter_at_mark ( buffer, &iter, mark );
2267
2268 /* the following block is hacked from GetCursorIdx */
2269 row = gtk_text_iter_get_line ( &iter );
2270 col = gtk_text_iter_get_line_offset ( &iter );
2271
2272 resList = Tcl_NewListObj ( 0, NULL );
2273 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewIntObj ( row ) );
2274 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewIntObj ( col ) );
2275 Tcl_SetObjResult ( interp, resList );
2276
2277 }
2278
2279 default:
2280 {
2281 //assert ( 0 );
2282 //return TCL_ERROR;
2283 }
2284 }
2285
2286 return TCL_OK;
2287
2288 }
2289
2290 /**
2291 \brief
2292
2293 pathName tag add tagName index1 ?index2 index1 index2 ...?
2294 pathName tag bind tagName ?sequence? ?script?
2295 pathName tag cget tagName option
2296 pathName tag configure tagName ?option? ?value? ?option value ...?
2297 pathName tag delete tagName ?tagName ...?
2298 pathName tag lower tagName ?belowThis?
2299 pathName tag names ?index?
2300 pathName tag nextrange tagName index1 ?index2?
2301 pathName tag prevrange tagName index1 ?index2?
2302 pathName tag properties tagName
2303 pathName tag raise tagName ?aboveThis?
2304 pathName tag ranges tagName
2305 pathName tag remove tagName index1 ?index2 index1 index2 ...?
2306
2307 \todo
2308 some Tk-compatible command synonyms
2309 add + apply?
2310 allow list arguments for add, remove and delete
2311
2312 **/
tagCmd(GtkTextBuffer * buffer,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[],int cmdNo)2313 int tagCmd ( GtkTextBuffer * buffer, Tcl_Interp * interp, int objc, Tcl_Obj * const objv[], int cmdNo )
2314 {
2315 #ifdef DEBUG_TAGS
2316 g_print ( "%s\n", __FUNCTION__ );
2317 #endif
2318
2319 // widgetname tag add tagname start_index end_index
2320 // widgetname tag remove tagname start_index end_index
2321
2322 // const char *cmds[] = { "create", "configure", "add", "delete", "remove", NULL };
2323 // enum cmdIdx { CreateIdx, ConfigureIdx, AddIdx, DeleteIdx};
2324 const char *cmds[] =
2325 {
2326 "cget", "create", "configure", "apply",
2327 "delete", "remove", "get", "clear", "set",
2328 "ranges", "names", "raise", "lower",
2329 "copy", "properties",
2330 NULL
2331 };
2332 enum cmdIdx
2333 {
2334 CgetIdx, CreateIdx, ConfigureIdx, ApplyIdx,
2335 DeleteIdx, RemoveIdx, GetIdx, ClearIdx, SetIdx,
2336 RangesIdx, NamesIdx, RaiseIdx, LowerIdx,
2337 CopyIdx, PropertiesIdx,
2338 };
2339
2340 /* see also list.c */
2341
2342 GnoclOption tagOptions[] =
2343 {
2344
2345 /* new options added 30/04/11, may need some revision */
2346
2347 {"-marginAccumulate", GNOCL_BOOL, "accumulative-margin"},
2348 {"-backgroundFullHeight", GNOCL_BOOL, "background-full-height"},
2349 {"-backgroundStipple", GNOCL_OBJ, gnoclOptTagBackgroundStipple},
2350 {"-direction", GNOCL_OBJ, "direction", gnoclOptTagTextDirection},
2351 {"-foregroundStipple", GNOCL_OBJ, "foreground-stipple", gnoclOptTextTagForegroundStipple},
2352 {"-indent", GNOCL_INT, "indent"},
2353 {"-language", GNOCL_OBJ, "language", gnocOptTextTagLanguage},
2354 {"-leftMargin", GNOCL_INT, "left-margin"},
2355 {"-name", GNOCL_STRING, "name"},
2356 {"-pixelsInsideWrap", GNOCL_INT, "pixels-inside-wrap"},
2357 {"-priority", GNOCL_OBJ, "", gnoclOptTextTagPriority},
2358 {"-rightMargin", GNOCL_INT, "right-margin"},
2359 {"-rise", GNOCL_INT, "rise"},
2360 {"-scale", GNOCL_DOUBLE, "scale"},
2361 {"-tabs", GNOCL_OBJ, "tabs", gnoclOptTextTagTabs},
2362 {"-variant", GNOCL_OBJ, "variant", gnoclOptTextTagVariant},
2363 {"-weight", GNOCL_INT, "weight"},
2364
2365 /*--------------- existing options ---------------*/
2366
2367 { "-background", GNOCL_OBJ, "background-gdk", gnoclOptGdkColor },
2368 { "-editable", GNOCL_BOOL, "editable" },
2369 { "-foreground", GNOCL_OBJ, "foreground-gdk", gnoclOptGdkColor },
2370 { "-font", GNOCL_STRING, "font" },
2371 { "-fontFamily", GNOCL_STRING, "family" },
2372 { "-fontStyle", GNOCL_OBJ, "style", gnoclOptPangoStyle },
2373 { "-fontVariant", GNOCL_OBJ, "variant", gnoclOptPangoVariant },
2374 { "-fontWeight", GNOCL_OBJ, "weight", gnoclOptPangoWeight },
2375 { "-fontRise", GNOCL_OBJ, "rise", gnoclOptPangoScaledInt },
2376 { "-fontStretch", GNOCL_OBJ, "stretch", gnoclOptPangoStretch },
2377 { "-fontSize", GNOCL_OBJ, "size", gnoclOptPangoScaledInt },
2378 //{ "-fontScale", GNOCL_OBJ, "scale", gnoclOptScale },
2379 { "-invisible", GNOCL_BOOL, "invisible" },
2380 { "-justification", GNOCL_OBJ, "justification", gnoclOptJustification },
2381 { "-paragraph", GNOCL_OBJ, "paragraph-background-gdk", gnoclOptGdkColor },
2382 { "-pixelsAboveLines", GNOCL_INT, "pixels-above-lines" },
2383 { "-pixelsBelowLines", GNOCL_INT, "pixels-below-lines" },
2384 { "-size", GNOCL_INT, "size" },
2385 { "-strikethrough", GNOCL_BOOL, "strikethrough" },
2386 { "-sizePoints", GNOCL_DOUBLE, "size-points" },
2387 { "-underline", GNOCL_OBJ, "underline", gnoclOptUnderline },
2388 { "-wrapMode", GNOCL_OBJ, "wrap-mode", gnoclOptWrapmode },
2389
2390 { "-data", GNOCL_OBJ, "", gnoclOptData },
2391
2392 /* settings, what to do with these? */
2393
2394 /*
2395 {"-backgroundFullHeightSet", GNOCL_BOOL, "background-full-height-set"},
2396 {"-backgroundSet", GNOCL_BOOL, "background-set"},
2397 {"-backgroundStippleSet", GNOCL_BOOL, "background-stipple-set"},
2398 {"-editableSet", GNOCL_BOOL, "editable-set"},
2399 {"-fontFamiltSet", GNOCL_BOOL, "family-set"},
2400 {"-foregroundStippleSet", GNOCL_BOOL, "foreground-stipple-set"},
2401 {"-indentSet", GNOCL_BOOL, "indent-set"},
2402 {"-invisibleSet", GNOCL_BOOL, "invisible-set"},
2403 {"-justificationSet", GNOCL_BOOL, "justification-set"},
2404 {"-languageSet", GNOCL_BOOL, "language-set"},
2405 {"-leftMarginSet", GNOCL_BOOL, "left-margin-set"},
2406 {"-paragraphBackgroundSet", GNOCL_BOOL, "paragraph-background-set"},
2407 {"-pixelsAboveLinesSet", GNOCL_BOOL, "pixels-above-lines-set"},
2408 {"-pixelsBelowLinesSet", GNOCL_BOOL, "pixels-below-lines-set"},
2409 {"-pixelsInsideWrapSet", GNOCL_BOOL, "pixels-inside-wrap-set"},
2410 {"-rightMarginSet", GNOCL_BOOL, "right-margin-set"},
2411 {"-riseSet", GNOCL_BOOL, "rise-set"},
2412 {"-scaleSet", GNOCL_BOOL, "scale-set"},
2413 {"-sizeSet", GNOCL_BOOL, "size-set"},
2414 {"-tabsSet", GNOCL_BOOL, "tabs-set"},
2415 {"-underlineSet", GNOCL_BOOL, "underline-set"},
2416 {"-variantSet", GNOCL_BOOL, "variant-set"},
2417 {"-weightSet", GNOCL_BOOL, "weight-set"},
2418 {"-wrapModeSet", GNOCL_BOOL, "wrap-mode-set"},
2419 */
2420
2421 /* GtkTextTag signal */
2422 { "-onEvent", GNOCL_OBJ, "", gnoclOptOnEvent },
2423 { NULL }
2424 };
2425
2426 int idx;
2427
2428 if ( objc < cmdNo + 1 )
2429 {
2430 Tcl_WrongNumArgs ( interp, cmdNo, objv, "subcommand ?option val ...?" );
2431 return TCL_ERROR;
2432 }
2433
2434 if ( Tcl_GetIndexFromObj ( interp, objv[cmdNo], cmds, "subcommand", TCL_EXACT, &idx ) != TCL_OK )
2435 {
2436 return TCL_ERROR;
2437 }
2438
2439 switch ( idx )
2440 {
2441
2442 case NamesIdx: // return a list of all tag names
2443 {
2444 #ifdef DEBUG_TAGS
2445 g_print ( "\ttag names\n" );
2446 #endif
2447 GtkTextTagTable *tagtable = gtk_text_buffer_get_tag_table ( buffer );
2448
2449 gchar names[512];
2450
2451 Tcl_Obj *resList;
2452 resList = Tcl_NewListObj ( 0, NULL );
2453 /* create a tcl list */
2454
2455 /* get the settings of each tag in the buffer*/
2456 /* note, pass the address of the pointer to the data assigned by the called function */
2457 gtk_text_tag_table_foreach ( tagtable, getTagName , &resList );
2458
2459 Tcl_SetObjResult ( interp, resList );
2460 /* reset the outsput string by using null pointers */
2461 //gnoclGetTagProperties ( NULL, NULL );
2462
2463 #ifdef DEBUG_TAGS
2464 g_print ( "tag names\n" );
2465 #endif
2466
2467 return TCL_OK;
2468 }
2469 break;
2470 case PropertiesIdx:
2471 {
2472 #ifdef DEBUG_TAGS
2473 g_print ( "\ttag properties %s\n", Tcl_GetString ( objv[3] ) );
2474 #endif
2475
2476 Tcl_Obj *resList;
2477 resList = Tcl_NewListObj ( 0, NULL );
2478
2479 GtkTextTagTable *table = gtk_text_buffer_get_tag_table ( buffer );
2480 GtkTextTag *tag = gtk_text_tag_table_lookup ( table, Tcl_GetString ( objv[3] ) );
2481
2482 gnoclGetTagProperties ( tag, resList );
2483
2484 Tcl_SetObjResult ( interp, resList );
2485
2486 return TCL_OK;
2487
2488 }
2489 break;
2490 case CopyIdx:
2491 {
2492 #ifdef DEBUG_TAGS
2493 g_print ( "\ttag copy\n" );
2494 #endif
2495 listParameters ( objc, objv, __FUNCTION__ );
2496
2497 GtkScrolledWindow *scrolled = gnoclGetWidgetFromName ( Tcl_GetString ( objv[3] ), interp );
2498 GtkTextView *text = GTK_TEXT_VIEW ( gtk_bin_get_child ( GTK_BIN ( scrolled ) ) );
2499 GtkTextBuffer *buffer2 = gtk_text_view_get_buffer ( text );
2500 GtkTextTagTable *table = gtk_text_buffer_get_tag_table ( buffer2 );
2501
2502 buffer->tag_table = table;
2503
2504 g_object_ref ( buffer->tag_table );
2505
2506 table->buffers = g_slist_prepend ( table->buffers, buffer );
2507
2508 }
2509 break;
2510 case RaiseIdx:
2511 {
2512 #ifdef DEBUG_TAGS
2513 g_print ( "\ttag raise\n" );
2514 #endif
2515
2516 GtkTextTagTable *table = gtk_text_buffer_get_tag_table ( buffer );
2517
2518 GtkTextTag *tag1;
2519 GtkTextTag *tag2;
2520
2521 tag1 = gtk_text_tag_table_lookup ( table, Tcl_GetString ( objv[cmdNo+2] ) );
2522 tag2 = gtk_text_tag_table_lookup ( table, Tcl_GetString ( objv[cmdNo+3] ) );
2523
2524 gint priority = gtk_text_tag_get_priority ( tag1 );
2525 priority++;
2526 gtk_text_tag_set_priority ( tag2, priority );
2527
2528 }
2529 break;
2530 case LowerIdx:
2531 {
2532 #ifdef DEBUG_TEXT
2533 g_print ( "tag lower\n" );
2534 #endif
2535
2536 GtkTextTagTable *table = gtk_text_buffer_get_tag_table ( buffer );
2537
2538 GtkTextTag *tag1;
2539 GtkTextTag *tag2;
2540
2541 tag1 = gtk_text_tag_table_lookup ( table, Tcl_GetString ( objv[cmdNo+2] ) );
2542 tag2 = gtk_text_tag_table_lookup ( table, Tcl_GetString ( objv[cmdNo+3] ) );
2543
2544 gint priority = gtk_text_tag_get_priority ( tag1 );
2545
2546 if ( priority >= 1 )
2547 {
2548 priority++;
2549 }
2550
2551 gtk_text_tag_set_priority ( tag2, priority );
2552 }
2553
2554 case RangesIdx:
2555 {
2556 #ifdef DEBUG_TAGS
2557 g_print ( "\ttag ranges\n" );
2558 #endif
2559 gnoclGetTagRanges ( interp, buffer, Tcl_GetString ( objv[cmdNo+1] ) );
2560 }
2561 break;
2562 case SetIdx:
2563 {
2564 /* control tag option application settings */
2565 }
2566 break;
2567 case ClearIdx:
2568 {
2569 GtkTextTagTable *tagtable = gtk_text_buffer_get_tag_table ( buffer );
2570
2571 /* get the settings of each tag in the buffer*/
2572 /* note, pass the address of the pointer to the data assigned by the called function */
2573 gtk_text_tag_table_foreach ( tagtable, deleteTag , tagtable );
2574
2575 }
2576 break;
2577 case CgetIdx: // tagCmd
2578 {
2579 //g_print ( "tag CgetIdx 1\n" );
2580
2581 int idx;
2582 Tcl_Obj *resList;
2583
2584 GtkTextTagTable *tagtable = gtk_text_buffer_get_tag_table ( buffer );
2585 //g_print ( "tag CgetIdx 2\n" );
2586 GtkTextTag *tag = gtk_text_tag_table_lookup ( tagtable, Tcl_GetString ( objv[cmdNo+1] ) );
2587 //g_print ( "tag CgetIdx 3\n" );
2588
2589 switch ( gnoclTagCget ( interp, objc, objv, G_OBJECT ( tag ), tagOptions, &idx ) )
2590 {
2591 case GNOCL_CGET_ERROR:
2592 {
2593 return TCL_ERROR;
2594 }
2595 case GNOCL_CGET_HANDLED:
2596 {
2597 return TCL_OK;
2598 }
2599 case GNOCL_CGET_NOTHANDLED:
2600 {
2601 return gnoclCgetOne ( interp, objv, G_OBJECT ( tag ), tagOptions, &idx );
2602 }
2603 }
2604
2605 break;
2606 }
2607
2608 /* return a list of tags applied to current iter */
2609 case GetIdx:
2610 {
2611 //int ret;
2612 GSList *p, *tagList;
2613 GtkTextIter iter;
2614
2615 Tcl_Obj *resList;
2616
2617 Tcl_Obj *err;
2618 Tcl_Obj *ret;
2619
2620 ret = 0;
2621
2622 static char *tagOpt[] =
2623 {
2624 "-on", "-off", "-all", NULL
2625 };
2626
2627 static enum tagOptIdx
2628 {
2629 OnIdx, OffIdx, AllIdx
2630 };
2631
2632 gint idx;
2633
2634 /* check the number of arguments */
2635 if ( objc < 4 || objc > 5 )
2636 {
2637 Tcl_WrongNumArgs ( interp, cmdNo + 1, objv, "position opts" );
2638 return TCL_ERROR;
2639 }
2640
2641 /* convert the position to a pointer */
2642 if ( posToIter ( interp, objv[3], buffer, &iter ) != TCL_OK )
2643 {
2644 return -1;
2645 }
2646
2647
2648 if ( objc == 5 )
2649 {
2650
2651 getIdx ( tagOpt, Tcl_GetString ( objv[4] ), &idx );
2652
2653 //g_print ("here I am... idx = %d\n", idx);
2654
2655 switch ( idx )
2656 {
2657 case OnIdx:
2658 {
2659 /* build a list of tagOn changes */
2660 //g_print ("get onTags\n");
2661 tagList = gtk_text_iter_get_toggled_tags ( &iter, TRUE );
2662 }
2663 break;
2664 case OffIdx:
2665 {
2666 /* build a list of tagOff changes */
2667 //g_print ("get offTags\n");
2668 tagList = gtk_text_iter_get_toggled_tags ( &iter, FALSE );
2669 }
2670 break;
2671 default:
2672 {
2673 //g_print ( "got everything!\n" );
2674 tagList = gtk_text_iter_get_tags ( &iter );
2675 }
2676 }
2677
2678 }
2679
2680 else
2681 {
2682 /* get a list of all applicable tags */
2683 tagList = gtk_text_iter_get_tags ( &iter );
2684 }
2685
2686 /* initialise list for return to the inpreter */
2687 resList = Tcl_NewListObj ( 0, NULL );
2688
2689 /* build up a list of names */
2690 for ( p = tagList; p != NULL; p = p->next )
2691 {
2692 gchar *name = ( GTK_TEXT_TAG ( p->data )->name );
2693
2694 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewStringObj ( name, -1 ) );
2695 }
2696
2697 /* tidy up and return the answer */
2698 g_slist_free ( tagList );
2699 Tcl_SetObjResult ( interp, resList );
2700 }
2701 break ;
2702 case CreateIdx:
2703 {
2704 int ret;
2705 GtkTextTag *tag;
2706 /* win tag create name */
2707
2708 if ( objc < cmdNo + 2 )
2709 {
2710 Tcl_WrongNumArgs ( interp, cmdNo + 1, objv, "tag-name ?option val ...?" );
2711 return TCL_ERROR;
2712 }
2713
2714 /* tag = gtk_text_tag_new( Tcl_GetString( objv[3] ) ); */
2715 tag = gtk_text_buffer_create_tag ( buffer, Tcl_GetString ( objv[cmdNo+1] ), NULL );
2716
2717 ret = gnoclParseAndSetOptions ( interp, objc - cmdNo - 1, objv + cmdNo + 1, tagOptions, G_OBJECT ( tag ) );
2718
2719 gnoclClearOptions ( tagOptions );
2720
2721 return ret;
2722 }
2723
2724 case ConfigureIdx:
2725 {
2726 int ret;
2727 GtkTextTag *tag;
2728
2729 /* win tag create name */
2730
2731 if ( objc < cmdNo + 2 )
2732 {
2733 Tcl_WrongNumArgs ( interp, cmdNo + 1, objv, "tag-name ?option val ...?" );
2734 return TCL_ERROR;
2735 }
2736
2737 /* TODO? first reset options */
2738 tag = gtk_text_tag_table_lookup ( gtk_text_buffer_get_tag_table ( buffer ), Tcl_GetString ( objv[cmdNo+1] ) );
2739
2740 if ( tag == NULL )
2741 {
2742 Tcl_AppendResult ( interp, "Unknown tag \"", Tcl_GetString ( objv[cmdNo+1] ), "\"", NULL );
2743 return TCL_ERROR;
2744 }
2745
2746 ret = gnoclParseAndSetOptions ( interp, objc - cmdNo - 1, objv + cmdNo + 1, tagOptions, G_OBJECT ( tag ) );
2747
2748 gnoclClearOptions ( tagOptions );
2749
2750 return ret;
2751 }
2752
2753 case ApplyIdx:
2754 {
2755 if ( applyTag ( buffer, interp, objc, objv, cmdNo + 1 ) != TCL_OK ) return -1;
2756
2757 break;
2758 }
2759
2760 case RemoveIdx:
2761 {
2762 if ( removeTag ( buffer, interp, objc, objv, cmdNo + 1 ) != TCL_OK ) return -1;
2763
2764 break;
2765 }
2766
2767 case DeleteIdx:
2768 {
2769 /*! WJG Added 28/03/08 */
2770 GtkTextTagTable *tagtable = gtk_text_buffer_get_tag_table ( buffer );
2771 GtkTextTag *tag = gtk_text_tag_table_lookup ( tagtable, Tcl_GetString ( objv[cmdNo+1] ) );
2772
2773 if ( tag != NULL )
2774 {
2775
2776 gtk_text_tag_table_remove ( tagtable, tag );
2777 }
2778
2779 break;
2780 }
2781
2782 default:
2783 {
2784 assert ( 0 );
2785 return TCL_ERROR;
2786 }
2787 }
2788
2789 return TCL_OK;
2790 }
2791
2792 /**
2793 **/
scrollToMark(GtkTextView * view,GtkTextBuffer * buffer,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[])2794 static int scrollToMark (
2795 GtkTextView * view,
2796 GtkTextBuffer * buffer,
2797 Tcl_Interp * interp,
2798 int objc,
2799 Tcl_Obj * const objv[] )
2800 {
2801 #ifdef DEBUG_TEXT
2802 printf ( "scrollToMark 1> %s \n", Tcl_GetString ( objv[2] ) );
2803 #endif
2804
2805 GtkTextMark *mark;
2806
2807 if ( objc < 3 )
2808 {
2809 Tcl_WrongNumArgs ( interp, 2, objv, "index ?-option val ...?" );
2810 return TCL_ERROR;
2811 }
2812
2813 /* check to see that the mark exists */
2814 mark = gtk_text_buffer_get_mark ( buffer, Tcl_GetString ( objv[2] ) );
2815
2816 /* reposition */
2817 if ( mark == NULL )
2818 {
2819 Tcl_SetResult ( interp, "This mark does not exist.", TCL_STATIC );
2820 return TCL_ERROR;
2821 }
2822
2823 gtk_text_view_scroll_mark_onscreen ( view, mark );
2824
2825 return TCL_OK;
2826
2827 }
2828
2829 /**
2830 \brief
2831 \author
2832 \date
2833 \note
2834 **/
scrollToPos(GtkTextView * view,GtkTextBuffer * buffer,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[])2835 static int scrollToPos (
2836 GtkTextView * view,
2837 GtkTextBuffer * buffer,
2838 Tcl_Interp * interp,
2839 int objc,
2840 Tcl_Obj * const objv[] )
2841 {
2842
2843 #ifdef DEBUG_TEXT
2844 printf ( "scrollToPos 1> %s \n", Tcl_GetString ( objv[2] ) );
2845 #endif
2846
2847 GnoclOption options[] =
2848
2849 {
2850 { "-margin", GNOCL_DOUBLE, NULL }, /* 0 */
2851 { "-align", GNOCL_OBJ, NULL }, /* 1 */
2852 { NULL }
2853 };
2854 const int marginIdx = 0;
2855 const int alignIdx = 1;
2856
2857 int ret = TCL_ERROR;
2858
2859 double margin = .0;
2860 int useAlign = 0;
2861 gfloat xAlign = 0.5, yAlign = 0.5;
2862 GtkTextIter iter;
2863 GtkTextMark *mark;
2864
2865 if ( objc < 3 )
2866 {
2867 Tcl_WrongNumArgs ( interp, 2, objv, "index ?-option val ...?" );
2868 return TCL_ERROR;
2869 }
2870
2871 if ( posToIter ( interp, objv[2], buffer, &iter ) != TCL_OK )
2872 {
2873 return TCL_ERROR;
2874 }
2875
2876 if ( gnoclParseOptions ( interp, objc - 2, objv + 2, options ) != TCL_OK )
2877 {
2878 goto clearExit;
2879 }
2880
2881 if ( options[alignIdx].status == GNOCL_STATUS_CHANGED )
2882 {
2883 if ( gnoclGetBothAlign ( interp, options[alignIdx].val.obj, &xAlign, &yAlign ) != TCL_OK )
2884 {
2885 goto clearExit;
2886 }
2887
2888 useAlign = 1;
2889 }
2890
2891 if ( options[marginIdx].status == GNOCL_STATUS_CHANGED )
2892 {
2893 margin = options[marginIdx].val.d;
2894
2895 if ( margin < 0.0 || margin >= 0.5 )
2896 {
2897 Tcl_SetResult ( interp, "-margin must be between 0 and 0.5", TCL_STATIC );
2898 goto clearExit;
2899 }
2900 }
2901
2902
2903 mark = gtk_text_buffer_create_mark ( buffer, "__gnoclScrollMark__", &iter, 0 );
2904
2905
2906 gtk_text_view_scroll_to_mark ( view, mark, margin, useAlign, xAlign, yAlign );
2907
2908 gtk_text_buffer_delete_mark ( buffer, mark );
2909
2910 ret = TCL_OK;
2911
2912 clearExit:
2913 gnoclClearOptions ( options );
2914 return ret;
2915 }
2916
2917 /**
2918 \brief Insert formatted string into specified text widget at a given location.
2919 \author PGB
2920 \date 2001-06:
2921 \bugs Recent changes to posToIter causing this function to crash.
2922 But, applyTag, which is hack of this function does not cause a crash!
2923 \history 2008-06-27 Began implementation of new keywords for text position. See TODO.
2924 **/
textInsert(GtkTextBuffer * buffer,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[],int cmdNo)2925 static int textInsert ( GtkTextBuffer * buffer, Tcl_Interp * interp, int objc, Tcl_Obj * const objv[], int cmdNo )
2926 {
2927 GnoclOption insertOptions[] =
2928 {
2929 { "-tags", GNOCL_LIST, NULL },
2930 { NULL }
2931 };
2932 const int tagsIdx = 0;
2933 gint startOffset;
2934 int ret = TCL_ERROR;
2935
2936 GtkTextIter iter;
2937
2938 if ( objc < cmdNo + 2 )
2939 {
2940 Tcl_WrongNumArgs ( interp, cmdNo, objv, "position text ?-option val ...?" );
2941 return TCL_ERROR;
2942 }
2943
2944 if ( posToIter ( interp, objv[cmdNo], buffer, &iter ) != TCL_OK )
2945 {
2946 return TCL_ERROR;
2947 }
2948
2949 if ( gnoclParseOptions ( interp, objc - cmdNo - 1, objv + cmdNo + 1, insertOptions ) != TCL_OK )
2950 {
2951 goto clearExit;
2952 }
2953
2954 startOffset = gtk_text_iter_get_offset ( &iter );
2955
2956
2957 /* handle pango strings first */
2958 gint type = gnoclGetStringType ( objv[cmdNo+1] );
2959
2960 if ( type == 48 )
2961 {
2962
2963 gnoclInsertMarkup ( buffer, &iter, gnoclGetString ( objv[cmdNo+1] ) );
2964
2965 //gtk_text_buffer_insert_markup ( buffer, &iter, gnoclGetString ( objv[cmdNo+1] ) );
2966 //gnoclMarkupInsertTest ( buffer, &iter );
2967
2968 }
2969
2970 else
2971 {
2972 gtk_text_buffer_insert ( buffer, &iter, gnoclGetString ( objv[cmdNo+1] ), -1 );
2973 }
2974
2975 if ( insertOptions[tagsIdx].status == GNOCL_STATUS_CHANGED )
2976 {
2977 GtkTextIter start;
2978 int k, no;
2979 Tcl_Obj *obj = insertOptions[tagsIdx].val.obj;
2980
2981 gtk_text_buffer_get_iter_at_offset ( buffer, &start, startOffset );
2982
2983 if ( Tcl_ListObjLength ( interp, obj, &no ) != TCL_OK )
2984 {
2985 goto clearExit;
2986 }
2987
2988 for ( k = 0; k < no; ++k )
2989 {
2990 Tcl_Obj *tp;
2991
2992 if ( Tcl_ListObjIndex ( interp, obj, k, &tp ) != TCL_OK )
2993 {
2994 Tcl_SetResult ( interp, "Could not read tag list", TCL_STATIC );
2995 goto clearExit;
2996 }
2997
2998 gtk_text_buffer_apply_tag_by_name ( buffer, Tcl_GetString ( tp ), &start, &iter );
2999 }
3000 }
3001
3002 ret = TCL_OK;
3003
3004 clearExit:
3005 gnoclClearOptions ( insertOptions );
3006
3007 return ret;
3008 }
3009
3010 /**
3011 \brief ** USING ** TEXTPARAMS
3012 **/
configure(Tcl_Interp * interp,TextParams * para,GnoclOption options[])3013 static int configure ( Tcl_Interp *interp, TextParams *para, GnoclOption options[] )
3014 {
3015
3016 GtkScrolledWindow *scrolled = para->scrolled;
3017 GtkTextView *text = GTK_TEXT_VIEW ( gtk_bin_get_child ( GTK_BIN ( scrolled ) ) );
3018 GtkTextBuffer *buffer = gtk_text_view_get_buffer ( text );
3019
3020
3021 /****************************/
3022
3023 gnoclAttachOptCmdAndVar (
3024 &options[onChangedIdx], ¶->onChanged,
3025 &options[variableIdx], ¶->textVariable,
3026 "changed", G_OBJECT ( buffer ),
3027 G_CALLBACK ( changedFunc ), interp, traceFunc, para );
3028
3029 if ( options[variableIdx].status == GNOCL_STATUS_CHANGED && para->textVariable != NULL )
3030 {
3031 // if variable does not exist -> set it, else set widget state
3032 const char *val = Tcl_GetVar ( interp, para->textVariable, TCL_GLOBAL_ONLY );
3033
3034 if ( val == NULL )
3035 {
3036
3037 GtkTextIter *start, *end;
3038
3039 gtk_text_buffer_get_bounds ( buffer, start, end );
3040
3041 val = gtk_text_buffer_get_text ( buffer, start, end, 0 );
3042
3043 setTextVariable ( para, val );
3044 }
3045
3046 else
3047 {
3048 //setVal ( para->label, val );
3049 }
3050 }
3051
3052 /*****************************/
3053
3054
3055 if ( options[textIdx].status == GNOCL_STATUS_CHANGED )
3056 {
3057 //printf ( "INSERT SOME TEXT-b\n" );
3058
3059 char *str = options[textIdx].val.str;
3060 gtk_text_buffer_set_text ( buffer, str, -1 );
3061 }
3062
3063 if ( options[scrollBarIdx].status == GNOCL_STATUS_CHANGED )
3064 {
3065 GtkPolicyType hor, vert;
3066
3067 if ( gnoclGetScrollbarPolicy ( interp, options[scrollBarIdx].val.obj, &hor, &vert ) != TCL_OK )
3068 {
3069 return TCL_ERROR;
3070 }
3071
3072 gtk_scrolled_window_set_policy ( scrolled, hor, vert );
3073 }
3074
3075 if ( options[bufferIdx].status == GNOCL_STATUS_CHANGED )
3076 {
3077 printf ( "APPLY NEW BUFFER-%s\n", options[bufferIdx].val.str );
3078
3079 GtkTextBuffer *buffer;
3080
3081 buffer = gnoclGetWidgetFromName ( options[bufferIdx].val.str, interp );
3082
3083 gtk_text_view_set_buffer ( text, buffer );
3084
3085 }
3086
3087
3088 return TCL_OK;
3089 }
3090
3091
3092 /**
3093 \brief ** USING ** TEXTPARAMS
3094 **/
configure_textView(Tcl_Interp * interp,GtkTextView * text,GnoclOption options[])3095 static int configure_textView ( Tcl_Interp *interp, GtkTextView *text, GnoclOption options[] )
3096 {
3097
3098 //GtkScrolledWindow *scrolled = para->scrolled;
3099 //GtkTextView *text = GTK_TEXT_VIEW ( gtk_bin_get_child ( GTK_BIN ( scrolled ) ) );
3100 GtkTextBuffer *buffer = gtk_text_view_get_buffer ( text );
3101
3102
3103 /****************************/
3104
3105 /*
3106 gnoclAttachOptCmdAndVar (
3107 &options[onChangedIdx], ¶->onChanged,
3108 &options[variableIdx], ¶->textVariable,
3109 "changed", G_OBJECT ( buffer ),
3110 G_CALLBACK ( changedFunc ), interp, traceFunc, para );
3111
3112 if ( options[variableIdx].status == GNOCL_STATUS_CHANGED && para->textVariable != NULL )
3113 {
3114 // if variable does not exist -> set it, else set widget state
3115 const char *val = Tcl_GetVar ( interp, para->textVariable, TCL_GLOBAL_ONLY );
3116
3117 if ( val == NULL )
3118 {
3119
3120 GtkTextIter *start, *end;
3121
3122 gtk_text_buffer_get_bounds ( buffer, start, end );
3123
3124 val = gtk_text_buffer_get_text ( buffer, start, end, 0 );
3125
3126 setTextVariable ( para, val );
3127 }
3128
3129 else
3130 {
3131 //setVal ( para->label, val );
3132 }
3133 }
3134 */
3135 /*****************************/
3136
3137
3138 if ( options[textIdx].status == GNOCL_STATUS_CHANGED )
3139 {
3140 //printf ( "INSERT SOME TEXT-b\n" );
3141
3142 char *str = options[textIdx].val.str;
3143 gtk_text_buffer_set_text ( buffer, str, -1 );
3144 }
3145
3146 /*
3147 if ( options[scrollBarIdx].status == GNOCL_STATUS_CHANGED )
3148 {
3149 GtkPolicyType hor, vert;
3150
3151 if ( gnoclGetScrollbarPolicy ( interp, options[scrollBarIdx].val.obj, &hor, &vert ) != TCL_OK )
3152 {
3153 return TCL_ERROR;
3154 }
3155
3156 gtk_scrolled_window_set_policy ( scrolled, hor, vert );
3157 }
3158 */
3159 if ( options[bufferIdx].status == GNOCL_STATUS_CHANGED )
3160 {
3161 printf ( "APPLY NEW BUFFER-%s\n", options[bufferIdx].val.str );
3162
3163 GtkTextBuffer *buffer;
3164
3165 buffer = gnoclGetWidgetFromName ( options[bufferIdx].val.str, interp );
3166
3167 gtk_text_view_set_buffer ( text, buffer );
3168
3169 }
3170
3171
3172 return TCL_OK;
3173 }
3174
3175 /**
3176 \brief
3177 **/
cget(Tcl_Interp * interp,GtkTextView * text,GnoclOption options[],int idx)3178 static int cget ( Tcl_Interp * interp, GtkTextView * text, GnoclOption options[], int idx )
3179 {
3180 /* get the option from the array? */
3181 Tcl_Obj *obj = NULL;
3182
3183
3184 if ( idx == tooltipIdx )
3185 {
3186 obj = Tcl_NewStringObj ( gtk_widget_get_tooltip_markup ( GTK_WIDGET ( text ) ), -1 );
3187 }
3188
3189 if ( idx == baseFontIdx )
3190 {
3191 //g_print ( "basefont\n" );
3192 PangoContext *context = gtk_widget_get_pango_context ( GTK_WIDGET ( text ) );
3193 PangoFontDescription *desc = pango_context_get_font_description ( context );
3194 char *font = pango_font_description_to_string ( desc );
3195
3196 obj = Tcl_NewStringObj ( font, -1 );
3197
3198
3199 }
3200
3201 if ( idx == dataIdx )
3202 {
3203 obj = Tcl_NewStringObj ( g_object_get_data ( text, "gnocl::data" ), -1 );
3204 }
3205
3206 if ( idx == baseColorIdx )
3207 {
3208 //g_print ( "basecolor\n" );
3209
3210 Tcl_Obj *ret = Tcl_NewListObj ( 0, interp );
3211 GdkColor color;
3212
3213 //modifyWidgetGdkColor ( interp, opts, G_OBJECT(text), gtk_widget_modify_base, G_STRUCT_OFFSET ( GtkStyle, base ), resList );
3214
3215 GtkStyle *style = gtk_rc_get_style ( GTK_WIDGET ( text ) );
3216 GdkColor *cp = ( GdkColor * ) G_STRUCT_MEMBER_P ( style, G_STRUCT_OFFSET ( GtkStyle, base ) );
3217 //GdkColor color = cp[type];
3218
3219 Tcl_ListObjAppendElement ( interp, ret, Tcl_NewIntObj ( color.red ) );
3220 Tcl_ListObjAppendElement ( interp, ret, Tcl_NewIntObj ( color.green ) );
3221 Tcl_ListObjAppendElement ( interp, ret, Tcl_NewIntObj ( color.blue ) );
3222
3223 Tcl_SetObjResult ( interp, obj );
3224
3225 return TCL_OK;
3226 }
3227
3228
3229 if ( obj != NULL )
3230 {
3231 Tcl_SetObjResult ( interp, obj );
3232 return TCL_OK;
3233 }
3234
3235
3236 return gnoclCgetNotImplemented ( interp, options + idx );
3237 }
3238
3239 /**
3240 \brief Return a list of all occuranances of a named tag within a buffer
3241 **/
gnoclGetTagRanges(Tcl_Interp * interp,GtkTextBuffer * buffer,gchar * tagName)3242 static void gnoclGetTagRanges ( Tcl_Interp *interp, GtkTextBuffer *buffer, gchar *tagName )
3243 {
3244 #if 0
3245 g_print ( "func = %s tagname = %s\n", __FUNCTION__, tagName );
3246 #endif
3247
3248 GtkTextIter iter;
3249 GtkTextTag *tag;
3250 GtkTextTagTable *table;
3251 gint row;
3252 gint col;
3253
3254 Tcl_Obj *res;
3255 res = Tcl_NewStringObj ( "", 0 );
3256
3257 static char s1[300];
3258 static char s2[10];
3259
3260
3261 gtk_text_buffer_get_start_iter ( buffer, &iter );
3262
3263 table = gtk_text_buffer_get_tag_table ( buffer );
3264
3265 tag = gtk_text_tag_table_lookup ( table, tagName );
3266
3267 if ( tag == NULL )
3268 {
3269
3270 return;
3271 }
3272
3273
3274
3275 /* check to see if tag applied at start of text */
3276 if ( gtk_text_iter_begins_tag ( &iter, tag ) == TRUE )
3277 {
3278
3279 row = gtk_text_iter_get_line ( &iter );
3280 col = gtk_text_iter_get_line_offset ( &iter );
3281
3282 sprintf ( s2, "%d %d ", row, col );
3283 strcat ( s1, s2 );
3284 }
3285
3286 while ( ( gtk_text_iter_forward_to_tag_toggle ( &iter, tag ) ) == TRUE )
3287 {
3288
3289 row = gtk_text_iter_get_line ( &iter );
3290 col = gtk_text_iter_get_line_offset ( &iter );
3291
3292 sprintf ( s2, "%d %d ", row, col );
3293 strcat ( s1, s2 );
3294
3295 }
3296
3297 Tcl_AppendStringsToObj ( res, trim ( s1 ), ( char * ) NULL );
3298 Tcl_SetObjResult ( interp, res );
3299
3300 sprintf ( s1, "" );
3301 sprintf ( s2, "" );
3302 }
3303
3304
3305 /**
3306 \brief Add tagname to a Tcl list.
3307 **/
getTagName(GtkTextTag * tag,gpointer data)3308 static void getTagName ( GtkTextTag * tag, gpointer data )
3309 {
3310 #ifdef DEBUG_TAGS
3311 g_print ( "%s %s\n", __FUNCTION__, tag->name );
3312 #endif
3313
3314 Tcl_Obj **resList = data;
3315
3316 Tcl_ListObjAppendElement ( NULL, *resList, Tcl_NewStringObj ( tag->name, -1 ) );
3317
3318 }
3319
3320 /**
3321 -> 0: Ok
3322 1: delete chosen
3323 2: configure chosen
3324 3: scrollToPosition chosen
3325 < 0: ERROR
3326 */
3327
3328 /**
3329 \brief Return list of tag properties and their values.
3330 \note Only returns those attribute which have been set away from their default values.
3331
3332 Getting a handle on the various tag parameters has been a process of trial and error.
3333
3334 An alternative way of getting the colour values but this time in hex is:
3335 GdkColor *bg_color2 = &tag_appearance->bg_color;
3336 char *clr = gdk_color_to_string ( bg_color2 );
3337 sprintf ( tmp2, "clr = %s ",clr);
3338 \arguments TAG POINTER, ptr to Tcl list
3339 \returns TCL_LIST
3340 **/
gnoclGetTagProperties(GtkTextTag * tag,Tcl_Obj * resList)3341 static void gnoclGetTagProperties ( GtkTextTag *tag, Tcl_Obj *resList )
3342 {
3343 #ifdef DEBUG_TAGS
3344 g_print ( "%s start\n", __FUNCTION__ );
3345 #endif
3346
3347 if ( tag == NULL )
3348 {
3349 return;
3350 }
3351
3352 /* modify the memory allocation here to use malloc and free to release it */
3353
3354 static char tmp[300];
3355
3356 GtkTextAppearance *tag_appearance; // use tag->values->appearance.underline etc.
3357
3358 /* Individual chunks of this can be set/unset as a group */
3359 PangoFontDescription *font;
3360 GtkTextDirection direction;
3361 guint realized;
3362
3363 /* -----------------------------------------------
3364 * get a handle on the tag appearance structure
3365 * it might be fair to say that these are 'options'
3366 * and take default values.
3367 * When values are returned following a dump tags call,
3368 * only return these values if they have been changed from
3369 * system defaults.
3370 * -----------------------------------------------*/
3371 tag_appearance = tag->values;
3372
3373 gchar **fontName;
3374 gchar **fontFamily;
3375 gchar **fontDesc;
3376
3377 #ifdef DEBUG_TAGS
3378 g_print ( "%s 1\n", __FUNCTION__ );
3379 #endif
3380
3381 /* priority */
3382 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "-priority", -1 ) );
3383 //sprintf ( tmp, "%d", tag->priority );
3384 //Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( tmp, -1 ) );
3385 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewIntObj ( tag->priority ) );
3386
3387 #ifdef DEBUG_TAGS
3388 g_print ( "%s priority\n", __FUNCTION__ );
3389 #endif
3390
3391 /* font */
3392
3393 #ifdef DEBUG_TAGS
3394 g_print ( "%s font start\n", __FUNCTION__ );
3395 #endif
3396
3397 /* these need to be concatenated into a meaningfull string */
3398 g_object_get ( G_OBJECT ( tag ), "font", &fontName, NULL );
3399 g_object_get ( G_OBJECT ( tag ), "family", &fontFamily, NULL );
3400 g_object_get ( G_OBJECT ( tag ), "font-desc", &fontDesc, NULL );
3401
3402 #ifdef DEBUG_TAGS
3403 g_print ( "%s font middle\n", __FUNCTION__ );
3404
3405 g_print ( "family = %s\n", fontFamily );
3406 g_print ( "desc = %s\n", fontDesc );
3407
3408 #endif
3409
3410 if ( fontName != NULL )
3411 {
3412 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "-font", -1 ) );
3413
3414 }
3415
3416 sprintf ( tmp, "%s", fontName );
3417 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( tmp, -1 ) );
3418
3419 /*
3420 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "-fontFamily", -1 ) );
3421 sprintf ( tmp, "%s", fontFamily );
3422 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( tmp, -1 ) );
3423 */
3424
3425 #ifdef DEBUG_TAGS
3426 g_print ( "%s font end\n", __FUNCTION__ );
3427 #endif
3428
3429 /* background stipple */
3430 if ( tag->bg_stipple_set )
3431 {
3432 GdkBitmap *bg_stipple = tag_appearance->bg_stipple;
3433 }
3434
3435 #ifdef DEBUG_TAGS
3436 g_print ( "%s stipple\n", __FUNCTION__ );
3437 #endif
3438
3439
3440 /* background colour */
3441 if ( tag->pg_bg_color_set )
3442 {
3443 GdkColor bg_color = tag_appearance->bg_color;
3444 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "-background", -1 ) );
3445 sprintf ( tmp, "%d %d %d", bg_color.red, bg_color.green, bg_color.blue );
3446 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( tmp, -1 ) );
3447 }
3448
3449 #ifdef DEBUG_TAGS
3450 g_print ( "%s backgroun\n", __FUNCTION__ );
3451 #endif
3452
3453 /* foreground colour */
3454 if ( tag->fg_color_set )
3455 {
3456 GdkColor fg_color = tag_appearance->fg_color;
3457 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "-foreground", -1 ) );
3458 sprintf ( tmp, "%d %d %d", fg_color.red, fg_color.green, fg_color.blue );
3459 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( tmp, -1 ) );
3460 }
3461
3462 #ifdef DEBUG_TAGS
3463 g_print ( "%s foreground\n", __FUNCTION__ );
3464 #endif
3465
3466 /* font scaling */
3467 if ( tag->scale_set )
3468 {
3469 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "-scale", -1 ) );
3470 sprintf ( tmp, "%f", tag->values->font_scale );
3471 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( tmp, -1 ) );
3472 }
3473
3474 /* foreground stipple */
3475 if ( tag->fg_stipple_set )
3476 {
3477 GdkBitmap *fg_stipple = tag_appearance->fg_stipple;
3478 }
3479
3480 /* text justfification */
3481 if ( tag->justification_set )
3482 {
3483
3484 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "-justification", -1 ) );
3485
3486 // GTK_JUSTIFY_LEFT | GTK_JUSTIFY_RIGHT | GTK_JUSTIFY_CENTER | GTK_JUSTIFY_FILL
3487 switch ( tag->values->justification )
3488 {
3489 case GTK_JUSTIFY_LEFT:
3490 {
3491 sprintf ( tmp, "left" );
3492 }
3493 break;
3494 case GTK_JUSTIFY_RIGHT:
3495 {
3496 sprintf ( tmp, "right" );
3497 }
3498 break;
3499 case GTK_JUSTIFY_CENTER:
3500 {
3501 sprintf ( tmp, "center" );
3502 }
3503 break;
3504 case GTK_JUSTIFY_FILL:
3505 {
3506 sprintf ( tmp, "fill" );
3507 }
3508 break;
3509 default: {}
3510 }
3511
3512 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( tmp, -1 ) );
3513 }
3514
3515 /* default indent */
3516 if ( tag->indent_set )
3517 {
3518 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "-indent", -1 ) );
3519 sprintf ( tmp, "%d", tag->values->indent );
3520 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewIntObj ( tag->values->indent ) );
3521 }
3522
3523 /* text rise, i.e. for superscript */
3524 if ( tag->rise_set )
3525 {
3526 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "-rise", -1 ) );
3527 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewIntObj ( tag_appearance->rise ) );
3528 }
3529
3530 /* strikethrough or, overstrike */
3531 if ( tag->strikethrough_set )
3532 {
3533 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "-strikethrough", -1 ) );
3534 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewIntObj ( tag->values->appearance.strikethrough ) );
3535 }
3536
3537 /* right margin */
3538 if ( tag->right_margin_set )
3539 {
3540 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "-rightMargin", -1 ) );
3541 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewIntObj ( tag->values->right_margin ) );
3542 }
3543
3544 /* pixels above lines */
3545 if ( tag->pixels_above_lines_set )
3546 {
3547 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "-pixelsAboveLines", -1 ) );
3548 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewIntObj ( tag->values->pixels_above_lines ) );
3549 }
3550
3551 /* pixels below lines */
3552 if ( tag->pixels_below_lines_set )
3553 {
3554 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "-pixelsBelowLines", -1 ) );
3555 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewIntObj ( tag->values->pixels_below_lines ) );
3556 }
3557
3558 /* wrapmode? */
3559 /*
3560 if ( tag->pixels_inside_wrap_set )
3561 {
3562 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "-wrapMode", -1 ) );
3563 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewIntObj( tag->values->pixels_inside_wrap ) );
3564 }
3565 */
3566 if ( tag->tabs_set )
3567 {
3568 PangoTabArray *tabs = tag->values->tabs;
3569 }
3570
3571 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
3572 /* underline */
3573 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
3574 if ( tag->underline_set )
3575 {
3576 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "-underline", -1 ) );
3577
3578 //switch ( tag_appearance->underline )
3579 switch ( tag->values->appearance.underline )
3580 {
3581 case PANGO_UNDERLINE_NONE:
3582 {
3583 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "none", -1 ) );
3584 } break;
3585 case PANGO_UNDERLINE_SINGLE:
3586 {
3587 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "single", -1 ) );
3588 } break;
3589 case PANGO_UNDERLINE_DOUBLE:
3590 {
3591 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "double", -1 ) );
3592 } break;
3593 case PANGO_UNDERLINE_LOW:
3594 {
3595 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "low", -1 ) );
3596 } break;
3597 case PANGO_UNDERLINE_ERROR:
3598 {
3599 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "error", -1 ) );
3600 } break;
3601 default:
3602 {
3603 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "single", -1 ) );
3604 }
3605 }
3606
3607 }
3608
3609 /* wrapmode */
3610 if ( tag->wrap_mode_set )
3611 {
3612
3613 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "-wrapMode", -1 ) );
3614
3615 switch ( tag->values->wrap_mode )
3616 {
3617 case GTK_WRAP_CHAR:
3618 {
3619 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "char", -1 ) );
3620 } break;
3621 case GTK_WRAP_NONE:
3622 {
3623 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "none", -1 ) );
3624 } break;
3625 case GTK_WRAP_WORD:
3626 {
3627 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "word", -1 ) );
3628 }
3629 case GTK_WRAP_WORD_CHAR:
3630 {
3631 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "word", -1 ) );
3632 }
3633 break;
3634 default: {}
3635 }
3636
3637
3638 }
3639
3640 if ( tag->bg_full_height_set )
3641 {
3642 /* Background is fit to full line height rather than
3643 * baseline +/- ascent/descent (font height)
3644 */
3645 guint bg_full_height;
3646
3647 //sprintf ( tmp, "bg_full_height %d", tag->values->pixels_inside_wrap );
3648 //Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( tmp, -1 ) );
3649 }
3650
3651 /* invisible */
3652 if ( tag->invisible_set )
3653 {
3654 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "-invisible", -1 ) );
3655 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewIntObj ( tag->values->invisible ) );
3656
3657 }
3658
3659 /* editable */
3660 if ( tag->editable_set )
3661 {
3662 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewStringObj ( "-editable", -1 ) );
3663 Tcl_ListObjAppendElement ( NULL, resList, Tcl_NewIntObj ( tag->values->editable ) );
3664 }
3665
3666 if ( tag->language_set )
3667 {
3668 PangoLanguage *language;
3669 }
3670
3671 /* Whether to use background-related values; this is irrelevant for
3672 * the values struct when in a tag, but is used for the composite
3673 * values struct; it's true if any of the tags being composited
3674 * had background stuff set.
3675 */
3676 guint draw_bg = tag_appearance->draw_bg;
3677
3678 /* These are only used when we are actually laying out and rendering
3679 * a paragraph; not when a GtkTextAppearance is part of a
3680 * GtkTextAttributes.
3681 */
3682 guint inside_selection = tag_appearance->inside_selection;
3683
3684 guint is_text = tag_appearance->is_text;
3685
3686 #ifdef DEBUG_TAGS
3687 g_print ( "%s end\n", __FUNCTION__ );
3688 #endif
3689 }
3690
3691
3692 /**
3693 \brief Return list of tag name
3694 **/
gnoclGetTagNames(GtkTextTag * tag,gpointer data)3695 static void gnoclGetTagNames ( GtkTextTag * tag, gpointer data )
3696 {
3697 #ifdef DEBUG_TEXT
3698 //g_print ( "%s 1 \n", __FUNCTION__ );
3699 #endif
3700
3701 if ( tag == NULL )
3702 {
3703 return;
3704 }
3705
3706 char **str = data;
3707
3708 /* modify the memory allocation here to use malloc and free to release it */
3709
3710 static char tmp[300];
3711
3712 sprintf ( tmp, "%s", tag->name );
3713
3714 *str = tmp;
3715
3716 }
3717
3718
3719 /**
3720 \brief
3721 **/
signalEmit(Tcl_Interp * interp,Tcl_Obj * obj,int cmdNo,GtkTextBuffer * buffer)3722 static int signalEmit ( Tcl_Interp * interp, Tcl_Obj * obj, int cmdNo, GtkTextBuffer * buffer )
3723 {
3724
3725 const char *signal = Tcl_GetString ( obj );
3726
3727 #ifdef DEBUG_TEXT
3728 printf ( ">> emitSignal %s\n", signal );
3729 #endif
3730
3731 /* the problem now, is how to get the right object */
3732 gtk_signal_emit_by_name ( GTK_OBJECT ( GTK_WIDGET ( buffer ) ), signal, NULL );
3733
3734 return TCL_OK;
3735 }
3736
3737 static const char *cmds[] =
3738 {
3739 "getMarkup", "getAttributes", "insertMarkup",
3740
3741 "delete", "configure", "scrollToPosition", "scrollToMark",
3742 "parent",
3743 "getIndex", "getCoords", "getRect",
3744 "undo", "redo", "grabFocus", "resetUndo", "getPos",
3745
3746 "set", "erase", "select", "get", "cut", "copy", "paste", "pasteRichText_",
3747 "cget", "getLineCount", "getWordLength", "getLength",
3748 "getLineLength", "setCursor", "getCursor", "insert", "tag",
3749 "dump", "signalEmit", "mark", "gotoWordStart",
3750 "gotoWordEnd", "search", "class", "spawn", "replace",
3751 "serialize", "deSerialize", "save", "load", "print", "lorem",
3752 "clear", "popup", "getSelectionBounds",
3753 "hasGlobalFocus", "isToplevelFocus",
3754
3755 NULL
3756 };
3757
3758 /**
3759 \brief
3760 **/
gnoclTextCommand(GtkTextView * textView,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[],int cmdNo,int isTextWidget)3761 int gnoclTextCommand ( GtkTextView *textView, Tcl_Interp * interp, int objc, Tcl_Obj * const objv[], int cmdNo, int isTextWidget )
3762 {
3763 #ifdef DEBUG_TEXT
3764 g_print ( "gnoclTextCommand %s %s\n", Tcl_GetString ( objv[cmdNo] ), Tcl_GetString ( objv[cmdNo+1] ) );
3765 #endif
3766
3767 GtkTextBuffer *buffer = gtk_text_view_get_buffer ( textView );
3768
3769
3770
3771 enum cmdIdx
3772 {
3773 GetMarkupIdx, GetAttributesIdx, InsertMarkupIdx,
3774
3775 DeleteIdx, ConfigureIdx, ScrollToPosIdx, ScrollToMarkIdx,
3776 ParentIdx,
3777 GetIndexIdx, GetCoordsIdx, GetRectIdx,
3778 UndoIdx, RedoIdx, GrabFocusIdx, ResetUndoIdx, GetPosIdx,
3779
3780 SetIdx, EraseIdx, SelectIdx, GetIdx, CutIdx, CopyIdx, PasteIdx, PasteRichTextIdx,
3781 CgetIdx, GetLineCountIdx, GetWordLengthIdx, GetLengthIdx,
3782 GetLineLengthIdx, SetCursorIdx, GetCursorIdx, InsertIdx, TagIdx,
3783 DumpIdx, SignalEmitIdx, MarkIdx, GotoWordStartIdx,
3784 GotoWordEndIdx, SearchIdx, ClassIdx, SpawnIdx, ReplaceIdx,
3785 SerializeIdx, DeSerializeIdx, SaveIdx, LoadIdx, PrintIdx, LoremIdx,
3786 ClearIdx, PopupIdx, GetSelectionBounds,
3787 HasGlobalFocusIdx, IsToplevelFocusIdx
3788 };
3789
3790
3791 int idx;
3792 GtkTextMark *mark;
3793
3794 /* WJG STUFF */
3795 char s[10];
3796
3797 if ( objc < cmdNo + 1 )
3798 {
3799 Tcl_WrongNumArgs ( interp, cmdNo, objv, "command" );
3800 return -1;
3801 }
3802
3803 if ( Tcl_GetIndexFromObj ( interp, objv[cmdNo], isTextWidget ? cmds : cmds + 3, "command", TCL_EXACT, &idx ) != TCL_OK )
3804 {
3805 return -1;
3806 }
3807
3808 if ( !isTextWidget )
3809 {
3810 idx += 3;
3811 }
3812
3813 // g_print ( "1\n" );
3814
3815 switch ( idx )
3816 {
3817 /* item 1...n are GtkTextView operations, pass args onto textFunc*/
3818 case DeleteIdx: return 1;
3819 case ConfigureIdx: return 2;
3820 case ScrollToPosIdx: return 3;
3821 case ScrollToMarkIdx: return 4;
3822 case ParentIdx: return 5;
3823 case GetIndexIdx: return 6;
3824 case GetCoordsIdx: return 7;
3825 case GetRectIdx: return 8;
3826 case UndoIdx: return 9;
3827 case RedoIdx: return 10;
3828 case GrabFocusIdx: return 11;
3829 case ResetUndoIdx: return 12;
3830 case GetPosIdx: return 13;
3831 case HasGlobalFocusIdx: return 14;
3832 case IsToplevelFocusIdx: return 15;
3833
3834 /*
3835 guint8 * gtk_clipboard_wait_for_rich_text (GtkClipboard *clipboard, GtkTextBuffer *buffer, GdkAtom *format, gsize *length);
3836 gtk_clipboard_request_rich_text (GtkClipboard *clipboard, GtkTextBuffer *buffer, GtkClipboardRichTextReceivedFunc callback, gpointer user_data);
3837 */
3838 #if 0
3839 case PasteRichTextIdx:
3840 {
3841 #if 0
3842 GtkClipboard *clipboard;
3843 GdkAtom format;
3844 gsize length;
3845 guint8 *data;
3846
3847 g_print ( "1\n" );
3848 clipboard = gtk_clipboard_get ( GDK_NONE );
3849 g_print ( "2\n" );
3850 //format = gtk_text_buffer_register_deserialize_tagset ( buffer, "default" );
3851 g_print ( "3\n" );
3852 //gtk_clipboard_request_rich_text (clipboard, buffer, NULL, NULL);
3853 data = gtk_clipboard_wait_for_rich_text ( clipboard, buffer, format, &length );
3854 gtk_text_buffer_deserialize ( buffer, buffer, format, &iter, data, length, NULL ); //??
3855 g_print ( "4\n" );
3856 g_free ( data );
3857 #endif
3858 GtkClipboard *clipboard;
3859 GdkAtom *targets;
3860 clipboard = gtk_clipboard_get ( GDK_SELECTION_PRIMARY );
3861 gint n_targets;
3862 //gboolean gtk_clipboard_wait_for_targets (GtkClipboard *clipboard, GdkAtom **targets, gint *n_targets);
3863 gtk_clipboard_wait_for_targets ( clipboard, &targets, &n_targets );
3864 g_print ( "n_targets = %d\n", n_targets );
3865 g_print ( "targets %s\n", gdk_atom_name ( targets ) );
3866
3867
3868 //GtkSelectionData * gtk_clipboard_wait_for_contents (clipboard, targets);
3869
3870 }
3871 break;
3872 #endif
3873 /* these are GtkTextBuffer operations */
3874 case InsertMarkupIdx:
3875 {
3876 GtkTextIter iter;
3877 g_print ( "InsertMarkupIdx %s\n", Tcl_GetString ( objv[cmdNo+2] ) );
3878
3879 if ( posToIter ( interp, objv[cmdNo+1], buffer, &iter ) != TCL_OK )
3880 {
3881 return TCL_ERROR;
3882 }
3883
3884 gnoclInsertMarkup ( buffer, &iter, Tcl_GetString ( objv[cmdNo+2] ) );
3885 }
3886 break;
3887
3888 case GetAttributesIdx:
3889 {
3890 if ( strcmp ( Tcl_GetString ( objv[cmdNo+1] ), "attributes" ) == 0 )
3891 {
3892
3893 GtkTextIter iter;
3894 GtkTextAttributes values;
3895
3896 if ( posToIter ( interp, objv[cmdNo+2], buffer, &iter ) != TCL_OK )
3897 {
3898 return TCL_ERROR;
3899 }
3900
3901 if ( gtk_text_iter_get_attributes ( &iter, &values ) )
3902 {
3903 #ifdef DEBUG_TEXT
3904 g_print ( "attributes at %s\n", Tcl_GetString ( objv[cmdNo+2] ) );
3905 #endif
3906 /*
3907 GtkJustification justification;
3908 GtkTextDirection direction;
3909 PangoFontDescription *font;
3910 gdouble font_scale;
3911 gint left_margin;
3912 gint indent;
3913 gint right_margin;
3914 gint pixels_above_lines;
3915 gint pixels_below_lines;
3916 gint pixels_inside_wrap;
3917 PangoTabArray *tabs;
3918 GtkWrapMode wrap_mode;
3919 PangoLanguage *language;
3920 guint invisible : 1;
3921 guint bg_full_height : 1;
3922 guint editable : 1;
3923 guint realized : 1;
3924 */
3925
3926 getAttributes ( interp, &values );
3927
3928 }
3929
3930 return TCL_OK;
3931
3932 }
3933 }
3934 break;
3935
3936 case GetMarkupIdx:
3937 {
3938 g_print ( "%s getMarkup\n", __FUNCTION__ );
3939
3940 GtkTextIter startIter, endIter;
3941
3942 posToIter ( interp, objv[cmdNo+1], buffer, &startIter );
3943 posToIter ( interp, objv[cmdNo+2], buffer, &endIter );
3944 //g_print ( "getMarkup 1\n" );
3945 Tcl_Obj *res = getMarkUpString ( interp, buffer, &startIter, &endIter );
3946 //g_print ( "getMarkup 2\n" );
3947 //char *txt = gtk_text_buffer_get_text ( buffer, &startIter, &endIter, 1 );
3948 Tcl_SetObjResult ( interp, res );
3949 //g_print ( "getMarkup 3\n" );
3950 }
3951 break;
3952
3953 case PrintIdx:
3954 {
3955 #ifdef DEBUG_TEXT
3956 g_print ( "print\n" );
3957 #endif
3958 /* reset parameters for this command and then call */
3959 gnoclPrintCmd ( buffer, interp, objc, objv );
3960
3961 }
3962
3963 break;
3964 case ClearIdx:
3965 {
3966 gtk_text_buffer_set_text ( buffer, "", 0 );
3967 }
3968 break;
3969 case LoremIdx:
3970 {
3971
3972 gchar lorem[] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas sed eleifend sem. Aenean at convallis ante. Etiam venenatis massa vitae nisl pretium sed pretium velit vehicula. Morbi vitae magna justo. Nullam ultricies rutrum felis rutrum tristique. Quisque orci mauris, cursus at dapibus quis, faucibus et nibh. Etiam posuere scelerisque libero eu rutrum. Nulla vel metus ut purus tempus adipiscing. Aenean lacus nunc, luctus sed tempor ac, semper vitae massa. Nunc et augue vitae ligula facilisis pulvinar a vestibulum magna. Quisque convallis rutrum vehicula. Morbi pulvinar nunc quis dui pharetra faucibus. Fusce sapien metus, varius eget fringilla quis, tristique vitae augue. Duis accumsan aliquet diam sed pretium. Nunc ipsum neque, auctor et convallis eget, molestie vitae libero. Integer eget velit at leo aliquam lobortis vel eu erat. Suspendisse sed orci neque. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Ut lobortis arcu gravida sapien vestibulum venenatis. In quis diam tellus.";
3973
3974 gtk_text_buffer_insert_at_cursor ( buffer, lorem, strlen ( lorem ) );
3975
3976 }
3977 break;
3978 case PopupIdx:
3979 {
3980 // 0 1 2 3 4
3981 // $id popup item <path>
3982 // $id popup subMenu <path1> <path2>
3983 #ifdef DEBUG_TEXT
3984 g_print ( "PopupIdx %s\n", Tcl_GetString ( objv[cmdNo] ) );
3985 g_print ( "PopupIdx %s\n", Tcl_GetString ( objv[cmdNo +1] ) );
3986 g_print ( "PopupIdx %s\n", Tcl_GetString ( objv[cmdNo +2] ) );
3987 #endif
3988
3989 static char *popupOptions[] =
3990 {
3991 "item", "subMenu", "separator",
3992 NULL
3993 };
3994
3995 static enum popupOptionsIdx
3996 {
3997 ItemIdx, SubMenuIdx, SeparatorIdx
3998 };
3999
4000 gint idx;
4001
4002 getIdx ( popupOptions, Tcl_GetString ( objv[cmdNo +1] ), &idx );
4003
4004 switch ( idx )
4005 {
4006 case SeparatorIdx:
4007 {
4008 gnoclPopupMenuAddSeparator ( interp );
4009 }
4010 break;
4011 case ItemIdx:
4012 {
4013 gnoclPopupMenuAddItem ( interp, Tcl_GetString ( objv[cmdNo+2] ) );
4014 } break;
4015 case SubMenuIdx:
4016 {
4017 gnoclPopupMenuAddSubMenu ( interp, Tcl_GetString ( objv[cmdNo+2] ), Tcl_GetString ( objv[cmdNo+3] ) );
4018 } break;
4019 default: {}
4020 }
4021
4022
4023 }
4024
4025 break;
4026 case SaveIdx:
4027 case SerializeIdx: /* WJG 29/04/09 */
4028 {
4029
4030 FILE *output;
4031 guint8 *data;
4032 gsize length;
4033 GtkTextIter start, end;
4034 GdkAtom se_format;
4035
4036 se_format = gtk_text_buffer_register_serialize_tagset ( buffer, NULL );
4037
4038 gtk_text_buffer_get_bounds ( buffer, &start, &end );
4039 data = gtk_text_buffer_serialize ( buffer, buffer, se_format, &start, &end, &length );
4040
4041 #ifdef DEBUG_TEXT
4042 g_print ( "%s\n", data );
4043 #endif
4044
4045
4046 output = fopen ( Tcl_GetString ( objv[cmdNo+1] ), "w" );
4047
4048 fwrite ( &length, sizeof ( gsize ), 1, output );
4049 fwrite ( data, sizeof ( guint8 ), length, output );
4050 fclose ( output );
4051
4052 #if 0 // attempt to serialize returning a text string
4053 GString *buf;
4054 buf = g_string_sized_new ( length );
4055
4056 int i;
4057
4058 output = fopen ( "serialize.xml", "w" );
4059
4060 /* ignore the first 32 characters */
4061 for ( i = 31; i < length ; i++ )
4062 {
4063 /* show the content of the data array */
4064 g_string_append_unichar ( buf, data[i] ); /* <--- problems here, but why? */
4065 }
4066
4067 fclose ( output );
4068
4069 Tcl_SetObjResult ( interp, Tcl_NewStringObj ( buf->str, -1 ) );
4070
4071 g_string_free ( buf, 1 );
4072
4073 #endif
4074
4075 return TCL_OK;
4076
4077 }
4078
4079 break;
4080 case LoadIdx:
4081 case DeSerializeIdx: /* WJG 29/04/09 */
4082 {
4083
4084 FILE *input;
4085 guint8 *data;
4086 gsize length;
4087 GtkTextIter iter;
4088 GdkAtom de_format;
4089
4090 #if 0 // binary file
4091 input = fopen ( Tcl_GetString ( objv[cmdNo+1] ), "r" );
4092
4093 // Return with error message if the file is not found.
4094
4095 if ( input == NULL )
4096 {
4097 char str[128];
4098 sprintf ( str, "File %s not found.\n", Tcl_GetString ( objv[cmdNo+1] ) );
4099 Tcl_SetObjResult ( interp, Tcl_NewStringObj ( str, -1 ) );
4100 return TCL_OK;
4101 }
4102
4103 // read data
4104 fread ( &length, sizeof ( gsize ), 1, input );
4105 data = malloc ( sizeof ( guint8 ) * length );
4106 fread ( data, sizeof ( guint8 ), length, input );
4107 fclose ( input );
4108
4109 de_format = gtk_text_buffer_register_deserialize_tagset ( buffer, "default" );
4110 gtk_text_buffer_get_iter_at_offset ( buffer, &iter, 0 );
4111 gtk_text_buffer_deserialize ( buffer, buffer, de_format, &iter, data, length, NULL );
4112
4113 g_free ( data );
4114
4115 #else // text file
4116 de_format = gtk_text_buffer_register_deserialize_tagset ( buffer, "default" );
4117 gtk_text_buffer_get_iter_at_offset ( buffer, &iter, 0 );
4118 gtk_text_buffer_deserialize ( buffer, buffer, de_format, &iter, Tcl_GetString ( objv[cmdNo+1] ), strlen ( Tcl_GetString ( objv[cmdNo+1] ) ), NULL );
4119 #endif
4120
4121 return TCL_OK;
4122 }
4123
4124 break;
4125 case ReplaceIdx: /* WJG 21/02/09 -Pretty much the same code as SearchIdx */
4126 {
4127 gint row1, col1, row2, col2;
4128 GtkTextIter start;
4129 GtkTextIter begin, end;
4130 GtkTextMark *replace;
4131 Tcl_Obj *resList;
4132 gint applyTags;
4133 gchar * pch;
4134 gchar * tagList;
4135 gint i;
4136
4137 replace = NULL;
4138
4139 if ( objc < cmdNo + 2 )
4140 {
4141 Tcl_WrongNumArgs ( interp, cmdNo + 1, objv, "<search-phrase> <swap-phrase>" );
4142 return -1;
4143 }
4144
4145 resList = Tcl_NewListObj ( 0, NULL );
4146
4147 /* default with the start of the buffer */
4148 gtk_text_buffer_get_start_iter ( buffer, &start );
4149
4150 i = 0;
4151
4152 while ( gtk_text_iter_forward_search ( &start, Tcl_GetString ( objv[cmdNo+1] ), 0, &begin, &end, NULL ) != NULL )
4153 {
4154
4155 if ( replace == NULL )
4156 {
4157 replace = gtk_text_buffer_create_mark ( buffer, "REPLACE_MARK", &begin, 1 );
4158 }
4159
4160 else
4161 {
4162 gtk_text_buffer_move_mark ( buffer, replace, &begin );
4163 }
4164
4165 gtk_text_buffer_delete ( buffer, &begin, &end );
4166
4167 gtk_text_buffer_get_iter_at_mark ( buffer, &end, replace );
4168 gtk_text_buffer_insert ( buffer, &end, Tcl_GetString ( objv[cmdNo+2] ), strlen ( Tcl_GetString ( objv[cmdNo+2] ) ) );
4169
4170 start = end;
4171 i++;
4172
4173 }
4174
4175 gtk_text_buffer_delete_mark ( buffer, replace );
4176
4177 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewIntObj ( i ) );
4178
4179 Tcl_SetObjResult ( interp, resList );
4180
4181 return TCL_OK;
4182 }
4183
4184 break;
4185 case SpawnIdx: /* WJG began 06/12/08 */
4186 {
4187 /* code taken from gnoclTextCmd */
4188 GtkTextView *spawn;
4189 GtkScrolledWindow *scrolled;
4190 GtkTextBuffer *spawnBuffer;
4191 spawnBuffer = buffer;
4192 #ifdef DEBUG_TEXT
4193 g_print ( "spawn -1\n" );
4194 #endif
4195 /* create a new text view with buffer GtkTextBuffer *buffer*/
4196 //g_object_ref (G_OBJECT(buffer));
4197 spawn = GTK_TEXT_VIEW ( gtk_text_view_new_with_buffer ( GTK_TEXT_BUFFER ( spawnBuffer ) ) );
4198 //spawn = GTK_TEXT_VIEW ( gtk_text_view_new_with_buffer ( NULL ) );
4199 //gtk_text_view_set_buffer (spawn, buffer);
4200 #ifdef DEBUG_TEXT
4201 g_print ( "spawn -2\n" );
4202 #endif
4203 /* add some extra signals to the default setting */
4204 gtk_widget_add_events ( spawn, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK );
4205 g_print ( "spawn -3\n" );
4206 scrolled = gtk_scrolled_window_new ( NULL, NULL );
4207 gtk_scrolled_window_set_policy ( scrolled, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
4208 gtk_container_add ( scrolled, GTK_WIDGET ( spawn ) );
4209 gtk_widget_show_all ( GTK_WIDGET ( scrolled ) );
4210 #ifdef DEBUG_TEXT
4211 g_print ( "spawn -4\n" );
4212 #endif
4213
4214 if ( 0 )
4215 {
4216 /* get properties of the parent widget */
4217 gint intval;
4218 gchar *strval;
4219 GObject *objval;
4220
4221 g_object_get ( spawn,
4222 "int-property", &intval,
4223 "str-property", &strval,
4224 "obj-property", &objval,
4225 NULL );
4226
4227 // Do something with intval, strval, objval
4228 g_free ( strval );
4229 g_object_unref ( objval );
4230 }
4231
4232 /* need to get options from the existing view */
4233 return gnoclRegisterWidget ( interp, GTK_WIDGET ( scrolled ), textFunc );
4234
4235 }
4236
4237 break;
4238
4239 case SearchIdx: /* WJG began 13/09/08 */
4240 {
4241
4242 int row1, col1, row2, col2;
4243 GtkTextIter start;
4244 GtkTextIter begin, end;
4245 Tcl_Obj *resList;
4246 gint applyTags;
4247 char * pch;
4248 char * tagList;
4249 GtkTextTagTable *table;
4250
4251 if ( objc < cmdNo + 1 )
4252 {
4253 Tcl_WrongNumArgs ( interp, cmdNo + 1, objv, "<search-phrase> -tags {taglist}" );
4254 return -1;
4255 }
4256
4257 applyTags = 0;
4258
4259 if ( objc == cmdNo + 4 )
4260 {
4261 if ( strcmp ( Tcl_GetString ( objv[cmdNo+2] ), "-tags" ) == 0 )
4262 {
4263 pch = strtok ( Tcl_GetString ( objv[cmdNo+3] ), " " );
4264
4265 table = gtk_text_buffer_get_tag_table ( buffer );
4266
4267 if ( gtk_text_tag_table_lookup ( table, pch ) == NULL )
4268 {
4269
4270 Tcl_SetObjResult ( interp, Tcl_NewStringObj ( "GNOCL ERROR! Specified tag not found.", -1 ) );
4271
4272 return TCL_ERROR;
4273 }
4274
4275 applyTags = 1;
4276 }
4277
4278 else
4279 {
4280 Tcl_SetObjResult ( interp, Tcl_NewStringObj ( "GNOCL ERROR! Invalid option given, it must be -tags <taglist>.", -1 ) );
4281
4282 return TCL_ERROR;
4283 }
4284 }
4285
4286
4287 resList = Tcl_NewListObj ( 0, NULL );
4288
4289 /* default with the start of the buffer */
4290 gtk_text_buffer_get_start_iter ( buffer, &start );
4291
4292 while ( gtk_text_iter_forward_search ( &start, Tcl_GetString ( objv[cmdNo+1] ), 0, &begin, &end, NULL ) != NULL )
4293 {
4294 /* return the index of the found location */
4295 row1 = gtk_text_iter_get_line ( &begin );
4296 col1 = gtk_text_iter_get_line_offset ( &begin );
4297 row2 = gtk_text_iter_get_line ( &end );
4298 col2 = gtk_text_iter_get_line_offset ( &end );
4299
4300 /* check if there is a taglist to apply */
4301 if ( applyTags == 1 )
4302 {
4303 /* currently supporting only one tag */
4304 gtk_text_buffer_apply_tag_by_name ( buffer, pch, &begin, &end );
4305
4306 }
4307
4308 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewIntObj ( row1 ) );
4309 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewIntObj ( col1 ) );
4310 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewIntObj ( row2 ) );
4311 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewIntObj ( col2 ) );
4312
4313 start = end;
4314
4315 }
4316
4317 Tcl_SetObjResult ( interp, resList );
4318
4319 return TCL_OK;
4320 }
4321
4322 break;
4323 case SignalEmitIdx:
4324 {
4325 /* error check the command */
4326 if ( objc != cmdNo + 2 )
4327 {
4328 Tcl_WrongNumArgs ( interp, cmdNo + 1, objv, "<signal-name>" );
4329
4330 return -1;
4331 }
4332
4333 /* DEBUG_TEXTging test line */
4334 #ifdef DEBUG_TEXT
4335 printf ( "signalEmit %s\n", objv[cmdNo+1] );
4336 #endif
4337
4338 /* attempt to emit the signal */
4339 if ( signalEmit ( interp, objv[cmdNo+1] , cmdNo, buffer ) != TCL_OK )
4340 {
4341 return -1;
4342 }
4343 }
4344
4345 break;
4346 case ClassIdx:
4347 {
4348 Tcl_SetObjResult ( interp, Tcl_NewStringObj ( "text", -1 ) );
4349 }
4350 break;
4351 case EraseIdx:
4352 case SelectIdx:
4353 case GetIdx:
4354 {
4355 GtkTextIter startIter, endIter;
4356
4357
4358 if ( objc < cmdNo + 3 )
4359 {
4360 Tcl_WrongNumArgs ( interp, cmdNo + 1, objv, "startIndex ?endIndex?" );
4361 return TCL_ERROR;
4362 }
4363
4364 #ifdef DEBUG_TEXT
4365 g_print ( "7\n" );
4366 #endif
4367
4368 if ( posToIter ( interp, objv[cmdNo+1], buffer, &startIter ) != TCL_OK )
4369 {
4370 return TCL_ERROR;
4371 }
4372
4373 #ifdef DEBUG_TEXT
4374 g_print ( "8\n" );
4375 #endif
4376
4377 if ( objc >= 4 )
4378 {
4379 if ( posToIter ( interp, objv[cmdNo+2], buffer, &endIter ) != TCL_OK )
4380 {
4381 return TCL_ERROR;
4382 }
4383 }
4384
4385 else
4386 {
4387 endIter = startIter;
4388 gtk_text_iter_backward_char ( &endIter );
4389 }
4390
4391 #ifdef DEBUG_TEXT
4392 g_print ( "9\n" );
4393 #endif
4394
4395 switch ( idx )
4396 {
4397 case EraseIdx:
4398 {
4399 gtk_text_buffer_delete ( buffer, &startIter, &endIter );
4400 }
4401 break;
4402 case SelectIdx:
4403 {
4404 gtk_text_buffer_place_cursor ( buffer, &startIter );
4405 gtk_text_buffer_move_mark_by_name ( buffer, "selection_bound", &endIter );
4406 }
4407 break;
4408 case GetIdx:
4409 {
4410 /* TODO: include_hidden_chars */
4411 #ifdef DEBUG_TEXT
4412 g_print ( "10 ----\n" );
4413 #endif
4414
4415 char *txt = gtk_text_buffer_get_text ( buffer, &startIter, &endIter, 1 );
4416 Tcl_SetObjResult ( interp, Tcl_NewStringObj ( txt, -1 ) );
4417
4418 }
4419 break;
4420 }
4421 }
4422 #ifdef DEBUG_TEXT
4423 g_print ( "11\n" );
4424 #endif
4425 break;
4426 case CutIdx:
4427 case CopyIdx:
4428 case PasteIdx:
4429 {
4430 /* TODO: option which clipboard */
4431 GtkClipboard *clipboard = gtk_clipboard_get ( GDK_NONE );
4432
4433 if ( objc != cmdNo + 1 )
4434 {
4435 Tcl_WrongNumArgs ( interp, cmdNo + 1, objv, NULL );
4436 return TCL_ERROR;
4437 }
4438
4439 switch ( idx )
4440 {
4441 case CutIdx:
4442 {
4443 gtk_text_buffer_cut_clipboard ( buffer, clipboard, 1 );
4444 }
4445 break;
4446 case CopyIdx:
4447 {
4448 gtk_text_buffer_copy_clipboard ( buffer, clipboard );
4449 }
4450 break;
4451 case PasteIdx:
4452 {
4453 gtk_text_buffer_paste_clipboard ( buffer, clipboard, NULL, 1 );
4454 }
4455 break;
4456 }
4457 }
4458
4459 break;
4460 case CgetIdx: // gnoclTextCommand
4461 {
4462 #ifdef DEBUG_TEXT
4463 g_print ( "%s CgetIdx\n", __FUNCTION__ );
4464 #endif
4465
4466
4467 int idx;
4468
4469 switch ( gnoclCget ( interp, objc, objv, G_OBJECT ( textView ), textOptions, &idx ) )
4470 {
4471 case GNOCL_CGET_ERROR:
4472 {
4473 return TCL_ERROR;
4474 }
4475 case GNOCL_CGET_HANDLED:
4476 {
4477 return TCL_OK;
4478 }
4479 case GNOCL_CGET_NOTHANDLED:
4480 {
4481 return cget ( interp, textView, textOptions, idx );
4482 }
4483 }
4484
4485 }
4486
4487 break;
4488 case GetLineCountIdx: /* WJG Added 24/04/08 */
4489 {
4490 /* editable getLength */
4491 if ( objc != cmdNo + 1 )
4492 {
4493 Tcl_WrongNumArgs ( interp, cmdNo + 1, objv, NULL );
4494 return -1;
4495 }
4496
4497 Tcl_SetObjResult ( interp, Tcl_NewIntObj ( gtk_text_buffer_get_line_count ( buffer ) ) );
4498 }
4499
4500 break;
4501 case GetLengthIdx: /* TODO getByteCount */
4502 {
4503 /* editable getLength */
4504 if ( objc != cmdNo + 1 )
4505 {
4506 Tcl_WrongNumArgs ( interp, cmdNo + 1, objv, NULL );
4507 return -1;
4508 }
4509
4510 Tcl_SetObjResult ( interp, Tcl_NewIntObj ( gtk_text_buffer_get_char_count ( buffer ) ) );
4511 }
4512
4513 break;
4514 case GetLineLengthIdx: /* Added WJG 17/05/08 */
4515 {
4516 GtkTextIter iter;
4517
4518 if ( objc != cmdNo + 2 )
4519 {
4520 Tcl_WrongNumArgs ( interp, cmdNo + 1, objv, "index" );
4521 return -1;
4522 }
4523
4524 if ( posToIter ( interp, objv[cmdNo+1], buffer, &iter ) != TCL_OK )
4525 {
4526 return -1;
4527 }
4528
4529 Tcl_SetObjResult ( interp, Tcl_NewIntObj ( gtk_text_iter_get_chars_in_line ( &iter ) ) );
4530 }
4531
4532 break;
4533 case GetWordLengthIdx: /* Added WJG 12/09/08 */
4534 {
4535 GtkTextIter iter, iter_a;
4536 int row_a, col_a, row_b, col_b, wordLength;
4537
4538 /* get the iter at the specified position */
4539 posToIter ( interp, objv[cmdNo+1], buffer, &iter );
4540
4541 /* move the iter to the start of the word */
4542 gtk_text_iter_backward_word_start ( &iter );
4543
4544 /* get row-offset values for the iter */
4545 row_a = gtk_text_iter_get_line ( &iter );
4546 col_a = gtk_text_iter_get_line_offset ( &iter );
4547
4548 /* move the iter to the end of the word */
4549 gtk_text_iter_forward_word_end ( &iter );
4550
4551 /* get the position... */
4552 row_b = gtk_text_iter_get_line ( &iter );
4553 col_b = gtk_text_iter_get_line_offset ( &iter );
4554
4555 /* subtract the larger from the smaller */
4556 wordLength = col_b - col_a;
4557
4558 /* return the value */
4559 Tcl_SetObjResult ( interp, Tcl_NewIntObj ( wordLength ) );
4560 }
4561
4562 break;
4563 case GotoWordStartIdx: /* Added WJG 12/09/08 */
4564 {
4565 GtkTextIter iter;
4566
4567 /* text setCursor index */
4568
4569 if ( objc != cmdNo + 2 )
4570 {
4571 Tcl_WrongNumArgs ( interp, cmdNo + 1, objv, "index" );
4572 return -1;
4573 }
4574
4575 gtk_text_buffer_get_iter_at_mark ( buffer, &iter, gtk_text_buffer_get_insert ( buffer ) );
4576
4577 gtk_text_iter_backward_word_start ( &iter );
4578
4579 gtk_text_buffer_place_cursor ( buffer, &iter );
4580 }
4581
4582 break;
4583 case GotoWordEndIdx: /* Added WJG 12/09/08 */
4584 {
4585 GtkTextIter iter;
4586
4587 /* text setCursor index */
4588
4589 if ( objc != cmdNo + 2 )
4590 {
4591 Tcl_WrongNumArgs ( interp, cmdNo + 1, objv, "index" );
4592 return -1;
4593 }
4594
4595 gtk_text_buffer_get_iter_at_mark ( buffer, &iter, gtk_text_buffer_get_insert ( buffer ) );
4596
4597 gtk_text_iter_forward_word_end ( &iter );
4598
4599 gtk_text_buffer_place_cursor ( buffer, &iter );
4600 }
4601
4602 break;
4603 case SetIdx:
4604 {
4605 gtk_text_buffer_set_text ( buffer, gnoclGetString ( objv[cmdNo+1] ), -1 );
4606 }
4607
4608 break;
4609 case SetCursorIdx:
4610 {
4611 GtkTextIter iter;
4612
4613 /* text setCursor index */
4614
4615 if ( objc != cmdNo + 2 )
4616 {
4617 Tcl_WrongNumArgs ( interp, cmdNo + 1, objv, "index" );
4618 return -1;
4619 }
4620
4621 if ( posToIter ( interp, objv[cmdNo+1], buffer, &iter ) != TCL_OK )
4622 {
4623 return -1;
4624 }
4625
4626 gtk_text_buffer_place_cursor ( buffer, &iter );
4627 }
4628
4629 break;
4630 case GetCursorIdx:
4631 {
4632 GtkTextIter iter;
4633 int row, col;
4634 Tcl_Obj *resList;
4635
4636 /* text getCursor */
4637 if ( objc != cmdNo + 1 )
4638 {
4639 Tcl_WrongNumArgs ( interp, cmdNo + 1, objv, NULL );
4640 return -1;
4641 }
4642
4643 gtk_text_buffer_get_iter_at_mark ( buffer, &iter, gtk_text_buffer_get_insert ( buffer ) );
4644
4645 row = gtk_text_iter_get_line ( &iter );
4646 col = gtk_text_iter_get_line_offset ( &iter );
4647
4648 resList = Tcl_NewListObj ( 0, NULL );
4649 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewIntObj ( row ) );
4650 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewIntObj ( col ) );
4651 Tcl_SetObjResult ( interp, resList );
4652 }
4653
4654 break;
4655
4656 case GetSelectionBounds:
4657 {
4658 GtkTextIter startIter, endIter;
4659
4660 int row, col;
4661 Tcl_Obj *resList;
4662
4663 if ( gtk_text_buffer_get_selection_bounds ( buffer, &startIter, &endIter ) )
4664 {
4665
4666 resList = Tcl_NewListObj ( 0, NULL );
4667
4668 row = gtk_text_iter_get_line ( &startIter );
4669 col = gtk_text_iter_get_line_offset ( &startIter );
4670
4671 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewIntObj ( row ) );
4672 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewIntObj ( col ) );
4673
4674 row = gtk_text_iter_get_line ( &endIter );
4675 col = gtk_text_iter_get_line_offset ( &endIter );
4676
4677 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewIntObj ( row ) );
4678 Tcl_ListObjAppendElement ( interp, resList, Tcl_NewIntObj ( col ) );
4679
4680 Tcl_SetObjResult ( interp, resList );
4681 return TCL_OK;
4682
4683 }
4684
4685 /* return null string if there is no selection */
4686 Tcl_SetObjResult ( interp, Tcl_NewStringObj ( "", -1 ) );
4687 return TCL_OK;
4688
4689
4690 }
4691 break;
4692
4693
4694 case InsertIdx:
4695 {
4696
4697 if ( textInsert ( buffer, interp, objc, objv, cmdNo + 1 ) != TCL_OK )
4698 {
4699 return -1;
4700 }
4701 }
4702 /* this action needs to emit an insert text signal */
4703
4704 break;
4705
4706 case MarkIdx:
4707 {
4708 if ( markCmd ( buffer, interp, objc, objv, cmdNo + 1 ) != TCL_OK )
4709 {
4710 return -1;
4711 }
4712 }
4713 break;
4714
4715 case TagIdx:
4716 {
4717 if ( tagCmd ( buffer, interp, objc, objv, cmdNo + 1 ) != TCL_OK )
4718 {
4719 return -1;
4720 }
4721 }
4722 break;
4723
4724 /* the widget dump has the format;
4725 * widgetId dump option startIndex endIndx
4726 */
4727 case DumpIdx:
4728 {
4729 /* some DEBUG_TEXTging feedback */
4730
4731 #ifdef DEBUG_TAGS
4732 g_print ( "\tdump: %d %d: %s %s %s %s\n",
4733 objc, cmdNo + 4,
4734 Tcl_GetString ( objv[cmdNo] ),
4735 Tcl_GetString ( objv[cmdNo+1] ),
4736 Tcl_GetString ( objv[cmdNo+2] ),
4737 Tcl_GetString ( objv[cmdNo+3] ) ) ;
4738 #endif
4739
4740
4741
4742 GtkTextIter startIter, endIter;
4743
4744 GtkTextTagTable *tagtable;
4745 char *txt;
4746 int idx;
4747
4748 static const char *cmds[] =
4749 {
4750 "all", "tags", "text",
4751 "window", "images", "marks",
4752 NULL
4753 };
4754
4755 enum opts
4756 {
4757 AllIdx, TagsIdx, TextIdx,
4758 WindowsIdx, ImagesIdx, MarksIdx
4759 };
4760
4761 /* do some error checking */
4762
4763 if ( objc < cmdNo + 4 )
4764 {
4765 Tcl_WrongNumArgs ( interp, cmdNo + 1, objv, "?all|text|tags|window|images|marks? startIndex ?endIndex?" );
4766 return TCL_ERROR;
4767 }
4768
4769 /* get iters for the required range */
4770
4771 if ( posToIter ( interp, objv[cmdNo+2], buffer, &startIter ) != TCL_OK )
4772 {
4773 return TCL_ERROR;
4774 }
4775
4776 if ( posToIter ( interp, objv[cmdNo+3], buffer, &endIter ) != TCL_OK )
4777 {
4778 return TCL_ERROR;
4779 }
4780
4781 /* get the sub-command, one of all, tags, text, images, marks */
4782
4783
4784 if ( Tcl_GetIndexFromObj ( interp, objv[cmdNo+1], cmds, "subcommand", TCL_EXACT, &idx ) != TCL_OK )
4785 {
4786 return TCL_ERROR;
4787 }
4788
4789 #if 0
4790 g_print ( "-----HERE\n" );
4791 #endif
4792
4793 //getIdx ( cmds, objv[cmdNo+1], &idx );
4794
4795
4796 /*
4797 * Respond to the second keyword..
4798 */
4799
4800 switch ( idx )
4801 {
4802 case AllIdx:
4803 {
4804 #if 0
4805 g_print ( "-----AllIdx\n" );
4806 #endif
4807
4808 Tcl_Obj *res;
4809 res = dumpAll ( interp, buffer, &startIter, &endIter ) ;
4810 Tcl_SetObjResult ( interp, res );
4811 return TCL_OK;
4812 }
4813
4814 break;
4815 case TagsIdx: /* include tagOn/Off changes in the text */
4816 {
4817 #ifdef DEBUG_TEXT
4818 g_print ( "dump text+tags start\n" );
4819 #endif
4820 GtkTextTagTable *tagtable = gtk_text_buffer_get_tag_table ( buffer );
4821
4822 /* get the settings of each tag in the buffer*/
4823 /* note, pass the address of the pointer to the data assigned by the called function */
4824
4825 gtk_text_tag_table_foreach ( tagtable, gnoclGetTagProperties, &txt ); //
4826
4827 #ifdef DEBUG_TEXT
4828 g_print ( "dump text+tags end\n" );
4829 #endif
4830
4831 //Tcl_SetObjResult ( interp, Tcl_NewStringObj ( txt, -1 ) );
4832 /* reset the outsput string by using null pointers */
4833 //gnoclGetTagProperties ( NULL, NULL );
4834 return TCL_OK;
4835 }
4836
4837 break;
4838 case TextIdx:
4839 {
4840 /* TODO: include_hidden_chars */
4841 txt = gtk_text_buffer_get_text ( buffer, &startIter, &endIter, 1 );
4842 Tcl_SetObjResult ( interp, Tcl_NewStringObj ( txt, -1 ) );
4843 return TCL_OK;
4844 }
4845
4846 break;
4847 case WindowsIdx:
4848 {
4849 txt = "dump windows... Feature not yet implmented\n";
4850 Tcl_SetObjResult ( interp, Tcl_NewStringObj ( txt, -1 ) );
4851 return TCL_OK;
4852 }
4853
4854 break;
4855 case ImagesIdx:
4856 {
4857 txt = "dump images... Feature not yet implmented\n";
4858 Tcl_SetObjResult ( interp, Tcl_NewStringObj ( txt, -1 ) );
4859 return TCL_OK;
4860 }
4861
4862 break;
4863 case MarksIdx:
4864 {
4865 txt = "dump marks... Feature not yet implmented\n";
4866 Tcl_SetObjResult ( interp, Tcl_NewStringObj ( txt, -1 ) );
4867 return TCL_OK;
4868 }
4869
4870 break;
4871 default:
4872 {
4873 assert ( 0 );
4874 }
4875 }
4876
4877 return TCL_OK;
4878
4879 }
4880
4881 break;
4882
4883 default:
4884 assert ( 0 );
4885 return -1;
4886 }
4887
4888 return 0;
4889 }
4890
4891
4892
4893 /**
4894 \brief ** USING ** TEXTPARAMS
4895 Handler for gnocl created instances that take into account the scrolled window
4896 \note Unlike gnocl, Builder/Glade not provide text objects within scrolled windows.
4897 Two handle functions are necessary, one for gnocl built widgets, and one for builder/glade widgets.
4898 **/
4899
textFunc(ClientData data,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[])4900 static int textFunc ( ClientData data, Tcl_Interp * interp, int objc, Tcl_Obj * const objv[] )
4901 {
4902 TextParams *para = ( TextParams * ) data;
4903
4904 GtkScrolledWindow *scrolled = para->scrolled;
4905 GtkTextView *text = GTK_TEXT_VIEW ( gtk_bin_get_child ( GTK_BIN ( scrolled ) ) );
4906 GtkTextBuffer *buffer = gtk_text_view_get_buffer ( text );
4907
4908 #ifdef DEBUG_TEXT_TEXT
4909 g_printf ( "textFunc\n" );
4910 gint _i;
4911
4912 for ( _i = 0; _i < objc; _i++ )
4913 {
4914 g_print ( "\targ %d = %s\n", _i, Tcl_GetString ( objv[_i] ) );
4915 }
4916
4917 #endif
4918
4919
4920 if ( objc < 2 )
4921 {
4922 Tcl_WrongNumArgs ( interp, 1, objv, "command" );
4923 return TCL_ERROR;
4924 }
4925
4926 /*
4927 case DeleteIdx: return 1;
4928 case ConfigureIdx: return 2;
4929 case ScrollToPosIdx: return 3;
4930 case ScrollToMarkIdx: return 4;
4931 case ParentIdx: return 5;
4932 case GetIndexIdx: return 6;
4933 case GetCoordsIdx: return 7;
4934 case GetRectIdx: return 8;
4935 case UndoIdx: return 9;
4936 case RedoIdx: return 10;
4937 case GrabFocusIdx: return 11;
4938 case ResetUndoIdx: return 12;
4939 case GetPosIdx: return 13;
4940 case HasFocus return 14;
4941 */
4942
4943 switch ( gnoclTextCommand ( text, interp, objc, objv, 1, 1 ) )
4944 {
4945 /* these are command which work upon the GtkTextView rather than the GtkTextBuffer */
4946 case 0: /* return TCL_OK */
4947 {
4948 break;
4949 }
4950 case 1: /* delete */
4951 {
4952 return gnoclDelete ( interp, GTK_WIDGET ( scrolled ), objc, objv );
4953 }
4954 case 2: /* configure */
4955 {
4956 int ret = TCL_ERROR;
4957
4958 if ( gnoclParseAndSetOptions ( interp, objc - 1, objv + 1, textOptions, G_OBJECT ( text ) ) == TCL_OK )
4959 {
4960 //ret = configure ( interp, scrolled, text, para, textOptions );
4961 ret = configure ( interp, para, textOptions );
4962 }
4963
4964 gnoclClearOptions ( textOptions );
4965
4966 return ret;
4967 }
4968
4969 break;
4970 case 3: /* scrollToPosition */
4971 {
4972 return scrollToPos ( text, buffer, interp, objc, objv );
4973 }
4974 case 4: /* scrollToMark */
4975 {
4976 return scrollToMark ( text, buffer, interp, objc, objv );
4977 }
4978 case 5: /* get parent, WJG added 06/12/08 */
4979 {
4980 GtkWidget * parent;
4981 Tcl_Obj *obj = NULL;
4982 parent = gtk_widget_get_parent ( GTK_WIDGET ( data ) );
4983 obj = Tcl_NewStringObj ( gnoclGetNameFromWidget ( parent ), -1 );
4984 Tcl_SetObjResult ( interp, obj );
4985
4986 /* this function not working too well! */
4987 /* return gnoclGetParent ( interp, data ); */
4988 return TCL_OK;
4989 }
4990
4991 break;
4992 // getIndex
4993 case 6: /* get line/row from root window coordinates, ie passed from an event */
4994 {
4995
4996 //g_print ( "tag getIndex\n" );
4997
4998 GtkTextIter iter;
4999 gint y, line_no;
5000 gint x, row_no;
5001
5002 gint wx, wy; /* window coordinates */
5003 gint bx, by; /* buffer coordinates */
5004 gint line, row;
5005
5006 //sscanf ( Tcl_GetString ( objv[2] ), "%d %d", &wx, &wy );
5007
5008 Tcl_GetIntFromObj ( NULL, objv[2], &wx ) ;
5009 Tcl_GetIntFromObj ( NULL, objv[3], &wy ) ;
5010
5011 //g_print ( "1\n" );
5012
5013 //gdk_window_get_pointer (TxT->window, &wx, &wy, NULL);
5014 gtk_text_view_window_to_buffer_coords ( text, GTK_TEXT_WINDOW_WIDGET, wx, wy, &bx, &by );
5015 gtk_text_view_get_iter_at_location ( text, &iter, bx, by );
5016
5017 //gtk_text_layout_get_iter_at_pixel (text->layout, &iter, x, y);
5018
5019 //g_print ( "2\n" );
5020
5021
5022 line = gtk_text_iter_get_line ( &iter );
5023 row = gtk_text_iter_get_line_offset ( &iter );
5024
5025 //g_print ( "3\n" );
5026
5027 gchar str[16];
5028 sprintf ( str, "%d %d", line, row );
5029
5030 //g_print ( "4\n" );
5031
5032 Tcl_SetObjResult ( interp, Tcl_NewStringObj ( str, -1 ) );
5033
5034 }
5035 break;
5036
5037 /* past line col position, return window location */
5038 case 7: /* window x/y coords from iter */
5039 {
5040
5041 gint wx;
5042 gint wy;
5043
5044 GtkTextIter iter;
5045 GdkRectangle rect;
5046
5047 if ( posToIter ( interp, objv[2], buffer, &iter ) != TCL_OK )
5048 {
5049 return TCL_ERROR;
5050 }
5051
5052 gtk_text_view_get_iter_location ( text, &iter, &rect );
5053
5054 // this line returns the buffer coordinates as window cooordinates!
5055 gtk_text_view_buffer_to_window_coords ( text, GTK_TEXT_WINDOW_WIDGET, rect.x, rect.y, &wx, &wy );
5056
5057 gchar str[24];
5058 sprintf ( str, "%d %d %d %d\n", wx, wy, rect.width, rect.height );
5059 Tcl_SetObjResult ( interp, Tcl_NewStringObj ( str, -1 ) );
5060
5061 }
5062 break;
5063 case 8: /* get visible rect */
5064 {
5065 GdkRectangle rect;
5066
5067 gtk_text_view_get_visible_rect ( text, &rect );
5068
5069 gchar str[24];
5070 sprintf ( str, "%d %d %d %d\n", rect.x, rect.y, rect.width, rect.height );
5071 Tcl_SetObjResult ( interp, Tcl_NewStringObj ( str, -1 ) );
5072
5073 }
5074 break;
5075 case 9: /* undo action */
5076 {
5077 gtk_undo_view_undo ( text );
5078 }
5079 break;
5080 case 10: /* redo action */
5081 {
5082 gtk_undo_view_redo ( text );
5083 }
5084 case 11: /* grab keyboard input */
5085 {
5086 gtk_widget_grab_focus ( text );
5087 return TCL_OK;
5088 }
5089 case 12: /* reset Undo/Redo buffer */
5090 {
5091
5092 gtk_undo_view_reset ( text );
5093
5094 return TCL_OK;
5095 }
5096
5097 case 13: /* get iter at pixel */
5098 {
5099
5100 //GtkTextIter iter;
5101 //gtk_text_layout_get_iter_at_pixel (text->layout, &iter, x, y);
5102 return TCL_OK;
5103 }
5104
5105 case 14: /* does the widget have focus */
5106 {
5107
5108 //GtkTextIter iter;
5109 //gtk_text_layout_get_iter_at_pixel (text->layout, &iter, x, y);
5110 Tcl_SetObjResult ( interp, Tcl_NewIntObj ( gtk_widget_has_focus ( text ) ) );
5111 return TCL_OK;
5112 }
5113
5114 case 15: /* does the widget have focus */
5115 {
5116
5117 //GtkTextIter iter;
5118 //gtk_text_layout_get_iter_at_pixel (text->layout, &iter, x, y);
5119 Tcl_SetObjResult ( interp, Tcl_NewIntObj ( gtk_widget_is_focus ( text ) ) );
5120 return TCL_OK;
5121 }
5122
5123
5124 default:
5125 {
5126 return TCL_ERROR;
5127 }
5128 }
5129
5130 return TCL_OK;
5131 }
5132
5133
5134 /**
5135 \brief Handler for glade created instances that have no scrolled window.
5136 **/
textViewFunc(ClientData data,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[])5137 int textViewFunc ( ClientData data, Tcl_Interp * interp, int objc, Tcl_Obj * const objv[] )
5138 {
5139
5140 GtkTextView *text = GTK_TEXT_VIEW ( data );
5141 GtkTextBuffer *buffer = gtk_text_view_get_buffer ( text );
5142
5143 if ( objc < 2 )
5144 {
5145 Tcl_WrongNumArgs ( interp, 1, objv, "command" );
5146 return TCL_ERROR;
5147 }
5148
5149 switch ( gnoclTextCommand ( text, interp, objc, objv, 1, 1 ) )
5150 {
5151 /* these are command which work upon the GtkTextView rather than the GtkTextBuffer */
5152 case 0:
5153 break; /* return TCL_OK */
5154 case 1: /* delete */
5155 //return gnoclDelete ( interp, GTK_WIDGET ( scrolled ), objc, objv );
5156 case 2: /* configure */
5157 {
5158 int ret = TCL_ERROR;
5159
5160 if ( gnoclParseAndSetOptions ( interp, objc - 1, objv + 1, textOptions, G_OBJECT ( text ) ) == TCL_OK )
5161 {
5162 //ret = configure ( interp, scrolled, text, para, textOptions );
5163 //ret = configure ( interp, scrolled, text, textOptions );
5164 }
5165
5166 gnoclClearOptions ( textOptions );
5167
5168 return ret;
5169 }
5170
5171 break;
5172 case 3: /* scrollToPosition */
5173 return scrollToPos ( text, buffer, interp, objc, objv );
5174 case 4: /* scrollToMark */
5175 return scrollToMark ( text, buffer, interp, objc, objv );
5176 case 5: /* get parent, WJG added 06/12/08 */
5177 {
5178 GtkWidget * parent;
5179 Tcl_Obj *obj = NULL;
5180 parent = gtk_widget_get_parent ( GTK_WIDGET ( data ) );
5181 obj = Tcl_NewStringObj ( gnoclGetNameFromWidget ( parent ), -1 );
5182 Tcl_SetObjResult ( interp, obj );
5183
5184 /* this function not working too well! */
5185 /* return gnoclGetParent ( interp, data ); */
5186 return TCL_OK;
5187 }
5188
5189 break;
5190 case 6: /* grab keyboard input */
5191 {
5192 gtk_widget_grab_focus ( text );
5193 return TCL_OK;
5194 }
5195 break;
5196 default:
5197 {
5198 return TCL_ERROR;
5199 }
5200 }
5201
5202 return TCL_OK;
5203 }
5204
5205
5206 /**
5207 \brief Create a fully developed text megawidget.
5208 \note ** USING ** TEXTPARAMS
5209 **/
gnoclTextCmd(ClientData data,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[])5210 int gnoclTextCmd ( ClientData data, Tcl_Interp * interp, int objc, Tcl_Obj * const objv[] )
5211 {
5212 if ( gnoclGetCmdsAndOpts ( interp, cmds, textOptions, objv, objc ) == TCL_OK )
5213 {
5214 return TCL_OK;
5215 }
5216
5217 TextParams *para;
5218
5219 int ret, k;
5220 GtkTextView *textView;
5221 GtkTextView *textBuffer;
5222 GtkScrolledWindow *scrolled;
5223
5224 para = g_new ( TextParams, 1 );
5225
5226 para->interp = interp;
5227 para->textVariable = NULL;
5228 para->onChanged = NULL;
5229 para->inSetVar = 0;
5230 para->useMarkup = FALSE;
5231
5232
5233 if ( gnoclParseOptions ( interp, objc, objv, textOptions ) != TCL_OK )
5234 {
5235 gnoclClearOptions ( textOptions );
5236 return TCL_ERROR;
5237 }
5238
5239 //textView = GTK_TEXT_VIEW ( gtk_text_view_new( ) );
5240
5241 // implement new undo/redo buffer
5242 textView = gtk_undo_view_new ( gtk_text_buffer_new ( NULL ) );
5243
5244 para->scrolled = GTK_SCROLLED_WINDOW ( gtk_scrolled_window_new ( NULL, NULL ) );
5245
5246 gtk_scrolled_window_set_policy ( para->scrolled, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
5247
5248 gtk_container_add ( GTK_CONTAINER ( para->scrolled ), GTK_WIDGET ( textView ) );
5249
5250 gtk_widget_show_all ( GTK_WIDGET ( para->scrolled ) );
5251
5252 //add some extra signals to the default setting -these have no effect!!!
5253 gtk_widget_add_events ( textView, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK );
5254
5255 ret = gnoclSetOptions ( interp, textOptions, G_OBJECT ( textView ), -1 );
5256
5257
5258 if ( ret == TCL_OK )
5259 {
5260 ret = configure ( interp, para, textOptions );
5261 }
5262
5263 gnoclClearOptions ( textOptions );
5264
5265 if ( ret != TCL_OK )
5266 {
5267 gtk_widget_destroy ( GTK_WIDGET ( para->scrolled ) );
5268 return TCL_ERROR;
5269 }
5270
5271 para->name = gnoclGetAutoWidgetId();
5272
5273 g_signal_connect ( G_OBJECT ( para->scrolled ), "destroy", G_CALLBACK ( destroyFunc ), para );
5274
5275 gnoclMemNameAndWidget ( para->name, GTK_WIDGET ( para->scrolled ) );
5276
5277 Tcl_CreateObjCommand ( interp, para->name, textFunc, para, NULL );
5278
5279 Tcl_SetObjResult ( interp, Tcl_NewStringObj ( para->name, -1 ) );
5280
5281 return TCL_OK;
5282
5283 }
5284
5285
5286 /**
5287 \brief Create a plain vanilla GtkTextView widget
5288 \todo Create modified version of the configure command
5289 **/
gnoclTextViewCmd(ClientData data,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[])5290 int gnoclTextViewCmd ( ClientData data, Tcl_Interp * interp, int objc, Tcl_Obj * const objv[] )
5291 {
5292
5293 TextParams *para;
5294
5295 int ret, k;
5296 GtkTextView *textView;
5297 GtkTextView *textBuffer;
5298
5299
5300 if ( gnoclParseOptions ( interp, objc, objv, textOptions ) != TCL_OK )
5301 {
5302 gnoclClearOptions ( textOptions );
5303 return TCL_ERROR;
5304 }
5305
5306 // implement new undo/redo buffer
5307 textView = gtk_undo_view_new ( gtk_text_buffer_new ( NULL ) );
5308
5309
5310 gtk_widget_show_all ( GTK_WIDGET ( textView ) );
5311
5312 //add some extra signals to the default setting -these have no effect!!!
5313 gtk_widget_add_events ( textView, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK );
5314
5315 ret = gnoclSetOptions ( interp, textOptions, G_OBJECT ( textView ), -1 );
5316
5317
5318 if ( ret == TCL_OK )
5319 {
5320 ret = configure_textView ( interp, textView, textOptions );
5321 }
5322
5323 gnoclClearOptions ( textOptions );
5324
5325 if ( ret != TCL_OK )
5326 {
5327 gtk_widget_destroy ( GTK_WIDGET ( textView ) );
5328 return TCL_ERROR;
5329 }
5330
5331 return gnoclRegisterWidget ( interp, textView, textViewFunc );
5332
5333 }
5334