Ask, and it shall be given # 8

How to post on this page

''This page has had numerous incidents of being deleted and corrupted.

Please be very careful when editing it. If you inadvertently delete it, immediately revert your edit using the History link on the left side of this page. Do NOT attempt to restore it by copying'n'pasting the text from a previous revision, or all page formatting will be lost!''

Please add hyperlinks leading to your question at the top of this page.
Also consider putting a **section heading** on the top of each new question.
And of course, please put new questions at the TOP of the page, so that as the page grows longer, new questions are seen first.

Once you have received a satisfactory answer, please put your question and answer directly on an appropriate page of the wiki (if you cannot find an existing page, create a new one).

And of course, please put new questions at the TOP of the page, so that as the page grows longer, new questions are seen first.

Afterwards, remove the original question and answer and leave a hyperlink here (as ARA has done on May 2 2009); this way everyone will know who needs help. This page could then act as a sort of reference page for questions asked by the Community - sort of Who has asked what and when. Thanks for your help.


Questions


Entry with progress bar as background

Hello,

Is it possible to create with Tcl/Tk an entry with a scrollbar as a background? One can see such a thing in e.g. Windows 7, address entry of windows explorer:

http://www.meshparts.de/pict/entry-progressbar.jpg

Thank you very much.

Best regards Alex

AMG: You may need to fabricate your own using the [canvas] widget. Put text on top of a rectangle. I warn you, it may be tough to get all the bindings right. You might also research how Ttk is implemented; there could be some clues in there.


couldn't open socket: connection refused

(Question regarding AIX that was inserted here on 2012-08-30 moved to the current Ask page, at [L1 ].)


linsert in recursive lists

Hi all,

I have written a code to get the index of recursive lists:

set a {a b {c {d e}}} 
%proc List{list_name {prefix {}}} { 
    set end_point [expr [llength $list_name] -1] 
    for {set start_point 0} {$start_point <= $end_point} {incr start_point} { 
    if {[llength [lindex $list_name $start_point]] == 1} { 
    puts "Index for [lindex $list_name $start_point] is $prefix$start_point" 
     } else { 
    append prefix $start_point 
    List[lindex $list_name $start_point] $prefix 
   } 
}

Now in this i want insert some elements inside, how can i do that. Eg: This is how the program should look like

puts "Enter element" 
gets stdin el { user enters as 4 } 
puts "Enter insert position" 
gets stdin ind { user gives as 210}

So if 210 index is valid in the list the new element should be inserted and if the user gives ind as something like 530 it should display "error in index entered".. How can i do this? Please help.

Thanks in advance

gold16jun2011, Ask9 has question on nested list input also. Maybe combine q&a? Found refs. list level, discussion in linsert and lset See section on list in http://en.wikibooks.org/wiki/Tcl_Programming/Introduction . Really asking for lset with multiple index.

 console operation
 % set test {{a b} {c d}}
 {a b} {c d}
 % lset test 1 1 x
 {a b} {c x}
 % lset test 1 1 { x gosh}
 {a b} {c { x gosh}}
  if { [ lset test 1 1 2 3 4 x ] != 1 } {
    error " index level not found"
  }
 console returns "list index out of range"

jbr - Here is a similar strange command I created just a little while ago. Maybe there should be a general discussion on commands that build data structures and need list variable semantics with multiple indices?

 proc dict-lappend { dict args } {
    upvar $dict D

    set keys  [lrange $args 0 end-1]
    set value [lindex $args end]

    if { [info exists D] && [dict exists $D {*}$keys] } {
        dict set D {*}$keys [list {*}[dict get $D {*}$keys] $value]
    } else {
        dict set D {*}$keys [list $value]
    }
 }

Shutting down a virtual machine by ssh'ing into it via Tcl/Expect

sg332 2011-012-06 I am trying to shutdown down a Virtual machine by ssh'ing into it via Tcl/Expect. At the point after I send "yes\r" using the send command in response to a confirmation request of my earlier shutdown request, sometimes I find a print out of just "y" and expect times out while waiting for the follow-on shutdown confirmation. Can someone help with a solution/workaround asap? I assume, send was not able to flush out the remaining characters for some reason to the Linux box. The Tcl/Expect script is on a Linux machine.

RLE (2011-02-06) Are you ssh'ing into another Linux based system? If so, any reason you can not just use "shutdown -h now" to shutdown immediately without asking any confirmation?

sg332 (2011-02-07) Thanks for replying. Good question. The reason is I want to gracefully shutdown the box, which means applications on that remote machine should shutdown gracefully before the OS starts shutting down. A OS platform command that I am using allows me to do so. But for that, I have to ssh into the platform using platform credentials.


Finding a way to have the 'alt' (and 'default') Ttk themes ttk::checkbox display their indeterminate state when the widget variable is undefined

peterc 2011-01-25 I'm trying to find a way to have the 'alt' (and 'default') Ttk themes ttk::checkbox display their indeterminate state when the widget variable is undefined. It works on Windows but not in these themes. It seems that the indeterminate state image has either never been set or has been set to the same image as "off".

I'm hoping the fix is something I can put at the start of my own scripts (after package require Ttk), rather than being an edit in Ttk's source, so I don't have to update Ttk's source every time I update Ttk. I'm happy to run up my own indeterminate state images, assuming that's part of the solution.


Difference in the types of objects returned with 'array get' when moving from 8.4 to 8.5

JonC Jan-21-2011 In moving from 8.4 to 8.5 we see a difference in the types of objects returned with 'array get. The otype command returns the typePtr->name from the object (based on the Islist c code from the wiki).

array set arr [list a 1 b 2 c [list 3] d [list 4 5]]
puts "from array"
foreach a [array names arr] { puts "[otype $arr($a)] $arr($a)" }
puts "from get"
foreach a [array get arr] { puts "[otype $a] $a" }

In 8.4.9 the values in the array retrieved with 'array get' are still lists.

% load otype.so
%  source check_array.tcl
from array
list 4 5
none 1
none 2
list 3
from get
none d
list 4 5
none a
none 1
none b
none 2
none c
list 3
% 

In 8.5.1 they turn into strings when using 'array get'.

% load otype.so
%  source check_array.tcl
from array
list 4 5
none 1
none 2
list 3
from get
none d
none 4 5
none a
none 1
none b
none 2
none c
none 3

Why does this happen? In our actual application we have other object types some of which may be expensive to construct.


EDIT: It didn't timestamp my edit, so I'll add it below manually.


Question regarding lappend's adding the bounding braces to each list element

2011-12-01 LtDrebin I have a simple question regarding lappend. In the following script:

set c varia[34]ble
set p [list]
set pins "YC YE"
foreach pin $pins {
   lappend p $c/$pin
}

an echo $p will display the following: {varia[34]ble/YC} {varia[34]ble/YE}. Why is lappend adding the bounding braces to each list element? I want the output to be: varia[34]ble/YC varia[34]ble/YE

The variable c has brackets around the 34. It is being interpreted as an image link here.

I have also tried setting each new element to variable p as a separate variable and then appending just that variable, but I get the same result.

I have a workaround to this using concat, but I'm curious as to why lappend is behaving this way. It seems that the brackets in the variable c are causing this. If c only has a slash in it, for instance, it seems to work correctly.

My workaround, fyi:

set c varia[34]ble
set p [list]
set pins "YC YE"
foreach pin $pins {
   set p [concat p $c/$pin]
}

MG Is that exactly the script you're using? For me that results in an 'invalid command name "34"' error in the 'set c ..' statement. But, ignoring that (and assuming you're actually escaping them there, with

  set c {varia[34]ble}
  set c varia\[34\]ble

or something similar), lappend isn't really adding curly braces - they're simply displayed in the string representation of the list.

  % set c {varia[34]ble}
  varia[34]ble
  % set p [list]
  % set pins "YC YE"
  YC YE
  % foreach pin $pins {
    lappend p $c/$pin
    }
  % set p
  {varia[34]ble/YC} {varia[34]ble/YE}
  % lindex $p 0
  varia[34]ble/YC
  % join $p " "
  varia[34]ble/YC varia[34]ble/YE

Using join creates a "true" string from the list, which doesn't include the curly braces (which are used only to denote/escape the individual list elements, as they contain special characters).

{gwm} also "lindex $p 0" and "lindex $p 1" return the 'true' elements of the list without the {}; any operation (such as foreach part $p {...}) which uses the list will then use the form you expected for each element of the list.

{LtDrebin} I'm running these scripts inside of a microchip development tool. It uses tcl for user-level scripting. I have tried both escaping the brackets and not, and setting the varaible works just fine. I'm guessing that our tcl shell has some sort of protection for brackets, as many of the instances in a microchip have all sorts of symbols used in their names.

It's probably more efficient to use lappend, then? I might have to use the entire list p as an argument in a later function. In that case, it will still keep the bounding braces. The function can handle that (I think), but it's not what I intended and I'm a perfectionist, dammit!

When I use the command set c varia34ble, the console of my tool gives the message: 's in strings are used to invoke sub-functions, escape 's or use {}'s to define the string. I understand that, but running echo $c shows that c was set correctly.

In my script, c will be set by a foreach statement, where c is an individual element of a list of all sorts of c's. The only way I can see to "properly" set c using {}'s would be to scrap the foreach and just iterate through the list of c's.

