Ask, and it shall be given # 4

How to post on Ask-pages

This page is not intended for new questions.

Please post your question on the latest version of Ask, and it shall be given.

Please do not edit this part, it is meant as a guide!



Questions


2006-08-08 Omar Medina

I will appreciate, if someone can check the modifications done by me in tcom, in order to generate from a tcl-list one-dimension array of VT_R8. Perhaps I have forgotten something. See below. FYI. The modification works fine.

REASON FOR MODIFICATION: The applications (not excel), what we are using, only expect certain Variant types, namely

 Either Variant.vt = VT_ARRAY|VT_UI1  or 
 Variant.vt = VT_ARRRAY| VT_I4    or 
 Variant.vt = VT_ARRAY|VT_R8

I saw during debugging of tcom version 3.9, that when a method with variant parameters is called, Tcom generates following arrays of VT_Variants

 set lst [list 10 20 30 ] 
 $appRef  methodName lst
 Variant.vt = VT_ARRAY|VT_VARIANT
 # 1 element = VT_VARIANT|VT_I4
 # 2 element = VT_VARIANT|VT_I4
 # 3 element = VT_VARIANT|VT_I4

 set lst [list 10.0 20.0 30.0]
 $appRef  methodName lst
 # Variant.vt = VT_ARRAY|VT_VARIANT
 # 1 element = VT_VARIANT|VT_BSTR
 # 2 element = VT_VARIANT|VT_BSTR
 # 3 element = VT_VARIANT|VT_BSTR

 set lst [list 10.0 20 30.0]
 $appRef  methodName lst
 # Variant.vt = VT_ARRAY|VT_VARIANT
 # 1 element = VT_VARIANT|VT_BSTR
 # 2 element = VT_VARIANT|VT_I4
 # 3 element = VT_VARIANT|VT_BSTR

And this Variant is not compatible wit our application

MODIFICATION ON SRC:

 Flow: the TCL-variable ::bUseArrayOfDoubles will be used as switcher to select between SafeArray as either VT_ARRAY|VT_VARIANT or VT_ARRAY|VT_R8 
 Modified File: TclObject.cpp
 Modified Functions:
  static void fillSaveArray
  TclObject::toVariant

  static void fillSaveArray (...)
  {
  ...
     else {
        //LINE 285-295
        double dValue = 0.0;
        TclObject tclobjVarName("::bUseArrayOfDoubles");
        Tcl_Obj *tcl_objUseArrayOfDoubles = Tcl_ObjGetVar2(interp, tclobjVarName, 0, TCL_LEAVE_ERR_MSG);
        BOOL bUseArrayOfDoubles = FALSE;
        if (tcl_objUseArrayOfDoubles != NULL) {
           TclObject tclobjUseArrayOfDoubles(tcl_objUseArrayOfDoubles);
           bUseArrayOfDoubles = tclobjUseArrayOfDoubles.getBool();
        }

        for (int i = 0; i < numElements; ++i) {
           TclObject element(pElements[i]);
           if (bUseArrayOfDoubles == FALSE) {
              _variant_t elementVar;
              element.toVariant(&elementVar, Type::variant(), interp, addRef);

              pIndices[dim1] = i;
              hr = SafeArrayPutElement(psa, pIndices, &elementVar);
              if (FAILED(hr)) {
                _com_issue_error(hr);
              }
           } else {
              if (Tcl_GetDoubleFromObj(interp, pElements[i], &dValue) != TCL_OK) {
                 _com_issue_error(E_INVALIDARG);
              }

              pIndices[dim1] = i;
              hr = SafeArrayPutElement(psa, pIndices, &dValue);
              if (FAILED(hr)) {
                 _com_issue_error(hr);
              }
           }
        }
     }
  }

  TclObject::toVariant (....)
  {
  ...
  //LINE 597-602
     TclObject tclobjVarName("::bUseArrayOfDoubles");
     Tcl_Obj *tcl_objUseArrayOfDoubles = Tcl_ObjGetVar2(interp, tclobjVarName, 0, TCL_LEAVE_ERR_MSG);
     BOOL bUseArrayOfDoubles = FALSE;
     if (numDimensions == 1)
     {
        if (tcl_objUseArrayOfDoubles != NULL) {
           TclObject tclobjUseArrayOfDoubles(tcl_objUseArrayOfDoubles);
           bUseArrayOfDoubles = tclobjUseArrayOfDoubles.getBool();
        }
     }

     if (bUseArrayOfDoubles == FALSE)
     {
        SAFEARRAY *psa = SafeArrayCreate(VT_VARIANT, numDimensions, bounds);
        std::vector<long> indices(numDimensions);
        fillSafeArray(m_pObj, psa, 1, &indices[0], interp, addRef);

        V_VT(pDest) = VT_ARRAY | VT_VARIANT;
        V_ARRAY(pDest) = psa;
     }
     else
     {
        SAFEARRAY *psa = SafeArrayCreate(VT_R8, numDimensions, bounds);
        std::vector<long> indices(numDimensions);
        fillSafeArray(m_pObj, psa, 1, &indices[0], interp, addRef);

        V_VT(pDest) = VT_ARRAY | VT_R8;
        V_ARRAY(pDest) = psa;
     }
  ...
  }

Thank for Your Help


CLI apps

2006-08-04 1S Well, I see that GUI applications could be developed just fine with Tcl/Tk. But how about CLI ones? Essential points include argument parsing and error reporting. And, the UI should be consistent with the rest of OS. In fact, I've written both argument parsing library (similar to the Argp facility of the GNU C Library; no nested parsers for now, though), and a small error reporing routine (gnuerr), but want to know whether I duplicated someone efforts before posting my code here.

Is anyone interested in this kind of things? - RS: I'm frequently doing CLI scripts in Tcl. But I'm not aware of a "consistent" CLI-UI for Windows (Cygwin or not); I do the argument parsing ad hoc as requirements go. It's often easier and more flexible than complying with standards that not all agree upon anyway :) My only strict rule is: Every script shall display an usage message when called without arguments, like this:

 set usage {
    usage: myscript.tcl ?-foo this? bar
    text that tells what the idea is
    -foo this    a parameter for extra control
 }
 if {[llength $argv]==0} {puts stderr $usage; exit}

