DOCUMENTATION FOR TCL4MIRC (FOR INSTALLATION SEE README.TXT)
=======================================================================
Last update on October 20th 2007 for version 1.0

0. FAQ
    > What is "supported mode"?
    
1. RUNNING TCL
    > Invoking the interpreter
    > Notes on $dllcall and asynchronous calls
    > Embedding Tcl into scripts
    > Caching embedded code

2. COMMUNICATING WITH MIRC
    > mirc package
    > mirc function
    > Passing variables from mIRC

3. MIRC SIGNAL CALLBACKS AND OUTPUT HANDLING
    > TCL_LOADED
    > TCL_ERROR
    > TCL_STDOUT_BEGIN / TCL_STDERR_BEGIN
    > TCL_STDOUT / TCL_STDERR
    > TCL_STDOUT_END / TCL_STDERR_END
    
4. USING TK

=======================================================================

0. FAQ

    > What is "supported mode"?
    
    Tcl4mIRC relies on the CLB (Common Language Bridge) which is part
    of the Dynamic Languages 4 mIRC project. The CLB extends the way
    a DLL can communicate with mIRC, enabling it specifically to be
    able to access event specific identifiers, like $opnick in the 
    ON OP event. In addition to extended functionality, this mode is
    roughly 3 times faster than using the standard SendMessage API 
    documented in the mIRC help (/help SendMessage). 
    
    However, a drawback of this mode is that it requires specific 
    knowledge about the makeup of the mIRC binary that is being run.
    In other words, to make use of the CLB's extended functionality, 
    the version of mIRC used with the DLL must be explicitly supported
    by the CLB, hence "supported mode".
    
    CLB is able to fallback on the standard SendMessage API when the
    version of mIRC is not supported, but beware that you may be using
    a script that requires the extended functionality that the CLB 
    provides. If you are using Tcl4mIRC in unsupported mode, verify
    that you do not have any embedded scripts inside events that make
    use of event specific identifiers. In such a case, your events will
    not function properly.


1. RUNNING TCL

    > Invoking the interpreter
    
    The first way to run Tcl code is to simply invoke the evaluation 
    method by simply calling:
    
        /tcl CODE_HERE
        
        * Note that /tcl is a convenience alias specified in tcl.mrc
        
    You can also use $tcl(CODE_HERE) to retrieve the return value
    from a block of Tcl code.
        
        
    > Notes on $dllcall and asynchronous calls
    
    Short answer: don't use it.
    
    Long answer: 
     
    Tcl has an event driven interpreter model. Threading is implicit,
    not explicit. Therefore, making asynchronous calls in Tcl is
    much like making asynchronous calls in mIRC: you use a timer 
    which will inevitably be processed by the Tcl event loop. This 
    means that you cannot and should not use `$dllcall` to perform
    asynchronous calls, because Tcl does not work properly across
    threads. Doing so will likely crash mIRC.
    
    
    > Embedding Tcl into scripts

    Most people don't just want Tcl sitting on the sidelines while
    mIRC does its thing. For this reason, you have the ability to
    embed your Ruby code directly into your mIRC scripts seamlessly.
    
    To do this, you must "memorize" the following snippet of code
    to have Tcl4mIRC jump from mIRC code into your Tcl script:
    
        if $($has_tcl,2) {
          # Tcl code goes here
        }

    If you're curious to know what it does, I can explain. $has_tcl 
    will return a call to the DLL to invoke the interpreter and parse
    the code starting at the beginning of the if extending to the end.
    The command must be $() evaluated to get $scriptline so that it knows
    where to begin parsing from. The identifier then returns $false so
    that mIRC ignores the if-block, happily skipping over the otherwise-
    invalid script.    
    

    > Caching embedded code

    To speed up the execution of each embedded call, you can cache your
    code in memory to avoid recompiling the Tcl code each round. To do
    this, simply use $has_cached_tcl (or $has_cached_async_tcl) instead.
    
    IMPORTANT: Note that the Tcl caching model is such that once you cache
               a block of code it can not be overidden by calling the non-
               cached function anymore. To clear the cache you will have
               to unload the DLL completely with `/tcl_unload`.
               
    Caching is not "on" by default because most people will most likely 
    have to make changes to their code before finalizing it, and having
    Tcl4mIRC cache all the time would cause a lot of headaches in 
    debugging. For this reason, the recommended flow of coding is to use
    $has_tcl until you are positive that you have a working product,
    and only then change the starting line to $has_cached_tcl. It may
    also be beneficial to add a note to yourself that you are caching
    the script results.
	