{LtDrebin} I'm running into more problems with lappend adding extra braces to list elements. My script has a lot of nested loops and so I'm a bit concerned about runtime. I read that using lappend is more efficient than using concat to append elements to a list. If I use concat via the workaround above, the list does not contain extra braces (well, so far...). So, I have a few options on how to remove these braces for future operations.

1) Use the [concat\] workaround. 2) After lappending everthing, use [join $list\] to convert it to a string with spaces in between. This seems to remove the extra braces and retains the list elements. 3) Whenever I need to call an element of the list, use [lindex\] or [lrange\] (haven't tested lrange yet).

As for the reason why lappend is adding the extra braces, I think it's because the tcl parser is using braces in strings with brackets to keep the parser from substituting results of the bracket phrase, which might be seen as a command.

gwm You might also like to experiment with append - this is like lappend, it adds at the end of the string, but is pure string. To retain the 'list-like' behaviour you need to put 'append p " new[34\]bit", like this:

foreach pin $pins {
    append p " $c/$pin"
}
puts $p

Major memory leak bug in TclOO

2011-02-01 gwm memory leak bug in TclOO (cured by 12 Feb 2011). I have created the following minimal demo of TclOO which creates one object, then uses its only method 6 million times.

 console show ; update
 # make it an O-O program using oo::
 package require TclOO 

 oo::class create cell {
    # a general cell.
    method setcp1 {vv} {my variable cp1;set cp1 $vv}
 }

 set a [cell new] ;# create just one object!

 set i 0;while {$i<6000000} {
    incr i;
    if {!($i%25000)} {puts "Looped $i times";update}
    $a setcp1 123
 }

 # NB $a destroy did not free the memory

After 6 million operations using Activestate's 8.6.0.0.b4 I had gobbled about 400MB (by just ONE TclOO object). Memory was still gobbled if you remove the "my" variable

    method setcp1 {vv} { variable cp1;set cp1 $vv}

But it was not gobbled if no variable was declared.

    method setcp1 {vv} { set cp1 $vv}

MS just ran this on HEAD/linux and does not see anything untoward

GWM DKF reported to me privately this bug is cured; the 8.6.0.0.b4 (beta release) for Windows from Activestate gave this effect. I can report 'fully cured and distributed' on this question with 8.6.0.0.b5. The resulting code runs faster too, not surprising as wish doesn't have to keep on finding blocks of memory.


How to call one's own methods in TclOO

2010-12-02 jbr How to call ones own methods in TclOO?

I don't do a lot of OO programming but I've tried snit and tcl oo on occasion. Today my question is, What best for calling a TclOO method from another method of the same object?

  1. my some_method arg1 arg2 ...
  2. [self] some_method arg1 arg2 ...
  3. some_method arg1 arg2

Option #3 doesn't appear to work, I guess namespace command path nesting isn't working as I thought it might?

??

Thanks

gwm Correct, option 3 deliberately does not work. 1 & 2 are equivalent although I would suggest using 1 so that any modification in a future release of TclOO affecting the 'my' operation would be implemented into your code.

Method 3 is more like how C++ would be coded; use of 'my' ensures that any overridden method of the base class is called by methods in the base class which call the (overridden) method.


How to http "GET" without using http package ?

<Start of New Question> Kirov How to http "GET" without using http package ?

fconfigure manual page says : "Upon output (i.e., with puts), the I/O system translates newlines to the external end-of-line representation."

This doesn't work :

proc down {args} {
        # splitting first arg into usefull components
        set srv [lindex [split [lindex $args 0] /] 2]
        set tar [join [lrange [split [lindex $args 0] /] 3 end] /]
        # connecting socket
        set s [socket $srv 80]
        # requesting target url via http protocol
        puts $s "GET /$tar HTTP/1.0"; flush $s
        puts $s "Host: $srv\n\n"; flush $s
        # check if active socket
        while {[gets $s in] != -1} {
                # data handling
                puts $in
        }
        close $s
}
down https://www.tcl-lang.org/man/tcl8.5/TclCmd/fconfigure.htm

But this works just fine :

proc down {args} {
        # splitting first arg into usefull components
        set srv [lindex [split [lindex $args 0] /] 2]
        set tar [join [lrange [split [lindex $args 0] /] 3 end] /]
        # connecting socket
        set s [socket $srv 80]
        # requesting target url via http protocol
        puts $s "GET /$tar HTTP/1.0"; flush $s
        puts $s "Host: $srv"; flush $s
        puts $s ""; flush $s
        # check if active socket
        while {[gets $s in] != -1} {
                # data handling
                puts $in
        }
        close $s
}
down https://www.tcl-lang.org/man/tcl8.5/TclCmd/fconfigure.htm

My question is : Why ? <End of Question>

<Answer>

2011-11-20 AMW The two versions do NOT send identical requests!

Version 1 sends two empty lines (three newlines) after the last HTTP header line ("Host:"...): two newlines generated by "\n\n", a third being added by the puts command when called without -nonewline.

Version 2 correctly sends just one empty line.

Version 1 could be fixed in either of the following ways:

puts -nonewline $s "Host: $srv\n\n"
puts $s "Host: $srv\n"

By the way: a single call to flush $s after sending the last byte would suffice, and will enhancen performance on connections with poor bandwith.


Too many initializer's errors in MS VS 2005; while writing a Tcl extension for C++)

<Start of New Question> To Many Initiallizers error in MS VS 2005 Hello everyone, I am trying to write a Tcl extension for C++. Below is my code.

int DLLEXPORT LitePoint_Init(Tcl_Interp *interp) {

   if (Tcl_InitStubs(interp,TCL_VERSION,0)==NULL) {  
          return TCL_ERROR;
        }
   if (Tcl_PkgProvide(interp, "Hello", "1.0") == TCL_ERROR) {
         return TCL_ERROR;
     }

   Tcl_Command Tcl_CreateObjCommand(interp, "connect", ConnectSystem , NULL, NULL);
   return TCL_OK;

}

Below is the ConnectSystem proc.

static int ConnectSystem(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj * const objv) {

        int LP_InitTester(char *ipAddress);
        return TCL_OK;

}

ConnectSystem is calling another function LP_InitTester(). I am using MS VC++ 2005. When i try to build it, it's giving me " Too many initiallizers " pointing at Tcl_Command Tcl_CreateObjCommand(). How do i resolve this.

Thanks <End of Question> <Answer> Tcl_CreateObjCommand(interp, "connect", ConnectSystem , NULL, NULL);

does not require the type of its return argument (Tcl_Command) to be declared too. Compiler gets that from the tcl.h file. just omit Tcl_Command from your code.


Increasing the number of elements in a graph option

KESHAV - 2010-08-19 00:37:40: HI, I am using a graph command from BLT/TK. The -xdata and -ydata options takes only 349524 elements. Is there any way to increase it? Or any settings to overcome this limitation? Please help

 [gold] 2010-10-11, found ref. 
  http://www.usenix.org/events/tcl98/tcl98/full_papers/howlett/howlett_html/howlett.html

Problem with the thrashcan object for canvas on Canvas Object Movement

gold 2Aug2010: I loaded a thrashcan object for canvas on Canvas Object Movement Example, Canvas Object Movement Example. This trashcan is sticking a little,eg sometimes the object does not disappear over the X on the first move or entry. Can somebody fix this item? Thanks. The deep patch appears to be:

       if { $y >= 20 && $y <= 70 }
       { if { $x >= 20 && $x <= 70 }
       {$w delete obj_$tilex } } #maybe should [lindex obj_$tilex 1 ]etc ?

Drawing a new series or new dataplot using Tklib Plotchart

JULY - 2010-07-30

Question: Hi, I am using TKlib Plotchart. Once I have drawn a plot, say an xyplot, I want to clear it and draw a new series or new dataplot. I am unable to find any command to clear the plots and draw a new one. I tried using the destroy command, but it doesn't work.

I don't want to destroy the whole canvas to plot all over again. Any suggestions/comments are appreciated!


gold Possible to 1)raise or lower the previous work on the canvas, 2)raise a covering object (white rectangle) or 3)write on top? I installed a raise or lower button in Chinese Xianqi Chessboard. grid is a tag on created objects in canvas.

        .cv itemconfigure grid -fill blue 
        if { $state2 == 1 } { .cv raise grid ;} 
        if { $state2 == 2 } { .cv lower grid ;} 

and Simple Canvas Demo Also, look at my gold perambulations with $c addtag point withtag $item & $w addtag selected withtag current on Ask, and it shall be given # 7. If you can add a tag to current and selected plot_1 like $w addtag plot_1 withtag current, you can raise or lower plot_1 with .c raise plot_1 or .c lower plot_1.(or .c lower all?)


Low volume level for a 24 bit wave file using snack

Sergey, 10 july 2010

I have a problem with snack, which i can't find solution for.

If i open a 24 bit wave file using snack and try to save it, resulting wave file has extremely low volume level, but if file is 16 or 32 bit, everything goes fine. Same thing happens in wavesurfer, so it's likely to be snack bug.

Does anyone know about this bug? Is there any workaround? Thanks in advance.


Making a tk image from a tk widget

ARR - 2010-06-30

Question 1: Hello specialists, how can I make a tk image from a tk widget?

Answer 1: use the image command: image create photo widget_image -format window -data $widget

Question 2: This is fine, but the widget must be fully visible. So, how can I make an image from a withdrawn widget? Any ideas anybody?

Answer 2: ???


Errors with tests for enable threads

rhinerfeld - 2009-09-02 18:56:28