1S Cygnus tools do behave just like their GNU counterparts (they're compiled from the same sources, BTW.) So, having support for the --help option is probably consistent with the interface. ``No arguments'' convention is almost fine, but sometimes I do something like:

 bash $ find foo/ CONDITIONS -print0 | xargs -0 ./script.tcl

And this convention requires me to add -r option to xargs. Furthermore, I'd suggest to use exit 1 in this case to indicate argument parsing error. (Not so long ago, had a lot of fun working with the set of huge Perl scripts calling several programs and not checking the returned values; this is the other side of the problem.)

Another thing is the --foo=bar form of writing long options. It could be very useful in doing things like this:

 bash $ ./coffee.tcl --put={milk,sugar}

The need to support both short options (with -abc meaning -a, -b, -c) and long ones is due to the dual nature of shell commands: they're stand-alone programs, used directly, yet they're the procedures of the Shell programming language. While it's more convenient for the user to use short options directly (and to abbreviate them like above), it's more self-documenting to use their longer counterparts in Shell (or Make) scripts. (Yes, I use Shell as well.)


Comma

1 August 2006: The following piece of text was found vandalising the Chin Huang page. Moved here, as the question might be legitimate.

Hello Chin,

what can I do, to resolve following problem:

Background Information: package tcom 3.9

description of problem: I have to use "," instead "." For double values, when I calling a method of activex-programm with one oder more double arguments (dTimeOut)

 set dTimeOut 0,5 
 set vMethodRetValue [$vCDS(ref) CANReceive $lDeviceNr $dTimeOut plDLC plByte1 plByte2 plByte3 plByte4 plByte5 plByte6 plByte7 plByte8 plDllError]

Is it normal or ?

if i send 0.5 the activex server receives the value 5.00000

thanks very much for your Help "omar.medina"

Omar Medina: 1 August 2006 Please take my apology, it was not intentionally to modify the Chin Huang page, who can help me with my problem I have to use "," instead "." For double values, when I calling a method of activex-programm with one oder more double Is it normal or ? if I send 0.5 the activex server receives the value 5.00000

MG 01/08/2006 - Only a guess, but this sounds like a localization problem to me. Is the computer you're on (or the computer running the code, if they're not the same machine) set up with a non-English locale? There are lots of locale settings which use a comma to mark the decimal place. (I'm also guessing that all the extra zeros tacked on the end are irrelevant, and that the ActiveX program just always returns numbers to a certain decimal precision.) Check your computer's region settings and see what it has set as the decimal separator? (If that's not the issue, an example of your code that we can test might help narrow down the problem - the snippet above can't be tried because several of the variables it mentions aren't set.)


state machine

TPS 28-7-2006: I searched and I found. Thanks for bringing together all this useful information! I synthesized the following state machine from various snippets and discussions on this Wiki. I think I got it right (as far as it goes) and I'd like to make it available also.

It makes use of the event loop such that the shell remains responsive while the state machine is active: I could have used threads but this seemed simpler, quicker, and I think more light-weight. Especially for someone new to Tcl/Tk like me.

I think it also avoids resource contentions issues because all tasks (state machine, Tcl shell, and Tk) run to completion before yielding to a single main event loop?

I'd also like to find info. on how I could combine this with Richard Suchenwirth's Procs as objects such that I could create multiple instances of it using the same technique.

 # -------------------------------------------------------------------
 # global variables

 set fsm_state halt
 set fsm_wait 2000

 # --------------------------------
 # simplifies handling of the state machine from the shell prompt

 proc fsm {cmd args} {
        global fsm_state
        global fsm_wait

        foreach {opt val} $args {
                set tmp [string trim $opt -]
                set $tmp $val
        }
        switch -- $cmd {
                halt {
                        switch -- $fsm_state {
                                halt {
                                        puts "fsm: already halted"
                                }
                                default {
                                        set fsm_state halt
                                }
                        }
                }
                stop -
                idle {
                        switch -- $fsm_state {
                                idle {
                                        puts "fsm: already idled"
                                }
                                default {
                                        set fsm_state idle
                                }
                        }
                }
                new {
                        if { [info exists state] } {
                                set fsm_state $state
                        } else {
                                puts "fsm: '-state state_name' not specified"
                        }
                }
                start {
                        switch -- $fsm_state {
                                halt -
                                idle {
                                        set fsm_state init
                                }
                                default {
                                        puts "fsm: already running"
                                }
                        }
                        fsm_loop
                }
                default  {error "Unrecognized command."}
        }
 }

 # --------------------------------
 # once called this appears to run in the background

 proc fsm_loop {} {
        global fsm_state
        global fsm_wait

        .tx.textarea insert end "fsm entry: $fsm_state $fsm_wait\n"
        switch -- $fsm_state {
                halt { 
                        .tx.textarea insert end "halted\n"
                        return
                }
                idle { 
                        .tx.textarea insert end "idle\n"
                        vwait fsm_state
                }
                init {
                        .tx.textarea insert end "init\n"
                        set fsm_state s0
                        set fsm_wait 1
                }       set fsm_wait 1
                s0 {
                        .tx.textarea insert end "s0\n"
                        set fsm_state s1        "s0\n"
                        set fsm_wait 2000
                }       set fsm_wait 2000
                s1 {
                        .tx.textarea insert end "s1\n"
                        set fsm_state s0
                        set fsm_wait 1000
                }       set fsm_wait 1000
                default  {error "Unrecognized state."}
        }
        .tx.textarea insert end "fsm exit: $fsm_state $fsm_wait\n"
        after $fsm_wait fsm_loop
 }

 # --------------------------------
 # simple Tk text area for displaying debug info.

 frame .tx
 text .tx.textarea -yscrollcommand ".tx.scroll set"
 scrollbar .tx.scroll -command ".tx.textarea yview"
 pack .tx.scroll -side left -fill y
 pack .tx.textarea -side left 
 pack .tx -side top
  focus .tx.textarea
 .tx.textarea insert end "Text widget ready.\n"


 # catch {console hide}
 catch {console show}


 # -------------------------------------------------------------------
 Trial results from the console:

 1 % source proto.tcl
 2 % fsm start
 after#1
 3 % fsm idle
 idle
 4 % fsm halt
 halt
 5 % 

 # --------------------------------
 Trial results from the Tk widget:

 Text widget ready.
 fsm entry: init 2000
 init
 fsm exit: s0 1
 fsm entry: s0 1
 s0
 fsm exit: s1 2000
 fsm entry: s1 2000
 s1
 fsm exit: s0 1000
 fsm entry: s0 1000
 s0
 fsm exit: s1 2000
 fsm entry: s1 2000
 s1
 fsm exit: s0 1000
 fsm entry: s0 1000
 s0
 fsm exit: s1 2000
 fsm entry: idle 2000
 idle
 fsm exit: halt 2000
 fsm entry: halt 2000
 halted

While trying to take this further I discovered the following which really surprised me.

If I tried to use an arg. with the proc in the same kind of looping arrangement like this:

 proc fsm {state} {
    puts "fsm: $state"
    after 2000 fsm $state
 }

I got a new task (instance) for each call to fsm:

 % fsm 1
 fsm: 1
 fsm: 1
 fsm: 1
 % fsm 2
 fsm: 1
 fsm: 2
 fsm: 1
 fsm: 2

Sarnold Please TPS, could you post this long message on a distinct page. Wiki users might find this page too long to be browsed. Thanks in advance


generate HTML with Tcl

MG 22-07-2006: I'm looking for a way to generate HTML with Tcl. The html package in tcllib doesn't seem to include anything for what I'm trying to do, though - I basically want something that will take strings like

  Testing <this> & "that"

and convert them into something like

  Testing <this> & "that"

similar to the htmlentities() function in PHP. Does anyone know if anything's available anywhere for this already, or if the best solution would be to try and roll my own? Thanks in advance for your help.

HZe 22-07-2006: look at the package htmlparse (at least it's part of ActiveState Tcl). There, an array of HTML special characters is available as escapes (try

  package require htmlparse
  parray ::htmlparse::escapes

and a proc mapEscapes to change from HTML chars back (the opposite of what you asked for). If you revert the array you will very easily find a proc doing what you want:

  foreach {a b} [array get ::htmlparse::escapes] {set reverse_escapes($b) $a}
  proc reverse_escapes {text} {
      global reverse_escapes
      set ret ""
      foreach char [split $text ""] {
          if {[info exists reverse_escapes($char)]} {
              append ret "&$reverse_escapes($char);"
          } else {
              append ret $char
          }
      }
      return $ret
  }

  % reverse_escapes {Testing <this> & "that"}
  Testing <this> & "that"

MG Thanks for the quick response. I took a look at htmlparse, but I can't find the array you mentioned (with ActiveTcl 8.4.9 and htmlparse 1.1). I have:

 % info vars ::htmlparse::*
 ::htmlparse::splitdata ::htmlparse::namedEntities

It looks like the second one there is (probably/possibly) what you're talking about, though - perhaps it was renamed between versions or something. Anyway, that should do it, I imagine, so thanks :)


drag+drop file

2006-07-20: I want to drop a file (from windows explorer or elsewhere) into an entry widget in a Tk app and insert the filename into that widget. The BWidget drag & drop doesnt support this kind of operation, though it is common on most windowing systems - have I missed that page in the manual? GWM

MG There's no 'native' support in Tcl for Drag and Drop, but there are various extensions mentioned on that page for doing it. TkDND seems (from what I've seen over the last couple of years in posts) to be regarded as the best one (I think the Bwidget drag and drop is only for dragging between Tk widgets in your app, not for interacting with other programs or the desktop/OS). Just downloaded TkDND and tried one of the demos very briefly - the new version 2 is dated April this year, and seems to work very nicely (and comes with a precompiled Windows binary and some docs), so is probably your best bet.


test on Windows/CE

2006-07-19: I would like to test whether a Tcl/Tk application of mine also works on Windows/CE. I don't have any device myself. Could someone please provide installation instructions on how to get started with Tcl/Tk using Microsoft's Standalone Device Emulator 1.0 with Windows Mobile OS Images [L1 ]? I.e., what software to install, how to run it, and how to copy your own code between Windows and the emulator?


ECS 2006-07-17: Is there a way to use a compressed (zlib) stream? I would like to use something as was done for tls, just register a compression/decompression layer.

Thanks in advance.

MG There are various libraries mentioned on the zlib page for (de)compression. Taking a guess that you're talking about the http package (and the way you can [http::register https 443 ::tls::socket] for https web pages), I would imagine the best way would be to use the standard method, and then decompress the data after it's been downloaded. If that's not the kind of thing you mean, could you provide more info?

ECS Thanks. I did not made myself clear. I have a client-server application. Client and server use a plain ASCII stream to communicate. I would like something as SSH (a compressed byte stream or, at least, it seems this way). Encryption is not needed, only compression. I could do a call to zlib to compress data before every put and do a call to zlib to decompress data after every gets but I am looking for an easier way :-)

MG Ahh, I see. Well, to be honest, I think doing that is probably the easiest way. Or, at least, something like

  proc _puts {args} {
    if { !$::compress } {
         puts {*}$args
         return;
       }
    set str [lindex $args end]
    set str [zlib compress $str];# compress string
    if { [llength $args] > 1 } {
         puts {*}[lrange $args 0 end-1] $str
       } else {
         puts $str
       }
  }

so that you can easily turn it on and off by setting $::compress to true/false. (I wouldn't recommend renaming puts - other packages you include are likely to call it for various things which wouldn't benefit from unexpected zlib compression. Better to just use _puts yourself when you want the compression.)


compile a TCL script

unperson July 13 2006

The wonderful adventures of unperson into the world of widgets continue. :-)

