freeWrap

How-To

  1. freeWrap as a TCL/TK wrapper program

  2. freeWrap as a single-file WISH interpreter

  3. freeWrap's console window

  4. Using the DDE and Registry packages (Windows only)

  5. Using wrapped text and binary files.

  6. Wrapping and using TCL/TK extensions

  7. Using the WINICO features under Windows

  8. Special variables, procedures and commands defined by freeWrap

  9. Character encodings

  10. Stdin/stdout redirection and pipes (using the exec and open commands) (Windows only)

1) freeWrap as a TCL/TK wrapper program

freeWrap can wrap TCL/TK applications that consist of multiple script and binary image files. freeWrap combines all the files together into a single executable file. The syntax for wrapping an application is described below.

Calling Syntax:

freewrap mainprog.tcl [-e] [-b BinFileList] [-f FileLoadList] [-p PackageList] [-w WrapFile] text_or_binary1 ... text_or_binaryN

where:






mainprog.tcl

text_or_binaryN

-b


-e

-f


-p


-w
main TCL/TK program script

name of a text or binary file to include.

specifies that the following named file (BinFileList) contains a list of binary files to wrap

specifies that code encryption should be turned off

specifies that the following named file (FileLoadList) contains a list of files (binary or text) to wrap

specifies that the following named file (PackageList) contains a list of files to package.

specifies that the following named file (WrapFile) is the name of the file to use as the freeWrap stub.

output:

mainprog (Linux)
mainprog.exe (Windows)

The wrapped file names may include either relative or full paths. The TCL/TK program can access the wrapped files by either refering to them by these paths or adding the paths to TCL's auto_path variable. If the auto_path method is used, the appropriate tclIndex or pkgIndex.tcl files should also be wrapped into the application. Please see the information on how to wrap a package extension.

Both text and binary files can be wrapped. When performing a wrap, freeWrap treats binary files slightly different from text files. Additionally, freeWrap normally considers wrapped files to be text unless their names end with one of the following extensions:

.gif .ppm .pgm .ico .bin .so .dll .jpg .jpeg .com .exe

The -b option can be used to specify a list of files that will be treated as binary files no matter what extension they have. This option specifies a text file which contains a list of files to wrap. The text file must contain one file name per line. Each file name listed in the file will be added to the wrapping as a binary file.

FreeWrap automatically encrypts your TCL/TK script code prior to wrapping it unless the -e option is used.

Larger wrap projects need to use freeWrap's -f option to specify a file which contains a list of files to wrap. The specified text file must contain one file name per line. Each file name listed in the file will be added to the wrapping. Use of the -f option does not preclude the specification of individual files on the freeWrap command line. The -f option may also be used several times on the same command line.

Example: freewrap myprog.tcl logo.gif -f projlist.txt code2.tcl -f special.txt

The packaging option provides a slightly different way of including a file into a freeWrap application. Use the -p option to specify a file which contains a list of files to package. The specified text file must contain one file name per line. Each file name listed in the file will be added to the application as a packaged file. Packaged files have less flexibility but are less likely to be seen by the end user. See item (5) below for more details about packaged files. The freeDelivery program is an application that makes extensive use of the -p capabilities.

By default, freeWrap attaches the wrapped files to a copy of the freeWrap program you use to do the wrapping. The -w option allows attaching the wrapped files to a different copy of freeWrap. Since freeWrap is available for multiple operating systems, this feature is useful for assembling freeWrapped applications for other operating systems while on a single computer.

Example (assembling a Windows version while running freeWrap on Linux):

freewrap myprog.tcl -w freewrap.exe

Example (assembling a Linux version while running freeWrap on Windows):

freewrap myprog.tcl -w freewrap

2) freeWrap as a single-file WISH interpreter

Renaming the freewrap program to some other file name causes freewrap to behave as a a stand-alone, single-file WISH that can be used to run any TCL/TK script. This can be done in the following manner.

Copy freewrap.exe to a new file name

      Examplecopy freewrap.exe  wishrun.exe

Use the new file as you would normally use WISH

      Examplewishrun  script_name.tcl

3) freeWrap's console window

Under freeWrap, the console command is available for both Windows and UNIX. The console window is the location that will receive any STDOUT or STDERR output. The console can also be used to interactively enter TCL/TK commands. Use console show to display the window and console hide to remove it.