I have just downloaded the TK8.5.7 build. I am using Linux Fedora Core 10 as an OS. I configure for --enable-threads and then make test. I receive a number of errors from the tests that are run.

 Tests ended at Wed Sep 02 18:45:24 EDT 2009
 all.tcl:        Total        8788        Passed        7776        Skipped        945        Failed        67
 Sourced 87 Test Files.
 Files with failing tests: canvText.test entry.test filebox.test font.test scrollbar.test spinbox.test text.test textDisp.test textImage.test textTag.test textWind.test unixEmbed.test unixFont.test unixSelect.test unixWm.test wm.test
 Number of tests skipped for each constraint:
        12        altDisplay
        1        aqua
        16        colorsFree
        3        colorsLeftover
        21        defaultPseudocolor8
        10        emptyTest
        139        fonts
        1        havePseudocolorVisual
        6        knownBug
        1        memory
        103        nonPortable
        33        nt
        5        pseudocolor8
        72        secureserver
        11        testmetrics
        7        testwinevent
        141        textfonts
        1        unthreaded
        1        userInteraction
        310        win
        51        winSend

Is this normal?


Errors in a Hello world code (attempting to make an IDE in C)

arin - 2010-06-09 02:10:43

hi, i am working on an ubuntu system. My aim is to basically make an IDE in C language using GUI tools from TCL/TK. I installed tcl 8.4, tk8.4, tcl8.4-dev, tk8.4-dev and have the tk.h and tcl.h headers file in my system. But, when I am running a basic hello world program it's showing a hell lot of errors.

 #include "tk.h"
 #include "stdio.h"
 void hello() {
      puts("Hello C++/Tk!");
 }
 int main(int, char *argv[])
 {     init(argv[0]);
      button(".b") -text("Say Hello") -command(hello);
      pack(".b") -padx(20) -pady(6);
 }

Some of the errors are

 tkDecls.h:644: error: expected declaration specifiers before ‘EXTERN’

 /usr/include/libio.h:488: error: expected ‘)’ before ‘*’ token

 In file included from tk.h:1559,
                  from new1.c:1:
 tkDecls.h:1196: error: storage class specified for parameter ‘TkStubs’
 tkDecls.h:1201: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘*’ token

 /usr/include/stdio.h:145: error: storage class specified for parameter ‘stdin’

 tk.h:1273: error: declaration for parameter ‘Tk_PhotoHandle’ but no such parameter

Can anyone please tell me how can I rectify these errors? Please help...

AM A better place to ask such questions is comp.lang.tcl


Getting rid of a console window

for a game listed at the bottom of Mahjong Style Deletion page 99

gold 5jun2010. I have some starter code for a game listed at the bottom of Mahjong Style Deletion page.

when i drop the cheap_poker.tcl into etcl, i get a console window that i don't want. I have a statement for console hide but doesn't seem to work. How do i get rid of console window? thanks,gold

AMG: [console hide] works just fine for me. I don't know what your problem could be. I'm not familiar with eTcl; maybe it's been customized somehow.

By the way, do you realize your last edit deleted this page? Please be more careful in the future!

gold Problem gone. I'll close out this question. Have rewritten code leaving out some upvar and canvas name substitutions. Problem gone.

     rewritten code left at [Mahjong_Style_Deletion]

Running "cd" , "source <_script_>" etc. commands using a GUI running all shell command

raja May 11 2010: Hi, I have created one simple GUI application using Tcl with one "entry" widget and "Run" button.My intention is to use this GUI to run all shell commands (like "cd" and other commands(I will enter command using "entry" widget and click on "Run" button to execute). i am able to run few commands like "ls","date", "cat" etc.. but I couldn't run "cd" , "source <_script_>" etc. commands. Could some one please help me in this?

Thanks for your time.

LV cd is not a normal command. It has to take action on the current process, but programs like you describe typically invoke exec or an opened pipe to execute commands in a second process. This means that things work something like this:

Process A: User logged into system
Process B: User's tk program
Process C: User types in "cd /tmp" and tk program invokes "exec cd /tmp"

When Process C completes, it goes away, and user is back in Process B.

The way to handle this is to add some code in your program that looks at the string before executing it. If the string begins with "cd ", then don't use exec, but call cd with the rest of the line as an argument.

That should take care of this problem. Depending on what platform and shell you are using, there are probably some additional commands you will end up having to add special code for as well.

RAJA May 12 2010: Thank you very much for your response. i have tried your suggestion but still i am getting error like "couldn't execute "cd": permission denied [for setenv commands I am getting " couldn't execute "setenv": no such file or directory " error]. I believe only shell built-in command i am getting errors. All other commands (ls , date , pwd etc..) are working fine.

here is my "Run" procedure.

 button .top.quit -text Quit -command exit  ; 
 set but [button .top.run -text "Run it" -command Run] ;
 pack .top.quit .top.run -side right  ; 

 label .top.l -text Command: -padx 0  ; 
 entry .top.cmd -width 20 -relief sunken -textvariable command  ;
 proc Run {} {
         global command input log but
         if [catch {open "|$command |& cat"} input] {
                 $log insert end $input\n
         } else {
                 fileevent $input readable Log
                 $log insert end $command\n
                 $but config -text Stop -command Stop
         }
 }

I have added all other required things into my application. "log" in the above code is text widget to log the output.

I have added another if statement in the above "Run" procedure to tackle "cd" command but didnt work. Please help me in this issue.

My hardware config is : Linux 2.6.9-67.ELlargesmp x86_64 x86_64 x86_64 GNU/Linux (from "uname" command)

AMG: cd isn't the only command that modifies the shell's internal state; setenv is another. Both are shell built-in commands, which means they aren't actual executable files on disk. (Unless you're using execline.)

One approach is to create a single instance of the shell and feed it a sequence of command lines, rather than start a new shell for each command. The shell can internally decide whether the command line is a program on disk or a built-in, and it can remember all its state changes. At this point you will have reimplemented xterm, at a very basic level.

Another approach is to handle cd and all other built-in commands yourself (like LV suggests), and only [exec] or [open |] external programs. At this point you will have reimplemented the shell. If you go this route, you will have to decide what set of built-ins you want and what their syntax should be. If your built-in commands are equal to or a superset of the Tcl commands, you will basically be reimplementing Tkcon, which already falls back on external programs when the Tcl interpreter can't internally handle a command.

raja May 12 2010: Thank you AMG. so in short, I have 2 options one is to implement/create xterm or create/handle built-in commands on my own using Tkcon.I am just beginner in Tcl. so i didn't have a idea of Tkcon. Can we just modify below code to handle shell build-in commands. BTM how can we create a new shell using this GUI/Tcl code (i.e using buttons and entry and Run procedure). I would appreciate your help.

 proc Run {} {
         global command input log but
         if [catch {open "|$command |& cat"} input] {
                 $log insert end $input\n
         } else {
                 fileevent $input readable Log
                 $log insert end $command\n
                 $but config -text Stop -command Stop
         }
 }

Thank you.

LV Sorry, but that proc is not easily modified to do what you want.

raja May 14 2010: i tried below code to get my application working.But it didnt. Now i have to create a single instance of the shell and feed it a sequence of commands in tcl.right now i dont have any clue how to create this but i will try.