In this page: https://wiki.tcl-lang.org/11861 , it was taught how to compile a TCL script into an exe. I have always used that method and it has always worked excellently, A1 as we say. Now, does anyone know how to add a Widgets library or any library in the list so that it gets compiled also?


unperson July 7 2006 I run every Tcl script with JCW's great tclkit.exe. (I copy the script and I paste it in tclkit.exe)

The Tclkit.exe file is installed in c:\Tcl. This way: c:\Tcl\tclkit.exe

Now I install libraries in the lib this way: c:\Tcl\lib\Widget

Unfortunately I get an error message everytime I want to run a script that requires a certain library.

It seems that I am missing something here: I believe I should not simply copy the library in c:\Tcl\lib\. Something else needs to be done. What? Thanks for the answer!

SEH 20060707 -- Do you run the load command to load the libraries (I assume you're talking about Tcl stubs-enabled shared libraries)?

unperson Thanks Steve. No I don't load the libraries. I don't know how to do that.

Maybe I should execute tcl.exe and when I get the prompt (as we used to call it in the DOS days), I should install the libraries. Is that how it should be done? What is the syntax?

I am talking about libraries such as BWidgets.

Perhaps I should get a copy of tclkit.tcl and make an exe out of it incorporating the needed widgets.

Or perhaps use the tcl.exe and type in the info. First enter the load library function and then the run function.

Anyone has an idea what the syntax will be to load a library and to run a program?

Sarnold See starkit. You'll probably be happy with a Starkit.

  • put all your code into a directory 'myproject.vfs'
  • put the main file as 'myproject.vfs/main.tcl'
  • put the libraries you need into 'myproject.vfs/lib' (e.g. 'myproject.vfs/lib/BWidgets/*.tcl')

Then you would need sdx to wrap these files into 'myproject.kit'. Libraries into the 'lib' subdirectory are automatically loaded by package require.

fr to return to tclkit.exe: see auto_path to know where libraries are searched. Type "set auto_path" in the console window to see. To include the working directory of c:/Tcl/tclkit.exe, insert the line "lappend auto_path c:/Tcl" on top of the main script. Or set the environment variable TCLLIBPATH, if present its value is the last element in the list auto_path. If you got it right the following should show your path:

 set version [package require "Widget"]
 puts [package ifneeded "Widget" $version]

unperson Un grand merci Stephane! Les Bleus, dimanche, dommage! Thanks to you also Roland.

This is what I did:

1) I typed in the console the following: set auto_path and this is what I got:

