Friday, November 11, 2011

gnocl::calendar

Had some feedback today on the gnocl::calendar. I've taken a look at the developement sources and have now wrapped my debugging/testing lines in #ifdef blocks. This means that users will not be inundated with debugging messages. There will still be cases, however, when the Gtk+ libraries write warning and error messages to the console.

The revised version is now available from SourceForge.

Thursday, October 27, 2011

gnocl::fileChooser completed support for multiple file type filters

Wanted to fix this one for some time. Basically, this allows multiple file filters to be set for the dialog. The sample script explains all.


# basic Tcl/Gnocl Script
#!/bin/sh \
exec tclsh "$0" "$@"
package require Gnocl


set ff1 [gnocl::fileFilter -name "Source Code" -pattern {*.tcl *.c} ]
set ff2 [gnocl::fileFilter -name "Text Files" -pattern {*.odt *.doc *.rtf *.abw} ]
set ff3 [gnocl::fileFilter -name "Image Files" -pattern {*.png *.jpg *.bmp *.tif} ]

gnocl::fileChooserDialog \
            -fileFilters [list $ff1 $ff2 $ff3]
            -currentFolder [pwd] \
            -title "Open Jiumoluo Project File"


15mins later....

Urgh, something always goes wrong. It looks like the destruction of the dialog window also results in the destuction of the file filters object too! I'll rework the code so that the filters are maintained as a list on the Tcl side; something along the lines of:

set filters {Filter1Name {*.A  *.B *.C} Filter2Name {*.D *.E *.F} }

15mins later....

Ok, rework the code and all now appears ok. In fact the core is much slimmer now as the code overhead for making the gnocl::fileFilter command was too much. So, the following script works. I'll upload a nightly build today.

set myFilters {Source {*.c *.tcl} Text {*.txt *.odt} Graphics {*.png *.jpg *.tif} }

gnocl::window -child [gnocl::button -text click-me -onClicked {
        gnocl::fileChooserDialog \
            -fileFilters $myFilters \
            -currentFolder [pwd] \
            -title "Open Jiumoluo Project File -1"
        }]


Thursday, October 06, 2011

gnocl::text getting tag names and properties

Just added another useful tag sub-command: properties. This command is pretty useful for obtaining the non-default property settings for text tags. For example;

foreach t [lsort [$::petxt tag names]] {
    puts "$t [$::petxt tag properties $t]"
}




Tuesday, October 04, 2011

Displaying pango strings in a gnocl::text widget.

After deciding that I'd wasted enough time looking at C coding to convert pango markup strings to text tags, I decided to script in Tcl. Got the project completed in less than an hour! Ok, there are some trade-offs, this is why the GtkText does not handle pango. It relies upon tags, and not markup strings. There is some code out there to render pango in a textview but, it will create new tags each and every time a text attribute changes. What I want to achieve is pango in and pango out. I've now got something working in Tcl which meets my needs but makes some compromises. In order to use tags, and not markup, only a limited range of settings are available. As I want the basics to change the font styling and the fg/bg colours for highlighting, I can be satisfied with a limited tag set. To make life easier, I've also named these after the pango markup. These make for some pretty unusual markup-strings, but hey - they work!

The following script reveals all.



# test-pango-text-widget.tcl

#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "$@"

package require Gnocl

#---------------
#
#---------------
proc gnocl::pango_init {w} {
   
    $w tag create <b> -fontWeight bold
    $w tag create <i> -fontStyle italic
    $w tag create <u> -underline single
    $w tag create <s> -strikethrough 1   
    $w tag create <tt> -font Courier
   
    $w tag create <span_background="cyan"> -background cyan   
    $w tag create <span_background="magenta"> -background magenta   
    $w tag create <span_background="yellow"> -background yellow
    $w tag create <span_background="grey"> -background grey
   
    $w tag create <span_foreground="red"> -foreground red   
    $w tag create <span_foreground="blue"> -foreground blue   
    $w tag create <span_foreground="black"> -foreground black
    $w tag create <span_foreground="grey"> -background grey   
}