Under Windows the normal WISH console is presented. Under UNIX, which doesn’t normally have a separate console for WISH, the console window is provided courtesy of code generated by MKTCLAPP.

4) Using the DDE and Registry packages (Windows only)

The DDE and Registry packages have been compiled into freeWrap. There is no need to load them with a package require command. Simply use the dde and registry commands without any preceding package require command.

5) Using wrapped or packaged files.

Wrapping

When running a wrapped application, the first file specified on the command line at the time of wrapping will be executed as a TCL/TK script. All other files specified on the command line or in a file load list are available to this executing script.

You can do the following with the wrapped files.

  1. Source them
  2. Open them
  3. Read them
  4. Close them
  5. Use the file open and file close commands
  6. Use them with the image create command
  7. Specify them for -bitmap widget options.

You CANNOT do the following with the wrapped files.

  1. File delete them (since they exist in the application, not on disk)
  2. Expect the glob command to display them.
  3. Use the load command on them. However, you can write them to disk first then use the load command on them. You may also wish to consider providing any load-able extension as a separate file instead of wrapping it.

Naming and refering to wrapped files

As a programmer, you need to be consistent in how you specify the name of a file both at the time of wrapping and within your application. The file names must match exactly.

For example, if an application is wrapped with the following command:

    freewrap myapp.tcl libmodule1.tcl

You would need to use a source command such as:

    source libmodule1.tcl

If you wrap using the command:

    freewrap myapp.tcl c:\devel\myapp1\libmodule1.tcl

Your source command would have to look like:

    source c:/devel/myapp1/libmodule1.tcl

If you wrap using the command:

    freewrap  myapp.tcl  _wrapped_files\libmodule1.tcl

Your source command should be:

    source _wrapped_files/libmodule1.tcl

DO NOT expect the relative path of wrapped files to change when you move the executable program. FreeWrap takes a "snapshot" of the file path for all wrapped files.

The same kind of stuff is true if you are going to use the file or open commands. Also, make sure the path you add to auto_path corresponds to the wrapped tclIndex file you include in your application. For example, if your wrapping command is:

    freewrap myapp.tcl c:\devel\myapp1\tclIndex c:\devel\myapp1\libmodule1.tcl

you should add c:/devel/myapp1 to auto_path.

In summary:

You should use the paths to the files as they exist at the time of wrapping. Wrapping takes a "snapshot" of the file path for all wrapped files. Do not use relative paths to refer to wrapped files if full paths were specified to wrap your files. The relative paths will evaluate to different paths when you move the executable, however your freeWrapped application still considers the wrapped files to be in their original location. You can use relative path names in your script only if you used relative path names at the time of wrapping.

Packaging

In addition to wrapping, you may also package files. Like wrapping, packaging embeds the file into the application. However, it provides only limited access to the file. The only thing that can be done with a packaged file is writing it to a file. This is done using the command _freewrap_pkgfilecopy which is available in all freeWrapped applications. Additionally, the TCL array _freewrap_package is defined in all freeWrapped applications that contain packaged files. Each index of the array represents the name of a packaged file.

6) Wrapping and using TCL/TK extensions

Script only extensions

Packages consisting only of TCL/TK scripts are generally easy to wrap. The list of files making up the package will normally be placed in a text file that can be specified with the freeWrap -f option.

As an example, let us consider the efftcl 1.0 extension. Place the following list in a text file named efftclproj.txt.