: {C:TCL/TCLKIT.EXE/lib/tcl8.4} {C:/TCL/TCLKIT.EXE/lib} {C:/TCL/TCLKIT.EXE/lib/tk8.4} (Tcl) 4 %

2) I'll put the following line on top in the main program: "lappend auto_path c:/Tcl"

3) Then if I type in set auto_path in the console, I should get:

set version package require "Widget" puts package ifneeded "Widget" $version

Am I right so far?

4) Afterwards, all I'll have to do to execute the script is to paste it into tclkit.exe like before?

Will the line "lappend auto_path c:/Tcl" tell tclkit.exe to load all the libraries in: C:/TCL/TCLKIT.EXE/lib/ for the program I am working on?

10 minutes later: I did steps 1, 2 3, 4. It's still not working. I am missing something.

fr the last element in auto_path seems to be incomplete (TCL) should be /Tcl alternative: look for the file pkgIndex.tcl in your library directory and insert "source /the_path/pkgIndex.tcl" instead of "package require .." (this is what package require normally does)

unperson OK! I have a pkgIndex.tcl file in: c:\TCL\Lib\BWidgets.

This is the code I have in the beginning of the file:

if {catch {package require Tcl}} return package ifneeded BWidget 1.7 "\

    package require Tk 8.1.1;\
    [list tclPkgSetup $dir BWidget 1.7 {

{arrow.tcl source {ArrowButton ArrowButton::create ArrowButton::use}}

I'll change the third line: package require Tk 8.1.1;\ to source /the_path/pkgIndex.tcl; \

Is that right?

fr using BWidget 1.7 in c:/Tcl/lib/BWidget-1.7

 # using absolute path
 lappend auto_path c:/Tcl/lib
 # using path relative to working directory, where Tclkit.exe is
 # lappend auto_path [file join [pwd] lib]
 # using path relative to where the script is, i.e where these lines are inserted
 # lappend auto_path [file join [info script] lib]
 package require BWidget

or

 set dir c:/Tcl/lib/BWidget-1.7 ;# variable required inside pkgIndex.tcl
 source [file join $dir pkgIndex.tcl]
 package require BWidget

or insert general initializations in file wishrc.tcl and place this in the home directory, see $env(HOME)


GWM I have changed the icon on my toplevel window to an xbm file using

  wm iconbitmap . @folder.xbm

and the icon is restricted to the 2 colours used by the wish feather icon. How can I change the colours to (say) red and green, or pink and transparent? Reply moved to how do I give my application a color icon


Sarnold (21 June 2006) I have a strategy game with Tcl/Tk under Windows XP (Mancala). I wrote a small library (dll) providing commands to compute the computer move. Previously, when I ran into a command of this extension, it freezed the GUI events. I found the solution and moved it into Threads vs. events (I tried both, and events won).


seo - (15 June 06) Double click event won't fired ... I typed in wish

 bind . <Double-1> {puts "double clicked"}
 bind . <1> {puts "clicked"}

and expectd this when double-click on toplevel window

 clicked
 double clicked

but it shows

  clicked
 clicked

I tried tclkit version 8.4.13 / 8.5b4 / etcl 1.0 rc6 / ActiveTcl 8.4.13.0 on windows xp sp2 (korean version) Double click rate are ok with other apps. Is there a way configure double click rate on Tk? or am I missing something?

MG This works fine for me in ActiveTcl 8.4.9 and Tclkit 8.4.11. I'm fairly sure that the double-click speed is taken from XP, too, so that shouldn't cause a problem, if you're clicking fast enough for XP to consider it a double click (which you can test in the Mouse properies under Control Panel). Are you sure that you had both the bindings set? I do get the behaviour you experienced if I bind to <1>, but not to <Double-1>.

seo - Thanks MG. But I checked it several times. Tested Tclkit 8.4.11 also, but it still act like above. When googled comp.lang.tcl, I found out there are others suffered from same symptom( [L2 ] and [L3 ] ). By his name(at first link), he may be korean, too. I suspect this behaviour is something to do with korean version (or non-english version) of Windows. Is there anyone who experienced similar case on non-english version of windows?

MG If it's not the double-click speed, and you're not moving the mouse at all between clicks (which does seem to 'interrupt' a double-click, as those posts suggest) then you may be right, though I unfortunately can't test that for you. Anyone else out there on a non-English version of Windows who can try it?

seo - MG, I really appreciate your concern. I finally figure out what makes it wrong. The korean IME! By turning off korean IME, Tk behaves properly. This bug has existed for a long time, and still be there! [L4 ]

jal_frezie - I have found out some more about this issue and created a Tk bug report on SourceForge [L5 ]


grid-based input screen

LB I think I'm making something that should be easy much too hard -- time to ask.

I have a grid-based input screen. Some of the entry widgets can be populated from pick lists activitated by a button to the right of the entry. I want the pick lists to appear over or just under the entry and to disappear when the selection is made.

AFAIK, only frames and toplevels can be made to appear and disappear. When I place a frame in the cell below the entry, it "works" but the appearance distorts the screen. So I'm using a toplevel which works but is hard to place. The issues are cosmetic, but I fear the windoze users will reject my work on this basis.

This is such a common convention in GUIs that I have to believe there is a simple way, perhaps a special widget designed just for this. I'd be grateful for any pointers. The simpler the better -- this development is not my primary job, and I'm under some pressure to produce quickly (part of how I sold Tcl/Tk).

TIA,

aricb: Tile has a combobox widget, as does BWidgets. A menubutton or other popup menu also works nicely for this kind of thing.


getOpenFile

unperson I'd like the name of the file to appear in File Name: when I click on Save as. Anyone knows what code I should enter so that the name of the file appears? Thanks!

-- See [L6 ] for the -initialfile option to tk_getSaveFile. You should also set -initialdir then.


save file

unperson I am on a split screen in my editor: there is a left window and a right window. A file is opened in each window. I want the user to be able to save the file on the left when the cursor is in the left window and vice-versa to save the file on the right when the cursor is in the right window.

Is this hard to do? Is this cursor approach ok or do I instead have to find another way to let the program know that we are on a split-screen?

I also get the similar problem when I click on Find. The Find works only in the right window even if the cursor is on the left window!

I obviously have window geometry problems. Anyone less geometrically-challenged than I am with an answer?

I was told 8.4 tcl had a paned window function. Would that help?

Thanks again!

fr how to query which widget has the focus:

 # the name of the active window is displayed in the title
 catch {destroy .f}
 frame .f
 entry .f.left
 entry .f.right
 pack .f.left -side left -padx 5
 pack .f.right -side right -padx 5
 pack .f -pady 5
 catch {destroy .l}
 label .l -text "Use Tab-key or mouseclick to change the active widget"
 pack .l -pady 5
 catch {destroy .b}
 button .b -text "Which entry is active?" -command {wm title . [focus -lastfor .]}
 pack .b

unperson Thanks Roland! I know the right window is active and not the left.

I asked Maurice Ulis and he provided me with an answer so clear even I, a total beginner could understand!

This is it (I have translated his text from French to English):

You must use ::current_ht instead of ::main_ht. Current_ht seems to have been made for this purpose.

But before, the ::current_ht must be updatated everytime the user changes windows.

Changing windows can mean two things:

Option 1: putting the cursor in a specific window Option 2: putting the mouse in a specific window

The procedure to determine which window has been opened is specific to the choice made.

For option 1, the event must be followed <FocusIn> in the two text widgets.

For the option 2, the event must be followed in <Enter> in the two text widgets.

I did understand the algorithm. But to code it is another story altogether. :-)


wikit.kit

rdt (2006 May 30) I have read about Wikit & producing a wiki with wikit.kit and using wikit.tkd. My question is how would one start such a wiki with _no_ pages built in. That is, the default wikit.tkd seems to have some extra pages up to 14. I realize that pages 0 through 9 are "special" and thats ok. Its the others and the, what seems to be built in, Recent Changes that I'm asking about.

rdt Ok, here is how I finally solved this.

  • Get dgMKviewer,
  • Get it to work (I had to temporarily patch it not to reload main.tcl),
  • Use dgMKviewer on a default wikit.tkd to clean out all the old pages/references, etc.

cross-platform starkits

LB (25 May 06) My question is on cross-platform starkits that have binary extensions. In this case, the only platforms are MS Windows and Linux (XP and FC3, but I doubt if the versions are the issue).

I have a program that requires Pgtcl. When I move the source and platform-appropriate Pgtcl libraries/dlls to the machines by hand, the program executes perfectly on both. The Linux kit version also works perfectly. However the Win XP kit gives an error message:

  couldn't load library "C:\DOCUMEN~1\lbarnes\LOCALS~1\Tmp\Tcl19.tmp"

... and then a trace dump back to the require Pgtcl line. The "19" in the above actually has incremented on each invocation (?? curious).

For the record, the .vfs structure is ./foo.vfs/lib/Pgtcl1.5 with the pkgIndex.tcl and dll's inside that.

Any thoughts?

LB I seem to do a lot of answering my own questions. Pgtcl1.5 for windows is not stubs enabled. When I replaced it with Pgtcl1.4 which is, all was well. "Never give up! Never surrender!" - Cmdr. Peter Quincy Taggart, Galaxy Quest


auto_path / starkit

LB (26 May 06) I cannot get auto_path to work within a starkit. I unwrap foo.kit into foo.vfs. Within that, I try at various stages in the code, including in main.tcl (after initialization but bfore requiring my app) to do this:

   lappend auto_path "/home/lbarnes/foo.kit/lib/linux"

But this has no effect. I still get the error that my package can't be found. Since the only package path recognized seems to be foo.kit/lib, I'm forced to surmise that auto_path is not how starkits control package searches.

What, if anything, does?

The goal, which may be easier another way, is to have several different platform specific binary packages made available from within one starkit.

Again, TIA

aricb Tile was released as a multi-platform starkit; maybe it can give you some ideas. On the download page (http://sourceforge.net/project/showfiles.php?group_id=11464 ), look under tile-0-7-2 for tile07.kit.


cursor positioning

unperson (22 May 2006) I would like the cursor to appear on the top left of the edit box when I click new on my editor. I have inserted: $::main_ht mark set insert 1.0 and it still does not work. Any one has an idea what the code could be? Thanks!

fr supposed the caret is not visible, try focus -force $::main_ht

unperson I did and it works impeccably! Thanks so much, fr!

Now I am really intrigued. When I place a focus -force $::main_ht in the open file procedure, it does not work. Why? It's because first the dialog window is opened. How do we tell the program to focus force main ht (that is to put the cursor on the top of the edit box) after the user has selected a file.

fr main_ht is the name of the text widget?

 set filename [tk_getOpenFile ...]
 # dialog lost focus
 # open the file and insert text into widget
 focus $main_ht   ;# use option -force if executed in console window

unperson main_ht is apparently the editing area. I believe the variable where the name of the file is inserted is: (file rootname [file tail $f))) (put parentheses instead of square brackets)

Therefore the whole function asking to put the cursor on the top of the file selected would be this?

(file rootname (file tail $f))) focus -force $::main_ht (file rootname (file tail $f)))