2. COMMUNICATING WITH MIRC

    > mirc package
    
    Tcl4mIRC registers a package called 'mirc' for to get information 
    about the DLL version, etc. It can be accessed via the standard Tcl
    package info command:
    
        /tcl puts [package present mirc]

    > mirc function

    The `mirc` function is the main command to use to have Tcl communicate
    with mIRC. The function takes a command, variable, or identifier as
    an argument and evaluates the expression, returning a result (if it
    is not a command). For example:
    
        mirc "echo -a hello world"
        
    Notice that the '/' prefix is not necessary, though it is allowed. 

    * Note: The mirc command will decide whether to evaluate code as an
            identifier or variable depending on the first character in
            the command string. If the first character is '%' or '$',
            the string will be evaluated, otherwise it will be executed.
            This means that the command "%x = 2" will not attempt to set
            the variable %x to 2. Please use "set %x 2" to do that 
            instead. Subsequent versions of Tcl4mIRC will address this
            issue, perhaps by splitting evaluation and commands into
            two separate functions.

    To evaluate an identifier use (in Tcl we always escape '$' when we
    are not accessing a Tcl variable):
    
        puts [mirc \$calc(1 + 2)]
        
    Or:
    
        puts [mirc %a_variable]
        
        
    * Note: Remember to escape '$' and '%' characters if you call the
            above code using /tcl or $tcl since you will be subject to
            parsing by mIRC before your data reaches Tcl4mIRC. In embedded
            code there is no need to escape anything for mIRC's sake.
    
    If you run Tcl in "supported mode" (See "supported mode" in the FAQ 
    for details) then you can take advantage of this command to evaluate
    event specific identifiers, for example, $opnick in an ON OP event.
    
    
    > Passing variables from mIRC
    
    It is likely that you will need to pass data to and from Tcl when
    creating a script. While the CLB does support event specific
    identifiers to reduce the number of data needed to be manually 
    passed in and out of mIRC, the CLB does not support local variables
    or the $1- identifier family, and therefore cannot communicate 
    completely transparently with mIRC.
    
    To solve this problem, you must unfortunately set the variables
    that Tcl4mIRC needs to read globally, unsetting them at the end
    of your alias or event. /set -u0 will not work to avoid the unset
    command at the end. A way to access local variables via the CLB
    is being worked on. An example of communicating between mIRC
    and Tcl would be:
    
        alias tcl_strlen {
          set %data $1-
          tcl puts [string length [mirc {%data}]]
          unset %data
        }

        /tcl_strlen Hello world
        
       
3. MIRC SIGNAL CALLBACKS AND OUTPUT HANDLING

    Tcl4mIRC sends a few signals to mIRC now and then that can be caught
    by the scripter. For more information on the SIGNAL event, read mIRC's
    help under "ON SIGNAL". The following signals are supplied:
    
        > TCL_ERROR
        
            This signal will be triggered in the rare case where the CLB
            cannot communicate with mIRC. This is a critical error and
            should be handled by halting further script processing. Error
            details will be filled into $1-.
    
        > TCL_LOADED
            
            Triggered when TCL is finished loading into memory. You can
            use this to load any important TCL support libraries. The
            identifier $1 will be filled with the "supported mode" value
            as $true / $false (whether or not the CLB is running in 
            supported mode). See "supported mode" in the FAQ for more
            information on this value.
            
        > TCL_STDOUT_BEGIN / TCL_STDERR_BEGIN
        
            Triggered when Tcl is about to read a block of text either
            from standard output or standard error. You can use this
            to /linesep if you wish.
        
        > TCL_STDOUT / TCL_STDERR
        
            Triggered when Tcl reads *one line* of data from standard
            output or standard error. $1- is filled with the line contents.
        
        > TCL_STDOUT_END / TCL_STDERR_END

            Triggered when Tcl finishes printing a block of text from
            standard output or standard error.
            
4. USING TK

    Ideally, Tk should be run within a separate process from mIRC. This will
    enable your Tk application to perform proper shutdown procedures. You can
    do this by using `exec` to run `wish` on your Tcl script (exec wish myfile.tcl)
    However, if you must run Tk code within the same process as mIRC, there are a 
    few things to keep in mind:
    
    1. As hinted above, Tcl/Tk is running in the same process space as mIRC.
       This means that if your Tk application calls `exit` to shutdown, it will
       close mIRC as well.
       
    2. Closing the root level window (the one that pops up when you require Tk) 
       will disable the Tk interpreter completely. You will probably see the
       following error message if you do so and try to use Tk:
       
           can't invoke "tk" command: application has been destroyed
           
       You can reinvoke Tk by unloading the dll (/dll -u $tcl_dll) and reloading
       it. Instead of closing the root window, hide it with:
       
           /tcl wm withdraw .
           
       You can reshow any withdrawn windows with `wm deiconify path`:
       
           /tcl wm deiconify .
           
       To ensure that you do not accidentally click the X button, you can add the
       following to any Tk initialization commands you may be doing: 
       
           alias tk_init {
             tcl package require Tk
             tcl wm protocol . WM_DELETE_WINDOW {wm withdraw .}
           } 
       
    Again, the above issues can be ignored if you run your Tk applications in their
    own process space.