#---------------
#
#---------------
proc gnocl::pango_parse {s w} {
   
    set textString ""
    set ::textTags ""
   
    # for each character in the string
    for {set i 0} {$i < [string length $s] } {incr i} {
           
        # get character
        set char [string index $s $i]
               
        # is it the start of a markup tag
        if { $char == "<"} {
               
            # insert any existing text
            $w insert end $textString -tags $::textTags
            set textString ""
           
            # test for span tags
            if { [string range $s 1 4 ] == "span" } {
                puts SPAN!
                # get the tag name
                set j [string first ">" $s $i]
                set tag [string range $s $i $j]
                set tag [string map [::list " " "_"] $tag]
            } else {
                # get the tag name
                set j [string first ">" $s $i]
                set tag [string range $s $i $j]
            }       
                       
            # increment counter to skip tag
            set i $j
           
            # tagON or tagOFF?
            if { [string first "/" $tag ] == -1 } {
                # tagON
                append ::textTags " " $tag
                set ::textTags [string trimleft $::textTags]
            } else {
                # tagOFF
                # check span
                if {$tag == "</span>"} {
                    ##puts spanOFF
                    ##puts 1>>>$::textTags<<<
                    set l [string first "<span" $::textTags ]
                    set m [string first ">" $::textTags $l]
                    set o [string range $::textTags $l $m]
                    ##puts 2>>>$o<<<
                    set ::textTags [string map [::list $o ""] $::textTags]
                    ##puts 3---$::textTags---
                } else {
                    # remove turned off tags from the tagList
                    set tag [string map [::list / ""] $tag]
                    set ::textTags [string map [::list $tag ""] $::textTags]
                    $w insert end $textString -tags $::textTags
                    set textString ""
                }
            }
        } else {
            append textString $char
        }
    }
    # insert any trailing text without markup
    # at this point any values remaining in the textTags list
    # will not be ballanced and so ignored
    set textTags [string map [::list " " ""] $::textTags]
    if {$textTags != ""} {
        puts "WARNING: Unbalanced tag(s) $textTags ignored.\n\n\t$s"
        }
    $w insert end $textString
}