fr to have a working example take this modified procedure from A minimal editor

 proc loadText {w fn} {
    if {$fn==""} return
    wm title . [file tail $fn]
    set fp [open $fn]
    $w delete 1.0 end
    $w insert end [read $fp]
    $w mark set insert 1.0
    focus $w
    close $fp
 }

unperson Well, all I would need at this stage is to be able to tell the program to put the cursor on the top of the editing zone once the user has opened a file. I remember there was a similar function in C.


TCL on Solaris

Ron I just installed TCL on Solaris system. When I type tclsh the message "ld.so.1: tclsh: fatal: libgcc_s.so.1: open failed: No such file or directory c/r Killed"

It looks like it compiled, but something else is wrong. Any ideas?

RJ had this - you need to -add- /usr/local/lib to your LD_LIBRARY_PATH environment variable. You will probably have other directories in it for some other application, It would find libgcc_s.so.1 if you did not. Unsetting the env variable is preferable (to allow it to look in shared default locations for load libraries, but that will probably break whatever app put it there. Just append /usr/loca/lib to the LD_LIBRARY_PATHvariable in .cshrc with a colon between directories. To approximate default search order:

     setenv LD_LIBRARY_PATH = /usr/local/X11/lib:/usr/local/lib:/usr/openwin/lib:<other non-standard load libraries>"  (for csh)
     set LD_LIBRARY_PATH = /usr/local/X11/lib:/usr/local/lib:/usr/openwin/lib:<other non-standard load libraries>  then   export LD_LIBRARY_PATH (for sh) 

file association

unperson 2006-05-17 I have a peculiar problem with the file association command on Windows (the file type). I have a file called: Story.wer . I gave the association on File type: wer, open c:\wer.exe The program opens ok when I click on: Story.wer . What it does wrong however, is it does not show the file name correctly and also does not show the directory name correctly. It only shows a few characters. What could be the problem? Thanks! I am getting there! They say half the fun in a trip is the journey getting there. Indeed!

MG I assume that 'wer.exe' is a Tcl program which you've wrapped into an executable? In which case, how did you wrap it, and how are you trying to display the file's name and path? Does it work correctly using an unwrapped copy of the Tcl script (ie, if you do Start->Run, "wish c:\wer.tcl c:\story.wer")?

unperson Yes indeed. wer.exe is a tcl program I have wrapped into an executable. It does work very well as an executable. I can see the file name and the directory name just fine. It also works well when I copy the wer.tcl file and paste it into tcl.exe (I use JCW's tcl.exe a lot; it's very useful and it works A1; I am not familiar with the Start->Run, "wish c:\wer.tcl c:\story.wer" however)? It's just when I click on a file to open the program that I have the problems mentioned above. I'll look into the way the directory name and the file name are displayed and I'll get back to you with the answer. Thanks Mike!

By the way, Mike, your bindings for home and key work very well (at: Home, End and other formatting problems. A million thanks! For two years I was editing like a crippled man with home and end working badly. Now, thanks to you, those keys work A1! It's a new day in my life!

Later. Here is what I believe is the code showing the directory on the top of the program.

 proc update.wm.title {args} {
  # FRINK: array ::tcl_platform 
  # FRINK: set ::data_dir
  if {"windows" == $::tcl_platform(platform)} {
     wm title . [string map {/ \\} "HLE [file normalize $::data_dir]" ]
  } else {
     wm title . "HLE [file normalize $::data_dir]"
  }
 }

#END src/update.wm.title.proc

Thanks!

MG (I edited the code you pasted in to format it properly for the wiki.) That is the code which changes the title. It just sets it to the value of the global variable $::data_dir though (after running [file normalize] on it, which isn't going to be what's breaking it). You'll need to find where that variable is set - seems like that's where the problem is occurring. Incidently, rather than that [string map], a better way to show the path is to use

  wm title . "HLE [file nativename [file normalize $::data_dir]]"

which can be used on any platform, so you don't need the if. (Glad you found the text widget bindings useful, btw.)

Ahh.. if you use Win 98, you might not have the Windows Start menu/Run, it's been so long since I used '98 I really can't remember. But does the same problem happen if you run the (unwrapped) Tcl script and tell it to load your .wer file, or does it only happen with the wrapped version? How did you produce the .exe (freeWrap, from a starkit, etc)?

unperson Thanks Mike!

You write: But does the same problem happen if you run the (unwrapped) Tcl script and tell it to load your .wer file, or does it only happen with the wrapped version? How did you produce the .exe (freeWrap, from a starkit, etc)?

I don't use the program that allows to load a file. I simply use the excellent tcl.exe to execute a tcl script. Great idea this pasting of the file into tcl.exe! I have shown it to a programmer-friend and he thought it was brilliant.

The programmer did provide me with an exe. I have no clue what program he has used.


tutorial for children

wdb 2006/05/17 Hi everybody! Is there any tutorial, or sample of ideas for such, intended for children (aged 10-18)? E.g. some popular game simply to realise in Tcl/Tk (except Lara Croft because tomb raidering is evil)? Any idea welcome!

-----> Question and answers moved to Teach programming to children.


Ravi Christianosk

Have d'loaded a TCL editor and I seem to have problems with the cursor; when I click Home I get to the beginning of the paragraph instead then the beginning of the line. Vice-versa: end gets me to the end of the paragraph. When I wanna an ascii code, I get the code 3 pages down instead of the location of the cursor. What seems to be the problem and how to fix it?

-----> Question and answers moved to Home, End and other formatting problems


add new configure option to a Tk widget

GWM how do I add a completely new configure option to a Tk widget? I have read Overloading widgets but that example shows how to create a megawidget such that the code can configure either the frame or its text content. I want to add a new option called 'pencolour' to a canvas such that when I call my 'addline' routine the new line will be drawn in the 'pencolour'. The addline procedure works fine as described. To be plain I want the following code to work:

  set ga [grapharea .mygraph -height 200 -width 400] ;# make a canvas that is overloaded as in [Overloading widgets]
  $ga configure -pencolour pink
  $ga addline 10 10 200 125

this will use the addline proc to add a line to the canvas, and I need the pencolour option to be configured to define the line's colour. I think I could do this by adding a global variable $ga.pencolour but distaste for globals.... Can I add a new option to the widget (I have tried

  option add pencolour red interactive

but this just added the option red, and would not let me modify it to pink, or even orange.)

aricb You need to write your [grapharea] proc so that it can parse such an option, and you need to create a persistent variable (such as a namespace variable) to remember it.

I'd recommend that you create a Snit widgetadaptor. I think it will greatly simplify your task.

GWM I have added my code as a (now slightly useful) example Another Graphing Widget. I have used a global variable to retain the value, but I am not happy spraying globals around - is there a better way, preferably such that the globals would be destroyed if the associated widget is destroyed.


iwidgets::tabnotebook

MK I am using iwidgets::tabnotebook. If I reduce the size of my tabnotebook by using the mouse, the widgets displayed in the selected page starts disappearing. To avoid this problem I think , I need to add scrollbar in each of the pages. Can someone tell me how to implement this, or any better solution to the above mentioned problem.

fr minimal window sizes could be defined by

 wm minsize toplevel width height  (using the window manager)
 grid columnconfigure ... -minsize ... (geometry manager for child widgets)

taskbar icons

MSH 16-Jun-2006: I am porting some of my apps to LINUX/Gnome and would like to have the same icons on the taskbar as I have under windows, is it possible to use a gif image or an XPM file instead of an XBM (only black and white) for a 'wm iconbitmap' command or is there some other way (xxx.so) which would allow this change ?

MG Take a look at How do I give my application a color icon, which uses the wm iconwindow command for it.

Thanks, I tried that and it does not seem to work with either of my windows managers KDE or GNOME, I used the code from KDE window icons which works on my KDE with a slight change to my startup alias and judicious choice of the name (I do not have permission to write to the /usr/share/... directories). I was looking for a small piece of critcl 'c' code or a small .so file, I guess I will have to wait for the TIP 159 [L7 ] to arrive.


complete filename

RPR 2006JUN20: I am writing a Tcl/Tk application running under Windows98 via Tcl/TK 8.4.13. I use file join $disk $dirpath $filename to create the full disk-to-filename path string.

The full path string comes out looking like C:/foo/bar/filename.txt (call that version 1) which is perfectly acceptable to Windows98 even though it's not according to the published preferred standards. However, It is NOT acceptable to the program (IrfanView) which I am running via exec, which requires that paths be like C:\foo\bar\filename.txt. (Version 2).

So what I'm look for is a code snippet, preferably debugged, that will take the version 1 path name as input and yield the version 2 path name. The only difference is that the forward slashes in version1 are converted into backward slashes in version 2.

MG This is actually a nice simple one :)

  % set path [file join c:/ foo bar filename.txt]
  c:/foo/bar/filename.txt
  % set path [file nativename $path]
  c:\foo\bar\filename.txt