c:\tcl\lib\efftcl1.0\efftcl.tcl
c:\tcl\lib\efftcl1.0\pkgIndex.tcl
c:\tcl\lib\efftcl1.0\scripts\AFTER.TCL
c:\tcl\lib\efftcl1.0\scripts\ANIMATE.TCL
c:\tcl\lib\efftcl1.0\scripts\APPOINT.TCL
c:\tcl\lib\efftcl1.0\scripts\BALLOON.TCL
c:\tcl\lib\efftcl1.0\scripts\BIND.TCL
c:\tcl\lib\efftcl1.0\scripts\BUSY.TCL
c:\tcl\lib\efftcl1.0\scripts\CALENDAR.TCL
c:\tcl\lib\efftcl1.0\scripts\CANVAS.TCL
c:\tcl\lib\efftcl1.0\scripts\CLRDIAL.TCL
c:\tcl\lib\efftcl1.0\scripts\CLRMENU.TCL
c:\tcl\lib\efftcl1.0\scripts\CONFIRM.TCL
c:\tcl\lib\efftcl1.0\scripts\DIALOG.TCL
c:\tcl\lib\efftcl1.0\scripts\EMAIL.TCL
c:\tcl\lib\efftcl1.0\scripts\FILESEL.TCL
c:\tcl\lib\efftcl1.0\scripts\FONT.TCL
c:\tcl\lib\efftcl1.0\scripts\GAUGE.TCL
c:\tcl\lib\efftcl1.0\scripts\HIERLIST.TCL
c:\tcl\lib\efftcl1.0\scripts\NOTEBOOK.TCL
c:\tcl\lib\efftcl1.0\scripts\NOTICE.TCL
c:\tcl\lib\efftcl1.0\scripts\PANEDWIN.TCL
c:\tcl\lib\efftcl1.0\scripts\PERCENT.TCL
c:\tcl\lib\efftcl1.0\scripts\PLACARD.TCL
c:\tcl\lib\efftcl1.0\scripts\PRINTER.TCL
c:\tcl\lib\efftcl1.0\scripts\RADIOBOX.TCL
c:\tcl\lib\efftcl1.0\scripts\SCRLFORM.TCL
c:\tcl\lib\efftcl1.0\scripts\TABNBOOK.TCL
c:\tcl\lib\efftcl1.0\scripts\TCLINDEX
c:\tcl\lib\efftcl1.0\scripts\TEXTDISP.TCL
c:\tcl\lib\efftcl1.0\scripts\TOOLBAR.TCL
c:\tcl\lib\efftcl1.0\images\flag.gif
c:\tcl\lib\efftcl1.0\images\back.xbm
c:\tcl\lib\efftcl1.0\images\arrow.xbm
c:\tcl\lib\efftcl1.0\images\fwd.xbm

Add the following two lines to our application, ourprog.tcl, in order to use the efftcl package.

lappend auto_path c:/tcl/lib/efftcl1.0  ;# Ensure our application can find the files
package require Efftcl

Wrap the application using the following command line.

freewrap ourprog.tcl -f efftclprog.txt

Extensions containing binary files

Wrapped applications can load TCL/TK shared binary extensions that have been compiled with the new TEA (i.e. stubs) interface. This is done using either a package require or load command. It is easiest if the shared library is used as a file separate from the wrapped program.

As an alternative (not necessarily recommended), it is possible to include shared binary libraries in the wrapping, but they cannot be directly loaded from their wrapped state. They must first be written to disk, then loaded from the new disk location. This task of course, is the responsibility of the application programmer. Following is an example of how this might be done.

Add the following code to the main application, teststub.tcl, in order to load the wrapped binary extension.

set extfile example.dll
if {[file exists $extfile]} {
    set tmpfile c:/windows/temp/$extfile
    set fin [open $extfile r]
    fconfigure $fin -translation binary
    set fout [open $tmpfile w]
    fconfigure $fout -translation binary
    puts -nonewline $fout [read $fin]
    close $fin
    close $fout
    load $tmpfile
if ![catch {load $tmpfile} result] {
    puts "Shared libary loaded."
   } {
       puts "Shared libary failed to load."
       puts $result
     }
} { puts "Failed to create $extfile" }

The example code above will copy the DLL file to the c:/windows/temp directory then load it from there.

Create the executable program and include the shared library file.

freewrap teststub.tcl example.dll

7) Using the WINICO features under Windows

Unfortunately the winico createfrom command cannot directly load an icon that is contained within a wrapped application. The icon file must first be written back to disk before it is loaded. The following example code demonstrates how this can be done.

# Ensure root window (.) is visible before running following code
set icofile smiley.ico
if {[file exists $icofile]} {
    set tmpfile c:/windows/temp/$icofile
    set fin [open $icofile r]
    fconfigure $fin -translation binary
    set fout [open $tmpfile w]
    fconfigure $fout -translation binary
    puts -nonewline $fout [read $fin]
    close $fin
    close $fout
    set ico [winico create $tmpfile]
    winico setwindow . $ico
    puts "you should see a yellow smiley in ."
}