if { [string first "cd" [string tolower $getcommand]] != -1 } {
               if [catch {exec "$getcommand |& cat"} input] {
                set pwd [pwd]
                   cd $pwd         #as a example cd to pwd   #cd is a tcl built in command
         }

or

if { [string first "cd" [string tolower $getcommand]] != -1 } {
                       set pwd [pwd]
                   cd $pwd  #cd is a tcl built in command
                #exec "cd $pwd"
         }

AMG: That's not how comments work. Unless # is the first character of a command, it has no special meaning. Either put it on a line by itself, or put a semicolon (;) before it, as in "cd $pwd ;# cd is a tcl built in command".

To create a single instance of the shell, use [open |], like you did in your first code sample, but the command you open is the shell. The shell will execute commands it receives on stdin, and it will direct the output of the commands to stdout. I assume you're using csh because you mentioned setenv.

Here's code!

(Code moved to: a way to 'pipe' from an external process into a text widget)

If I understand what you're asking for, the above code does what you want, and we should move this discussion to its own Wiki page.

Unfortunately, this code only handles the shell's stdin and stdout; it ignores stderr. I haven't figured out how to effectively and portably handle stderr. Right now the only thing I can think of is to use exec to run mknod [L2 ] to make a FIFO, open the FIFO for reading, monitor it in the same way $chan is monitored, and redirect the shell's stderr to that FIFO using 2> notation. I'd like to do this all in pure-Tcl with reflected channels, but this is not possible at the moment.

raja 17-05-10 Thank you very much AMG.It is working fine now. The only problem I am seeing now is when I source any file(file with multiple commands) it is not working properly but when I execute commands one by one then it is working fine. Some times it is showing "ctrl-m" characters (after and before filename) while i am executing "ls" command.

AMG: Sounds like a DOS/Unix line ending problem. Are you using a Windows text editor to create files you're reading on Unix? Check if there are ctrl-m (carriage return) characters in the file you're sourcing. I assume you're asking csh to do the sourcing, not Tcl.

Here's a version of the code that separately handles stdout and stderr. It turns out this is possible in pure-Tcl, if you have Tcl 8.6. For fun, I threw in some apply magic to demonstrate how to make fileevent and anonymous lambdas instead of named procs. Also I switched to the Ttk widgets and the chan ensemble commands, and I added end-of-file detection.

(Code moved to: a way to 'pipe' from an external process into a text widget)


Expect question (Re: Automating the login to a remote machine)

pcam - 2010-04-27 08:30:00

I am trying to automate as much as possible the login to a remote machine. From my Solaris box I manually I am doing the following:

  1. In a teminal establish a SSH tunnel ssh -l <username> -L 5988:localhost:5901 <ip_address>
  2. In ANOTHER terminal launch vncviewer :5988
  3. Login from the vnc GUI login prompt (a step not required to be scripted/automatic)

I can do both bits independently, but cannot manage with one expect session.

I thought about using fork

but I am unsure and suspect this is not the best way to go about that. Any ideas or pointers ?


Cross-compiling Tcl on arm-linux

Smarak - 2010-04-23 04:44:40

Hi I am using ubuntu 8.04. I have a arm-linux installed on to this ubuntu. My gumstix supports arm-angstrom-linux-gnueabi-gcc. Now my problem is I want to cross compile tcl on arm-linux. But I am confused with configure,make and make install. My overo-oe is in the folder named gumstix and tcl84.19-src.tar extracted in another folder named DTN2. Now i don't know how to use the below commands

'''''PATH= $PATH:/usr/local/arm/oe/bin'''''

'''''export CROSS_COMPILE=arm-linux'''''
'''''export CC=arm-linux-gcc'''''

export tcl_cv_type'''bold text'''_64bit="long long"
export ac_cv_c_bigendian=no
export tcl_cv_strtod_buggy=1
export ac_cv_func_strstr=yes
export ac_cv_func_opendir=yes
export ac_cv_func_strtod=yes
export tcl_cv_strtod_buggy=1

./configure ../.. \
            '''''--host=arm \'''''
            '''''--prefix=/home/zhepeng/Desktop/tcl-for-arm \'''''
            '''''--with-tcl=/home/zhepeng/Desktop/tcl-for-arm/lib/tcl8.4 \'''''
            '''''--host=arm-linux \'''''
            '''''--build=i386-pc-linux \'''''
            --with-endianness=little \
            '''''--with-cc=arm-linux-gcc \'''''
            '''''--with-ar=arm-linux-ar \'''''
            '''''--with-install-prefix=../'''''.. \
            --with-cflags="-O2" 

export tcl_cv_type_64bit="long long"
export ac_cv_c_bigendian=no
export tcl_cv_strtod_buggy=1
export ac_cv_func_strstr=yes
export ac_cv_func_opendir=yes
export ac_cv_func_strtod=yes
export tcl_cv_strtod_buggy=1

./configure ../.. \
            '''''--host=arm \'''''
            '''''--prefix=/home/zhepeng/Desktop/tcl-for-arm \'''''
            '''''--with-tcl=/home/zhepeng/Desktop/tcl-for-arm/lib/tcl8.4 \'''''
            '''''--host=arm-linux \'''''
            --build=i386-pc-linux \
            --with-endianness=little \
            '''''--with-cc=arm-linux-gcc \'''''
            '''''--with-ar=arm-linux-ar \'''''
            '''''--with-install-prefix=../..''''' \
            --with-cflags="-O2" 

Pls help!!! thanks in advance

Steve Bennett I'm not sure what you have planned for Tcl, but you might want to check out Jim. It is very compatible with Tcl, smaller and easy to cross compile.

 $  ./configure --host=arm-linux
  ...
 checking extension aio... enabled (default)
 checking extension array... enabled (default)
 checking extension bio... not enabled
 checking extension clock... enabled (default)
 checking extension eventloop... enabled (default)
 checking extension exec... enabled (default)
 checking extension file... enabled (default)
 checking extension glob... enabled (default)
 checking extension load... enabled (default)
 checking extension nvp... not enabled
 checking extension package... enabled (default)
 checking extension posix... enabled (default)
 checking extension readdir... enabled (default)
 checking extension regexp... enabled (default)
 checking extension signal... enabled (default)
 checking extension stdlib... enabled (default)
 checking extension syslog... enabled (default)
 checking extension tclcompat... enabled (default)
 checking extension tree... not enabled
 Jim extensions: aio array clock eventloop exec file glob load package posix readdir regexp signal stdlib syslog tclcompat
 configure: creating ./config.status
 config.status: creating Makefile
 config.status: creating jimautoconfext.h
 config.status: creating jimautoconf.h
 $ make && make DESTDIR=/tmp/installdir install

RFC5322 compliant mails with tcllib mime package; Tcllib reveice emails

Linkel Stephan - 2010-04-08 05:38:28

moved the question/answer to page RFC5322 compliant mails with tcllib mime package. Please have a look there. Thx


Tcl and memory mapped files question

plap 2010.03.12

Is it possible to communicate with a Windows application via a "memory mapped file" (commands such as CreateFileMapping()) ? I see that mmap is sort of available but it doesn't seem to be the same thing. Any ideas?


Coroutine names in the info procs list?

jbr, May 5 2010: Coroutine names don't appear in the info procs list?

AMG: See coroutine for the answer.


Dont brace your expressions

GeoffM: Problem with braced expressions. Brace your expressions recommends always bracing your expressions. Here is a counter example where I wish to evaluate an expression created as a string.

  proc sqr {a} {return [expr {sqrt($a)}]}
  proc tn {a} { return "2*tan([sqr $a])"}

Then the command "sqr 8" and "expr {[sqr 8]}" returns: 2.8284271247461903. And 'tn 2' returns "2*tan(1.4142135623730951)"

However:

  expr [tn 2] returns: 12.668238334084391
  expr {[tn 2]} returns: 2*tan(1.4142135623730951)

Don't brace your expr-essions?

Lars H: Why didn't you simply

  proc tn {a} { return [expr {2*tan([sqr $a])}]}

? Then [tn 2] will return the wanted result, with no need for a surrounding expr.

But in general: Yes, if you're constructing expressions dynamically, then you do want ordinary substitution to take place in the argument of the expr command, and therefore cannot brace it. (expr is just like eval in this respect.) The price for doing so is speed, since each dynamic reconstruction of such an expression must be parsed anew. In your "expr [tn 2]" example, this happens every time it is used, and there is furthermore shimmering going on since the 1.4142135623730951 is (under the hood) first converted double->string, then pasted into a larger string, cut out from that string by the expr parser, and finally converted back string->double by tan. Lots of unnecessary work, so you'd be better off bracing your expr-esssions.

GeoffM: Actually my proc is a little more complex than my example. Proc tn defines a formula; but if some constants of the formula are not defined (there are values other than the argument "a" used in evaluation the result is an algebraic manipulation of the best values so far) then tn returns the formula with as many variables substituted as possible. Finally if the result can become a number I expr it; if this fails then I retain the formula for printing/debugging. It should however be possible for each component of the formula tn to be 'expr'd before returning its value. However I will need to do the expr finally to evaluate all the terms in the formula.

Is there a test for 'would this value (string) evaluate to a numerical value'? I have used

  if {[catch {return [expr [tn 2]]}]} {return [tn 2]}

but I think the catch has significant overhead.

Lars H: That's pretty much it, but the return in there will make your test misbehave, since

  catch {return something}

always has the value 2 (catch catches return too). You're probably looking for

  set formula [tn 2]
  if {[catch {expr $formula} val]} then {return $formula} else {return $val}

Whether this (relying on that the string representation of a number is also a valid expression, which takes on the same value) is Good Style is another matter. Programming-wise, you might be better off using a lambda or command prefix than a dynamically generated expression.


Event loop in tclsh

ero - 2010.02.26: event loop in tclsh

The following test code works correclty using Tk (wish):

 proc pp {} {
  global x
  puts $x
  if {$x > 10000} {return}
  incr x
  after 10 [list pp]
 }
 #
 set ::x 1
 pp

To use the same proc in Tcl (tclsh) I added the vwait command (to trigger the event loop):

 proc pp {} {
  global x
  puts $x
  if {$x > 10000} {return}
  incr x
  after 10 [list pp]
  vwait x
 }

but after 500 dummy lines I got:

error in background error handler: too many nested evaluations (infinite loop?) while executing "::tcl::Bgerror {too many nested evaluations (infinite loop?)} {-code 1 -level 0 -errorcode NONE -errorinfo {too many nested evaluations (infinite loop..."

Why this happens? How start the event loop correctly in tclsh? Thanks.

Lars H: Don't call vwait inside pp, but instead once after, like so:

 proc pp {} {
  global x
  puts $x
  if {$x > 10000} {set ::done 1; return}
  incr x
  after 10 [list pp]
 }
 #
 set ::x 1
 pp
 vwait ::done

This is what most closely corresponds to the Wish case, since there your script is being run from within a surrounding event loop.


Problem running a starpack'd app on Fedora

MG A friend trying to run a starpack'd app on Fedora has run into an issue: using the 8.5.8 Tclkit from the Google Code site , he gets an error "error while loading shared libraries: libstdc++.so.5: cannot open shared object file: No such file or directory.". According to Fedora's Add/Remove Software dialog, libstdc++ is installed/available. The 8.5.2 Tclkit (from equi4.com ), which is the last build version I used for my app, works fine. Does anyone have any ideas/fixes that might help?


How can I stop my TCL app from taking focus

and moving to the top (over TPlayer) if it is clicked?**

Beware: Here's a strange one, hopefully with an easy answer... I want to write an app that is a full black screen. It then loads another (already compiled) app (called TPlayer - google is your friend). The reason is I don't want to see my desktop while using TPlayer (looks more professional at a gig, as Tplayer is a DJ app). All easy enough so far, but how can I stop my TCL app from taking focus and moving to the top (over TPlayer) if it is clicked? (Tplayer has very few options). Secondly, how can I link the two apps so if the user closes TPlayer, the TCL closes, and vice-versa?

Any hints/tips much appreciated.

PS. Windows XP. I'd rather not use extensions if possible, as I like a nice easy freewrap compile :)

Beware(the next day): Using a program called PowerMenu, I can make TPlayer always on top. This works well, but is there a TCL solution?

MG I'm not aware of any Pure-Tcl one. While you can easily position . to fill the screen and then use 'exec $app ; exit' to launch the app (the exec call won't return until your app closes, then running the exit), the . window will still take focus on click, and appear to Windows to have hung. There might be an extension that would let you easily embed another app into a Tk window, though?