RPR Many thanks. Just what I wanted.


focus

RPR 2006JUN27: I am (still) writing a Tcl/Tk application running under Windows98 via Tcl/TK 8.4.13. It has a textentry widget. It also spawns IrfanView as graphics display mechanism (faster than Img), using the & option of exec, so that the tcl script can continue processing while the IrFanView executable is running. The spawning process is a one line console-type input (i.e. no further keyboard or mouse input is needed. The problem is that when IrfanView is finished displaying the image, (and waiting for further mouse or keyboard input), it is still the Windows98 window that has the machine's focus (blue strip at top of window is blue, not greyed out).

What I'm looking for is a command that I can execute from the tcl script that will get Windows98 to put the machine's focus back on the wish window executing the tcl script.

Things that work:

 tk_messageBox -type ok -message " Stopped here. " 

Things that don't work (so far):

 focus  
 grab 

Working name for command: ComeBackHereYouSOB . . . (grin)

MG This might work

  focus -force .

If your app doesn't already have the focus, you need to use -force to "steal" it from the application which does.

RPR Once again, many thanks. It worked perfectly!


upload screenshot

goldshell7 new item on 30JUN2006. I need a screenshot loaded on TCL/wiki for {Refrigerator_Magnetic_Poetry} in category toys. I can email a gif, but not sure who's on vacation? thankx.

MG If you have any webspace anywhere (plenty of places offer free webspace) you can just upload the image there, and then link to it in the normal way. I'm not sure if/how you can get an image hosted on the mini.net server, though I know some are.


"keysym" binding

Barney Blankenship I'm having a problem that I'm not sure why it's a problem, I'm thinking it's either vTCL or ActiveTCL related (caused, not sure). Anyhow, a "keysym" binding is what I need, for control sequence keys, like Ctrl+Z, which I have SEEN used... but when I use them I get an "invalid keysym" error. I seem to only be able to use the keysyms listed in the ActiveState help list for keysyms, like <F1> or <F11> and such. I really need those other sequences, such as <Ctrl-C> copy, etc... what gives?

MG You just need to get the names (exactly) right - it's "Control", not "Ctrl". So something like

  bind $widget <Control-z> [list doUndo $widget]

Barney Blankenship Just tried and tested your solution, it works! Thank you so much!


tktreectrl/tile

MSH 2006-07-04 I have an application using tclkit with tktreectrl 2.1 and tile0.6 which works great under windows and linux, I have a user who would like it to run on a sun-sparc I thought no-problem recovered tclkit (8.4.9) for sparc and wrapped up the tktreectrl and the tile06.so from the tile06.kit file into a starkit but the tile 06.so refuses to load and gives :

 couldn't load file "/var/tmp/tcl9iaWnk": ld.so.1: Program.SUN: fatal: libgcc_s.so.1: open failed: No such file or directory
    while executing
 "load /home/smith/sources/Program.SUN/lib/tile0.6/SunOS-sparc/tile06.so"
    ("package ifneeded" script)
    invoked from within
 "package require tile"

Does anyone have a version of tile 0.6 which runs on a sun sparc platform ? I can load a later version but would have to recode a large library to work with tile 0.7 which is not compatible. (maybe the active tcl archives but which version was delivered with tile0.6 ?) (I do not have access to ftp from work)


text / Windows 98

RPR 2006JUL19 I've made a text widget with TCL/TK 8.4.13 from Activ running under Windows 98 SE

   text .txt  -height 8  -font " courier 16 bold "   

After putting a bunch of text in the widget on several lines, I cue the user for input with

   .txt insert end "?>" 

At that point I'd like to have the characters entered by the user via the keyboard (up to the {ENTER} key) appear underlined (as they are being entered). Nothing I've tried so far works. Suggestions?

MG The best way that springs to mind is something like this:

  pack [text .txt]
  .txt insert end "Instructions go here\n\n?> "
  .txt tag configure underline -underline 1
  bindtags .txt [list .txt Text UserInput . all]
  bind UserInput <KeyPress> [list .txt tag add underline [.txt index end-1c] end]

That will add the "underline" tag from after "?> " up until the end of the text widget whenever the user presses a key. (If they move the cursor to before the 'prompt' and type, things will go wrong, so you'd need to check for that too.) Other, easier ways to do it might include using labels for any instructions, and using a single entry widget for them to enter the response/command/whatever, binding to the Enter key on that widget and using it to process/clear their input and move onto whatever happens next, depending on what it is you want to achieve.

RPR 2006JUL19 Thanks! That was just what I wanted.


Is there any libraries to use XRC with Tk?


USB

PSP Tartu: I wonder if Tcl comes with any USB interface modules, so it would be possible to write a platform-independent application which could find and communicate with a known USB device plugged in to that machine, regardless of the OS.


build scripts

SG 2006Aug17

I'm looking for a simple way to build scripts to be evaluated from C. What I'd ideally like is something that has printf-style formating. Something like: Tcl_Evalf( interp, "lsearch -exact {a b c d e} %s", mychar );

I'm guess that somebody has done this sort of thing once or twice already.

Lars H: In your example (a script of only one command), the right thing is to construct a list with the words of the command, and then evaluate that; this saves you from quoting hell. Larger scripts can be constructed by appending (as strings!) the individual command pieces (delimited by suitable separators, e.g. newline between commands) to the whole. Using Tcl library data structures such as Tcl_Objs and DStrings is usually much preferable to primitive C constructions for this kind of thing (usually less work, much less risk for bugs, etc.)

SG: Well, I'm doing what you suggest now (using Tcl_Objs, building up scripts by appending Tcl_Objs, etc) and I've got to say, it's not less work nor low risk for bugs (Maybe it's just me, but I've never been able to fully grok when I need to manage the reference count and when I can omit it). It vertainly makes the code longer, and I'm of the opinion that the more code there is, the more likely I've made a mistake.

That said, I didn't know about DString. It looks like it might be just the ticket. Thanks.

Omar Medina : 18 Aug. 2006 Hi SG probability you can use following, of course you need to convert in c if you don not know c++ ->

 CString could be Replace for char ABC[1024]={'\0'};

have lot Fun

 #include "include\tcl.h"


 class CTclInterpreter  
 {
 private:
        Tcl_Interp *m_Interp;
 public:
        int RegExpr(const char *strPattern, const char *strText,int &iExprMached, CString &strResult, BOOL bCaseSensitive = FALSE);
        int Evaluate(const CString strScript, CString &strResult);
        CTclInterpreter();
        virtual ~CTclInterpreter();

 };


 CTclInterpreter::CTclInterpreter(): m_Interp(NULL)
 {
        m_Interp = Tcl_CreateInterp(); 
 }

 CTclInterpreter::~CTclInterpreter()
 {
         if(m_Interp != NULL)  
        { 
                Tcl_DeleteInterp(m_Interp);
                m_Interp=NULL;
        }
 }
 /* return: 0 all Ok; -1 Error
   iExpMached: 0 not mached; 1 mached 

   CString strResult;
   Evaluate("set a 988", strResult)
 */

 int CTclInterpreter::Evaluate(const CString strScript, CString &strResult)
 {
        int iRetValue = 0;
        CString strTemp = strScript;
        if(m_Interp != NULL)
        {
                iRetValue = Tcl_GlobalEval(m_Interp,strTemp.GetBuffer(strTemp.GetLength()));
                strResult = m_Interp->result;
                if (iRetValue != TCL_OK)
                {
                        iRetValue = -1;
                        strResult.Format("tcl error : %s",m_Interp->result);
                }
        }
        else
        {
                iRetValue = -1;
                strResult = "tcl error not initialized!";
        }
        return iRetValue;
 }

 /* return: 0 all Ok; -1 Error
   iExpMached: 0 not mached; 1 mached 

   CString strResult;
   int iMached = 0;
   RegExpr("^[0-9]$", "94949494",iMached ,strResult, 0)
 */
 int CTclInterpreter::RegExpr(const char *strPattern, const char *strText,int &iExprMached, CString &strResult, BOOL bCaseSensitive)
 {
        int iCode=0, iRetValue = 0;
        if(m_Interp != NULL)
        {
                iExprMached = 0;
                iCode = Tcl_VarEval(m_Interp, "regexp ",
                                              (bCaseSensitive == TRUE ? "--" : "-nocase --"),
                                              " ",
                                              strPattern,
                                              " ",
                                              strText, (char *)NULL);
                strResult = m_Interp->result;
                if (iCode == TCL_OK)
                {

                        if(strcmp(m_Interp->result,"1") == 0)
                        {
                                iExprMached = 1;
                        }
                }
                else
                {
                        iExprMached = 0;
                        iRetValue = -1;
                }
        }
        else
        {
                iExprMached = 0;
                iRetValue = -1;
                strResult = "tcl error not initialized!";
        }
        return iRetValue;
 }

SG: Thanks for the pointers. I found the sort of thing I was looking for over in Useful C Commands for Tcl. It generates a Tcl_Obj containing a substituted printf-style string. I added another function that takes that and Tcl_EvalObjEx the resulting object.


-> in a regexp

I was wondering, what is the meaning of -> in a regexp?

Example:

 if [regexp {\001ACTION(.+)\001} $msg -> msg] {set tag italic} 

RS: If you look at the regexp man page, the -> is at the position of the variable name which receives the full match. As we usually are not interested in that, I made it a habit to call this variable "->", which gives a visual indication of the value flow: from the input to the output variables :^)


doubleclicking in Korean IME

jal_frezie - 2011-03-30 05:28:52

Re: the problem with doubleclicking in the Korean IME, I have found some more details about this which I have submitted in a SourceForge bug report 3259766