You can read some excerpted Winico documentation for more information.

8) Special variables, procedures and commands defined by freeWrap

::freewrap namespace

FreeWrap now has a namespace which contains all of the freeWrap specific variables, commands and procedures. These variables, commands and procedures may be reference using the ::freewrap:: prefix or imported into any other namespace.

Variables

The following variables are defined in the ::freewrap namespace of each wrapped application.

Name

Description

contents List of all TCL/TK extensions included in the freeWrap compilation.
pkInfo This TCL array is only defined in freeWrapped applications that contain packaged files. Each index of the array represents the name of a packaged file. The value of each array member is a list of the following items.
  1. position of the file data from the end of the application file
  2. length of file in bytes
  3. file date/time in seconds (use TCL's clock command to format properly)
  4. boolean flag indicating whether file needs a freeWrap stub reattached.

The pkgfilecopy procedure uses the information in this array to perform its task.The programmer does not need to use the array directly.

patchLevel Revision level of the freeWrap program used to wrap the application.
progname The proper name for the freeWrap program for the current operating system. This is normally freewrap.exe under Windows and freewrap under UNIX.
stubsize This value is the size, in bytes, of the base freeWrap executable program embedded in the wrapped application.

It is important to note that all freeWrapped applications contain a copy of the freeWrap program itself. The first part of a wrapped application consists of this freeWrap "stub". Therefore, knowing the size of this freeWrap stub, it is possible to extract freeWrap from the wrapped application and copy it to another file.

Procedures

The following procedures are defined in the ::freewrap namespace of each wrapped application. The commands names starting with shell_ are only available under the Windows operating system.

Name

Arguments

Description

iswrapped

file_name

Determines whether the file named file_name is a freeWrapped application.

If file_name is a freeWrapped application this procedure returns an open file descriptor to the file.

If file_name is NOT a freeWrapped application this procedure returns an empty string

pkgfilecopy

src dest ?force?

Copies the packaged file named src to an external file named dest. Existing destination files will be overwritten only if the word "force" is used as a third argument.

On success, this procedure returns an empty string

On failure, this procedure returns and an error message

shell_assoc_exist

extension

Check whether a key exists for an extension

Example: shell_assoc_exist .txt => 1
Example: shell_assoc_exist .NEVER => 0

shell_fileType_exist

fileType

Determine whether a file type exists

Example: shell_fileType_exist txtfile => 1
Example: shell_fileType_exist NEVER => 0

shell_fileExtension_setup extension, fileType Creates a file extension and associates it with fileType.
Example: shell_fileExtension_setup .txt txtfile

Remove connection between extension and fileType
Example: shell_fileExtension_setup .txt ""

shell_fileType_setup fileType, title Creates a file type.
Example: shell_fileType_setup txtfile "Text Document"
shell_fileType_open fileType, openCommand Creates a open command. Sets action for double click.
Example: shell_fileType_open txtfile "C:\\WINDOWS\\NOTEPAD.EXE %1"
shell_fileType_print fileType, printCommand Creates a print command for right mouse button menu.
Example: shell_fileType_print txtfile "C:\\WINDOWS\\NOTEPAD.EXE /p %1"}
shell_fileType_icon fileType, icon Sets an icon for a fileType.
Example: shell_fileType_icon txtfile "C:\\WINDOWS\\SYSTEM\\shell32.dll,-152"
Example: shell_fileType_icon txtfile "C:\\mydir\\myicon.ico"

We can give a name.ico file or a dll or exe file here. If a dll or exe file is used the index for the resource inside the file must be specified

shell_fileType_quickView fileType, quickViewCmd Sets the command to execute to perform a quick view for a fileType.
Example: shell_fileType_quickView txtfile "write.exe %1"
shell_fileType_addAny_cmd fileType, cmdName, cmd Adds any command you want to a fileType.
Example: shell_fileType_addAny_cmd scrfile config "%1"
shell_fileType_setMenuName fileType, cmdName, str Change description in right mouse menu for a command associated with a fileType.
Example: shell_fileType_setMenuName txtfile print "Print file"
shell_fileType_showExt fileType, yesOrNo Always show the extension on the fileType.
Example: shell_fileType_showExt txtfile 1