Duoas There isn't any simple way to do this without extensions. You can get kind of close, though, with standard Tcl/Tk by configuring your main window as "disabled" and using the XP Pro utility "tasklist" to watch for when TPlayer closes. If you don't have XP Pro, you'll have to get a copy of tasklist.exe from online.

Keep in mind that this is a very simple solution -- but it satisfies your requirements. You can still switch things around with Alt-Tab and other stuff, so if anything goes wrong just Alt-Tab back to your application.

Also remember that tasklist is another application that gets loaded and unloaded each time it is used. That is a lot of overhead just to watch a child. You would be better off using an extension like Ffidl to track the child's status.

Here's what I wrote:

 # dj.tcl
 # 2009 Michael Thomas Greer
 # Released to the Public Domain

 #-----------------------------------------------------------------------------
 # Modify these to the appropriate values.
 # 
 # COMMAND is the full path and any command arguments to the program to run.
 # IMAGE   is the x,y position and name of the image to display in the
 #         background. You can give an empty list if you desire no image to
 #         display.
 #         The x value may be a pixel coordinate (as in "100"), a percentage
 #         (as in "20%"), the value "left", or the value "right".
 #         The y value may also be a pixel coordinate, a percentage, or the
 #         values "top" or "bottom".
 #         Remember, the image file must be a BMP or a GIF.
 # TIMEOUT The number of milliseconds to wait before checking to see if the
 #         COMMAND has terminated yet or not.
 #
 set COMMAND {Notepad.exe dj.tcl}
 set IMAGE   [list right 50% C:/WINDOWS/system32/ntimage.gif]
 set TIMEOUT 500

 #-----------------------------------------------------------------------------
 # The following is the main program
 #
 package require Tcl 8.5
 package require Tk  8.5

 proc position {value dimension image} {
    set d [expr {[winfo screen$dimension .] - [image $dimension $image]}]
    switch -glob -nocase -- $value {
      *%      { return [expr {$d * [string range $value 0 end-1] / 100}] }
      c*      { return [expr {$d / 2}] }
      l* - t* { return 0 }
      r* - b* { return $d }
      default { return $value }
    }
 }

 proc initialize_gui {} {

    . configure -background black -bd 0 -highlightthickness 0

    wm attributes . -fullscreen true
    wm title      . {DJ Background}

    lassign $::IMAGE x y imagefile
    if {$imagefile ne {}} {
        set image [image create photo -file $imagefile]
        set x [position $x width  $image]
        set y [position $y height $image]

        label .image -image [image create photo -file $imagefile] -bd 0 -highlightthickness 0
        place .image -x $x -y $y
    }

    update

    wm attributes . -disabled true
 }

 proc check pid {
    set tasklist [open "| tasklist /fi \"pid eq $pid\""]
    set data [read $tasklist]
    if {[catch {close $tasklist} err]} \
      then { exit } \
      else { after $::TIMEOUT check $pid }
 }

 proc main {} {

    initialize_gui

    if {[catch {open "| $::COMMAND"} pipe]} {
        tk_messageBox -message "Could not execute: $::COMMAND"
        exit 1
    }
    set pid [pid $pipe]

    after $::TIMEOUT check $pid
 }

 main

You'll have to change the COMMAND of course. I don't know if your PC has that IMAGE on it (it should), but my ActiveState Tk 8.5 couldn't load the windows Bliss.bmp as an example.

Hope this helps.


Strange behaviour with text widget bindings

MG has just discovered some behaviour with text widget bindings that seem a little strange. If you do:

  pack [text .t]
  .t insert end foo bar
  foreach x [list Enter Leave ButtonPress-1 ButtonRelease-1] {
   bind .t <$x> [list puts "Widget $x"]
   .t tag bind bar <$x> [list puts "Tag $x"]
  }

Then move the mouse over the 'foo' text, hold down the left button, drag the mouse out of the text widget, and then release the mouse button. The "tag" binding doesn't trigger a Leave event until after the button is released, but the "widget" binding triggers both the moment the mouse leaves the widget (as I would've expected), and then again when the button is released. This is on Win XP with an 8.5.7 Tclkit. Can anyone confirm and tell me whether or not this is a bug? (I would expect both the tag and widget bindings to fire just once, when the mouse moves outside the text/widget boundaries.) Any help is greatly appreciated.


Accessing UNIX filters from TCL

I use UNIX filters every day, almost every thing I type at the command line is a filter. How can I access these filters from Tcl?

How can I run data through an external filter?

jbr


Basic code for the switch function: Running two procedures and a cancel

Keith Sarandon 2009-11-05 I am asking a very simple question re: the switch function. See on top of the switch page. Tx.

(aricb moved the question back here.)

November 5th 2009 by Keith Sarandon

I need some very basic code for the switch function. If the user clicks on Item a in the window, proc open.a runs and conversely if he clicks on item b in the window proc open.b runs. There is also a third item: Cancel. Tx for the help.

Duoas You don't need switch for that. Instead you should bind on the button press to do the right thing. In your case, your bindings may be as simple as

    bind .a <ButtonPress> open.a
    bind .b <ButtonPress> open.b
    bind .c <ButtonPress> cancelproc  ;# whatever your cancel proc does

Hope this helps.


Way to trace changes to a font

Duoas 2009-11-03: Is there any way to trace changes to a font?

I ask, because I want to avoid a full set of traces on the font command itself... I am currently playing with zooming fonts, and it would be nice for changes to the font that the user supplied to be automagically reflected in the local fonts that I scale and display. Would a trace like that prove burdensome to the application's running time?


Question regarding creating a directory

Steven, October 22nd 2009: I put a simple question here in regards to creating a directory. Directory, General Questions; Thanks for your help!


Problem with coding several different grid-layouts on the same window.

HJG 2009-09-27: I want several different grid-layouts on the same window. E.g. a table as in the example on the page for grid, and below the table a set to buttons, using a new grid:

    foreach field {Name Address City State Phone} {
        set l [label .lab$field -text $field]
        set e [entry .ent$field -justify right]
        grid $l $e -padx 4 -pady 4
        grid $l -sticky e
        grid $e -sticky ew
    }
    button .b1 -text New
    button .b2 -text Search
    button .b3 -text Delete
    button .b4 -text Exit
    grid .b1 .b2 .b3 .b4   ;# !! uses same grid-layout as table above

It seems, there is no command to reset/finish one grid and start another. Also, packing a grid inside a frame does not work as expected, and the docs have no info about how to use Geometry managers like grid and pack together.

HE 2009-09-28: You need to put different layouts/geometry managers into different frames:

 frame .f1
 foreach field {Name Address City State Phone} {
        set l [label .f1.lab$field -text $field]
        set e [entry .f1.ent$field -justify right]
        grid $l $e -padx 4 -pady 4
        grid $l -sticky e
        grid $e -sticky ew
    }

 frame .f2
 button .f2.b1 -text New    
 button .f2.b2 -text Search    
 button .f2.b3 -text Delete    
 button .f2.b4 -text Exit    
 grid .f2.b1 .f2.b2 .f2.b3 .f2.b4 
 pack .f1 .f2 -side top

Using re-entrant procedures

lannet 06 Aug 09 - Am I heading for trouble if I use re-entrant procedures?


Problems with list handling in connection with the "unknown" proc

lannet 23 Jul 09 - Problems with list handling in connection with the "unknown" proc


Separate spec and body source files

LGT Jul 13 2009 - itcl : Is it recommended to have separate spec and body source files ?


Silly link!!!

tehbrozor Jul 7 2009 - My question is listed here--Please help!!!


Working with button press with a ttk::treeview widget

MG Jun 16 2009 - I have a ttk::treeview widget set up along these lines:

  set image [image create photo -file $path]
  pack [ttk::treeview .t]
  set id [.t insert {} end -text Foo -image $image]
  .t insert $id end -text Bar -image $image
  .t insert $id end -text Baz -image $image

I'd like to do something particular when a ButtonPress occurs over the image; anyone know if this is possible? I had a look at the bindings in treeview.tcl and found an undocumented

  $treeview identify $x $y

command, but (at least in the usage in treeview.tcl, and from my quick test of it) it doesn't seem to return anything special for the image. Is there another way?

What I'm trying to create is something akin to the MS installers which show a tree of program components grouped together, with a checkbutton for each group/component. I was planning to use different images (empty box, box with tick, greyed out box with tick) to simulate a tri-state checkbutton, and alter the image/state when the image is clicked. Would be interested to hear any suggestions for a better/different way to go about it, too.

Thanks for your help.


Problem using bindvariables with oratcl 4.4

HE June 7 2009 - I have a problem to use bindvariables with oratcl 4.4. Something like a memoryleak.