set box [gnocl::box -orientation vertical]
set lab(1) [gnocl::label]
set txt(1) [gnocl::text]
set txt(2) [gnocl::text -baseColor #FFFEDA]
set but(1) [gnocl::button -icon %#Paste]

$but(1) configure -onClicked {
    set str(3) [$txt(2) get start end]
    $txt(1) clear
    gnocl::pango_parse $str(3) $txt(1)
    $lab(1) configure -text $str(3)
}

$box add $lab(1) -fill {1 0} -expand 1
$box add $txt(1) -fill {1 1} -expand 1
$box add $txt(2) -fill {1 1} -expand 1
$box add $but(1) -align left -expand 0 -fill {0 0}
gnocl::window -child $box -setSize 0.25

gnocl::pango_init $txt(1)





Friday, September 30, 2011

Return to coding!

Its been almost a month since a last posting. How time flies. Most of my time has been taken up between making some final adjustments to my Ph.D thesis prior to submission and chasing up a whole pile of work related matters. But now, for a while at least, I can give some more attention to Gnocl. The last issue that I was working was inserting/retrieving Pango markup strings with a GtkTextBuffer. After solving something of a glitch in adding tags to single characters (I'd completely forgotten that iters are invalid after changes to the content of text buffer. Resolved the problem through the use of markers as in function that I've just added to the code:

        GtkTextMark *tagStart, *tagEnd;
        GtkTextIter start, end;
       
        tagStart  = gtk_text_buffer_create_mark (buffer,"tagStart", iter, 1);           
                
        gtk_text_buffer_insert  (buffer, iter, txt, -1);

        tagEnd = gtk_text_buffer_get_insert(buffer);

        applyTags (buffer, tag, tagStart, tagEnd);



Where:

void applyTags (GtkTextBuffer *buffer, gchar *tag, GtkTextMark *tagStart, GtkTextMark *tagEnd) {
   
        GtkTextIter start, end;
   
        gtk_text_buffer_get_iter_at_mark(buffer,&start,tagStart);
        gtk_text_buffer_get_iter_at_mark(buffer,&end,tagEnd);
        gtk_text_buffer_apply_tag_by_name  (buffer,tag, &start,&end);
   
}


At the moment single tags are fine, ie bold but it might be necessary to nest tags, ie bold-underline. The next question is, should I pass a string of tag names, or a linked-list? I'll think about this one tomorrow!



Thursday, September 01, 2011

More on generating pango strings...

This is not so easy a 'nut to crack'. I've noticed that the solution that I've come up with so far fails to implement nested markup, ie <b> <s> text </s></b>. Conversely, getting the <span> </span> block is an issue too! Clearly there is a need for this functionality, but there is no clear solution that I can find. The Gimp developers are working on something similar but I notice that they have problems with <span> too!

So, I've gone back to basics. Rather than relying the pango string parser, I'll put something together of my own. Today I've been working on some extra string funcs. Here's what I've produced so far:

/*
gcc -o first first.c
*/

#include <stdio.h>
#include <string.h>
 
/**
    search for first occurance of p in s, starting from i
    done
**/
int strnfrst(char *s, char *p, int i)
{
        char *f;
        int l;
       
        l = strlen(p);  /* length of search string */
        f = s+i;
 
        /* search through string till match found */
        while (*f != '\0') {
                if ( !strncmp(f, p, l) ) {
                    return f-s;
                }
                f++;
        }
        return -1;
}

/**
    extract a range of characters from string s starting from position a to position b
    done
**/
char *strrng (char *dest, const char *src, int a, int b) {
  unsigned i,j;
 
  j=0;
  for (i=a; i<b; i++)
  {
    dest[j++] = src[i];
  }
  dest[j] = '\0';
  return dest;

}

/*
char *strcpy(char *dest, const char *src)
{
  unsigned i;
  for (i=0; src[i] != '\0'; ++i)
    dest[i] = src[i];
  dest[i] = '\0';
  return dest;
}
*/

/**
    gettag
    get name of next tag in string, starting at position i
**/
int getTag (char *str, char *tag, int i) {

        int a,b;
       
        a = strnfrst(str,"</",i);
       
        if (a) {
            a = strnfrst(str,"<",i);
        }
       
        b = strnfrst(str,">",a+1);

        strrng(tag,str,a,b+1);
       
        return a;
}


/**
    test
**/
int main()
{

        // p in s, starting from i
        char str1[] = "abCdefC";
       
        int i = strnfrst(str1, "C", 0);
        int j = strnfrst(str1, "C", i+1);
        printf("locations %d %d in %s\n",i,j,str1);

        char buf[32];

        /* get the characters between the Cs */
        printf("'%s' lies between chars %d and %d\n",strrng (buf,str1, i+1,j),i+1,j);

        char str2[] = "<b>bold</b>   <i>italic</i>   <u>underline</u>   <s>strikethrough</s>";

        printf("text range 3 thro' 8 = '%s'\n", strrng (buf, str2, 3, 8));

        /* get the next tag in the string */
        i= getTag (str2, buf, 3);
        printf("next tag %s at pos %d\n", buf, i);
       
        i=getTag (str2, buf, i+1);
        printf("next tag %s at pos %d\n", buf, i);

        /* parse the whole string */
        // get the position of the first tag toggle
        i = getTag (str2, buf, 0);
        printf("%d %s\n",i,buf);
       
        // parse the remainder of the string
        while ( i < strlen(str2) ) {
            i=getTag (str2, buf, i+1);
            printf("%d %s\n",i,buf);
           
        }

        return 0;

}


Sunday, August 07, 2011

gnocl::rtf

Just created a binding to the Osxcart module which provided rtf import and export for GtkTextBuffers. Its a lot of coding for what is effectively a couple of library calls! The API allows for loading from files, but it seems more appropriate to import and export strings.

#---------------
# test-rtf.tcl
#---------------
# Created by William J Giddings
# 07-August-2011
#---------------
# Description:
# Import/Export rtf formatted files from gnocl::text widgets.
#---------------

#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "$@"

package require Gnocl
package require GnoclOsxCart

set txt [gnocl::text]

gnocl::window -child $txt

gnocl::rtf register $txt

set fp1 [open "p006a_hello_world.rtf" "r"]
set fp2 [open "test.rtf" "w"]

gnocl::rtf import $txt [read $fp1]
close $fp1

puts $fp2 [gnocl::rtf export $txt]
close $fp2

json_shell_utils.tcl