Turn off "Always show" of extension on the fileType
Example: shell_fileType_showExt txtfile 0

shell_fileType_setCmdOrder fileType, cmds Over-ride the default ordering of commands on right mouse menu.
Example: shell_fileType_setCmdOrder txtfile {print open}
shell_fileType_neverShowExt fileType, yesOrNo Never show extension on fileType.
Example: shell_fileType_neverShowExt txtfile 1

Turn off "Never show" of extension on the fileType.
Example: shell_fileType_neverShowExt txtfile 0

shell_getCmds file Retrieves all the commands assocated with an extension.
Example: shell_getCmds file.txt => open print
shell_getCmd_imp file, cmd Retrieves the implimentation of a command given a file extension and command.
Example: shell_getCmd_imp test.txt open => C:\\WINDOWS\\NOTEPAD.EXE %1

Commands

The following TCL commands are defined in the ::freewrap namespace of each wrapped application. The encrypt and decrypt commands are used by freeWrap in the performance of its tasks.

Name

Arguments

Description

decrypt string_to_decrypt Decrypts a string that has been encrypted by the freewrap_encrypt command.

Returns the decrypted string.

encrypt string_to_encrypt Encrypts the specified string using a simple algorithm.

Returns the encrypted string.

getSpecialDir dirType Find "Start Menu", "Desktop" and similar directory locations under Windows. DirType must be one of the following strings:
DESKTOP INTERNET
PROGRAMS CONTROLS
PRINTERS PERSONAL
FAVORITES STARTUP
RECENT SENDTO
BITBUCKET STARTMENU
DESKTOPDIRECTORY DRIVES
NETWORK NETHOOD
FONTS TEMPLATES
COMMON_STARTMENU COMMON_PROGRAMS
COMMON_STARTUP COMMON_DESKTOPDIRECTORY
APPDATA PRINTHOOD
ALTSTARTUP COMMON_ALTSTARTUP
COMMON_FAVORITES INTERNET_CACHE
COOKIES HISTORY
shortcut linkPath

?-objectPath objectPath?

?-description description?

?-workingDirectory dir?

?-icon path index?

?-arguments args?

Creates a Windows shortcut. The only required parameter is the linkPath. This means you can create a shortcut with no target, which probably isn't useful. The icon of the shortcut will default to the icon of the target item if not specified.
Argument Explanation
linkPath The path to the shortcut file (including the extension .lnk)
objectPath The target of the link
description Shortcut description
workingDirectory Working (startup) directory for the target of the shortcut
path index (icon) Specifies the path to a file and the index of the icon in that file to use for the shortcut
args Arguments passed to the target of the shortcut when started.

9) Character encodings

The numerous encoding files available with the TCL distribution have not been compiled into the freeWrap application. Including all the encoding files into freeWrap would have significantly increased the size of freeWrap executables. However, for those people wishing to work with alternate encodings, the TCL encoding files can be wrapped along with your individual scripts. The character encoding files themeselves are available from the normal TCL distribution. Instructions on how to use the encoding files follow.

Simply wrap the desired encoding file into your application. At wrap time you must make sure to specify the full path to the encoding file.

        Example:    freewrap myprog.tcl C:\tcl\lib\tcl8.3\encoding\cp1250.enc

Ensure that the path to the encoding file is included in your auto_path variable.

        Example:    lappend auto_path C:/tcl/lib/tcl8.3/encoding

Use the full path name, excluding the file extension, when referring to the encoding file.

        Example:    encoding system C:/tcl/lib/tcl8.3/encoding/cp1250

Using this method, the encoding names command will not be able to list your wrapped encoding file. However, the other encoding commands will work correctly.

10) Stdin/Stdout redirection and pipes (using the exec and open commands)

The Windows version of freeWrap now includes the tcl83pip.dll file from the normal TCL distribution. This file is necessary when running scripts that redirect stdin/stdout through pipes using the open or exec commands. Tcl83pip.dll is actually an executable program that helps do the redirection of stdin and stdout when execing programs under Windows. Make sure that tclpip83.dll can be found in a location that TCL normally looks (e.g the current directory, the Windows directory or the same directory as the executable program).


 Send comments to dlabelle@nycap.rr.com