Transferring files of using ftp over TLS

Hai Vu June 1 2009 - How do I Transfer Files of Using ftp over TLS? I often need to do this, so am thinking of a way to automate it.


Problems using Tile/Ttk

MG May 12 2009 - I'm having some (more) issues with Tile, explained at Problems using Tile/Ttk, and would greatly appreciate any help.


General question regarding Undo

ARA (May 2 2009) My question has been placed in a new page called: Undo, a few pointers at how to code the Undo function for a text editor. Please have a look there. Tx.


Coding recognizable radio/checkbuttons in Tk8.5 menus

Schnexel (May 5 2009) Is it possible to have radio/checkbuttons in Tk8.5 menus that are recognizable as such even if not checked? I don't want to change much of my old 8.4 code. See new page: Tk8.5 menu radio/checkbutton without information loss?. Tx.


Uploadable images to a Teclers' wiki page instead of a link out to a remote site

why can't wiki have uploadable images ? I just want to have a picture included with a wiki page. I don't wan't it to link out to a remote web site. Is this possible yet ? thanks. Art

AMG: Yes, it is possible. Just create a new page in the usual way (link to it with brackets or do Create New Page, then do Upload From File.


Implementation of a command with an ensemble

I'm finding many cases where the "obvious" implementation of a command is with an ensemble, but the command is actually a method on an object. I can hack up an implementation, but it's very ugly. Any suggestions as to a better way to do it? Does anybody else want to do this too? Thanks, Paul Object method ensemble


Talking to a device using RS 232; Developing a GUI which can send and receive strings from the device

ADESH - 2009-09-15 15:03:26

I am trying to talk to a device using RS 232 and my programming platform is Tcl/Tk in ubuntu. I need to be able to develop a GUI which can send and receive strings from the device. To start with, I ran the following piece of codes to open the serial port, then send the string MN to the device. and to get the output from the device :

 set serial [open /dev/ttyUSB0]
 fconfigure $serial -mode "9600,n,8,1"
 fconfigure $serial -blocking 0 -buffering none
 puts -nonewline $serial "MN\r"
 puts "Modem echo: [read $serial]"

I have connected the device to my computer via RS 232 and a USB. When I wish the above command containing file I get the following response;

Error in startup script: channel "file6" wasn't opened for writing
    while executing
"puts -nonewline $serial "MN\r""
    (file "tt.tcl" line 8)

Please help me get rid of the problem.

Thanks in advance Adesh


LV Have you read the wiki page for open? In your code above, you don't provide an indicator of whether you are opening for read or for write. Also, be certain to read the information about setting appropriate fconfigure value if you need to send or receive binary data over the device.


Tool implemented in expect that sends commands to remote node

srinadh - 2009-10-03 11:22:46

I have a tool implemented in expect that sends commands to remote node (I spawn telnet session to the node) and parses its output.

But when I launch the tool from a small window, the command that is being sent by the tool is getting stripped at the beginning so node cannot understand the command and fails to respond, my tool stops.

To fix this issue, I added "stty rows 50 columns 120" before it sends command to the node. It works fine but when I run the tool in background, it goes to suspended mode: "1 + Suspended (tty output) ./console_logs -l tmp". I need to type 'fg' explicitly for the tool to resume its operation..

I cannot use stty??? If not, please suggest me a better way to be able to run the tool from smaller windows..

HJG That looks like a task for expect.


Problems with developing a GUI in VTCL

plasma - 2009-11-02 23:20:57

I am developing a GUI in VTCL that involves drag and drop of widgets. These are the components in my GUI:

  • a tree with nodes and child nodes
  • an 'Insert' button
  • A Separator widget

When I select a node and click on Insert,a widget should get inserted in the Separator. The widget can be either a button or a labelentry,having the name of the selected node as the text value. The purpose is that once the widget comes in the Separator, it should be dragable inside the Separator. On the Wiki,I was told that the button widget cannot be made dragable, so now I insert a LabelEntry widget instead,which being a BWidget,has an option to be made dragable.

I have done the insertion part using the following code:

#############################################################################
## Procedure:  insertElement

proc ::insertElement {} {
global widget
set sep $::widget(Separator1)
set tr $::widget(Tree1)

set sel_element [$tr selection get]
if { $sel_element != ""} {
 set lb [LabelEntry $sep[incr ::my_data::count] -label "" -text "$sel_element" \
        -relief "raised" -justify "center" -width "15" -editable "No" \
        -font {-family helvetica -size 10 -weight "bold"} \
        -dragenabled 1 -dragevent 1]
 place $lb -in $sep -x $::my_data::x_pos -y [incr ::my_data::y_pos 30]
} else {
 tk_messageBox -title "Error" -message "Please select an element" -type ok
}
if { $::my_data::y_pos > 180 } { 
 incr ::my_data::x_pos 60
 set ::my_data::y_pos 0
}
if { $::my_data::x_pos > 550 } {
 set ::my_data::x_pos 50
}
}
#############################################################################

Now the separator has to be registered as a drop site for the labelentrty widget using DropSite::regsiter. Please tell me how to write the dropendcmd for the separator. EDIT: JOB has posted a code for making a button dragable [L3 ]here. Is it possible to change the position of a widget in real time by dragging?


Problems writing a small Tcl extension

that makes driver specific ioctl() calls on files that are otherwise handled by the normal Tcl file commands

filker0 - 2009-11-04 18:50:46 I am attempting to write a small Tcl extension that makes driver specific ioctl() calls on files that are otherwise handled by the normal Tcl file commands. (This is to be used in an embedded environment.) An example of usage would be:

#############################################################################
package require fldr
# The device node opens an IPC channel between two CPU boards using a special
# minor device number (the main purpose of the driver is a different type of
# domain specific IPC not being used for remote ROM access)
proc update_remote_if_needed {remote local} {
  if {![file exists $local]} {
    puts stderr "Local file $local does not exist"
    return 0
  }
  if {![file exists $remote]} {
    puts stderr "Remote file $remote does not exist"
    return 0
  }
  set localSize [file size $local]
  set rfd [open remote rw]
  set limit [fldr::getLimit $rfd]  # performs an ioctl() and returns a long integer value
  if {$limit < $localSize} {
    puts stderr "Local file $local ($localSize bytes) exceeds limit for $remote ($limit bytes)"
    close $rfd
    return 0
  }

  set lfd [open $local r]
  fconfigure $rfd -translation binary -encoding binary
  fconfigure $lfd -translation binary -encoding binary
  seek $rfd 20
  seek $lfd 20
  set remote_version [read $rfd 32]
  set local_version [read $lfd 32]
  if ($remote_version == $local_version) {
    puts stdout "Remote file is up to date"
    close $lfd
    close $rfd
    return 1
  }
  seek $lfd 0
  seek $rfd 0
  puts stdout "Erasing at least $localSize bytes of remote flash"
  if {[fldr::eraseFileArea $rfd $localSize] < 0} {
    puts stderr "Error when erasing $localSize bytes on remote file $remote"
    close $lfd
    close $rfd
    return 0
  }
  puts stdout "Copying $localSize bytes of data from local file $local to remote file $remote"
  set remain $localSize
  set chunk  2048
  while {$remain > 0} {
    if {$chunk > $remain} {
      set chunk $remain
    }
    set copyBuff [read $lfd $chunk]
    puts -nonewline $rfd $copyBuff
    set remain [expr $remain - $chunk]
    puts -nonewline stdout .
  }
  close $lfd
  close $rfd
  puts stdout ""
  puts stdout "Copy successful"
  return 1
}
#############################################################################

Note that the above code is not the real thing; there are things done between each write and the following read.

Unfortunately, I can find no standard way to get the file descriptor for the open channel (Tcl_Channel being a pointer to an incomplete type), and there is no uniformity between the Windows, Mac and Unix ports as to the name of the system specific channel information and the names of the fields. The Unix specific header file is not visible to apps using an installed version of Tcl (I have to use the 8.2 that is provided by the embedded OS vendor, and the sources for their port are not provided).

Am I overlooking something? Is there a standard (and portable) way for extensions to access the POSIX style file descriptor for a Tcl_Channel object? I've written several Tcl extensions in the past, but none of them had to deal with Tcl_Channels at this level.


Call to discussion regarding the Semantics of the oo::class command

mpdanielson would like to discuss the Semantics of the oo::class command, wrt the interaction with packages


Finding a faster way of reaching a particular line number N in a file

than by looping on "gets $f" for lines before it

[m] - 2009-11-28 12:27:47

Is there a faster way of reaching a particular line number N in a file than by looping on "gets $f" for lines before it? In my case, the file is 2GB in size, ASCII content, with varying number of characters per line. It takes about 5 minutes just to reach line 5000000 (N), and only then does the actual processing begin. I can't use "seek" because number of bytes before line N is not known.

EG You can combine chan read, chan gets and split to build reasonably-sized lists of one element per line, and iterate over the file until you reach the line you want.

# pure gets
proc UsingGets {fname linenumber} {
    set fd [open $fname]
    for {set i 1} {$i <= $linenumber} {incr i} {
        chan gets $fd data
    }
    chan close $fd
    return $data
}

# using read plus gets for the remaining chars
# chunk is the chunk size to read in one go
proc UsingRead {fname linenumber {chunk 100000}} {
    set fd [open $fname]
    set line 0
    while 1 {
        set data [chan read $fd $chunk]
        append data [chan gets $fd]
        set sdata [split $data \n]
        set nl [llength $sdata]
        if {$line + $nl < $linenumber} {
            incr line $nl
        } else {
            chan close $fd
            return [lindex $sdata [expr {$linenumber - $line - 1}]]
        }
    }
}

# this is a big_but_not_THAT_big file on my system
set f /var/log/messages.1
set linenumber 13500

puts "Pure gets: [time {puts [UsingGets $f $linenumber]}]"
puts "Read-gets: [time {puts [UsingRead $f $linenumber]}]"

On my system, the output is

$ tclsh8.6 reading.tcl
Nov 26 17:07:24 merlot kernel: sd 6:0:0:0: [sdc] ASC=0x24 ASCQ=0x0
Pure gets: 153451 microseconds per iteration
Nov 26 17:07:24 merlot kernel: sd 6:0:0:0: [sdc] ASC=0x24 ASCQ=0x0
Read-gets: 67498 microseconds per iteration

Try testing several values of the chunk parameter to find the optimal for your system. Note that I've not tested the behaviour with another line ending than \n (Unix system).

dcd - 2009-12-30

   I'm assuming you don't care about the first part of the file before line N (although even 
   if you do, I think I'm proposing a faster line counter.) Given that, regexp is pretty fast
   and you don't need to malloc for lines you don't care about. ok, untested code alert...

   set N 5000000 # or whatever
   set n 0
   set eolre {\n} # or whatever
   set f [open file]
   set lines [read $f $chunksize]
   while {! [eof $f]} {
      incr n [regexp -all $eolre $lines]
      if {$n >= $N} {break}
      set lines [read $f $chunksize]
   }
   # deal with what's in $lines and go on

dcd - a little later

   I tested a variant of my implementation against [EG]s and on a reasonably large file mine lost.
   we have:
   $ ls -l bigfile.txt
   -rw-r--r-- 1 dcd Domain Users 876275714 Dec 30 16:59 bigfile.txt
   $ time wc -l bigfile.txt
   6085879 bigfile.txt

   real    0m4.187s
   user    0m2.343s
   sys     0m1.421s

   so, I tried, in tkcon
   % time {UsingRead bigfile.txt 5000000} 1
   12592066 microseconds per iteration
   vs a version of my code above
   % time {readto $f 5000000 100000} 1
   28341788 microseconds per iteration

   near as I can tell, this means that tcl can allocate space and split on lines about twice as 
   fast as regexp can walk through a buffer counting matches of a single character. whoda thunk it?

   % puts $tcl_version
   8.6

Invoking tclsh for interactive execution, but specify file(s) to be sourced before issuing the first command prompt

Lavin, 2009-12-24 12:58:52: How can I invoke tclsh for interactive execution, but specify file(s) to be sourced before issuing the first command prompt? TIA, -- Mark

AMG: See tclshrc for the answer.


Resizable text widget

gasty - 2009-12-29 09:34:04

Hi all! I need a resizable text widget. Using pack as geometry manager works well:

pack .t -expand 1 -fill both

However I want to use grid:

grid .t -row 0 -column 0 -sticky nwes

but the widget do not "expand" when I change the size of their container. I also tried with rowconfigure and columnconfigure for this widget to set the weight parameter, but the results are the same. Which can be the problem? I need some other option in the command above? Thanks in advance for any tip.

Duoas 2009-12-29 10:28 What did you set the weight as? The following should work just fine:

  grid .t -row 0 -column 0 -sticky news
  grid rowconfigure    . .t -weight 1
  grid columnconfigure . .t -weight 1

Hope this helps.

gasty I was using rowconfigure and columnconfigure incorrectly... Thanks!


How to execute an application in the background

while being able to know when that application has ended.

OK - 2010 -1-25 10:36

Hi all, I'm new to tcl and need to find out how to exec an application in the background but be able to know when that application has ended.

So far, I browsed different sources and know I can execute in the background with &, but are not able to find how to known when this application has ended.

exec cmd /c "path_to_exec/prog.exe /123q" &

People recommended using wait, but I can't find an example of how to implement this. Please advise.

AMG: Use [open |cmdline] to create pipelines. [wait] is a TclX command.

Hai Vu See this thread: http://groups.google.com/group/comp.lang.tcl/browse_thread/thread/f8ccd018858026a0/e109d759a3debcb2?lnk=gst&q=exec+wait#e109d759a3debcb2


Problem with the documentation that comes with critcl, i.e. the file critcl.tkd.

sdwillingham 2010.02.12:

I'm having trouble with the documentation that comes with critcl, i.e. the file critcl.tkd. I've tried several versions of Wikit, both as regulars scripts and using tclkit on two different Windows XP computers with ActiveTCL 8.4 and 8.5. The problem is that the the first page loads up and renders fine, but when I click on links, most pages are nearly empty with just a character or two. Using wikitool.tcl, I can see that the information is intact within critcl.tkd, but other than that, I am stumped on how to fix the problem.


Problem with using tcom to interface with into the SAPI COM object for Text To Speech

notlistening 2010.02.27

I am using tcom to interface with into the SAPI COM object for Text To Speech. I am trying to get SAPI to pass back an audio stream for use within my tcl script. I have come up short on a problem with iDispatch on tcom. I was hoping that someone could begin to explain where i need to look to make the nessesary changes to make ole32 to implement iDispatch or suggest some ideas on how I can get the audio stream directly into my app. The test code that I have so far is:

package require tcom

       # ::tcom::configure -concurrency multithreaded
       set voice [::tcom::ref createobject Sapi.SpVoice]
       set APO [::tcom::ref createobject Sapi.SpCustomStream]
       set GI [::tcom::ref createobject  Sapi.SPStream]
       
       set GIC [$GI -call CreateStreamOnHGlobal]; # At the moment the code errors here with - object does not implement IDispatch

       [$GIC hGlobal NULL]
       [$GIC fDeleteOnRelease True]
       [$GIC ppstm $GI]


       
       set APOBS [$APO BaseStream]
       set $APOBS $GI
       
       set VAOS [$voice AudioOutputStream] 
       set $VAOS $APO
        

       $voice Speak "Welcome!"
       while {1} {
           [$APO Read $GI 100]
           puts $test
       }

Any suggestions on how i can go about getting this to work in tcl / tcom / other would be great. I am not afraid of doing the hard work in the background but am a little bit unclear how to start. I have very little to no knowledge of COM objects and mechanisms in Windows but I am willing to learn. Ideally a quick dirty hack would suffice but beggars can not be choosers.


How to make the frame with the data to fill both vertical and horizontal with BWidget ScrollableFrame

ICU - 2010-03-01 06:59:59

I added scrollbar to simple Tktable with the help of BWidget ScrollableFrame. It works BUT I just can't figure out how to make the frame with the data to fill both vertical and horizontal. I can make it work with ScrollableFrame -width/-height commands, but it would be better if the frame would resize itself.

Here is the code where the table is being built. I would appreciate if someone could help me at where I'm going wrong.

        destroy $pathName
        frame $pathName

        set r 0; set c 0
        set w [ScrolledWindow "$pathName.r${r},$c"]
        pack $w -fill both -expand true

        set t [ScrollableFrame $w$pathName -height 650 -width 650]        
        $w setwidget $t
        set uf [$t getframe]

    for {set r 0} {$r < $A(-rows)} {incr r} {
        for {set c 0} {$c < $A(-cols)} {incr c} {
                set w "$uf.r${r},$c"                
            if {$r < $A(-titlerows) || $c < $A(-titlecols)} {
                if { $::tcl_platform(platform) eq "windows" } {
                    set bg SystemDisabledText
                } else {
                    set bg darkgrey
                }
                label $w  -textvariable $A(-variable)\($r,$c\) \
                    -relief flat -bg $bg -fg white
            } elseif {[lsearch $A(-readonlyrows) $r] != -1 || \
                      [lsearch $A(-readonlycols) $c] != -1} {
                label $w -textvariable $A(-variable)\($r,$c\) \
                    -relief sunken -bd 0
                $w config -font [lindex [$w config -font] 3]
            } else {
                entry $w -textvariable $A(-variable)\($r,$c\) \
                    -relief sunken -bd 2 -justify center -width 0

                #if {[info exists A(-vcmd)]} {
                    #$w config -validate key \
                        -vcmd [list $A(-vcmd) $r $c %P]
                #}
            }
            grid $uf.r${r},$c -row $r -column $c -sticky ew

        }
    }
 }

ICU I was able to solve it.

Fro - 2010-04-06 17:28:34

Thanks for the reply, I got it working.


Problem with info hostname

MaheshD - 2010-04-08 05:38:28 info hostname issue

Help needed with the following issue : ambiguous result with "info hostname "


Problem in namespace scope of variables

MaheshD - 2010-04-14 04:40:12

Problem in namespace scope of variables

Write a TCL file with a namespace definition in it as :

file "a.tcl"

  namespace eval nse {
    set WorkDir "/home/sj/name"
  }

Under TCL prompt, do the following :

 % set WorkDir "asdf"
 asdf
 % source a.tcl
 /home/sj/name
 % puts $nse::WorkDir
 can't read "nse::WorkDir": no such variable
 %

Why is this behaviour, why are the variable names in global scope clashing with the one in namespace "nse"

Please help ?

Martyn Smith 14 Apr 2010 There is not a clash your namespace eval only executes the code in the namespace fo your WorkingDir variable is destroyed at the end of the namespace eval. What you are looking for is

  namespace eval nse {
    variable WorkDir "/home/sj/name"
  }

Which creates a variable in the nse namespace and initialises it. Then to access you variable in another procedure you use

  variable WorkDir

Lars H: While Martyn's fix is correct, I think his explanation is wrong. Namespace variables don't get destroyed when a namespace eval ends, this is rather an example of the dangers of creative writing: the namespaced set chose to update the existing ::WorkDir variable rather than the ::nse::WorkDir that would have to be created.


Help with tcltest harness

18MAR2010

Hi all, I'm new to tcltest but not completely green with tcl in general. I'm trying to get my head around the use of the tcltest harness. We tend to write multiple .tcl files as part of a Component-level test (CSC test). So I think what I would do is write an individual .test file for each software Component, which would have some number of calls to tcltest::test in order to run each script file that makes up the whole set of functionality tests for a given Component.

Below is the high-level 'master' tcl that whould run all lower-level '.test' tcl files, and then one sample .test file for a Component named CSC_foo.

I guess I have 2 questions: 1) Am I understanding all this correctly as far as what goes in each type of file (.tcl, .test), and
2) Where I need to use a raw 'filename.tcl' vs. a 'source filename.tcl' call in order to have individual .tcl files get run. (this stems from the man page text talking about -setup, -cleanup, and -body.

For example, for -setup, it says "The optional -setup attribute indicates a script", I'm not sure if the -setup syntax is "-setup filename.tcl" or if it would be "-setup source filename.tcl".)

Thanks very much in advance.

- Jeff

# FILENAME: CSCI.tcl
# Top-level script (usually named all.tcl) to run all tests defined in
# .test files 
# 

package require Tcl
package require tcltest
namespace import tcltest::*
configure {*}$argv -testdir [file dir [info script]]
runAllTests

# end CSCI.tcl

# FILENAME: CSC_foo.test
#           
# There's one of these .test files for each CSC.
# A CSC test may have multiple .tcl files associated with it.
#  
#  e.g.  As part of CSC foo, there may be the following script files
#        to segregate testing into logical chunks: 
#
#        foo_mode_tests.tcl 
#        foo_parameter_tests.tcl
#        foo_fault_tests.tcl
#
package require tcltest
eval ::tcltest::configure $argv
package require CSC_foo
namespace eval ::CSC_foo::test {
   namespace import ::tcltest::*
   testConstraint X [expr {...}]
   variable SETUP {FQT_TC_Setup.tcl}
   variable CLEANUP {FQT_TC_Cleanup.tcl}

   # Run all 3 test cases for CSC_foo

   test CSC_foo-mode_tests {runs foo_mode_tests.tcl script} 
      -setup $SETUP 
      -constraints X 
      -body {

         source foo_mode_tests.tcl  # this needs to return a value
                                    # to compare with -result {}

   } -cleanup $CLEANUP -result {#expected results}

   test CSC_foo-param_tests {runs foo_param_tests.tcl script} 
      -setup $SETUP 
      -constraints X 
      -body {

         source foo_parameter_tests.tcl  # this needs to return a value
                                         # to compare with -result {}

   } -cleanup $CLEANUP -result {#expected results}

   test CSC_foo-fault_tests {runs foo_fault_tests.tcl script} 
      -setup $SETUP 
      -constraints X 
      -body {

         source foo_fault_tests.tcl  # this needs to return a value
                                     # to compare with -result {}

   } -cleanup $CLEANUP -result {#expected results}

   cleanupTests # this is a tcltest function, it prints the 
                # PASS/FAIL/SKIP info # among other things

} # end namespace eval ::CSC_XYZ::test

namespace delete ::CSC_foo::test

# end CSC_foo.test

hv Here are what I notice: (1) Yes, you understood correctly. By default, the *.test files will be included in the test suite. (2) The arguments to -setup and -cleanup are just a block of code. For example:

    set SETUP {
        set x 1 
        set s "some string"
    }   

    test testName {description} -setup $SETUP -body {
        # Body of test ...
    } -result {expected result}

Similarly, you can define a variable and pass that to the -cleanup flag. Note that if you don't fit everything into one line, you have to use line contiuation (\), the only exception is the open brace {:

   test CSC_foo-mode_tests {runs foo_mode_tests.tcl script} \
      -setup $SETUP \
      -constraints X \
      -body {

         source foo_mode_tests.tcl  # this needs to return a value
                                    # to compare with -result {}

   } -cleanup $CLEANUP -result {#expected results}

As a personal preference, I structure my tests as:

    test testName {
        Test description goes here
    } -setup $SETUP -cleanup $cLEANUP -body {
        # test body goes here
    } -result {expected result}

Fro Thanks for the reply hv, I was able to get it working.


How to return a list of arguments from a procedure

mreister - 2010-05-26 23:18:42

Ok so I am pretty new to TCL and I am using it for scripting a command line (modelsim for anyone who cares) but anyways I am having trouble figuring out how i can return a string of arguements from a precudure. As i understand it when a procedure i wrote executes its return value get executed on the command line. So I am able to return a command with a singal word but when i try to return a command with multiple words tcl seems to only try to read the first word of the command and when i put it return command in quotes it seems that the command line interprets the return value in quotes"". For example:

proc set_f {cycle_number} {

    switch  $cycle_number {
        1{
            return "force -freeze sim:/uart/reset 1 0"
        }
        2{
            puts "force -freeze sim:/uart/reset 0 0" 
        }
        default{
            puts "hello"   
        }
    }   
    return force -freeze sim:/uart/reset 1 0

}

In this situation its seems to try to return force

But when I do this:

proc set_f {cycle_number} {

    switch  $cycle_number {
        1{
            return "force -freeze sim:/uart/reset 1 0"
        }
        2{
            puts "force -freeze sim:/uart/reset 0 0" 
        }
        default{
            puts "hello"   
        }
    }   
    return "force -freeze sim:/uart/reset 1 0"

}

It seems to retrun "force -freeze sim:/uart/reset 1 0" to the command line rather than force -freeze sim:/uart/reset 1 0. Which is what I want. So my question is how can i return the line "force -freeze sim:/uart/reset 1 0" to the command line WITHOUT the quotes?

AM You do not describe the code that gets this returned string and needs to deal with the multiple returned strings. I will make a guess: "force -freeze sim:/uart/reset 1 0" is meant as an external program with arguments. If so, then:

(if you use Tcl 8.5)

    set command [set_f $cycle_number]
    exec {*}$command

(or if you use Tcl 8.4 or previous)

    set command [set_f $cycle_number]
    eval exec $command

will run the program "force" with the individual arguments -freeze, sim:/uart/reset, 1 and 0.

The expansion operator {*} expands a list into individual arguments and the command eval re-interprets the entire list of arguments as a string. (Note the eval command should actually be more complicated to avoid nasty stuff with embedded [] and the like - the very reason for the introduction of {*}).

So, it is the caller that needs to deal with the multiple arguments, not the callee.

Furthermore: if you want to return multiple pieces, it is best to use a list:

    return [list force -freeze sim:/uart/reset 1 0]

as then the individual pieces are well defined and protected against haphazard conversions.


How to copy drawings from the canvas and paste into Word or PowerPoint

Beware, 5th June 2010: Where can I find some information on 'general' Windows copy and paste? I'd quite like to be able to copy drawings from the canvas and paste into Word or PowerPoint, where they would become Office drawings.

I can't find any useful information through Microsoft.

Lars H: The -type option of clipboard is probably relevant, but I don't know what might be meaningful values on Microsoft Windows. The likeliest place to find an answer to this is probably some sort of Windows/Tk FAQ, as this is an area where the Tk manpages are very X-centric. I also notice the Wiki clipboard page has some pointers regarding bitmap copy and paste on Windows.

MG Copy image to and from the Windows clipboard may be of some use.


Problem with directories which are to be checked

maheshd - 2010-06-30 08:44:06

The command file writable was used to know, if a certain directory has write permissions for a certain user. The command is written as a TCL script which is then remotely executed onto the slave machine from the master. Now, the problem is, the directories which are to be checked for write permissions are automounted on slave. As is the case with auto mount, until and unless the mount partition is used, the partition remains unmounted. Hence the command "file writable <DirectoryName>" fails, i.e it reports that <DirectoryName> has no write permissions. But, if the remote directory <DirectoryName> is visited once, i.e a "cd <Directoryname> and ls", it results in the partition being mounted and from then on the TCL script containing file writable command works fine.

The question : Is there any way to check for the same without actually hard mounting the partition and without visiting the directory (not even once).

AMG: This isn't a Tcl question. It's very OS-specific.

I suspect the answer is "no" because (if I read you right) you're trying to figure out the permissions of the root directory of a filesystem without mounting that filesystem. It's impossible to read the permissions bits without reading the filesystem, and the only sensible way to do this is to mount it.


Does anyone have

a simple TK C callback Example?

stevieb - 2011-07-17 21:54:00

I am new to TCL/TK, I have some C code and I want to put a TK front end on it, can anyone get me started by providing a simple example of a TK GUI that invokes a C callback, it could be as simple as the HelloWorld.c example, where you click a button and the C function is called by TK to write out Hello World!

Thanks

stevieb

RLE (2011-07-17): You may want to take a look at the Critcl and Critcl 2 pages, as well as search for other wiki pages relating to Critcl. It provides a very easy way to interface C code into Tcl code.


Kc - 2014-09-25 15:22:48 - adjust brightness in androwish

Can any one show me how to adjust the screen brightness in androwish